diff --git a/.github/workflows/startos-iso.yaml b/.github/workflows/startos-iso.yaml index 1ec009dfb..ecf15a54f 100644 --- a/.github/workflows/startos-iso.yaml +++ b/.github/workflows/startos-iso.yaml @@ -12,6 +12,9 @@ on: - dev - unstable - dev-unstable + - docker + - dev-docker + - dev-unstable-docker runner: type: choice description: Runner @@ -28,6 +31,13 @@ on: - aarch64 - aarch64-nonfree - raspberrypi + deploy: + type: choice + description: Deploy + options: + - NONE + - alpha + - beta push: branches: - master @@ -42,8 +52,52 @@ env: ENVIRONMENT: '${{ fromJson(format(''["{0}", ""]'', github.event.inputs.environment || ''dev''))[github.event.inputs.environment == ''NONE''] }}' jobs: - all: - name: Build + compile: + name: Compile Base Binaries + strategy: + fail-fast: true + matrix: + arch: >- + ${{ + fromJson('{ + "x86_64": ["x86_64"], + "x86_64-nonfree": ["x86_64"], + "aarch64": ["aarch64"], + "aarch64-nonfree": ["aarch64"], + "raspberrypi": ["aarch64"], + "ALL": ["x86_64", "aarch64"] + }')[github.event.inputs.platform || 'ALL'] + }} + runs-on: ${{ fromJson('["ubuntu-22.04", "buildjet-32vcpu-ubuntu-2204"]')[github.event.inputs.runner == 'fast'] }} + steps: + - run: | + sudo mount -t tmpfs tmpfs . + if: ${{ github.event.inputs.runner == 'fast' }} + + - uses: actions/checkout@v3 + with: + submodules: recursive + + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODEJS_VERSION }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Make + run: make ARCH=${{ matrix.arch }} compiled-${{ matrix.arch }}.tar + + - uses: actions/upload-artifact@v3 + with: + name: compiled-${{ matrix.arch }}.tar + path: compiled-${{ matrix.arch }}.tar + image: + name: Build Image + needs: [compile] strategy: fail-fast: false matrix: @@ -65,80 +119,30 @@ jobs: format( '["ubuntu-22.04", "{0}"]', fromJson('{ - "x86_64": ["buildjet-32vcpu-ubuntu-2204", "buildjet-32vcpu-ubuntu-2204"], - "x86_64-nonfree": ["buildjet-32vcpu-ubuntu-2204", "buildjet-32vcpu-ubuntu-2204"], - "aarch64": ["buildjet-16vcpu-ubuntu-2204-arm", "buildjet-32vcpu-ubuntu-2204-arm"], - "aarch64-nonfree": ["buildjet-16vcpu-ubuntu-2204-arm", "buildjet-32vcpu-ubuntu-2204-arm"], - "raspberrypi": ["buildjet-16vcpu-ubuntu-2204-arm", "buildjet-32vcpu-ubuntu-2204-arm"], - }')[matrix.platform][github.event.inputs.platform == matrix.platform] + "x86_64": "buildjet-8vcpu-ubuntu-2204", + "x86_64-nonfree": "buildjet-8vcpu-ubuntu-2204", + "aarch64": "buildjet-8vcpu-ubuntu-2204-arm", + "aarch64-nonfree": "buildjet-8vcpu-ubuntu-2204-arm", + "raspberrypi": "buildjet-8vcpu-ubuntu-2204-arm", + }')[matrix.platform] ) )[github.event.inputs.runner == 'fast'] }} + env: + ARCH: >- + ${{ + fromJson('{ + "x86_64": "x86_64", + "x86_64-nonfree": "x86_64", + "aarch64": "aarch64", + "aarch64-nonfree": "aarch64", + "raspberrypi": "aarch64", + }')[matrix.platform] + }} steps: - - name: Free space - run: df -h && rm -rf /opt/hostedtoolcache* && df -h - if: ${{ github.event.inputs.runner != 'fast' }} - - - run: | - sudo mount -t tmpfs tmpfs . - if: ${{ github.event.inputs.runner == 'fast' && (matrix.platform == 'x86_64' || matrix.platform == 'x86_64-nonfree' || github.event.inputs.platform == matrix.platform) }} - - - uses: actions/checkout@v3 - with: - repository: Start9Labs/embassy-os-deb - path: embassy-os-deb - - uses: actions/checkout@v3 with: submodules: recursive - path: embassy-os-deb/embassyos-0.3.x - - - run: | - cp -r debian embassyos-0.3.x/ - VERSION=0.3.x ./control.sh - cp embassyos-0.3.x/backend/startd.service embassyos-0.3.x/debian/embassyos.startd.service - working-directory: embassy-os-deb - - - uses: actions/setup-node@v3 - with: - node-version: ${{ env.NODEJS_VERSION }} - - - name: Get npm cache directory - id: npm-cache-dir - run: | - echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT - - uses: actions/cache@v3 - id: npm-cache - with: - path: ${{ steps.npm-cache-dir.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install \ - debmake \ - debhelper-compat \ - crossbuild-essential-arm64 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Run dpkg build - working-directory: embassy-os-deb - run: "make VERSION=0.3.x TAG=${{ github.ref_name }}" - env: - OS_ARCH: ${{ matrix.platform }} - - - uses: actions/checkout@v3 - with: - repository: Start9Labs/startos-image-recipes - path: startos-image-recipes - name: Install dependencies run: | @@ -157,52 +161,77 @@ jobs: - run: sudo mount -t tmpfs tmpfs /var/tmp/debspawn if: ${{ github.event.inputs.runner == 'fast' && (matrix.platform == 'x86_64' || matrix.platform == 'x86_64-nonfree') }} - - uses: actions/cache@v3 + - name: Download compiled artifacts + uses: actions/download-artifact@v3 with: - path: /var/lib/debspawn - key: ${{ runner.os }}-${{ matrix.platform }}-debspawn-init + name: compiled-${{ env.ARCH }}.tar - - run: "mkdir -p startos-image-recipes/overlays/deb" + - name: Extract compiled artifacts + run: tar -xvf compiled-${{ env.ARCH }}.tar - - run: "mv embassy-os-deb/embassyos_0.3.x-1_*.deb startos-image-recipes/overlays/deb/" - - - run: "rm -rf embassy-os-deb ${{ steps.npm-cache-dir.outputs.dir }} $HOME/.cargo" + - name: Prevent rebuild of compiled artifacts + run: | + mkdir -p frontend/dist/raw + PLATFORM=${{ matrix.platform }} make -t compiled-${{ env.ARCH }}.tar - name: Run iso build - working-directory: startos-image-recipes - run: | - ./run-local-build.sh ${{ matrix.platform }} + run: PLATFORM=${{ matrix.platform }} make iso + if: ${{ matrix.platform != 'raspberrypi' }} + + - name: Run img build + run: PLATFORM=${{ matrix.platform }} make img + if: ${{ matrix.platform == 'raspberrypi' }} - uses: actions/upload-artifact@v3 with: name: ${{ matrix.platform }}.squashfs - path: startos-image-recipes/results/*.squashfs + path: results/*.squashfs - uses: actions/upload-artifact@v3 with: name: ${{ matrix.platform }}.iso - path: startos-image-recipes/results/*.iso + path: results/*.iso if: ${{ matrix.platform != 'raspberrypi' }} - - uses: actions/checkout@v3 - with: - submodules: recursive - path: start-os - if: ${{ matrix.platform == 'raspberrypi' }} - - - run: "mv startos-image-recipes/results/startos-*_raspberrypi.squashfs start-os/startos.raspberrypi.squashfs" - if: ${{ matrix.platform == 'raspberrypi' }} - - - run: rm -rf startos-image-recipes - if: ${{ matrix.platform == 'raspberrypi' }} - - - name: Build image - working-directory: start-os - run: make startos_raspberrypi.img - if: ${{ matrix.platform == 'raspberrypi' }} - - uses: actions/upload-artifact@v3 with: - name: raspberrypi.img - path: start-os/startos-*_raspberrypi.img + name: ${{ matrix.platform }}.img + path: results/*.img if: ${{ matrix.platform == 'raspberrypi' }} + + - name: Upload OTA to registry + run: >- + PLATFORM=${{ matrix.platform }} make upload-ota TARGET="${{ + fromJson('{ + "alpha": "alpha-registry-x.start9.com", + "beta": "beta-registry.start9.com", + }')[github.event.inputs.deploy] + }}" KEY="${{ + fromJson( + format('{{ + "alpha": "{0}", + "beta": "{1}", + }}', secrets.ALPHA_INDEX_KEY, secrets.BETA_INDEX_KEY) + )[github.event.inputs.deploy] + }}" + if: ${{ github.event.inputs.deploy != '' && github.event.inputs.deploy != 'NONE' }} + + index: + if: ${{ github.event.inputs.deploy != '' && github.event.inputs.deploy != 'NONE' }} + needs: [image] + runs-on: ubuntu-22.04 + steps: + - run: >- + curl "https://${{ + fromJson('{ + "alpha": "alpha-registry-x.start9.com", + "beta": "beta-registry.start9.com", + }')[github.event.inputs.deploy] + }}:8443/resync.cgi?key=${{ + fromJson( + format('{{ + "alpha": "{0}", + "beta": "{1}", + }}', secrets.ALPHA_INDEX_KEY, secrets.BETA_INDEX_KEY) + )[github.event.inputs.deploy] + }}" diff --git a/.gitignore b/.gitignore index c91de92fd..b97eb7334 100644 --- a/.gitignore +++ b/.gitignore @@ -16,13 +16,15 @@ deploy_web.sh secrets.db .vscode/ /cargo-deps/**/* +/PLATFORM.txt /ENVIRONMENT.txt /GIT_HASH.txt /VERSION.txt -/embassyos-*.tar.gz /eos-*.tar.gz /*.deb /target /*.squashfs -/debian -/DEBIAN \ No newline at end of file +/results +/dpkg-workdir +/compiled.tar +/compiled-*.tar \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index f5e17510c..000000000 --- a/Cargo.lock +++ /dev/null @@ -1,5607 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if 1.0.0", - "cipher", - "cpufeatures", - "ctr", - "opaque-debug", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom 0.2.8", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "0.7.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" -dependencies = [ - "memchr", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -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 = "anyhow" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - -[[package]] -name = "ast_node" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc4c00309ed1c8104732df4a5fa9acc3b796b6f8531dfbd5ce0078c86f997244" -dependencies = [ - "darling 0.10.2", - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "async-stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" -dependencies = [ - "async-stream-impl", - "futures-core", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "async-trait" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "atoi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "avahi-sys" -version = "0.10.0" -source = "git+https://github.com/Start9Labs/avahi-sys?branch=feature/dynamic-linking#12bef9e435cfb0d36cb229b9d08e2114c176ea7a" -dependencies = [ - "bindgen", - "libc", -] - -[[package]] -name = "backtrace" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" -dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" - -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64ct" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" - -[[package]] -name = "basic-cookies" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb53b6b315f924c7f113b162e53b3901c05fc9966baf84d201dfcc7432a4bb38" -dependencies = [ - "lalrpop", - "lalrpop-util", - "regex", -] - -[[package]] -name = "better_scoped_tls" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73e8ecdec39e98aa3b19e8cd0b8ed8f77ccb86a6b0b2dc7cd86d105438a2123" -dependencies = [ - "scoped-tls", -] - -[[package]] -name = "bindgen" -version = "0.55.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b13ce559e6433d360c26305643803cb52cfbabbc2b9c47ce04a58493dfb443" -dependencies = [ - "bitflags", - "cexpr", - "cfg-if 0.1.10", - "clang-sys", - "clap 2.34.0", - "env_logger 0.7.1", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "proc-macro2 1.0.47", - "quote 1.0.21", - "regex", - "rustc-hash", - "shlex", - "which 3.1.1", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - -[[package]] -name = "bitmaps" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" - -[[package]] -name = "bitvec" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2b_simd" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" -dependencies = [ - "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "bollard" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82e7850583ead5f8bbef247e2a3c37a19bd576e8420cd262a6711921827e1e5" -dependencies = [ - "base64 0.13.1", - "bollard-stubs", - "bytes", - "futures-core", - "futures-util", - "hex", - "http", - "hyper", - "hyperlocal", - "log", - "pin-project-lite", - "serde", - "serde_derive", - "serde_json", - "serde_urlencoded", - "thiserror", - "tokio", - "tokio-util", - "url", - "winapi", -] - -[[package]] -name = "bollard-stubs" -version = "1.42.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" -dependencies = [ - "serde", - "serde_with 1.14.0", -] - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" - -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cexpr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" -dependencies = [ - "nom 5.1.2", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-integer", - "num-traits", - "serde", - "time 0.1.44", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "ciborium" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" - -[[package]] -name = "ciborium-ll" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - -[[package]] -name = "clang-sys" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap 0.11.0", - "unicode-width", - "vec_map", -] - -[[package]] -name = "clap" -version = "3.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" -dependencies = [ - "atty", - "bitflags", - "clap_lex", - "indexmap", - "strsim 0.10.0", - "termcolor", - "textwrap 0.16.0", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "color-eyre" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error 0.2.0", -] - -[[package]] -name = "color-spantrace" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" -dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error 0.2.0", -] - -[[package]] -name = "const-oid" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" -dependencies = [ - "percent-encoding", - "time 0.3.16", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" -dependencies = [ - "cookie", - "idna 0.2.3", - "log", - "publicsuffix", - "serde", - "serde_json", - "time 0.3.16", - "url", -] - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "cpufeatures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "csv" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher", -] - -[[package]] -name = "current_platform" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74858bcfe44b22016cb49337d7b6f04618c58e5dbfdef61b06b8c434324a0bc" - -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - -[[package]] -name = "cxx" -version = "1.0.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "scratch", - "syn 1.0.103", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core 0.10.2", - "darling_macro 0.10.2", -] - -[[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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" -dependencies = [ - "darling_core 0.14.2", - "darling_macro 0.14.2", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2 1.0.47", - "quote 1.0.21", - "strsim 0.9.3", - "syn 1.0.103", -] - -[[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 1.0.47", - "quote 1.0.21", - "strsim 0.10.0", - "syn 1.0.103", -] - -[[package]] -name = "darling_core" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2 1.0.47", - "quote 1.0.21", - "strsim 0.10.0", - "syn 1.0.103", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core 0.10.2", - "quote 1.0.21", - "syn 1.0.103", -] - -[[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 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "darling_macro" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" -dependencies = [ - "darling_core 0.14.2", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "dashmap" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" - -[[package]] -name = "data-url" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30bfce702bcfa94e906ef82421f2c0e61c076ad76030c16ee5d2e9a32fe193" -dependencies = [ - "matches", -] - -[[package]] -name = "debug_unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -dependencies = [ - "unreachable", -] - -[[package]] -name = "deno_ast" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2989afff97ba7da10f186e9a45e946b4ef943b9d4babd2ee7b4b24cc9906b69" -dependencies = [ - "anyhow", - "base64 0.13.1", - "data-url", - "dprint-swc-ext", - "serde", - "swc_ecmascript", - "text_lines", - "url", -] - -[[package]] -name = "deno_core" -version = "0.136.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ced67ffe84c64aee6e84e40558835752b6f12807f84d15da8f5954e2b670c5" -dependencies = [ - "anyhow", - "deno_ops", - "futures", - "indexmap", - "libc", - "log", - "once_cell", - "parking_lot", - "pin-project", - "serde", - "serde_json", - "serde_v8", - "sourcemap", - "url", - "v8", -] - -[[package]] -name = "deno_ops" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05520711837dd592d2861319ea3cf2dfd81e39bb92e41758ee9172f3623daebd" -dependencies = [ - "proc-macro-crate", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "der" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2 1.0.47", - "quote 1.0.21", - "rustc_version 0.4.0", - "syn 1.0.103", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" -dependencies = [ - "block-buffer 0.10.3", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "divrem" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69dde51e8fef5e12c1d65e0929b03d66e4c0c18282bc30ed2ca050ad6f44dd82" - -[[package]] -name = "dotenvy" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" - -[[package]] -name = "dprint-swc-ext" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df529037ff02f1c43ae8c6cce54d9ad85546ff89cb5c1988f56130c16e16a48" -dependencies = [ - "bumpalo", - "num-bigint", - "rustc-hash", - "swc_atoms", - "swc_common", - "swc_ecmascript", - "text_lines", -] - -[[package]] -name = "ed25519" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" -dependencies = [ - "pkcs8", - "serde", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand 0.7.3", - "serde", - "serde_bytes", - "sha2 0.9.9", - "zeroize", -] - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" -dependencies = [ - "serde", -] - -[[package]] -name = "embassy-os" -version = "0.3.2-rev.1" -dependencies = [ - "aes", - "async-stream", - "async-trait", - "avahi-sys", - "base32", - "base64 0.13.1", - "base64ct", - "basic-cookies", - "bollard", - "chrono", - "ciborium", - "clap 3.2.23", - "color-eyre", - "cookie_store", - "current_platform", - "digest 0.10.5", - "digest 0.9.0", - "divrem", - "ed25519", - "ed25519-dalek", - "embassy_container_init", - "emver", - "fd-lock-rs", - "futures", - "git-version", - "helpers", - "hex", - "hmac 0.12.1", - "http", - "hyper", - "hyper-ws-listener", - "imbl 2.0.0", - "indexmap", - "isocountry", - "itertools 0.10.5", - "josekit", - "js_engine", - "jsonpath_lib", - "lazy_static", - "libc", - "log", - "models", - "nix 0.25.0", - "nom 7.1.1", - "num", - "num_enum", - "openssh-keys", - "openssl", - "patch-db", - "pbkdf2", - "pin-project", - "pkcs8", - "prettytable-rs", - "proptest", - "proptest-derive", - "rand 0.7.3", - "rand 0.8.5", - "regex", - "reqwest", - "reqwest_cookie_store", - "rpassword", - "rpc-toolkit", - "rust-argon2", - "scopeguard", - "serde", - "serde_json", - "serde_with 2.0.1", - "serde_yaml", - "sha2 0.10.6", - "sha2 0.9.9", - "simple-logging", - "sqlx", - "stderrlog", - "tar", - "thiserror", - "tokio", - "tokio-stream", - "tokio-tar", - "tokio-tungstenite", - "tokio-util", - "toml", - "torut", - "tracing", - "tracing-error 0.2.0", - "tracing-futures", - "tracing-subscriber 0.3.16", - "trust-dns-server", - "typed-builder", - "url", - "uuid", -] - -[[package]] -name = "embassy_container_init" -version = "0.1.0" -dependencies = [ - "async-stream", - "color-eyre", - "futures", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tracing", - "tracing-error 0.2.0", - "tracing-futures", - "tracing-subscriber 0.3.16", -] - -[[package]] -name = "emver" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed260c4d7efaec031b9c4f6c4d3cf136e3df2bbfe50925800236f5e847f28704" -dependencies = [ - "either", - "fp-core", - "nom 6.1.2", - "serde", -] - -[[package]] -name = "ena" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" -dependencies = [ - "log", -] - -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - -[[package]] -name = "encoding_rs" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "enum-as-inner" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" -dependencies = [ - "heck 0.4.0", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "enum_kind" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b940da354ae81ef0926c5eaa428207b8f4f091d3956c891dfbd124162bed99" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" -dependencies = [ - "atty", - "humantime 2.1.0", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "eyre" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - -[[package]] -name = "fd-lock-rs" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0f547e1d79e058664f2ea7d3a6d82b2ddd5fea4a6650b97b70c38979f34db3" -dependencies = [ - "nix 0.24.2", -] - -[[package]] -name = "filetime" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.2.16", - "windows-sys 0.42.0", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fp-core" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338a5feb6c7248603dfa3da758da4e99abb65e792a157fe1d657e7c2f5fbcd0b" -dependencies = [ - "itertools 0.8.2", -] - -[[package]] -name = "from_variant" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0981e470d2ab9f643df3921d54f1952ea100c39fdb6a3fdc820e20d2291df6c" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "fslock" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57eafdd0c16f57161105ae1b98a1238f97645f2f588438b2949c99a2af9616bf" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - -[[package]] -name = "futures" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" - -[[package]] -name = "futures-executor" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-intrusive" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6bdbb8c5a42b2bb5ee8dd9dc2c7d73ce3e15d26dfe100fb347ffa3f58c672b" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot", -] - -[[package]] -name = "futures-io" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" - -[[package]] -name = "futures-macro" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "futures-sink" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" - -[[package]] -name = "futures-task" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" - -[[package]] -name = "futures-util" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" - -[[package]] -name = "git-version" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" -dependencies = [ - "git-version-macro", - "proc-macro-hack", -] - -[[package]] -name = "git-version-macro" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "h2" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashlink" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "helpers" -version = "0.1.0" -dependencies = [ - "color-eyre", - "futures", - "models", - "pin-project", - "tokio", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.5", -] - -[[package]] -name = "http" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.4", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error 1.2.3", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.4", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "hyper-ws-listener" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3fb761e568fdb34ff794d284bfe1769efc5d16b9d716286451ab3a70ab82bea" -dependencies = [ - "anyhow", - "base64 0.13.1", - "env_logger 0.9.1", - "futures", - "hyper", - "log", - "sha-1", - "tokio", - "tokio-tungstenite", -] - -[[package]] -name = "hyperlocal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" -dependencies = [ - "futures-util", - "hex", - "hyper", - "pin-project", - "tokio", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" -dependencies = [ - "cxx", - "cxx-build", -] - -[[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.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - -[[package]] -name = "imbl" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "543682c9082b25e63d03b5acbd65ad111fd49dd93e70843e5175db4ff81d606b" -dependencies = [ - "bitmaps 2.1.0", - "rand_core 0.6.4", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "imbl" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2806b69cd9f4664844027b64465eacb444c67c1db9c778e341adff0c25cdb0d" -dependencies = [ - "bitmaps 3.2.0", - "imbl-sized-chunks", - "rand_core 0.6.4", - "rand_xoshiro", - "version_check", -] - -[[package]] -name = "imbl-sized-chunks" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" -dependencies = [ - "bitmaps 3.2.0", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" -dependencies = [ - "autocfg", - "hashbrown", - "serde", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "ipnet" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" - -[[package]] -name = "is-macro" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c068d4c6b922cd6284c609cfa6dec0e41615c9c5a1a4ba729a970d8daba05fb" -dependencies = [ - "Inflector", - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "isocountry" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea1dc4bf0fb4904ba83ffdb98af3d9c325274e92e6e295e4151e86c96363e04" -dependencies = [ - "serde", - "thiserror", -] - -[[package]] -name = "itertools" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" - -[[package]] -name = "josekit" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee6af62ad98bdf699ad2ecc8323479a1fdc7aa5faa6043d93119d83f6c5fca8" -dependencies = [ - "anyhow", - "base64 0.13.1", - "flate2", - "once_cell", - "openssl", - "regex", - "serde", - "serde_json", - "thiserror", - "time 0.3.16", -] - -[[package]] -name = "js-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "js_engine" -version = "0.1.0" -dependencies = [ - "async-trait", - "dashmap", - "deno_ast", - "deno_core", - "dprint-swc-ext", - "embassy_container_init", - "helpers", - "models", - "reqwest", - "serde", - "serde_json", - "sha2 0.10.6", - "swc_atoms", - "swc_common", - "swc_config", - "swc_config_macro", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_codegen_macros", - "swc_ecma_parser", - "swc_ecma_transforms", - "swc_ecma_transforms_base", - "swc_ecma_transforms_classes", - "swc_ecma_transforms_macros", - "swc_ecma_transforms_proposal", - "swc_ecma_transforms_react", - "swc_ecma_transforms_typescript", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_ecmascript", - "swc_eq_ignore_macros", - "swc_macros_common", - "swc_visit", - "swc_visit_macros", - "tokio", - "tracing", -] - -[[package]] -name = "json-patch" -version = "0.2.7-alpha.0" -dependencies = [ - "json-ptr", - "rand 0.7.3", - "serde", - "serde_json", - "treediff", -] - -[[package]] -name = "json-ptr" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "jsonpath_lib" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" -dependencies = [ - "log", - "serde", - "serde_json", -] - -[[package]] -name = "keccak" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838" - -[[package]] -name = "lalrpop" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823" -dependencies = [ - "ascii-canvas", - "atty", - "bit-set", - "diff", - "ena", - "itertools 0.10.5", - "lalrpop-util", - "petgraph", - "pico-args", - "regex", - "regex-syntax", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid 0.2.4", -] - -[[package]] -name = "lalrpop-util" -version = "0.19.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4" -dependencies = [ - "regex", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lexical" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" -dependencies = [ - "lexical-core 0.8.5", -] - -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec 0.5.2", - "bitflags", - "cfg-if 1.0.0", - "ryu", - "static_assertions", -] - -[[package]] -name = "lexical-core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "libc" -version = "0.2.137" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" - -[[package]] -name = "libloading" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - -[[package]] -name = "link-cplusplus" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" -dependencies = [ - "cc", -] - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "md-5" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" -dependencies = [ - "digest 0.10.5", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", -] - -[[package]] -name = "models" -version = "0.1.0" -dependencies = [ - "embassy_container_init", - "emver", - "patch-db", - "rand 0.8.5", - "serde", - "thiserror", - "tokio", -] - -[[package]] -name = "native-tls" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" -dependencies = [ - "autocfg", - "bitflags", - "cfg-if 1.0.0", - "libc", - "memoffset", - "pin-utils", -] - -[[package]] -name = "nom" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "6.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" -dependencies = [ - "bitvec", - "funty", - "lexical-core 0.7.6", - "memchr", - "version_check", -] - -[[package]] -name = "nom" -version = "7.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "serde", -] - -[[package]] -name = "num-complex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" -dependencies = [ - "proc-macro-crate", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssh-keys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7249a699cdeea261ac73f1bf9350777cb867324f44373aafb5a287365bf1771" -dependencies = [ - "base64 0.13.1", - "byteorder", - "md-5 0.9.1", - "sha2 0.9.9", - "thiserror", -] - -[[package]] -name = "openssl" -version = "0.10.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" -dependencies = [ - "bitflags", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "111.22.0+1.1.1q" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a" -dependencies = [ - "autocfg", - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "os_str_bytes" -version = "6.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "owo-colors" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "windows-sys 0.42.0", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" - -[[package]] -name = "patch-db" -version = "0.1.0" -dependencies = [ - "async-trait", - "fd-lock-rs", - "futures", - "imbl 1.0.1", - "json-patch", - "json-ptr", - "lazy_static", - "nix 0.23.1", - "patch-db-macro", - "proptest", - "rand 0.8.5", - "serde", - "serde_cbor 0.11.1", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-error 0.1.2", -] - -[[package]] -name = "patch-db-macro" -version = "0.1.0" -dependencies = [ - "patch-db-macro-internals", - "proc-macro2 1.0.47", - "syn 1.0.103", -] - -[[package]] -name = "patch-db-macro-internals" -version = "0.1.0" -dependencies = [ - "heck 0.3.3", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "patch-db-util" -version = "0.1.0" -dependencies = [ - "clap 3.2.23", - "patch-db", - "serde_json", - "tokio", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.5", - "hmac 0.12.1", - "password-hash", - "sha2 0.10.6", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pem-rfc7468" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "petgraph" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros", - "phf_shared", - "proc-macro-hack", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pico-args" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" - -[[package]] -name = "pin-project" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" - -[[package]] -name = "pmutil" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "prettytable-rs" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f375cb74c23b51d23937ffdeb48b1fbf5b6409d4b9979c1418c1de58bc8f801" -dependencies = [ - "atty", - "csv", - "encode_unicode", - "lazy_static", - "term", - "unicode-width", -] - -[[package]] -name = "proc-macro-crate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" -dependencies = [ - "once_cell", - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] - -[[package]] -name = "proc-macro2" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" -dependencies = [ - "bit-set", - "bitflags", - "byteorder", - "lazy_static", - "num-traits", - "quick-error 2.0.1", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", -] - -[[package]] -name = "proptest-derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90b46295382dc76166cb7cf2bb4a97952464e4b7ed5a43e6cd34e1fec3349ddc" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", -] - -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - -[[package]] -name = "publicsuffix" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" -dependencies = [ - "idna 0.3.0", - "psl-types", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - -[[package]] -name = "quote" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" -dependencies = [ - "proc-macro2 1.0.47", -] - -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "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]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "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]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.8", -] - -[[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 = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.8", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "reqwest" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" -dependencies = [ - "base64 0.13.1", - "bytes", - "cookie", - "cookie_store", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "proc-macro-hack", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tokio-socks", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "reqwest_cookie_store" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0568e27f107b933735a07b3f8cb985ecfe3d3ce2f2225f82f10b3750f5981263" -dependencies = [ - "bytes", - "cookie", - "cookie_store", - "reqwest", - "url", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "rpassword" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c9f5d2a0c3e2ea729ab3706d22217177770654c3ef5056b68b69d07332d3f5" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "rpc-toolkit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5353673ffd8265292281141560d2b851e4da49e83e2f5e255fd473736d45ee10" -dependencies = [ - "clap 3.2.23", - "futures", - "hyper", - "lazy_static", - "openssl", - "reqwest", - "rpc-toolkit-macro", - "serde", - "serde_cbor 0.11.2", - "serde_json", - "thiserror", - "tokio", - "url", - "yajrc", -] - -[[package]] -name = "rpc-toolkit-macro" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8e4b9cb00baf2d61bcd35e98d67dcb760382a3b4540df7e63b38d053c8a7b8b" -dependencies = [ - "proc-macro2 1.0.47", - "rpc-toolkit-macro-internals", - "syn 1.0.103", -] - -[[package]] -name = "rpc-toolkit-macro-internals" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e2ce21b936feaecdab9c9a8e75b9dca64374ccc11951a58045ad6559b75f42" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "rust-argon2" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" -dependencies = [ - "base64 0.13.1", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[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.14", -] - -[[package]] -name = "rustls" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" -dependencies = [ - "base64 0.13.1", -] - -[[package]] -name = "rustversion" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error 1.2.3", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "schannel" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" -dependencies = [ - "lazy_static", - "windows-sys 0.36.1", -] - -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scratch" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "security-framework" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[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.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_cbor" -version = "0.11.1" -dependencies = [ - "half", - "serde", - "serde_derive", -] - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "serde_json" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" -dependencies = [ - "indexmap", - "itoa 1.0.4", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa 1.0.4", - "ryu", - "serde", -] - -[[package]] -name = "serde_v8" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ca1daa2506c9d62744fff84d3534192f2e1c70cdf3bed95f298d89156c00b06" -dependencies = [ - "bytes", - "derive_more", - "serde", - "v8", -] - -[[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 1.5.2", -] - -[[package]] -name = "serde_with" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f2d60d049ea019a84dcd6687b0d1e0030fe663ae105039bdf967ed5e6a9a7" -dependencies = [ - "base64 0.13.1", - "chrono", - "hex", - "indexmap", - "serde", - "serde_json", - "serde_with_macros 2.0.1", - "time 0.3.16", -] - -[[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 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "serde_with_macros" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ccadfacf6cf10faad22bbadf55986bdd0856edfb5d9210aa1dcf1f516e84e93" -dependencies = [ - "darling 0.14.2", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "serde_yaml" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d232d893b10de3eb7258ff01974d6ee20663d8e833263c99409d4b13a0209da" -dependencies = [ - "indexmap", - "itoa 1.0.4", - "ryu", - "serde", - "unsafe-libyaml", -] - -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.5", -] - -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.5", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.5", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] - -[[package]] -name = "sharded-slab" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - -[[package]] -name = "simple-logging" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00d48e85675326bb182a2286ea7c1a0b264333ae10f27a937a72be08628b542" -dependencies = [ - "lazy_static", - "log", - "thread-id", -] - -[[package]] -name = "siphasher" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps 2.1.0", - "typenum", -] - -[[package]] -name = "slab" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "snapshot-creator" -version = "0.1.0" -dependencies = [ - "dashmap", - "deno_ast", - "deno_core", -] - -[[package]] -name = "socket2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "sourcemap" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e031f2463ecbdd5f34c950f89f5c1e1032f22c0f8e3dc4bdb2e8b6658cf61eb" -dependencies = [ - "base64 0.11.0", - "if_chain", - "lazy_static", - "regex", - "rustc_version 0.2.3", - "serde", - "serde_json", - "url", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "sqlformat" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" -dependencies = [ - "itertools 0.10.5", - "nom 7.1.1", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" -dependencies = [ - "sqlx-core", - "sqlx-macros", -] - -[[package]] -name = "sqlx-core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" -dependencies = [ - "ahash", - "atoi", - "base64 0.13.1", - "bitflags", - "byteorder", - "bytes", - "chrono", - "crc", - "crossbeam-queue", - "dirs", - "dotenvy", - "either", - "event-listener", - "futures-channel", - "futures-core", - "futures-intrusive", - "futures-util", - "hashlink", - "hex", - "hkdf", - "hmac 0.12.1", - "indexmap", - "itoa 1.0.4", - "libc", - "log", - "md-5 0.10.5", - "memchr", - "once_cell", - "paste", - "percent-encoding", - "rand 0.8.5", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "sha1", - "sha2 0.10.6", - "smallvec", - "sqlformat", - "sqlx-rt", - "stringprep", - "thiserror", - "tokio-stream", - "url", - "webpki-roots", - "whoami", -] - -[[package]] -name = "sqlx-macros" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" -dependencies = [ - "dotenvy", - "either", - "heck 0.4.0", - "hex", - "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "serde", - "serde_json", - "sha2 0.10.6", - "sqlx-core", - "sqlx-rt", - "syn 1.0.103", - "url", -] - -[[package]] -name = "sqlx-rt" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "stderrlog" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af95cb8a5f79db5b2af2a46f44da7594b5adbcbb65cbf87b8da0959bfdd82460" -dependencies = [ - "atty", - "chrono", - "log", - "termcolor", - "thread_local", -] - -[[package]] -name = "string_cache" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2 1.0.47", - "quote 1.0.21", -] - -[[package]] -name = "string_enum" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "994453cd270ad0265796eb24abf5540091ed03e681c5f3c12bc33e4db33253e1" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "stringprep" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "swc_atoms" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba8735ce37e421749498e038955abc1135eec6a4af0b54a173e55d2e5542d472" -dependencies = [ - "string_cache", - "string_cache_codegen", -] - -[[package]] -name = "swc_common" -version = "0.18.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4516bf4969a924bfd1801aed5c4b214687665898c14b7584d227827faff9d6c" -dependencies = [ - "ahash", - "ast_node", - "better_scoped_tls", - "cfg-if 1.0.0", - "debug_unreachable", - "either", - "from_variant", - "num-bigint", - "once_cell", - "rustc-hash", - "serde", - "siphasher", - "sourcemap", - "string_cache", - "swc_eq_ignore_macros", - "swc_visit", - "tracing", - "unicode-width", - "url", -] - -[[package]] -name = "swc_config" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb05ef56c14b95dd7e62e95960153af811b9a447287f1f6ca59f1337fb83d4" -dependencies = [ - "anyhow", - "indexmap", - "serde", - "serde_json", - "swc_config_macro", -] - -[[package]] -name = "swc_config_macro" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb64bc03d90fd5c90d6ab917bb2b1d7fbd31957df39e31ea24a3f554b4372251" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "swc_ecma_ast" -version = "0.78.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21f40169fe465e9a93cda5fe397c3afcb69be5ba2f76c4ab22137af6effaebcc" -dependencies = [ - "is-macro", - "num-bigint", - "scoped-tls", - "serde", - "string_enum", - "swc_atoms", - "swc_common", - "unicode-id", -] - -[[package]] -name = "swc_ecma_codegen" -version = "0.108.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eec1d30c8f85e8267a8efc66d680aa777902d567c3a05b7dfd42965a4872243" -dependencies = [ - "bitflags", - "memchr", - "num-bigint", - "once_cell", - "rustc-hash", - "sourcemap", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen_macros", - "tracing", -] - -[[package]] -name = "swc_ecma_codegen_macros" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59949619b2ef45eedb6c399d05f2c3c7bc678b5074b3103bb670f9e05bb99042" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.104.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fea08aeb2eb1469928ac7ca2d208fe7816871787e4d93e34924495e724bb25" -dependencies = [ - "either", - "enum_kind", - "lexical", - "num-bigint", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_transforms" -version = "0.154.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bce21d9e8ff785aaf9b4ac11375d9f5767630fcaf882f72e6af0516224085a6" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_proposal", - "swc_ecma_transforms_react", - "swc_ecma_transforms_typescript", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "0.85.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528c99be91500ed393e04e5cfc37763b4b68b71bc4f9b54ff0cd21d714920130" -dependencies = [ - "better_scoped_tls", - "once_cell", - "phf", - "rustc-hash", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_classes" -version = "0.73.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74a27c29def9db5ff03db4d3ab3d37701fb6d100951162223b71132908451eb" -dependencies = [ - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18712e4aab969c6508dff3540ade6358f1e013464aa58b3d30da2ab2d9fcbbed" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "swc_ecma_transforms_proposal" -version = "0.107.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47fc0f3b336764f89adf1899830321c3f5a7e845ede3ad5949eeb7468aa260ab" -dependencies = [ - "either", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_classes", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_react" -version = "0.114.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbfcd197ebeb0547b59dee39a164633bcf4fb0edbae886f8046e471e6a10502" -dependencies = [ - "ahash", - "base64 0.13.1", - "dashmap", - "indexmap", - "once_cell", - "regex", - "serde", - "sha-1", - "string_enum", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_typescript" -version = "0.117.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bf410ffcf91d85dc1f8f1bb969fa2637f9430a6917f2174ad76458c776cb89" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_react", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_utils" -version = "0.85.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031ac49cf598f00f048fecd87b3bda5e14b86f6ccd561ada7fce461e0a3ea8d1" -dependencies = [ - "indexmap", - "once_cell", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_visit" -version = "0.64.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d3783a0dd1e301ae2945ab1241405f913427f9512ec62756d3d2072f7c21bb" -dependencies = [ - "num-bigint", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_ecmascript" -version = "0.157.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd35679e1dc392f776b691b125692d90a7bebd5d23ec96699cfe37d8ae8633b1" -dependencies = [ - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_parser", - "swc_ecma_transforms", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_eq_ignore_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c8f200a2eaed938e7c1a685faaa66e6d42fa9e17da5f62572d3cbc335898f5e" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "swc_macros_common" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5dca3f08d02da4684c3373150f7c045128f81ea00f0c434b1b012bc65a6cce3" -dependencies = [ - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "swc_visit" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c639379dd2a8a0221fa1e12fafbdd594ba53a0cace6560054da52409dfcc1a" -dependencies = [ - "either", - "swc_visit_macros", -] - -[[package]] -name = "swc_visit_macros" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b9b72892df873972549838bf84d6c56234c7502148a7e23b5a3da6e0fedfb8" -dependencies = [ - "Inflector", - "pmutil", - "proc-macro2 1.0.47", - "quote 1.0.21", - "swc_macros_common", - "syn 1.0.103", -] - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - -[[package]] -name = "syn" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", - "unicode-xid 0.2.4", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tar" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "libc", - "redox_syscall 0.2.16", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "text_lines" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49e3c53dd04de8b8e8390bc4fab57f6db7af7d33b086fe411803e6351c9f9f9" -dependencies = [ - "serde", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "thiserror" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "thread-id" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" -dependencies = [ - "libc", - "redox_syscall 0.1.57", - "winapi", -] - -[[package]] -name = "thread_local" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" -dependencies = [ - "once_cell", -] - -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" -dependencies = [ - "itoa 1.0.4", - "libc", - "num_threads", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" - -[[package]] -name = "time-macros" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" -dependencies = [ - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" -dependencies = [ - "autocfg", - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "winapi", -] - -[[package]] -name = "tokio-macros" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-socks" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" -dependencies = [ - "either", - "futures-util", - "thiserror", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-tar" -version = "0.3.0" -source = "git+https://github.com/dr-bonez/tokio-tar.git#071db00962a66f8552d418d60be7bdf1c8ed8216" -dependencies = [ - "filetime", - "futures-core", - "libc", - "redox_syscall 0.2.16", - "tokio", - "tokio-stream", - "xattr", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite", -] - -[[package]] -name = "tokio-util" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" -dependencies = [ - "serde", -] - -[[package]] -name = "torut" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99febc413f26cf855b3a309c5872edff5c31e0ffe9c2fce5681868761df36f69" -dependencies = [ - "base32", - "base64 0.13.1", - "derive_more", - "ed25519-dalek", - "hex", - "hmac 0.11.0", - "rand 0.7.3", - "serde", - "serde_derive", - "sha2 0.9.9", - "sha3", - "tokio", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if 1.0.0", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-error" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" -dependencies = [ - "tracing", - "tracing-subscriber 0.2.25", -] - -[[package]] -name = "tracing-error" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" -dependencies = [ - "tracing", - "tracing-subscriber 0.3.16", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - -[[package]] -name = "tracing-log" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" -dependencies = [ - "lazy_static", - "log", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" -dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "treediff" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" -dependencies = [ - "serde_json", -] - -[[package]] -name = "trust-dns-client" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c408c32e6a9dbb38037cece35740f2cf23c875d8ca134d33631cec83f74d3fe" -dependencies = [ - "cfg-if 1.0.0", - "data-encoding", - "futures-channel", - "futures-util", - "lazy_static", - "radix_trie", - "rand 0.8.5", - "thiserror", - "time 0.3.16", - "tokio", - "tracing", - "trust-dns-proto", -] - -[[package]] -name = "trust-dns-proto" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" -dependencies = [ - "async-trait", - "cfg-if 1.0.0", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.2.3", - "ipnet", - "lazy_static", - "rand 0.8.5", - "smallvec", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "trust-dns-server" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cf9f8a359c9f16fdf760b79cb2be3f261b98db8027f81959c7a4f6645e2c" -dependencies = [ - "async-trait", - "bytes", - "cfg-if 1.0.0", - "enum-as-inner", - "futures-executor", - "futures-util", - "serde", - "thiserror", - "time 0.3.16", - "tokio", - "toml", - "tracing", - "trust-dns-client", - "trust-dns-proto", -] - -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "native-tls", - "rand 0.8.5", - "sha-1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "typed-arena" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" - -[[package]] -name = "typed-builder" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "unicode-bidi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" - -[[package]] -name = "unicode-id" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" - -[[package]] -name = "unicode-ident" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -dependencies = [ - "void", -] - -[[package]] -name = "unsafe-libyaml" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e5fa573d8ac5f1a856f8d7be41d390ee973daf97c806b2c1a465e4e1406e68" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna 0.3.0", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "uuid" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83" -dependencies = [ - "getrandom 0.2.8", -] - -[[package]] -name = "v8" -version = "0.43.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c87ec36fec9ea2cd5a368ae9d0a662a7c5e8caa8768ec1fcc02bea623681b98" -dependencies = [ - "bitflags", - "fslock", - "lazy_static", - "libc", - "which 4.3.0", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -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 = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "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.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" -dependencies = [ - "quote 1.0.21", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" - -[[package]] -name = "web-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" -dependencies = [ - "webpki", -] - -[[package]] -name = "which" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" -dependencies = [ - "libc", -] - -[[package]] -name = "which" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" -dependencies = [ - "either", - "libc", - "once_cell", -] - -[[package]] -name = "whoami" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6631b6a2fd59b1841b622e8f1a7ad241ef0a46f2d580464ce8140ac94cbd571" -dependencies = [ - "bumpalo", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - -[[package]] -name = "xattr" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" -dependencies = [ - "libc", -] - -[[package]] -name = "yajrc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40687b4c165cb760e35730055c8840f36897e7c98099b2d3d66ba8cb624c79a" -dependencies = [ - "anyhow", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "zeroize" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" -dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", - "synstructure", -] diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..110071e0d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Start9 Labs, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index bacd53575..000000000 --- a/LICENSE.md +++ /dev/null @@ -1,42 +0,0 @@ -# START9 NON-COMMERCIAL LICENSE v1 -Version 1, 22 September 2022 - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -### 1.Definitions - -"License" means version 1 of the Start9 Non-Commercial License. - -"Licensor" means the Start9 Labs, Inc, or its successor(s) in interest, or a future assignee of the copyright. - -"You" (or "Your") means an individual or organization exercising permissions granted by this License. - -"Source Code" for a work means the preferred form of the work for making modifications to it. - -"Object Code" means any non-source form of a work, including the machine-language output by a compiler or assembler. - -"Work" means any work of authorship, whether in Source or Object form, made available under this License. - -"Derivative Work" means any work, whether in Source or Object form, that is based on (or derived from) the Work. - -"Distribute" means to convey or to publish and generally has the same meaning here as under U.S. Copyright law. - -"Sell" means practicing any or all of the rights granted to you under the License to provide to third parties, for a fee or other consideration (including, without limitation, fees for hosting, consulting, or support services), a product or service whose value derives, entirely or substantially, from the functionality of the Work or Derivative Work. - -### 2. Grant of Rights - -Subject to the terms of this license, the Licensor grants you, the licensee, a non-exclusive, worldwide, royalty-free copyright license to access, audit, copy, modify, compile, run, test, distribute, or otherwise use the Software. - -### 3. Limitations - -1. The grant of rights under the License does NOT include, and the License does NOT grant You the right to Sell the Work or Derivative Work. -2. If you Distribute the Work or Derivative Work, you expressly undertake not to remove or modify, in any manner, the copyright notices attached to the Work or displayed in any output of the Work when run, and to reproduce these notices, in an identical manner, in any distributed copies of the Work or Derivative Work together with a copy of this License. -3. If you Distribute a Derivative Work, it must carry prominent notices stating that it has been modified from the Work, providing a relevant date. - -### 4. Contributions - -You hereby grant to Licensor a perpetual, irrevocable, worldwide, non-exclusive, royalty-free license to use and exploit any Derivative Work of which you are the author. - -### 5. Disclaimer - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. LICENSOR HAS NO OBLIGATION TO SUPPORT RECIPIENTS OF THE SOFTWARE. diff --git a/Makefile b/Makefile index 1a4fab0fd..ec2183178 100644 --- a/Makefile +++ b/Makefile @@ -1,23 +1,31 @@ -OS_ARCH := $(shell echo "${OS_ARCH}") -ARCH := $(shell if [ "$(OS_ARCH)" = "raspberrypi" ]; then echo aarch64; else echo $(OS_ARCH) | sed 's/-nonfree$$//g'; fi) -ENVIRONMENT_FILE = $(shell ./check-environment.sh) -GIT_HASH_FILE = $(shell ./check-git-hash.sh) -VERSION_FILE = $(shell ./check-version.sh) +PLATFORM_FILE := $(shell ./check-platform.sh) +ENVIRONMENT_FILE := $(shell ./check-environment.sh) +GIT_HASH_FILE := $(shell ./check-git-hash.sh) +VERSION_FILE := $(shell ./check-version.sh) +BASENAME := $(shell ./basename.sh) +PLATFORM := $(shell if [ -f ./PLATFORM.txt ]; then cat ./PLATFORM.txt; else echo unknown; fi) +ARCH := $(shell if [ "$(PLATFORM)" = "raspberrypi" ]; then echo aarch64; else echo $(PLATFORM) | sed 's/-nonfree$$//g'; fi) +IMAGE_TYPE=$(shell if [ "$(PLATFORM)" = raspberrypi ]; then echo img; else echo iso; fi) EMBASSY_BINS := backend/target/$(ARCH)-unknown-linux-gnu/release/startbox libs/target/aarch64-unknown-linux-musl/release/embassy_container_init libs/target/x86_64-unknown-linux-musl/release/embassy_container_init EMBASSY_UIS := frontend/dist/raw/ui frontend/dist/raw/setup-wizard frontend/dist/raw/diagnostic-ui frontend/dist/raw/install-wizard -BUILD_SRC := $(shell find build) +BUILD_SRC := $(shell git ls-files build) build/lib/depends build/lib/conflicts +DEBIAN_SRC := $(shell git ls-files debian/) +IMAGE_RECIPE_SRC := $(shell git ls-files image-recipe/) EMBASSY_SRC := backend/startd.service $(BUILD_SRC) -COMPAT_SRC := $(shell find system-images/compat/ -not -path 'system-images/compat/target/*' -and -not -name *.tar -and -not -name target) -UTILS_SRC := $(shell find system-images/utils/ -not -name *.tar) -BINFMT_SRC := $(shell find system-images/binfmt/ -not -name *.tar) -BACKEND_SRC := $(shell find backend/src) $(shell find backend/migrations) $(shell find patch-db/*/src) $(shell find libs/*/src) libs/*/Cargo.toml backend/Cargo.toml backend/Cargo.lock frontend/dist/static -FRONTEND_SHARED_SRC := $(shell find frontend/projects/shared) $(shell ls -p frontend/ | grep -v / | sed 's/^/frontend\//g') frontend/package.json frontend/node_modules frontend/config.json patch-db/client/dist frontend/patchdb-ui-seed.json -FRONTEND_UI_SRC := $(shell find frontend/projects/ui) -FRONTEND_SETUP_WIZARD_SRC := $(shell find frontend/projects/setup-wizard) -FRONTEND_INSTALL_WIZARD_SRC := $(shell find frontend/projects/install-wizard) -PATCH_DB_CLIENT_SRC := $(shell find patch-db/client -not -path patch-db/client/dist -and -not -path patch-db/client/node_modules) +COMPAT_SRC := $(shell git ls-files system-images/compat/) +UTILS_SRC := $(shell git ls-files system-images/utils/) +BINFMT_SRC := $(shell git ls-files system-images/binfmt/) +BACKEND_SRC := $(shell git ls-files backend) $(shell git ls-files --recurse-submodules patch-db) $(shell git ls-files libs) frontend/dist/static +FRONTEND_SHARED_SRC := $(shell git ls-files frontend/projects/shared) $(shell ls -p frontend/ | grep -v / | sed 's/^/frontend\//g') frontend/node_modules frontend/config.json patch-db/client/dist frontend/patchdb-ui-seed.json +FRONTEND_UI_SRC := $(shell git ls-files frontend/projects/ui) +FRONTEND_SETUP_WIZARD_SRC := $(shell git ls-files frontend/projects/setup-wizard) +FRONTEND_DIAGNOSTIC_UI_SRC := $(shell git ls-files frontend/projects/diagnostic-ui) +FRONTEND_INSTALL_WIZARD_SRC := $(shell git ls-files frontend/projects/install-wizard) +PATCH_DB_CLIENT_SRC := $(shell git ls-files --recurse-submodules patch-db/client) GZIP_BIN := $(shell which pigz || which gzip) -ALL_TARGETS := $(EMBASSY_BINS) system-images/compat/docker-images/$(ARCH).tar system-images/utils/docker-images/$(ARCH).tar system-images/binfmt/docker-images/$(ARCH).tar $(EMBASSY_SRC) $(shell if [ "$(OS_ARCH)" = "raspberrypi" ]; then echo cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep; fi) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE) +TAR_BIN := $(shell which gtar || which tar) +COMPILED_TARGETS := $(EMBASSY_BINS) system-images/compat/docker-images/$(ARCH).tar system-images/utils/docker-images/$(ARCH).tar system-images/binfmt/docker-images/$(ARCH).tar +ALL_TARGETS := $(EMBASSY_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE) $(COMPILED_TARGETS) $(shell if [ "$(PLATFORM)" = "raspberrypi" ]; then echo cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep; fi) $(shell /bin/bash -c 'if [[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]; then echo cargo-deps/$(ARCH)-unknown-linux-gnu/release/tokio-console; fi') $(PLATFORM_FILE) ifeq ($(REMOTE),) mkdir = mkdir -p $1 @@ -25,20 +33,27 @@ ifeq ($(REMOTE),) cp = cp -r $1 $2 ln = ln -sf $1 $2 else - mkdir = ssh $(REMOTE) 'mkdir -p $1' - rm = ssh $(REMOTE) 'sudo rm -rf $1' - ln = ssh $(REMOTE) 'sudo ln -sf $1 $2' + ifeq ($(SSHPASS),) + ssh = ssh $(REMOTE) $1 + else + ssh = sshpass -p $(SSHPASS) ssh $(REMOTE) $1 + endif + mkdir = $(call ssh,'sudo mkdir -p $1') + rm = $(call ssh,'sudo rm -rf $1') + ln = $(call ssh,'sudo ln -sf $1 $2') define cp - tar --transform "s|^$1|x|" -czv -f- $1 | ssh $(REMOTE) "sudo tar --transform 's|^x|$2|' -xzv -f- -C /" + $(TAR_BIN) --transform "s|^$1|x|" -czv -f- $1 | $(call ssh,"sudo tar --transform 's|^x|$2|' -xzv -f- -C /") endef endif .DELETE_ON_ERROR: -.PHONY: all gzip install clean format sdk snapshots frontends ui backend reflash startos_raspberrypi.img sudo +.PHONY: all metadata install clean format sdk snapshots frontends ui backend reflash deb $(IMAGE_TYPE) squashfs sudo wormhole all: $(ALL_TARGETS) +metadata: $(VERSION_FILE) $(PLATFORM_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) + sudo: sudo true @@ -55,9 +70,13 @@ clean: rm -rf patch-db/client/dist rm -rf patch-db/target rm -rf cargo-deps - rm ENVIRONMENT.txt - rm GIT_HASH.txt - rm VERSION.txt + rm -rf dpkg-workdir + rm -rf image-recipe/deb + rm -rf results + rm -f ENVIRONMENT.txt + rm -f PLATFORM.txt + rm -f GIT_HASH.txt + rm -f VERSION.txt format: cd backend && cargo +nightly fmt @@ -66,8 +85,20 @@ format: sdk: cd backend/ && ./install-sdk.sh -startos_raspberrypi.img: $(BUILD_SRC) startos.raspberrypi.squashfs $(VERSION_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep | sudo - ./build/raspberrypi/make-image.sh +deb: results/$(BASENAME).deb + +debian/control: build/lib/depends build/lib/conflicts + ./debuild/control.sh + +results/$(BASENAME).deb: dpkg-build.sh $(DEBIAN_SRC) $(VERSION_FILE) $(PLATFORM_FILE) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) + PLATFORM=$(PLATFORM) ./dpkg-build.sh + +$(IMAGE_TYPE): results/$(BASENAME).$(IMAGE_TYPE) + +squashfs: results/$(BASENAME).squashfs + +results/$(BASENAME).$(IMAGE_TYPE) results/$(BASENAME).squashfs: $(IMAGE_RECIPE_SRC) results/$(BASENAME).deb + ./image-recipe/run-local-build.sh "results/$(BASENAME).deb" # For creating os images. DO NOT USE install: $(ALL_TARGETS) @@ -76,56 +107,71 @@ install: $(ALL_TARGETS) $(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/startd) $(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/start-cli) $(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/start-sdk) + $(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/start-deno) $(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/avahi-alias) $(call ln,/usr/bin/startbox,$(DESTDIR)/usr/bin/embassy-cli) - if [ "$(OS_ARCH)" = "raspberrypi" ]; then $(call cp,cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep,$(DESTDIR)/usr/bin/pi-beep); fi + if [ "$(PLATFORM)" = "raspberrypi" ]; then $(call cp,cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep,$(DESTDIR)/usr/bin/pi-beep); fi + if /bin/bash -c '[[ "${ENVIRONMENT}" =~ (^|-)unstable($$|-) ]]'; then $(call cp,cargo-deps/$(ARCH)-unknown-linux-gnu/release/tokio-console,$(DESTDIR)/usr/bin/tokio-console); fi + $(call mkdir,$(DESTDIR)/lib/systemd/system) + $(call cp,backend/startd.service,$(DESTDIR)/lib/systemd/system/startd.service) + $(call mkdir,$(DESTDIR)/usr/lib) - $(call rm,$(DESTDIR)/usr/lib/embassy) - $(call cp,build/lib,$(DESTDIR)/usr/lib/embassy) + $(call rm,$(DESTDIR)/usr/lib/startos) + $(call cp,build/lib,$(DESTDIR)/usr/lib/startos) - $(call cp,ENVIRONMENT.txt,$(DESTDIR)/usr/lib/embassy/ENVIRONMENT.txt) - $(call cp,GIT_HASH.txt,$(DESTDIR)/usr/lib/embassy/GIT_HASH.txt) - $(call cp,VERSION.txt,$(DESTDIR)/usr/lib/embassy/VERSION.txt) + $(call cp,PLATFORM.txt,$(DESTDIR)/usr/lib/startos/PLATFORM.txt) + $(call cp,ENVIRONMENT.txt,$(DESTDIR)/usr/lib/startos/ENVIRONMENT.txt) + $(call cp,GIT_HASH.txt,$(DESTDIR)/usr/lib/startos/GIT_HASH.txt) + $(call cp,VERSION.txt,$(DESTDIR)/usr/lib/startos/VERSION.txt) - $(call mkdir,$(DESTDIR)/usr/lib/embassy/container) - $(call cp,libs/target/aarch64-unknown-linux-musl/release/embassy_container_init,$(DESTDIR)/usr/lib/embassy/container/embassy_container_init.arm64) - $(call cp,libs/target/x86_64-unknown-linux-musl/release/embassy_container_init,$(DESTDIR)/usr/lib/embassy/container/embassy_container_init.amd64) + $(call mkdir,$(DESTDIR)/usr/lib/startos/container) + $(call cp,libs/target/aarch64-unknown-linux-musl/release/embassy_container_init,$(DESTDIR)/usr/lib/startos/container/embassy_container_init.arm64) + $(call cp,libs/target/x86_64-unknown-linux-musl/release/embassy_container_init,$(DESTDIR)/usr/lib/startos/container/embassy_container_init.amd64) - $(call mkdir,$(DESTDIR)/usr/lib/embassy/system-images) - $(call cp,system-images/compat/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/embassy/system-images/compat.tar) - $(call cp,system-images/utils/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/embassy/system-images/utils.tar) - $(call cp,system-images/binfmt/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/embassy/system-images/binfmt.tar) + $(call mkdir,$(DESTDIR)/usr/lib/startos/system-images) + $(call cp,system-images/compat/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/startos/system-images/compat.tar) + $(call cp,system-images/utils/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/startos/system-images/utils.tar) + $(call cp,system-images/binfmt/docker-images/$(ARCH).tar,$(DESTDIR)/usr/lib/startos/system-images/binfmt.tar) -update-overlay: +update-overlay: $(ALL_TARGETS) @echo "\033[33m!!! THIS WILL ONLY REFLASH YOUR DEVICE IN MEMORY !!!\033[0m" @echo "\033[33mALL CHANGES WILL BE REVERTED IF YOU RESTART THE DEVICE\033[0m" @if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi - @if [ "`ssh $(REMOTE) 'cat /usr/lib/embassy/VERSION.txt'`" != "`cat ./VERSION.txt`" ]; then >&2 echo "StartOS requires migrations: update-overlay is unavailable." && false; fi - ssh $(REMOTE) "sudo systemctl stop startd" - $(MAKE) install REMOTE=$(REMOTE) OS_ARCH=$(OS_ARCH) - ssh $(REMOTE) "sudo systemctl start startd" + @if [ "`ssh $(REMOTE) 'cat /usr/lib/startos/VERSION.txt'`" != "`cat ./VERSION.txt`" ]; then >&2 echo "StartOS requires migrations: update-overlay is unavailable." && false; fi + $(call ssh,"sudo systemctl stop startd") + $(MAKE) install REMOTE=$(REMOTE) SSHPASS=$(SSHPASS) PLATFORM=$(PLATFORM) + $(call ssh,"sudo systemctl start startd") -update: +wormhole: backend/target/$(ARCH)-unknown-linux-gnu/release/startbox + @wormhole send backend/target/$(ARCH)-unknown-linux-gnu/release/startbox 2>&1 | awk -Winteractive '/wormhole receive/ { printf "sudo /usr/lib/startos/scripts/chroot-and-upgrade \"cd /usr/bin && rm startbox && wormhole receive --accept-file %s && chmod +x startbox\"\n", $$3 }' + +update: $(ALL_TARGETS) @if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi - ssh $(REMOTE) "sudo rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next/" - $(MAKE) install REMOTE=$(REMOTE) DESTDIR=/media/embassy/next OS_ARCH=$(OS_ARCH) - ssh $(REMOTE) "sudo touch /media/embassy/config/upgrade && sudo sync && sudo reboot" + $(call ssh,"sudo rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next/") + $(MAKE) install REMOTE=$(REMOTE) SSHPASS=$(SSHPASS) DESTDIR=/media/embassy/next PLATFORM=$(PLATFORM) + $(call ssh,'sudo NO_SYNC=1 /media/embassy/next/usr/lib/startos/scripts/chroot-and-upgrade "apt-get install -y $(shell cat ./build/lib/depends)"') -emulate-reflash: +emulate-reflash: $(ALL_TARGETS) @if [ -z "$(REMOTE)" ]; then >&2 echo "Must specify REMOTE" && false; fi - ssh $(REMOTE) "sudo rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next/" - $(MAKE) install REMOTE=$(REMOTE) DESTDIR=/media/embassy/next OS_ARCH=$(OS_ARCH) - ssh $(REMOTE) "sudo touch /media/embassy/config/upgrade && sudo rm -f /media/embassy/config/disk.guid && sudo sync && sudo reboot" + $(call ssh,"sudo rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next/") + $(MAKE) install REMOTE=$(REMOTE) SSHPASS=$(SSHPASS) DESTDIR=/media/embassy/next PLATFORM=$(PLATFORM) + $(call ssh,"sudo touch /media/embassy/config/upgrade && sudo rm -f /media/embassy/config/disk.guid && sudo sync && sudo reboot") -system-images/compat/docker-images/aarch64.tar system-images/compat/docker-images/x86_64.tar: $(COMPAT_SRC) | sudo - cd system-images/compat && make +upload-ota: results/$(BASENAME).squashfs + TARGET=$(TARGET) KEY=$(KEY) ./upload-ota.sh -system-images/utils/docker-images/aarch64.tar system-images/utils/docker-images/x86_64.tar: $(UTILS_SRC) | sudo - cd system-images/utils && make +build/lib/depends build/lib/conflicts: build/dpkg-deps/* + build/dpkg-deps/generate.sh -system-images/binfmt/docker-images/aarch64.tar system-images/binfmt/docker-images/x86_64.tar: $(BINFMT_SRC) | sudo - cd system-images/binfmt && make +system-images/compat/docker-images/$(ARCH).tar: $(COMPAT_SRC) backend/Cargo.lock + cd system-images/compat && make docker-images/$(ARCH).tar && touch docker-images/$(ARCH).tar + +system-images/utils/docker-images/$(ARCH).tar: $(UTILS_SRC) + cd system-images/utils && make docker-images/$(ARCH).tar && touch docker-images/$(ARCH).tar + +system-images/binfmt/docker-images/$(ARCH).tar: $(BINFMT_SRC) + cd system-images/binfmt && make docker-images/$(ARCH).tar && touch docker-images/$(ARCH).tar snapshots: libs/snapshot_creator/Cargo.toml cd libs/ && ./build-v8-snapshot.sh @@ -138,27 +184,26 @@ $(EMBASSY_BINS): $(BACKEND_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) frontend/pa frontend/node_modules: frontend/package.json npm --prefix frontend ci -frontend/dist/raw/ui: $(FRONTEND_UI_SRC) $(FRONTEND_SHARED_SRC) $(ENVIRONMENT_FILE) +frontend/dist/raw/ui: $(FRONTEND_UI_SRC) $(FRONTEND_SHARED_SRC) npm --prefix frontend run build:ui -frontend/dist/raw/setup-wizard: $(FRONTEND_SETUP_WIZARD_SRC) $(FRONTEND_SHARED_SRC) $(ENVIRONMENT_FILE) +frontend/dist/raw/setup-wizard: $(FRONTEND_SETUP_WIZARD_SRC) $(FRONTEND_SHARED_SRC) npm --prefix frontend run build:setup -frontend/dist/raw/install-wizard: $(FRONTEND_INSTALL_WIZARD_SRC) $(FRONTEND_SHARED_SRC) $(ENVIRONMENT_FILE) +frontend/dist/raw/diagnostic-ui: $(FRONTEND_DIAGNOSTIC_UI_SRC) $(FRONTEND_SHARED_SRC) + npm --prefix frontend run build:dui + +frontend/dist/raw/install-wizard: $(FRONTEND_INSTALL_WIZARD_SRC) $(FRONTEND_SHARED_SRC) npm --prefix frontend run build:install-wiz -frontend/dist/static: $(EMBASSY_UIS) +frontend/dist/static: $(EMBASSY_UIS) $(ENVIRONMENT_FILE) ./compress-uis.sh frontend/config.json: $(GIT_HASH_FILE) frontend/config-sample.json - jq '.useMocks = false' frontend/config-sample.json > frontend/config.json - jq '.packageArch = "$(ARCH)"' frontend/config.json > frontend/config.json.tmp - jq '.osArch = "$(OS_ARCH)"' frontend/config.json.tmp > frontend/config.json - rm frontend/config.json.tmp - npm --prefix frontend run-script build-config + jq '.useMocks = false' frontend/config-sample.json | jq '.gitHash = "$(shell cat GIT_HASH.txt)"' > frontend/config.json frontend/patchdb-ui-seed.json: frontend/package.json - jq '."ack-welcome" = $(shell yq '.version' frontend/package.json)' frontend/patchdb-ui-seed.json > ui-seed.tmp + jq '."ack-welcome" = $(shell jq '.version' frontend/package.json)' frontend/patchdb-ui-seed.json > ui-seed.tmp mv ui-seed.tmp frontend/patchdb-ui-seed.json patch-db/client/node_modules: patch-db/client/package.json @@ -169,7 +214,7 @@ patch-db/client/dist: $(PATCH_DB_CLIENT_SRC) patch-db/client/node_modules npm --prefix frontend run build:deps # used by github actions -backend-$(ARCH).tar: $(EMBASSY_BINS) +compiled-$(ARCH).tar: $(COMPILED_TARGETS) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(VERSION_FILE) tar -cvf $@ $^ # this is a convenience step to build all frontends - it is not referenced elsewhere in this file @@ -178,8 +223,8 @@ frontends: $(EMBASSY_UIS) # this is a convenience step to build the UI ui: frontend/dist/raw/ui -# used by github actions -backend: $(EMBASSY_BINS) - -cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep: | sudo +cargo-deps/aarch64-unknown-linux-gnu/release/pi-beep: ARCH=aarch64 ./build-cargo-dep.sh pi-beep + +cargo-deps/$(ARCH)-unknown-linux-gnu/release/tokio-console: | sudo + ARCH=$(ARCH) ./build-cargo-dep.sh tokio-console diff --git a/README.md b/README.md index 125a956a4..db3c24e73 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,35 @@
- StartOS Logo + StartOS Logo

StartOS

- + GitHub release (with filter) - - + + Static Badge - + + X (formerly Twitter) Follow + + - + Static Badge - + Static Badge - + Static Badge - + Static Badge - + Website

@@ -35,7 +38,7 @@ Welcome to the era of Sovereign Computing

- StartOS is a Debian-based Linux distro optimized for running a personal server. It facilitates the discovery, installation, network configuration, service configuration, data backup, dependency management, and health monitoring of self-hosted software services. + StartOS is an open source Linux distribution optimized for running a personal server. It facilitates the discovery, installation, network configuration, service configuration, data backup, dependency management, and health monitoring of self-hosted software services.


@@ -65,7 +68,7 @@ There are multiple ways to contribute: work directly on StartOS, package a servi To report security issues, please email our security team - security@start9.com. ## 🌎 Marketplace -There are dozens of service available for StartOS, and new ones are being added all the time. Check out the full list of available services [here](https://marketplace.start9.com/marketplace). To read more about the Marketplace ecosystem, check out this [blog post](https://blog.start9.com/start9-marketplace-strategy/) +There are dozens of services available for StartOS, and new ones are being added all the time. Check out the full list of available services [here](https://marketplace.start9.com/marketplace). To read more about the Marketplace ecosystem, check out this [blog post](https://blog.start9.com/start9-marketplace-strategy/) ## 🖥️ User Interface Screenshots diff --git a/backend/.sqlx/query-1ce5254f27de971fd87f5ab66d300f2b22433c86617a0dbf796bf2170186dd2e.json b/backend/.sqlx/query-1ce5254f27de971fd87f5ab66d300f2b22433c86617a0dbf796bf2170186dd2e.json new file mode 100644 index 000000000..d36100fef --- /dev/null +++ b/backend/.sqlx/query-1ce5254f27de971fd87f5ab66d300f2b22433c86617a0dbf796bf2170186dd2e.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO network_keys (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "1ce5254f27de971fd87f5ab66d300f2b22433c86617a0dbf796bf2170186dd2e" +} diff --git a/backend/.sqlx/query-21471490cdc3adb206274cc68e1ea745ffa5da4479478c1fd2158a45324b1930.json b/backend/.sqlx/query-21471490cdc3adb206274cc68e1ea745ffa5da4479478c1fd2158a45324b1930.json new file mode 100644 index 000000000..e0b1d7cf2 --- /dev/null +++ b/backend/.sqlx/query-21471490cdc3adb206274cc68e1ea745ffa5da4479478c1fd2158a45324b1930.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM ssh_keys WHERE fingerprint = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "21471490cdc3adb206274cc68e1ea745ffa5da4479478c1fd2158a45324b1930" +} diff --git a/backend/.sqlx/query-28ea34bbde836e0618c5fc9bb7c36e463c20c841a7d6a0eb15be0f24f4a928ec.json b/backend/.sqlx/query-28ea34bbde836e0618c5fc9bb7c36e463c20c841a7d6a0eb15be0f24f4a928ec.json new file mode 100644 index 000000000..e234a72a9 --- /dev/null +++ b/backend/.sqlx/query-28ea34bbde836e0618c5fc9bb7c36e463c20c841a7d6a0eb15be0f24f4a928ec.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT hostname, path, username, password FROM cifs_shares WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "hostname", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "path", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "username", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "password", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [ + false, + false, + false, + true + ] + }, + "hash": "28ea34bbde836e0618c5fc9bb7c36e463c20c841a7d6a0eb15be0f24f4a928ec" +} diff --git a/backend/.sqlx/query-4099028a5c0de578255bf54a67cef6cb0f1e9a4e158260700f1639dd4b438997.json b/backend/.sqlx/query-4099028a5c0de578255bf54a67cef6cb0f1e9a4e158260700f1639dd4b438997.json new file mode 100644 index 000000000..761af064b --- /dev/null +++ b/backend/.sqlx/query-4099028a5c0de578255bf54a67cef6cb0f1e9a4e158260700f1639dd4b438997.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM ssh_keys WHERE fingerprint = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "fingerprint", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "openssh_pubkey", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "created_at", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "4099028a5c0de578255bf54a67cef6cb0f1e9a4e158260700f1639dd4b438997" +} diff --git a/backend/.sqlx/query-4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96.json b/backend/.sqlx/query-4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96.json new file mode 100644 index 000000000..1f7edd1ce --- /dev/null +++ b/backend/.sqlx/query-4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96.json @@ -0,0 +1,50 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM session WHERE logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "logged_in", + "type_info": "Timestamp" + }, + { + "ordinal": 2, + "name": "logged_out", + "type_info": "Timestamp" + }, + { + "ordinal": 3, + "name": "last_active", + "type_info": "Timestamp" + }, + { + "ordinal": 4, + "name": "user_agent", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "metadata", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + true, + false, + true, + false + ] + }, + "hash": "4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96" +} diff --git a/backend/.sqlx/query-4bcfbefb1eb3181343871a1cd7fc3afb81c2be5c681cfa8b4be0ce70610e9c3a.json b/backend/.sqlx/query-4bcfbefb1eb3181343871a1cd7fc3afb81c2be5c681cfa8b4be0ce70610e9c3a.json new file mode 100644 index 000000000..2157198e5 --- /dev/null +++ b/backend/.sqlx/query-4bcfbefb1eb3181343871a1cd7fc3afb81c2be5c681cfa8b4be0ce70610e9c3a.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "4bcfbefb1eb3181343871a1cd7fc3afb81c2be5c681cfa8b4be0ce70610e9c3a" +} diff --git a/backend/.sqlx/query-629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a.json b/backend/.sqlx/query-629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a.json new file mode 100644 index 000000000..764cff84a --- /dev/null +++ b/backend/.sqlx/query-629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT password FROM account", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "password", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false + ] + }, + "hash": "629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a" +} diff --git a/backend/.sqlx/query-687688055e63d27123cdc89a5bbbd8361776290a9411d527eaf1fdb40bef399d.json b/backend/.sqlx/query-687688055e63d27123cdc89a5bbbd8361776290a9411d527eaf1fdb40bef399d.json new file mode 100644 index 000000000..2e8a9ee0e --- /dev/null +++ b/backend/.sqlx/query-687688055e63d27123cdc89a5bbbd8361776290a9411d527eaf1fdb40bef399d.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT key FROM tor WHERE package = $1 AND interface = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "key", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "687688055e63d27123cdc89a5bbbd8361776290a9411d527eaf1fdb40bef399d" +} diff --git a/backend/.sqlx/query-6d35ccf780fb2bb62586dd1d3df9c1550a41ee580dad3f49d35cb843ebef10ca.json b/backend/.sqlx/query-6d35ccf780fb2bb62586dd1d3df9c1550a41ee580dad3f49d35cb843ebef10ca.json new file mode 100644 index 000000000..3f859bd10 --- /dev/null +++ b/backend/.sqlx/query-6d35ccf780fb2bb62586dd1d3df9c1550a41ee580dad3f49d35cb843ebef10ca.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = $1 AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "6d35ccf780fb2bb62586dd1d3df9c1550a41ee580dad3f49d35cb843ebef10ca" +} diff --git a/backend/.sqlx/query-770c1017734720453dc87b58c385b987c5af5807151ff71a59000014586752e0.json b/backend/.sqlx/query-770c1017734720453dc87b58c385b987c5af5807151ff71a59000014586752e0.json new file mode 100644 index 000000000..cf3591e01 --- /dev/null +++ b/backend/.sqlx/query-770c1017734720453dc87b58c385b987c5af5807151ff71a59000014586752e0.json @@ -0,0 +1,24 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO network_keys (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO UPDATE SET package = EXCLUDED.package RETURNING key", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "key", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Bytea" + ] + }, + "nullable": [ + false + ] + }, + "hash": "770c1017734720453dc87b58c385b987c5af5807151ff71a59000014586752e0" +} diff --git a/backend/.sqlx/query-7b64f032d507e8ffe37c41f4c7ad514a66c421a11ab04c26d89a7aa8f6b67210.json b/backend/.sqlx/query-7b64f032d507e8ffe37c41f4c7ad514a66c421a11ab04c26d89a7aa8f6b67210.json new file mode 100644 index 000000000..53fc6f066 --- /dev/null +++ b/backend/.sqlx/query-7b64f032d507e8ffe37c41f4c7ad514a66c421a11ab04c26d89a7aa8f6b67210.json @@ -0,0 +1,65 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications WHERE id < $1 ORDER BY id DESC LIMIT $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "package_id", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "created_at", + "type_info": "Timestamp" + }, + { + "ordinal": 3, + "name": "code", + "type_info": "Int4" + }, + { + "ordinal": 4, + "name": "level", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "message", + "type_info": "Text" + }, + { + "ordinal": 7, + "name": "data", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4", + "Int8" + ] + }, + "nullable": [ + false, + true, + false, + false, + false, + false, + false, + true + ] + }, + "hash": "7b64f032d507e8ffe37c41f4c7ad514a66c421a11ab04c26d89a7aa8f6b67210" +} diff --git a/backend/.sqlx/query-7c7a3549c997eb75bf964ea65fbb98a73045adf618696cd838d79203ef5383fb.json b/backend/.sqlx/query-7c7a3549c997eb75bf964ea65fbb98a73045adf618696cd838d79203ef5383fb.json new file mode 100644 index 000000000..245a838d8 --- /dev/null +++ b/backend/.sqlx/query-7c7a3549c997eb75bf964ea65fbb98a73045adf618696cd838d79203ef5383fb.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO account (\n id,\n server_id,\n hostname,\n password,\n network_key,\n root_ca_key_pem,\n root_ca_cert_pem\n ) VALUES (\n 0, $1, $2, $3, $4, $5, $6\n ) ON CONFLICT (id) DO UPDATE SET\n server_id = EXCLUDED.server_id,\n hostname = EXCLUDED.hostname,\n password = EXCLUDED.password,\n network_key = EXCLUDED.network_key,\n root_ca_key_pem = EXCLUDED.root_ca_key_pem,\n root_ca_cert_pem = EXCLUDED.root_ca_cert_pem\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Text", + "Bytea", + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "7c7a3549c997eb75bf964ea65fbb98a73045adf618696cd838d79203ef5383fb" +} diff --git a/backend/.sqlx/query-7e0649d839927e57fa03ee51a2c9f96a8bdb0fc97ee8a3c6df1069e1e2b98576.json b/backend/.sqlx/query-7e0649d839927e57fa03ee51a2c9f96a8bdb0fc97ee8a3c6df1069e1e2b98576.json new file mode 100644 index 000000000..e3ce7957d --- /dev/null +++ b/backend/.sqlx/query-7e0649d839927e57fa03ee51a2c9f96a8bdb0fc97ee8a3c6df1069e1e2b98576.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM tor WHERE package = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "7e0649d839927e57fa03ee51a2c9f96a8bdb0fc97ee8a3c6df1069e1e2b98576" +} diff --git a/backend/.sqlx/query-8951b9126fbf60dbb5997241e11e3526b70bccf3e407327917294a993bc17ed5.json b/backend/.sqlx/query-8951b9126fbf60dbb5997241e11e3526b70bccf3e407327917294a993bc17ed5.json new file mode 100644 index 000000000..e39aebf69 --- /dev/null +++ b/backend/.sqlx/query-8951b9126fbf60dbb5997241e11e3526b70bccf3e407327917294a993bc17ed5.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO tor (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Bytea" + ] + }, + "nullable": [] + }, + "hash": "8951b9126fbf60dbb5997241e11e3526b70bccf3e407327917294a993bc17ed5" +} diff --git a/backend/.sqlx/query-94d471bb374b4965c6cbedf8c17bbf6bea226d38efaf6559923c79a36d5ca08c.json b/backend/.sqlx/query-94d471bb374b4965c6cbedf8c17bbf6bea226d38efaf6559923c79a36d5ca08c.json new file mode 100644 index 000000000..e7fe8d38c --- /dev/null +++ b/backend/.sqlx/query-94d471bb374b4965c6cbedf8c17bbf6bea226d38efaf6559923c79a36d5ca08c.json @@ -0,0 +1,64 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications ORDER BY id DESC LIMIT $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "package_id", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "created_at", + "type_info": "Timestamp" + }, + { + "ordinal": 3, + "name": "code", + "type_info": "Int4" + }, + { + "ordinal": 4, + "name": "level", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "message", + "type_info": "Text" + }, + { + "ordinal": 7, + "name": "data", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + true, + false, + false, + false, + false, + false, + true + ] + }, + "hash": "94d471bb374b4965c6cbedf8c17bbf6bea226d38efaf6559923c79a36d5ca08c" +} diff --git a/backend/.sqlx/query-95c4ab4c645f3302568c6ff13d85ab58252362694cf0f56999bf60194d20583a.json b/backend/.sqlx/query-95c4ab4c645f3302568c6ff13d85ab58252362694cf0f56999bf60194d20583a.json new file mode 100644 index 000000000..aadc0fc3a --- /dev/null +++ b/backend/.sqlx/query-95c4ab4c645f3302568c6ff13d85ab58252362694cf0f56999bf60194d20583a.json @@ -0,0 +1,44 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, hostname, path, username, password FROM cifs_shares", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "hostname", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "path", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "username", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "password", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + false, + false, + true + ] + }, + "hash": "95c4ab4c645f3302568c6ff13d85ab58252362694cf0f56999bf60194d20583a" +} diff --git a/backend/.sqlx/query-a60d6e66719325b08dc4ecfacaf337527233c84eee758ac9be967906e5841d27.json b/backend/.sqlx/query-a60d6e66719325b08dc4ecfacaf337527233c84eee758ac9be967906e5841d27.json new file mode 100644 index 000000000..c56a9ebd1 --- /dev/null +++ b/backend/.sqlx/query-a60d6e66719325b08dc4ecfacaf337527233c84eee758ac9be967906e5841d27.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM cifs_shares WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "a60d6e66719325b08dc4ecfacaf337527233c84eee758ac9be967906e5841d27" +} diff --git a/backend/.sqlx/query-a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e.json b/backend/.sqlx/query-a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e.json new file mode 100644 index 000000000..86bd9250e --- /dev/null +++ b/backend/.sqlx/query-a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e.json @@ -0,0 +1,32 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT fingerprint, openssh_pubkey, created_at FROM ssh_keys", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "fingerprint", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "openssh_pubkey", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "created_at", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e" +} diff --git a/backend/.sqlx/query-b1147beaaabbed89f2ab8c1e13ec4393a9a8fde2833cf096af766a979d94dee6.json b/backend/.sqlx/query-b1147beaaabbed89f2ab8c1e13ec4393a9a8fde2833cf096af766a979d94dee6.json new file mode 100644 index 000000000..c8ff84277 --- /dev/null +++ b/backend/.sqlx/query-b1147beaaabbed89f2ab8c1e13ec4393a9a8fde2833cf096af766a979d94dee6.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE cifs_shares SET hostname = $1, path = $2, username = $3, password = $4 WHERE id = $5", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Text", + "Text", + "Int4" + ] + }, + "nullable": [] + }, + "hash": "b1147beaaabbed89f2ab8c1e13ec4393a9a8fde2833cf096af766a979d94dee6" +} diff --git a/backend/.sqlx/query-b203820ee1c553a4b246eac74b79bd10d5717b2a0ddecf22330b7d531aac7c5d.json b/backend/.sqlx/query-b203820ee1c553a4b246eac74b79bd10d5717b2a0ddecf22330b7d531aac7c5d.json new file mode 100644 index 000000000..b76542db8 --- /dev/null +++ b/backend/.sqlx/query-b203820ee1c553a4b246eac74b79bd10d5717b2a0ddecf22330b7d531aac7c5d.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM network_keys WHERE package = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "b203820ee1c553a4b246eac74b79bd10d5717b2a0ddecf22330b7d531aac7c5d" +} diff --git a/backend/.sqlx/query-d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca.json b/backend/.sqlx/query-d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca.json new file mode 100644 index 000000000..b77ba7ce9 --- /dev/null +++ b/backend/.sqlx/query-d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT openssh_pubkey FROM ssh_keys", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "openssh_pubkey", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false + ] + }, + "hash": "d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca" +} diff --git a/backend/.sqlx/query-da71f94b29798d1738d2b10b9a721ea72db8cfb362e7181c8226d9297507c62b.json b/backend/.sqlx/query-da71f94b29798d1738d2b10b9a721ea72db8cfb362e7181c8226d9297507c62b.json new file mode 100644 index 000000000..5c5c89c27 --- /dev/null +++ b/backend/.sqlx/query-da71f94b29798d1738d2b10b9a721ea72db8cfb362e7181c8226d9297507c62b.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO notifications (package_id, code, level, title, message, data) VALUES ($1, $2, $3, $4, $5, $6)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Int4", + "Text", + "Text", + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "da71f94b29798d1738d2b10b9a721ea72db8cfb362e7181c8226d9297507c62b" +} diff --git a/backend/.sqlx/query-e185203cf84e43b801dfb23b4159e34aeaef1154dcd3d6811ab504915497ccf7.json b/backend/.sqlx/query-e185203cf84e43b801dfb23b4159e34aeaef1154dcd3d6811ab504915497ccf7.json new file mode 100644 index 000000000..a4dc187cd --- /dev/null +++ b/backend/.sqlx/query-e185203cf84e43b801dfb23b4159e34aeaef1154dcd3d6811ab504915497ccf7.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM notifications WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "e185203cf84e43b801dfb23b4159e34aeaef1154dcd3d6811ab504915497ccf7" +} diff --git a/backend/.sqlx/query-e545696735f202f9d13cf22a561f3ff3f9aed7f90027a9ba97634bcb47d772f0.json b/backend/.sqlx/query-e545696735f202f9d13cf22a561f3ff3f9aed7f90027a9ba97634bcb47d772f0.json new file mode 100644 index 000000000..97a4ec95a --- /dev/null +++ b/backend/.sqlx/query-e545696735f202f9d13cf22a561f3ff3f9aed7f90027a9ba97634bcb47d772f0.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT tor_key FROM account WHERE id = 0", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "tor_key", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + true + ] + }, + "hash": "e545696735f202f9d13cf22a561f3ff3f9aed7f90027a9ba97634bcb47d772f0" +} diff --git a/backend/.sqlx/query-e5843c5b0e7819b29aa1abf2266799bd4f82e761837b526a0972c3d4439a264d.json b/backend/.sqlx/query-e5843c5b0e7819b29aa1abf2266799bd4f82e761837b526a0972c3d4439a264d.json new file mode 100644 index 000000000..b2aa04370 --- /dev/null +++ b/backend/.sqlx/query-e5843c5b0e7819b29aa1abf2266799bd4f82e761837b526a0972c3d4439a264d.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO session (id, user_agent, metadata) VALUES ($1, $2, $3)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "e5843c5b0e7819b29aa1abf2266799bd4f82e761837b526a0972c3d4439a264d" +} diff --git a/backend/.sqlx/query-e95322a8e2ae3b93f1e974b24c0b81803f1e9ec9e8ebbf15cafddfc1c5a028ed.json b/backend/.sqlx/query-e95322a8e2ae3b93f1e974b24c0b81803f1e9ec9e8ebbf15cafddfc1c5a028ed.json new file mode 100644 index 000000000..fd5a467ec --- /dev/null +++ b/backend/.sqlx/query-e95322a8e2ae3b93f1e974b24c0b81803f1e9ec9e8ebbf15cafddfc1c5a028ed.json @@ -0,0 +1,40 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n network_keys.package,\n network_keys.interface,\n network_keys.key,\n tor.key AS \"tor_key?\"\n FROM\n network_keys\n LEFT JOIN\n tor\n ON\n network_keys.package = tor.package\n AND\n network_keys.interface = tor.interface\n WHERE\n network_keys.package = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "package", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "interface", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "key", + "type_info": "Bytea" + }, + { + "ordinal": 3, + "name": "tor_key?", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + }, + "hash": "e95322a8e2ae3b93f1e974b24c0b81803f1e9ec9e8ebbf15cafddfc1c5a028ed" +} diff --git a/backend/.sqlx/query-eb750adaa305bdbf3c5b70aaf59139c7b7569602adb58f2d6b3a94da4f167b0a.json b/backend/.sqlx/query-eb750adaa305bdbf3c5b70aaf59139c7b7569602adb58f2d6b3a94da4f167b0a.json new file mode 100644 index 000000000..fb8a7c1e5 --- /dev/null +++ b/backend/.sqlx/query-eb750adaa305bdbf3c5b70aaf59139c7b7569602adb58f2d6b3a94da4f167b0a.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM notifications WHERE id < $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "eb750adaa305bdbf3c5b70aaf59139c7b7569602adb58f2d6b3a94da4f167b0a" +} diff --git a/backend/.sqlx/query-ecc765d8205c0876956f95f76944ac6a5f34dd820c4073b7728c7067aab9fded.json b/backend/.sqlx/query-ecc765d8205c0876956f95f76944ac6a5f34dd820c4073b7728c7067aab9fded.json new file mode 100644 index 000000000..27c9752b2 --- /dev/null +++ b/backend/.sqlx/query-ecc765d8205c0876956f95f76944ac6a5f34dd820c4073b7728c7067aab9fded.json @@ -0,0 +1,25 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO cifs_shares (hostname, path, username, password) VALUES ($1, $2, $3, $4) RETURNING id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Text", + "Text", + "Text", + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "ecc765d8205c0876956f95f76944ac6a5f34dd820c4073b7728c7067aab9fded" +} diff --git a/backend/.sqlx/query-f6d1c5ef0f9d9577bea8382318967b9deb46da75788c7fe6082b43821c22d556.json b/backend/.sqlx/query-f6d1c5ef0f9d9577bea8382318967b9deb46da75788c7fe6082b43821c22d556.json new file mode 100644 index 000000000..6ed9898f6 --- /dev/null +++ b/backend/.sqlx/query-f6d1c5ef0f9d9577bea8382318967b9deb46da75788c7fe6082b43821c22d556.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO ssh_keys (fingerprint, openssh_pubkey, created_at) VALUES ($1, $2, $3)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "f6d1c5ef0f9d9577bea8382318967b9deb46da75788c7fe6082b43821c22d556" +} diff --git a/backend/.sqlx/query-f7d2dae84613bcef330f7403352cc96547f3f6dbec11bf2eadfaf53ad8ab51b5.json b/backend/.sqlx/query-f7d2dae84613bcef330f7403352cc96547f3f6dbec11bf2eadfaf53ad8ab51b5.json new file mode 100644 index 000000000..f48ccb074 --- /dev/null +++ b/backend/.sqlx/query-f7d2dae84613bcef330f7403352cc96547f3f6dbec11bf2eadfaf53ad8ab51b5.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT network_key FROM account WHERE id = 0", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "network_key", + "type_info": "Bytea" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false + ] + }, + "hash": "f7d2dae84613bcef330f7403352cc96547f3f6dbec11bf2eadfaf53ad8ab51b5" +} diff --git a/backend/.sqlx/query-fe6e4f09f3028e5b6b6259e86cbad285680ce157aae9d7837ac020c8b2945e7f.json b/backend/.sqlx/query-fe6e4f09f3028e5b6b6259e86cbad285680ce157aae9d7837ac020c8b2945e7f.json new file mode 100644 index 000000000..6ef1d5023 --- /dev/null +++ b/backend/.sqlx/query-fe6e4f09f3028e5b6b6259e86cbad285680ce157aae9d7837ac020c8b2945e7f.json @@ -0,0 +1,62 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM account WHERE id = 0", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "password", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "tor_key", + "type_info": "Bytea" + }, + { + "ordinal": 3, + "name": "server_id", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "hostname", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "network_key", + "type_info": "Bytea" + }, + { + "ordinal": 6, + "name": "root_ca_key_pem", + "type_info": "Text" + }, + { + "ordinal": 7, + "name": "root_ca_cert_pem", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + true, + true, + true, + false, + false, + false + ] + }, + "hash": "fe6e4f09f3028e5b6b6259e86cbad285680ce157aae9d7837ac020c8b2945e7f" +} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 508d65a9b..4aafa0aa8 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -34,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if 1.0.0", - "cipher", + "cipher 0.3.0", "cpufeatures", "ctr", "opaque-debug", @@ -58,15 +58,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if 1.0.0", + "getrandom 0.2.10", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -118,9 +119,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arrayref" @@ -145,15 +146,15 @@ dependencies = [ [[package]] name = "ast_node" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c704e2f6ee1a98223f5a7629a6ef0f3decb3b552ed282889dc957edff98ce1e6" +checksum = "c09c69dffe06d222d072c878c3afe86eee2179806f20503faec97250268b4c24" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -169,9 +170,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.3.15" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +checksum = "f658e2baef915ba0f26f1f7c42bfb8e12f532a01f449a090ded75ae7a07e9ba2" dependencies = [ "brotli", "flate2", @@ -198,27 +199,27 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "async-trait" -version = "0.1.69" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "atoi" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" dependencies = [ "num-traits", ] @@ -250,10 +251,55 @@ dependencies = [ ] [[package]] -name = "backtrace" -version = "0.3.68" +name = "axum" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -266,9 +312,9 @@ dependencies = [ [[package]] name = "base16ct" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base32" @@ -284,9 +330,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" @@ -316,9 +362,9 @@ dependencies = [ [[package]] name = "bimap" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0455254eb5c6964c4545d8bac815e1a1be4f3afe0ae695ea539c12d728d44b" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" dependencies = [ "serde", ] @@ -348,8 +394,8 @@ dependencies = [ "lazycell", "log", "peeking_take_while", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "regex", "rustc-hash", "shlex", @@ -379,17 +425,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" - -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" dependencies = [ - "typenum", + "serde", ] [[package]] @@ -412,13 +452,13 @@ dependencies = [ [[package]] name = "blake2b_simd" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" dependencies = [ "arrayref", "arrayvec", - "constant_time_eq 0.2.6", + "constant_time_eq", ] [[package]] @@ -446,49 +486,11 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" -[[package]] -name = "bollard" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82e7850583ead5f8bbef247e2a3c37a19bd576e8420cd262a6711921827e1e5" -dependencies = [ - "base64 0.13.1", - "bollard-stubs", - "bytes", - "futures-core", - "futures-util", - "hex", - "http", - "hyper", - "hyperlocal", - "log", - "pin-project-lite", - "serde", - "serde_derive", - "serde_json", - "serde_urlencoded", - "thiserror", - "tokio", - "tokio-util", - "url", - "winapi", -] - -[[package]] -name = "bollard-stubs" -version = "1.42.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" -dependencies = [ - "serde", - "serde_with 1.14.0", -] - [[package]] name = "brotli" -version = "3.3.4" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -497,9 +499,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.4" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" +checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -507,27 +509,30 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cexpr" @@ -552,18 +557,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", - "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -611,6 +615,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.6.1" @@ -673,7 +687,7 @@ dependencies = [ "indenter", "once_cell", "owo-colors", - "tracing-error 0.2.0", + "tracing-error", ] [[package]] @@ -685,35 +699,99 @@ dependencies = [ "once_cell", "owo-colors", "tracing-core", - "tracing-error 0.2.0", + "tracing-error", ] [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode 0.3.6", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + +[[package]] +name = "console-api" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" +dependencies = [ + "futures-core", + "prost", + "prost-types", + "tonic", + "tracing-core", +] + +[[package]] +name = "console-subscriber" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7481d4c57092cd1c19dd541b92bdce883de840df30aa5d03fd48a3935c01842e" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures-task", + "hdrhistogram", + "humantime 2.1.0", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "constant_time_eq" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "convert_case" @@ -721,6 +799,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[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 = "cookie" version = "0.16.2" @@ -728,7 +815,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.3.23", + "time", + "version_check", +] + +[[package]] +name = "cookie" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd91cf61412820176e137621345ee43b3f4423e589e7ae4e50d601d93e35ef8" +dependencies = [ + "time", "version_check", ] @@ -738,31 +846,31 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d606d0fba62e13cf04db20536c05cb7f13673c161cb47a47a82b9b9e7d3f1daa" dependencies = [ - "cookie", + "cookie 0.16.2", "idna 0.2.3", "log", "publicsuffix", "serde", "serde_derive", "serde_json", - "time 0.3.23", + "time", "url", ] [[package]] name = "cookie_store" -version = "0.19.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5a18f35792056f8c7c2de9c002e7e4fe44c7b5f66e7d99f46468dbb730a7ea7" +checksum = "387461abbc748185c3a6e1673d826918b450b87ff22639429c694619a83b6cf6" dependencies = [ - "cookie", + "cookie 0.17.0", "idna 0.3.0", "log", "publicsuffix", "serde", "serde_derive", "serde_json", - "time 0.3.23", + "time", "url", ] @@ -815,6 +923,16 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.8" @@ -842,9 +960,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.4.9" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -874,9 +992,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ "csv-core", "itoa", @@ -886,9 +1004,9 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" dependencies = [ "memchr", ] @@ -899,7 +1017,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] @@ -922,13 +1040,31 @@ dependencies = [ ] [[package]] -name = "darling" -version = "0.13.4" +name = "curve25519-dalek" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", + "cfg-if 1.0.0", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version 0.4.0", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -937,22 +1073,8 @@ version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[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 1.0.66", - "quote 1.0.31", - "strsim 0.10.0", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -963,21 +1085,10 @@ checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "strsim 0.10.0", - "syn 2.0.18", -] - -[[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 1.0.31", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -986,22 +1097,22 @@ version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core 0.20.3", - "quote 1.0.31", - "syn 2.0.18", + "darling_core", + "quote", + "syn 2.0.38", ] [[package]] name = "dashmap" -version = "5.5.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if 1.0.0", - "hashbrown 0.14.0", + "hashbrown 0.14.1", "lock_api", "once_cell", - "parking_lot_core 0.9.8", + "parking_lot_core", ] [[package]] @@ -1012,9 +1123,19 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "data-url" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5" +checksum = "41b319d1b62ffbd002e057f36bebd1f42b9f97927c9577461d855f3513c4289f" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] [[package]] name = "deno-proc-macro-rules" @@ -1023,8 +1144,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c65c2ffdafc1564565200967edc4851c7b55422d3913466688907efd05ea26f" dependencies = [ "deno-proc-macro-rules-macros", - "proc-macro2 1.0.66", - "syn 2.0.18", + "proc-macro2", + "syn 2.0.38", ] [[package]] @@ -1034,16 +1155,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3047b312b7451e3190865713a4dd6e1f821aed614ada219766ebc3024a690435" dependencies = [ "once_cell", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "deno_ast" -version = "0.27.2" +version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a39dc5554b1c835c62914b545f8b378563a997521e39a8f03450b37b216143ef" +checksum = "8a8adb6aeb787db71d015d8e9f63f6e004eeb09c86babb4ded00878be18619b1" dependencies = [ "anyhow", "base64 0.13.1", @@ -1077,25 +1198,26 @@ dependencies = [ [[package]] name = "deno_core" -version = "0.195.0" +version = "0.222.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "408e433386de30dd501cf82d26ca1fb4cd84b055536f8f6f9c78c3380649d94b" +checksum = "b13c81b9ea8462680e7b77088a44fc36390bab3dbfa5a205a285e11b64e0919c" dependencies = [ "anyhow", "bytes", "deno_ops", + "deno_unsync", "futures", - "indexmap 1.9.3", + "indexmap 2.0.2", "libc", "log", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "pin-project", "serde", "serde_json", "serde_v8", "smallvec", - "sourcemap", + "sourcemap 7.0.0", "tokio", "url", "v8", @@ -1103,9 +1225,9 @@ dependencies = [ [[package]] name = "deno_media_type" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63772a60d740a41d97fbffb4788fc3779e6df47289e01892c12be38f4a5beded" +checksum = "a798670c20308e5770cc0775de821424ff9e85665b602928509c8c70430b3ee0" dependencies = [ "data-url", "serde", @@ -1114,46 +1236,63 @@ dependencies = [ [[package]] name = "deno_ops" -version = "0.73.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d06feb9b26ccd2997f35610517d5a8f1dd423e21364509523f72474601f87f" +checksum = "bf89da1a3e50ff7c89956495b53d9bcad29e1f1b3f3d2bc54cad7155f55419c4" dependencies = [ "deno-proc-macro-rules", "lazy-regex", "once_cell", "pmutil", "proc-macro-crate", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "regex", "strum", "strum_macros", - "syn 1.0.109", - "syn 2.0.18", + "syn 2.0.38", "thiserror", - "v8", +] + +[[package]] +name = "deno_unsync" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a8f3722afd50e566ecfc783cc8a3a046bc4dd5eb45007431dfb2776aeb8993" +dependencies = [ + "tokio", ] [[package]] name = "der" -version = "0.6.1" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "pem-rfc7468", "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", - "proc-macro2 1.0.66", - "quote 1.0.31", + "convert_case 0.4.0", + "proc-macro2", + "quote", "rustc_version 0.4.0", "syn 1.0.109", ] @@ -1185,15 +1324,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs-next" version = "2.0.0" @@ -1204,17 +1334,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1240,9 +1359,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "dprint-swc-ext" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4dda8a1b920e8be367aeaad035753d21bb69b3c50515afb41ab1eefbb886b5" +checksum = "6a0a2492465344a58a37ae119de59e81fe5a2885f2711c7b5048ef0dfa14ce42" dependencies = [ "bumpalo", "num-bigint", @@ -1255,33 +1374,32 @@ dependencies = [ ] [[package]] -name = "dyn-clone" -version = "1.0.12" +name = "drain" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "2f1a0abf3fcefad9b4dd0e414207a7408e12b68414a01e6bb19b897d5bd7632d" dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature 1.6.4", + "tokio", ] [[package]] -name = "ecdsa" -version = "0.15.1" +name = "dyn-clone" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12844141594ad74185a926d030f3b605f6a903b4e3fec351f3ea338ac5b7637e" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" + +[[package]] +name = "ecdsa" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ "der", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature 2.0.0", + "spki", ] [[package]] @@ -1289,10 +1407,19 @@ name = "ed25519" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "serde", - "signature 1.6.4", + "signature 2.0.0", ] [[package]] @@ -1301,33 +1428,46 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", - "ed25519", + "curve25519-dalek 3.2.0", + "ed25519 1.5.3", "rand 0.7.3", "serde", - "serde_bytes", "sha2 0.9.9", "zeroize", ] [[package]] -name = "either" -version = "1.8.1" +name = "ed25519-dalek" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +dependencies = [ + "curve25519-dalek 4.1.1", + "ed25519 2.2.3", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "signature 2.0.0", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" dependencies = [ "serde", ] [[package]] name = "elliptic-curve" -version = "0.12.3" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" dependencies = [ "base16ct", "crypto-bigint", - "der", "digest 0.10.7", "ff", "generic-array", @@ -1348,17 +1488,17 @@ dependencies = [ "color-eyre", "futures", "helpers", - "imbl 2.0.0", - "nix 0.25.1", + "imbl", + "nix 0.27.1", "procfs", "serde", "serde_json", "tokio", "tokio-stream", "tracing", - "tracing-error 0.2.0", + "tracing-error", "tracing-futures", - "tracing-subscriber 0.3.17", + "tracing-subscriber", "yajrc 0.1.0 (git+https://github.com/dr-bonez/yajrc.git?branch=develop)", ] @@ -1382,6 +1522,12 @@ dependencies = [ "log", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -1390,29 +1536,23 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - [[package]] name = "enum-as-inner" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ - "heck 0.4.1", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "heck", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -1430,12 +1570,12 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "atty", "humantime 2.1.0", + "is-terminal", "log", "regex", "termcolor", @@ -1449,23 +1589,23 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "etcetera" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "cc", - "libc", + "cfg-if 1.0.0", + "home", + "windows-sys 0.48.0", ] [[package]] @@ -1486,12 +1626,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fd-lock-rs" @@ -1504,26 +1641,38 @@ dependencies = [ [[package]] name = "ff" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", "subtle", ] [[package]] -name = "filetime" -version = "0.2.21" +name = "fiat-crypto" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + +[[package]] +name = "filetime" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] +[[package]] +name = "finl_unicode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1532,14 +1681,25 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1581,14 +1741,14 @@ dependencies = [ [[package]] name = "from_variant" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d449976075322384507443937df2f1d5577afbf4282f12a5a66ef29fa3e6307" +checksum = "03ec5dc38ee19078d84a692b1c41181ff9f94331c76cee66ff0208c770b5e54f" dependencies = [ "pmutil", - "proc-macro2 1.0.66", + "proc-macro2", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -1651,13 +1811,13 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.11.2", + "parking_lot", ] [[package]] @@ -1672,9 +1832,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -1715,6 +1875,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1741,31 +1902,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "git-version" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" -dependencies = [ - "git-version-macro", - "proc-macro-hack", -] - -[[package]] -name = "git-version-macro" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", -] +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "glob" @@ -1779,7 +1918,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "crc", "log", "uuid", @@ -1787,9 +1926,9 @@ dependencies = [ [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", @@ -1798,9 +1937,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -1832,9 +1971,18 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" dependencies = [ "ahash 0.8.3", "allocator-api2", @@ -1842,20 +1990,24 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.1", ] [[package]] -name = "heck" -version = "0.3.3" +name = "hdrhistogram" +version = "7.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" dependencies = [ - "unicode-segmentation", + "base64 0.13.1", + "byteorder", + "flate2", + "nom 7.1.3", + "num-traits", ] [[package]] @@ -1896,9 +2048,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -1940,6 +2092,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "http" version = "0.2.9" @@ -1970,9 +2131,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -2006,13 +2167,25 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -2028,13 +2201,13 @@ dependencies = [ [[package]] name = "hyper-ws-listener" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3fb761e568fdb34ff794d284bfe1769efc5d16b9d716286451ab3a70ab82bea" +checksum = "dcbfe4981e45b0a7403a55d4af12f8d30e173e722409658c3857243990e72180" dependencies = [ "anyhow", - "base64 0.13.1", - "env_logger 0.9.3", + "base64 0.21.4", + "env_logger 0.10.0", "futures", "hyper", "log", @@ -2043,31 +2216,18 @@ dependencies = [ "tokio-tungstenite", ] -[[package]] -name = "hyperlocal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" -dependencies = [ - "futures-util", - "hex", - "hyper", - "pin-project", - "tokio", -] - [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -2133,28 +2293,15 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "imbl" -version = "1.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "543682c9082b25e63d03b5acbd65ad111fd49dd93e70843e5175db4ff81d606b" +checksum = "85b4555023847ca2cd6fd11f20b553886e6981c7e8aee9b3e7e960b4b17fb440" dependencies = [ - "bitmaps 2.1.0", - "rand_core 0.6.4", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "imbl" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2806b69cd9f4664844027b64465eacb444c67c1db9c778e341adff0c25cdb0d" -dependencies = [ - "bitmaps 3.2.0", + "bitmaps", "imbl-sized-chunks", "rand_core 0.6.4", "rand_xoshiro", + "serde", "version_check", ] @@ -2164,7 +2311,19 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" dependencies = [ - "bitmaps 3.2.0", + "bitmaps", +] + +[[package]] +name = "imbl-value" +version = "0.1.0" +source = "git+https://github.com/Start9Labs/imbl-value.git#929395141c3a882ac366c12ac9402d0ebaa2201b" +dependencies = [ + "imbl", + "serde", + "serde_json", + "treediff", + "yasi", ] [[package]] @@ -2182,8 +2341,8 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", ] [[package]] @@ -2205,12 +2364,36 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.1", + "serde", +] + +[[package]] +name = "indicatif" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "tokio", + "unicode-width", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", ] [[package]] @@ -2222,27 +2405,13 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "internment" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161079c3ad892faa215fcfcf3fd7a6a3c9288df2b06a2c2bad7fbfad4f01d69d" -dependencies = [ - "ahash 0.7.6", - "dashmap", - "hashbrown 0.12.3", - "once_cell", - "parking_lot 0.12.1", - "serde", -] - [[package]] name = "io-lifetimes" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", "windows-sys 0.48.0", ] @@ -2268,15 +2437,15 @@ dependencies = [ [[package]] name = "is-macro" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7d079e129b77477a49c5c4f1cfe9ce6c2c909ef52520693e8e811a714c7b20" +checksum = "f4467ed1321b310c2625c5aa6c1b1ffc5de4d9e42668cf697a08fb033ee8265e" dependencies = [ "Inflector", "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -2285,8 +2454,8 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", + "hermit-abi 0.3.3", + "rustix 0.38.19", "windows-sys 0.48.0", ] @@ -2318,6 +2487,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -2326,9 +2504,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jaq-core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab6f495d0fe97460255aef70fbd77d3b5a7701930163ad69c963b9c6d5d5726" +checksum = "eb52eeac20f256459e909bd4a03bb8c4fab6a1fdbb8ed52d00f644152df48ece" dependencies = [ "ahash 0.7.6", "dyn-clone", @@ -2364,12 +2542,12 @@ dependencies = [ [[package]] name = "josekit" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a96c4f2128a6f44ecf7c36df2b03dddf5a07b060a4d5ebc0a81e9821f7c60e" +checksum = "5754487a088f527b1407df470db8e654e4064dccbbe1fe850e0773721e9962b7" dependencies = [ "anyhow", - "base64 0.21.2", + "base64 0.21.4", "flate2", "once_cell", "openssl", @@ -2377,7 +2555,7 @@ dependencies = [ "serde", "serde_json", "thiserror", - "time 0.3.23", + "time", ] [[package]] @@ -2399,14 +2577,14 @@ dependencies = [ "deno_core", "embassy_container_init", "helpers", - "itertools 0.10.5", + "itertools 0.11.0", "lazy_static", "models", "pin-project", "reqwest", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "tokio", "tracing", ] @@ -2415,9 +2593,9 @@ dependencies = [ name = "json-patch" version = "0.2.7-alpha.0" dependencies = [ + "imbl-value", "json-ptr", "serde", - "serde_json", "treediff", ] @@ -2425,17 +2603,18 @@ dependencies = [ name = "json-ptr" version = "0.1.0" dependencies = [ + "imbl", + "imbl-value", "serde", - "serde_json", "thiserror", ] [[package]] name = "jsonpath_lib" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" +source = "git+https://github.com/Start9Labs/jsonpath.git#1cacbd64afa2e1941a21fef06bad14317ba92f30" dependencies = [ + "imbl-value", "log", "serde", "serde_json", @@ -2469,7 +2648,7 @@ dependencies = [ "string_cache", "term", "tiny-keccak", - "unicode-xid 0.2.4", + "unicode-xid", ] [[package]] @@ -2483,9 +2662,9 @@ dependencies = [ [[package]] name = "lazy-regex" -version = "2.5.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff63c423c68ea6814b7da9e88ce585f793c87ddd9e78f646970891769c8235d4" +checksum = "e723bd417b2df60a0f6a2b6825f297ea04b245d4ba52b5a22cb679bdf58b05fa" dependencies = [ "lazy-regex-proc_macros", "once_cell", @@ -2494,14 +2673,14 @@ dependencies = [ [[package]] name = "lazy-regex-proc_macros" -version = "2.4.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8edfc11b8f56ce85e207e62ea21557cfa09bb24a8f6b04ae181b086ff8611c22" +checksum = "0f0a1d9139f0ee2e862e08a9c5d0ba0470f2aa21cd1e1aa1b1562f83116c725f" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "regex", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -2520,7 +2699,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] [[package]] @@ -2529,84 +2708,11 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lexical" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" -dependencies = [ - "lexical-util", - "static_assertions", -] - [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" @@ -2620,9 +2726,20 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] [[package]] name = "linux-raw-sys" @@ -2632,21 +2749,15 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -2654,9 +2765,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "matchers" @@ -2673,6 +2784,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "mbrman" version = "0.5.2" @@ -2688,29 +2805,19 @@ dependencies = [ [[package]] name = "md-5" -version = "0.9.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "md-5" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ + "cfg-if 1.0.0", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -2721,6 +2828,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -2757,11 +2873,10 @@ dependencies = [ name = "models" version = "0.1.0" dependencies = [ - "bollard", + "base64 0.21.4", "color-eyre", - "ed25519-dalek", + "ed25519-dalek 2.0.0", "emver", - "internment", "ipnet", "lazy_static", "mbrman", @@ -2769,6 +2884,7 @@ dependencies = [ "patch-db", "rand 0.8.5", "regex", + "reqwest", "rpc-toolkit", "serde", "serde_json", @@ -2778,6 +2894,7 @@ dependencies = [ "tokio", "torut", "tracing", + "yasi", ] [[package]] @@ -2814,28 +2931,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.24.3" @@ -2845,23 +2940,33 @@ dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] name = "nix" -version = "0.25.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "autocfg", "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "memoffset", + "memoffset 0.7.1", "pin-utils", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "nom" version = "5.1.3" @@ -2908,9 +3013,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ "autocfg", "num-integer", @@ -2938,9 +3043,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" dependencies = [ "num-traits", ] @@ -2980,9 +3085,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", @@ -2994,36 +3099,42 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.3", "libc", ] [[package]] name = "num_enum" -version = "0.5.11" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.11" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] -name = "object" -version = "0.31.1" +name = "number_prefix" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -3042,24 +3153,24 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssh-keys" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7249a699cdeea261ac73f1bf9350777cb867324f44373aafb5a287365bf1771" +checksum = "c75a0ec2d1b302412fb503224289325fcc0e44600176864804c7211b055cfd58" dependencies = [ - "base64 0.13.1", + "base64 0.21.4", "byteorder", - "md-5 0.9.1", - "sha2 0.9.9", + "md-5", + "sha2 0.10.8", "thiserror", ] [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "cfg-if 1.0.0", "foreign-types", "libc", @@ -3074,9 +3185,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -3087,18 +3198,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.26.0+1.1.1u" +version = "300.1.5+3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37" +checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -3109,9 +3220,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "overload" @@ -3127,47 +3238,26 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "p256" -version = "0.11.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve", - "sha2 0.10.7", -] - -[[package]] -name = "p256" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c124b3cbce43bcbac68c58ec181d98ed6cc7e6d0aa7c3ba97b2563410b0e55" -dependencies = [ - "ecdsa 0.15.1", + "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "p384" -version = "0.11.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" dependencies = [ - "ecdsa 0.14.8", + "ecdsa", "elliptic-curve", - "sha2 0.10.7", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "primeorder", + "sha2 0.10.8", ] [[package]] @@ -3177,45 +3267,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.8.6" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", - "windows-targets 0.48.1", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", + "windows-targets 0.48.5", ] [[package]] @@ -3231,19 +3296,19 @@ dependencies = [ "async-trait", "fd-lock-rs", "futures", - "imbl 1.0.1", + "imbl", + "imbl-value", "json-patch", "json-ptr", "lazy_static", - "nix 0.23.2", + "nix 0.26.4", "patch-db-macro", "serde", "serde_cbor 0.11.1", - "serde_json", "thiserror", "tokio", "tracing", - "tracing-error 0.1.2", + "tracing-error", ] [[package]] @@ -3251,7 +3316,7 @@ name = "patch-db-macro" version = "0.1.0" dependencies = [ "patch-db-macro-internals", - "proc-macro2 1.0.66", + "proc-macro2", "syn 1.0.109", ] @@ -3259,9 +3324,9 @@ dependencies = [ name = "patch-db-macro-internals" version = "0.1.0" dependencies = [ - "heck 0.3.3", - "proc-macro2 1.0.66", - "quote 1.0.31", + "heck", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -3273,14 +3338,12 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ "digest 0.10.7", "hmac 0.12.1", - "password-hash", - "sha2 0.10.7", ] [[package]] @@ -3291,9 +3354,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem-rfc7468" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] @@ -3306,12 +3369,12 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap 2.0.2", ] [[package]] @@ -3344,8 +3407,8 @@ dependencies = [ "phf_generator", "phf_shared", "proc-macro-hack", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -3360,29 +3423,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -3392,21 +3455,20 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs1" -version = "0.4.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ "der", "pkcs8", "spki", - "zeroize", ] [[package]] name = "pkcs8" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", @@ -3419,16 +3481,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] -name = "pmutil" -version = "0.5.3" +name = "platforms" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "pmutil" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "proc-macro2", + "quote", + "syn 2.0.38", ] +[[package]] +name = "portable-atomic" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -3448,7 +3528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" dependencies = [ "csv", - "encode_unicode", + "encode_unicode 1.0.0", "is-terminal", "lazy_static", "term", @@ -3457,9 +3537,9 @@ dependencies = [ [[package]] name = "primeorder" -version = "0.12.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b54f7131b3dba65a2f414cf5bd25b66d4682e4608610668eae785750ba4c5b2" +checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" dependencies = [ "elliptic-curve", ] @@ -3471,7 +3551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -3482,27 +3562,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "0.4.30" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", -] - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.14.2" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" +checksum = "943ca7f9f29bab5844ecd8fdb3992c5969b6622bb9609b9502fef9b4310e3f1f" dependencies = [ "bitflags 1.3.2", "byteorder", @@ -3510,24 +3581,24 @@ dependencies = [ "flate2", "hex", "lazy_static", - "rustix 0.36.15", + "rustix 0.36.16", ] [[package]] name = "proptest" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.4.1", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax 0.7.5", "rusty-fork", "tempfile", "unarray", @@ -3535,13 +3606,45 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90b46295382dc76166cb7cf2bb4a97952464e4b7ed5a43e6cd34e1fec3349ddc" +checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "prost-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" +dependencies = [ + "prost", ] [[package]] @@ -3577,20 +3680,11 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "0.6.13" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 0.4.30", -] - -[[package]] -name = "quote" -version = "1.0.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" -dependencies = [ - "proc-macro2 1.0.66", + "proc-macro2", ] [[package]] @@ -3599,16 +3693,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - [[package]] name = "rand" version = "0.7.3" @@ -3722,6 +3806,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -3735,14 +3828,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.3", - "regex-syntax 0.7.4", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -3756,13 +3849,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", ] [[package]] @@ -3773,19 +3866,25 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bytes", - "cookie", + "cookie 0.16.2", "cookie_store 0.16.2", "encoding_rs", "futures-core", @@ -3806,6 +3905,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-socks", @@ -3821,26 +3921,24 @@ dependencies = [ [[package]] name = "reqwest_cookie_store" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06b407c05de7a0f7e4cc2a56af5e9bd6468e509124e81078ce1f8bc2ed3536bf" +checksum = "ba529055ea150e42e4eb9c11dcd380a41025ad4d594b0cb4904ef28b037e1061" dependencies = [ "bytes", - "cookie", - "cookie_store 0.19.1", + "cookie_store 0.20.0", "reqwest", "url", ] [[package]] name = "rfc6979" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "crypto-bigint", "hmac 0.12.1", - "zeroize", + "subtle", ] [[package]] @@ -3852,7 +3950,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -3897,7 +3995,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8e4b9cb00baf2d61bcd35e98d67dcb760382a3b4540df7e63b38d053c8a7b8b" dependencies = [ - "proc-macro2 1.0.66", + "proc-macro2", "rpc-toolkit-macro-internals", "syn 1.0.109", ] @@ -3908,18 +4006,19 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e2ce21b936feaecdab9c9a8e75b9dca64374ccc11951a58045ad6559b75f42" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "syn 1.0.109", ] [[package]] name = "rsa" -version = "0.7.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" dependencies = [ "byteorder", + "const-oid", "digest 0.10.7", "num-bigint-dig", "num-integer", @@ -3928,8 +4027,9 @@ dependencies = [ "pkcs1", "pkcs8", "rand_core 0.6.4", - "signature 1.6.4", - "smallvec", + "sha2 0.10.8", + "signature 2.0.0", + "spki", "subtle", "zeroize", ] @@ -3946,14 +4046,13 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" +checksum = "1e71971821b3ae0e769e4a4328dbcb517607b434db7697e9aba17203ec14e46a" dependencies = [ - "base64 0.13.1", + "base64 0.21.4", "blake2b_simd", - "constant_time_eq 0.1.5", - "crossbeam-utils", + "constant_time_eq", ] [[package]] @@ -3983,14 +4082,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.18", + "semver 1.0.20", ] [[package]] name = "rustix" -version = "0.36.15" +version = "0.36.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" +checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab" dependencies = [ "bitflags 1.3.2", "errno", @@ -4002,41 +4101,27 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.38.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" -dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys 0.4.10", "windows-sys 0.48.0", ] [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -4045,7 +4130,17 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +dependencies = [ + "ring", + "untrusted", ] [[package]] @@ -4105,9 +4200,9 @@ dependencies = [ [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", @@ -4119,9 +4214,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -4132,9 +4227,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -4151,9 +4246,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "semver-parser" @@ -4163,9 +4258,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] @@ -4181,9 +4276,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.10" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c5113243e4a3a1c96587342d067f3e6b0f50790b6cf40d2868eb647a3eef0e" +checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" dependencies = [ "serde", ] @@ -4208,27 +4303,36 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "itoa", "ryu", "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4243,9 +4347,9 @@ dependencies = [ [[package]] name = "serde_v8" -version = "0.106.0" +version = "0.131.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1506733ba5b864018c44320fa3bb11dbb4bf01b62dd09eda007be73034371c51" +checksum = "38cafa16d0a4288d75925351bb54d06d2e830118ad3fad393947bb11f91b18f3" dependencies = [ "bytes", "derive_more", @@ -4259,61 +4363,40 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "serde", - "serde_with_macros 1.5.2", -] - -[[package]] -name = "serde_with" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "base64 0.13.1", + "base64 0.21.4", "chrono", "hex", "indexmap 1.9.3", + "indexmap 2.0.2", "serde", "serde_json", - "serde_with_macros 2.3.3", - "time 0.3.23", + "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ - "darling 0.13.4", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", -] - -[[package]] -name = "serde_with_macros" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" -dependencies = [ - "darling 0.20.3", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "darling", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "serde_yaml" -version = "0.9.23" +version = "0.9.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da6075b41c7e3b079e5f246eb6094a44850d3a4c25a67c581c80796c80134012" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", "itoa", "ryu", "serde", @@ -4333,9 +4416,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4357,9 +4440,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4380,9 +4463,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -4407,10 +4490,6 @@ name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] [[package]] name = "signature" @@ -4435,34 +4514,24 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps 2.1.0", - "typenum", -] +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "smartstring" @@ -4486,12 +4555,39 @@ dependencies = [ ] [[package]] -name = "sourcemap" -version = "6.2.3" +name = "socket2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed16231c92d0a6f0388f56e0ab2be24ecff1173f8e22f0ea5e074d0525631cb" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "sourcemap" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4cbf65ca7dc576cf50e21f8d0712d96d4fcfd797389744b7b222a85cdf5bd90" dependencies = [ "data-encoding", + "debugid", + "if_chain", + "rustc_version 0.2.3", + "serde", + "serde_json", + "unicode-id", + "url", +] + +[[package]] +name = "sourcemap" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbecc42a2b6131acc3bf9a25c9fe4161dba438eb52131bba83c5d781b5b70be3" +dependencies = [ + "data-encoding", + "debugid", "if_chain", "rustc_version 0.2.3", "serde", @@ -4507,10 +4603,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "spki" -version = "0.6.0" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", "der", @@ -4518,138 +4623,282 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" +checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85" dependencies = [ - "itertools 0.10.5", + "itertools 0.11.0", "nom 7.1.3", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.6.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33" dependencies = [ "sqlx-core", "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", ] [[package]] name = "sqlx-core" -version = "0.6.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d" dependencies = [ - "ahash 0.7.6", + "ahash 0.8.3", "atoi", - "base64 0.13.1", - "bitflags 1.3.2", "byteorder", "bytes", "chrono", "crc", "crossbeam-queue", - "dirs", "dotenvy", "either", "event-listener", "futures-channel", "futures-core", "futures-intrusive", + "futures-io", "futures-util", "hashlink", "hex", - "hkdf", - "hmac 0.12.1", - "indexmap 1.9.3", - "itoa", - "libc", + "indexmap 2.0.2", "log", - "md-5 0.10.5", "memchr", "once_cell", "paste", "percent-encoding", - "rand 0.8.5", "rustls", "rustls-pemfile", "serde", "serde_json", - "sha1", - "sha2 0.10.7", + "sha2 0.10.8", "smallvec", "sqlformat", - "sqlx-rt", - "stringprep", "thiserror", + "tokio", "tokio-stream", + "tracing", "url", "webpki-roots", - "whoami", ] [[package]] name = "sqlx-macros" -version = "0.6.3" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc" dependencies = [ "dotenvy", "either", - "heck 0.4.1", + "heck", "hex", "once_cell", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.8", "sqlx-core", - "sqlx-rt", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", "syn 1.0.109", + "tempfile", + "tokio", "url", ] [[package]] -name = "sqlx-rt" -version = "0.6.3" +name = "sqlx-mysql" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" +checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db" dependencies = [ + "atoi", + "base64 0.21.4", + "bitflags 2.4.1", + "byteorder", + "bytes", + "chrono", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac 0.12.1", + "itoa", + "log", + "md-5", + "memchr", "once_cell", - "tokio", - "tokio-rustls", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624" +dependencies = [ + "atoi", + "base64 0.21.4", + "bitflags 2.4.1", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac 0.12.1", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", +] + +[[package]] +name = "sscanf" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c713ebd15ce561dd4a13ed62bc2a0368e16806fc30dcaf66ecf1256b2a3fdde6" +dependencies = [ + "const_format", + "lazy_static", + "regex", + "sscanf_macro", +] + +[[package]] +name = "sscanf_macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84955aa74a157e5834d58a07be11af7f0ab923f0194a0bb2ea6b3db8b5d1611d" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "regex-syntax 0.6.29", + "strsim 0.10.0", + "syn 2.0.38", + "unicode-width", +] + +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher 0.4.4", + "ssh-encoding", ] [[package]] name = "ssh-encoding" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19cfdc32e0199062113edf41f344fbf784b8205a94600233c84eb838f45191e1" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" dependencies = [ "base64ct", "pem-rfc7468", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] name = "ssh-key" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288d8f5562af5a3be4bda308dd374b2c807b940ac370b5efa1c99311da91d9a1" +checksum = "2180b3bc4955efd5661a97658d3cf4c8107e0d132f619195afe9486c13cca313" dependencies = [ - "ed25519-dalek", - "p256 0.11.1", + "ed25519-dalek 2.0.0", + "p256", "p384", "rand_core 0.6.4", "rsa", "sec1", - "sha2 0.10.7", - "signature 1.6.4", + "sha2 0.10.8", + "signature 2.0.0", + "ssh-cipher", "ssh-encoding", + "subtle", "zeroize", ] @@ -4674,7 +4923,7 @@ dependencies = [ [[package]] name = "start-os" -version = "0.3.4-rev.4" +version = "0.3.5" dependencies = [ "aes", "async-compression", @@ -4682,29 +4931,29 @@ dependencies = [ "async-trait", "avahi-sys", "base32", - "base64 0.13.1", + "base64 0.21.4", "base64ct", "basic-cookies", "bimap", - "bollard", "bytes", "chrono", "ciborium", "clap 3.2.25", "color-eyre", - "cookie", - "cookie_store 0.19.1", + "console", + "console-subscriber", + "cookie 0.18.0", + "cookie_store 0.20.0", "current_platform", "digest 0.10.7", - "digest 0.9.0", "divrem", - "ed25519", - "ed25519-dalek", + "ed25519 2.2.3", + "ed25519-dalek 1.0.1", + "ed25519-dalek 2.0.0", "embassy_container_init", "emver", "fd-lock-rs", "futures", - "git-version", "gpt", "helpers", "hex", @@ -4713,13 +4962,15 @@ dependencies = [ "hyper", "hyper-ws-listener", "id-pool", - "imbl 2.0.0", + "imbl", + "imbl-value", "include_dir", - "indexmap 1.9.3", + "indexmap 2.0.2", + "indicatif", "ipnet", "iprange", "isocountry", - "itertools 0.10.5", + "itertools 0.11.0", "jaq-core", "jaq-std", "josekit", @@ -4731,13 +4982,13 @@ dependencies = [ "mbrman", "models", "new_mime_guess", - "nix 0.25.1", + "nix 0.27.1", "nom 7.1.3", "num", "num_enum", "openssh-keys", "openssl", - "p256 0.12.0", + "p256", "patch-db", "pbkdf2", "pin-project", @@ -4745,7 +4996,6 @@ dependencies = [ "prettytable-rs", "proptest", "proptest-derive", - "rand 0.7.3", "rand 0.8.5", "regex", "reqwest", @@ -4756,12 +5006,12 @@ dependencies = [ "scopeguard", "serde", "serde_json", - "serde_with 2.3.3", + "serde_with", "serde_yaml", - "sha2 0.10.7", - "sha2 0.9.9", + "sha2 0.10.8", "simple-logging", "sqlx", + "sscanf", "ssh-key", "stderrlog", "tar", @@ -4773,12 +5023,13 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml", + "toml 0.8.2", "torut", "tracing", - "tracing-error 0.2.0", + "tracing-error", "tracing-futures", - "tracing-subscriber 0.3.17", + "tracing-journald", + "tracing-subscriber", "trust-dns-server", "typed-builder", "url", @@ -4814,7 +5065,7 @@ checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "phf_shared", "precomputed-hash", "serde", @@ -4828,29 +5079,30 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" dependencies = [ "phf_generator", "phf_shared", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", ] [[package]] name = "string_enum" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0090512bdfee4b56d82480d66c0fd8a6f53f0fe0f97e075e949b252acdd482e0" +checksum = "8fa4d4f81d7c05b9161f8de839975d3326328b8ba2831164b465524cc2f55252" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "stringprep" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3737bde7edce97102e0e2b15365bf7a20bfdb5f60f4f9e8d7004258a51a8da" +checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" dependencies = [ + "finl_unicode", "unicode-bidi", "unicode-normalization", ] @@ -4869,24 +5121,24 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck 0.4.1", - "proc-macro2 1.0.66", - "quote 1.0.31", + "heck", + "proc-macro2", + "quote", "rustversion", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -4897,9 +5149,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "swc_atoms" -version = "0.5.6" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d0307dc4bfd107d49c7528350c372758cfca94fb503629b9a056e6a1572860" +checksum = "9f54563d7dcba626d4acfe14ed12def7ecc28e004debe3ecd2c3ee07cc47e449" dependencies = [ "once_cell", "rustc-hash", @@ -4911,11 +5163,10 @@ dependencies = [ [[package]] name = "swc_common" -version = "0.31.12" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c774005489d2907fb67909cf42af926e72edee1366512777c605ba2ef19c94" +checksum = "39cb7fcd56655c8ae7dcf2344f0be6cbff4d9c7cb401fe3ec8e56e1de8dfe582" dependencies = [ - "ahash 0.7.6", "ast_node", "better_scoped_tls", "cfg-if 1.0.0", @@ -4927,7 +5178,7 @@ dependencies = [ "rustc-hash", "serde", "siphasher", - "sourcemap", + "sourcemap 6.4.1", "string_cache", "swc_atoms", "swc_eq_ignore_macros", @@ -4939,9 +5190,9 @@ dependencies = [ [[package]] name = "swc_config" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c8fc2c12bb1634c7c32fc3c9b6b963ad8f034cc62c4ecddcf215dc4f6f959d" +checksum = "9ba1c7a40d38f9dd4e9a046975d3faf95af42937b34b2b963be4d8f01239584b" dependencies = [ "indexmap 1.9.3", "serde", @@ -4951,24 +5202,24 @@ dependencies = [ [[package]] name = "swc_config_macro" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dadb9998d4f5fc36ef558ed5a092579441579ee8c6fcce84a5228cca9df4004" +checksum = "e5b5aaca9a0082be4515f0fbbecc191bf5829cd25b5b9c0a2810f6a2bb0d6829" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "swc_ecma_ast" -version = "0.104.5" +version = "0.109.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5cf9dd351d0c285dcd36535267953a18995d4dda0cbe34ac9d1df61aa415b26" +checksum = "7bc2286cedd688a68f214faa1c19bb5cceab7c9c54d0cbe3273e4c1704e38f69" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "is-macro", "num-bigint", "scoped-tls", @@ -4981,16 +5232,16 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "0.139.17" +version = "0.144.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d1ea16bb9b7ea6f87f17325742ff256fcbd65b188af57c2bf415fe4afc945" +checksum = "8e62ba2c0ed1f119fc1a76542d007f1b2c12854d54dea15f5491363227debe11" dependencies = [ "memchr", "num-bigint", "once_cell", "rustc-hash", "serde", - "sourcemap", + "sourcemap 6.4.1", "swc_atoms", "swc_common", "swc_ecma_ast", @@ -5000,24 +5251,23 @@ dependencies = [ [[package]] name = "swc_ecma_codegen_macros" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ee0caee1018808d94ecd09490cb7affd3d504b19aa11c49238f5fc4b54901" +checksum = "dcdff076dccca6cc6a0e0b2a2c8acfb066014382bc6df98ec99e755484814384" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "swc_ecma_loader" -version = "0.43.14" +version = "0.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe45f1e5dcc1b005544ff78253b787dea5dfd5e2f712b133964cdc3545c954a4" +checksum = "e7d7c322462657ae27ac090a2c89f7e456c94416284a2f5ecf66c43a6a3c19d1" dependencies = [ - "ahash 0.7.6", "anyhow", "pathdiff", "serde", @@ -5027,13 +5277,13 @@ dependencies = [ [[package]] name = "swc_ecma_parser" -version = "0.134.12" +version = "0.139.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a3fcfe3d83dd445cbd9321882e47b467594433d9a21c4d6c37a27f534bb89e" +checksum = "3eab46cb863bc5cd61535464e07e5b74d5f792fa26a27b9f6fd4c8daca9903b7" dependencies = [ "either", - "lexical", "num-bigint", + "num-traits", "serde", "smallvec", "smartstring", @@ -5047,12 +5297,12 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_base" -version = "0.127.18" +version = "0.132.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c33ec5369178f3a0580ab86cfe89ffb9c3fbd122aed379cfb71d469d9d61c1" +checksum = "01ffd4a8149052bfc1ec1832fcbe04f317846ce635a49ec438df33b06db27d26" dependencies = [ "better_scoped_tls", - "bitflags 2.3.3", + "bitflags 2.4.1", "indexmap 1.9.3", "once_cell", "phf", @@ -5070,9 +5320,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_classes" -version = "0.116.18" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3b0d5f362f0da97be1f1b06d7b0d8667ea70b4adeabff0dcaecb6259c09525" +checksum = "f4b7fee0e2c6f12456d2aefb2418f2f26529b995945d493e1dce35a5a22584fc" dependencies = [ "swc_atoms", "swc_common", @@ -5084,22 +5334,22 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_macros" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "984d5ac69b681fc5438f9abf82b0fda34fe04e119bc75f8213b7e01128c7c9a2" +checksum = "8188eab297da773836ef5cf2af03ee5cca7a563e1be4b146f8141452c28cc690" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "swc_macros_common", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "swc_ecma_transforms_proposal" -version = "0.161.22" +version = "0.166.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cdce42d44ef775bc29f5ada3678a80ff72fa17a0ef705e14f63cfd0e0155e0e" +checksum = "122fd9a69f464694edefbf9c59106b3c15e5cc8cb8575a97836e4fb79018e98f" dependencies = [ "either", "rustc-hash", @@ -5117,11 +5367,10 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "0.173.20" +version = "0.178.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb9481ad4e2acba34c6fbb6d4ccc64efe9f1821675e883dcfa732d7220f4b1e" +checksum = "675b5c755b0448268830e85e59429095d3423c0ce4a850b209c6f0eeab069f63" dependencies = [ - "ahash 0.7.6", "base64 0.13.1", "dashmap", "indexmap 1.9.3", @@ -5142,9 +5391,9 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_typescript" -version = "0.177.23" +version = "0.182.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe2eea4f5b8a25c93cdaa29fb1ce4108893da88a11e61e04b7f5295b5468829" +checksum = "4eba97b1ea71739fcf278aedad4677a3cacb52288a3f3566191b70d16a889de6" dependencies = [ "serde", "swc_atoms", @@ -5158,9 +5407,9 @@ dependencies = [ [[package]] name = "swc_ecma_utils" -version = "0.117.13" +version = "0.122.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad791bbfdafcebd878584021e050964c8ab68aba7eeac9d0ee4afba4c284a629" +checksum = "11006a3398ffd4693c4d3b0a1b1a5030edbdc04228159f5301120a6178144708" dependencies = [ "indexmap 1.9.3", "num_cpus", @@ -5176,9 +5425,9 @@ dependencies = [ [[package]] name = "swc_ecma_visit" -version = "0.90.5" +version = "0.95.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce3ac941ae1d6c7e683aa375fc71fbf58df58b441f614d757fbb10554936ca2" +checksum = "0f628ec196e76e67892441e14eef2e423a738543d32bffdabfeec20c29582117" dependencies = [ "num-bigint", "swc_atoms", @@ -5190,33 +5439,33 @@ dependencies = [ [[package]] name = "swc_eq_ignore_macros" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c20468634668c2bbab581947bb8c75c97158d5a6959f4ba33df20983b20b4f6" +checksum = "05a95d367e228d52484c53336991fdcf47b6b553ef835d9159db4ba40efb0ee8" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "swc_macros_common" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e582c3e3c2269238524923781df5be49e011dbe29cf7683a2215d600a562ea6" +checksum = "7a273205ccb09b51fabe88c49f3b34c5a4631c4c00a16ae20e03111d6a42e832" dependencies = [ "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "swc_visit" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f412dd4fbc58f509a04e64f5c8038333142fc139e8232f01b883db0094b3b51" +checksum = "e87c337fbb2d191bf371173dea6a957f01899adb8f189c6c31b122a6cfc98fc3" dependencies = [ "either", "swc_visit_macros", @@ -5224,27 +5473,16 @@ dependencies = [ [[package]] name = "swc_visit_macros" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cfc226380ba54a5feed2c12f3ccd33f1ae8e959160290e5d2d9b4e918b6472a" +checksum = "0f322730fb82f3930a450ac24de8c98523af7d34ab8cb2f46bcb405839891a99" dependencies = [ "Inflector", "pmutil", - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "swc_macros_common", - "syn 1.0.109", -] - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", + "syn 2.0.38", ] [[package]] @@ -5253,22 +5491,49 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.18" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", + "proc-macro2", + "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -5277,26 +5542,25 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", - "xattr", + "xattr 1.0.1", ] [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "autocfg", "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.23", + "rustix 0.38.19", "windows-sys 0.48.0", ] @@ -5346,22 +5610,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -5387,22 +5651,13 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ + "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -5410,15 +5665,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -5449,33 +5704,43 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.4", "tokio-macros", + "tracing", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] @@ -5490,13 +5755,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] @@ -5534,14 +5798,14 @@ dependencies = [ "redox_syscall 0.2.16", "tokio", "tokio-stream", - "xattr", + "xattr 0.2.3", ] [[package]] name = "tokio-tungstenite" -version = "0.17.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", @@ -5553,9 +5817,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", @@ -5567,11 +5831,26 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", ] [[package]] @@ -5579,18 +5858,63 @@ name = "toml_datetime" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", + "serde", + "serde_spanned", "toml_datetime", "winnow", ] +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.4", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "torut" version = "0.2.1" @@ -5600,7 +5924,7 @@ dependencies = [ "base32", "base64 0.13.1", "derive_more", - "ed25519-dalek", + "ed25519-dalek 1.0.1", "hex", "hmac 0.11.0", "rand 0.7.3", @@ -5611,6 +5935,32 @@ dependencies = [ "tokio", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -5619,11 +5969,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" dependencies = [ - "cfg-if 1.0.0", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5631,35 +5981,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-error" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" -dependencies = [ - "tracing", - "tracing-subscriber 0.2.25", -] - [[package]] name = "tracing-error" version = "0.2.0" @@ -5667,7 +6007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" dependencies = [ "tracing", - "tracing-subscriber 0.3.17", + "tracing-subscriber", ] [[package]] @@ -5680,6 +6020,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-journald" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd" +dependencies = [ + "libc", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.1.3" @@ -5691,17 +6042,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-subscriber" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" -dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", -] - [[package]] name = "tracing-subscriber" version = "0.3.17" @@ -5739,31 +6079,11 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "trust-dns-client" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c408c32e6a9dbb38037cece35740f2cf23c875d8ca134d33631cec83f74d3fe" -dependencies = [ - "cfg-if 1.0.0", - "data-encoding", - "futures-channel", - "futures-util", - "lazy_static", - "radix_trie", - "rand 0.8.5", - "thiserror", - "time 0.3.23", - "tokio", - "tracing", - "trust-dns-proto", -] - [[package]] name = "trust-dns-proto" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" +checksum = "559ac980345f7f5020883dd3bcacf176355225e01916f8c2efecad7534f682c6" dependencies = [ "async-trait", "cfg-if 1.0.0", @@ -5772,9 +6092,9 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna 0.2.3", + "idna 0.4.0", "ipnet", - "lazy_static", + "once_cell", "rand 0.8.5", "smallvec", "thiserror", @@ -5786,23 +6106,23 @@ dependencies = [ [[package]] name = "trust-dns-server" -version = "0.22.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99022f9befa6daec2a860be68ac28b1f0d9d7ccf441d8c5a695e35a58d88840d" +checksum = "f4307166910ddf09378e651e9d4730c44900e9e0e1f157a6b955e48b539cd1d6" dependencies = [ "async-trait", "bytes", "cfg-if 1.0.0", + "drain", "enum-as-inner", "futures-executor", "futures-util", "serde", "thiserror", - "time 0.3.23", + "time", "tokio", - "toml", + "toml 0.7.8", "tracing", - "trust-dns-client", "trust-dns-proto", ] @@ -5814,19 +6134,19 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" -version = "0.17.3" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", "native-tls", "rand 0.8.5", - "sha-1", + "sha1", "thiserror", "url", "utf-8", @@ -5840,20 +6160,29 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typed-builder" -version = "0.10.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" +checksum = "b1c6a006a6d3d6a6f143fda41cf4d1ad35110080687628c9f2117bd3cc7924f3" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 1.0.109", + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fa054ee5e2346187d631d2f1d1fd3b33676772d6d03a2d84e1c5213b31674ee" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", ] [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unarray" @@ -5863,9 +6192,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -5878,15 +6207,15 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-id" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -5905,15 +6234,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -5941,9 +6264,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna 0.4.0", @@ -5953,9 +6276,9 @@ dependencies = [ [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf-8" @@ -5965,23 +6288,23 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom 0.2.10", ] [[package]] name = "v8" -version = "0.74.2" +version = "0.79.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7568bf38565bd5b350d96abbf3d09417e8c9dd74fbb38860e91b759e46f9009c" +checksum = "b15561535230812a1db89a696f1f16a12ae6c2c370c6b2241c68d4cb33963faf" dependencies = [ "bitflags 1.3.2", "fslock", "once_cell", - "which 4.4.0", + "which 4.4.2", ] [[package]] @@ -6032,12 +6355,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -6063,9 +6380,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -6087,7 +6404,7 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "quote 1.0.31", + "quote", "wasm-bindgen-macro-support", ] @@ -6097,9 +6414,9 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6112,9 +6429,9 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-streams" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" dependencies = [ "futures-util", "js-sys", @@ -6133,23 +6450,13 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" -version = "0.22.6" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" dependencies = [ - "webpki", + "rustls-webpki", ] [[package]] @@ -6163,13 +6470,14 @@ dependencies = [ [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix 0.38.19", ] [[package]] @@ -6177,10 +6485,6 @@ name = "whoami" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" -dependencies = [ - "wasm-bindgen", - "web-sys", -] [[package]] name = "winapi" @@ -6200,9 +6504,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -6214,12 +6518,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -6237,7 +6541,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -6257,17 +6561,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -6278,9 +6582,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -6290,9 +6594,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -6302,9 +6606,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -6314,9 +6618,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -6326,9 +6630,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -6338,9 +6642,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -6350,26 +6654,27 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.0" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] [[package]] @@ -6390,6 +6695,15 @@ dependencies = [ "libc", ] +[[package]] +name = "xattr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +dependencies = [ + "libc", +] + [[package]] name = "yajrc" version = "0.1.0" @@ -6413,6 +6727,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "yasi" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f355ab62ebe30b758c1f4ab096a306722c4b7dbfb9d8c07d18c70d71a945588" +dependencies = [ + "ahash 0.8.3", + "hashbrown 0.13.2", + "lazy_static", + "serde", +] + [[package]] name = "zeroize" version = "1.6.0" @@ -6428,7 +6754,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.66", - "quote 1.0.31", - "syn 2.0.18", + "proc-macro2", + "quote", + "syn 2.0.38", ] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 6c6c706f9..77da1b5a3 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -14,7 +14,8 @@ keywords = [ name = "start-os" readme = "README.md" repository = "https://github.com/Start9Labs/start-os" -version = "0.3.4-rev.4" +version = "0.3.5" +license = "MIT" [lib] name = "startos" @@ -26,142 +27,149 @@ path = "src/main.rs" [features] avahi = ["avahi-sys"] -default = ["avahi-alias", "cli", "sdk", "daemon", "js_engine"] -dev = [] -unstable = ["patch-db/unstable"] avahi-alias = ["avahi"] cli = [] -sdk = [] daemon = [] +default = ["cli", "sdk", "daemon", "js_engine"] +dev = [] +docker = [] +sdk = [] +unstable = ["console-subscriber", "tokio/tracing"] [dependencies] aes = { version = "0.7.5", features = ["ctr"] } -async-compression = { version = "0.3.15", features = [ +async-compression = { version = "0.4.4", features = [ "gzip", "brotli", "tokio", ] } -async-stream = "0.3.3" -async-trait = "0.1.56" +async-stream = "0.3.5" +async-trait = "0.1.74" avahi-sys = { git = "https://github.com/Start9Labs/avahi-sys", version = "0.10.0", branch = "feature/dynamic-linking", features = [ "dynamic", ], optional = true } base32 = "0.4.0" -base64 = "0.13.0" -base64ct = "1.5.1" +base64 = "0.21.4" +base64ct = "1.6.0" basic-cookies = "0.1.4" bimap = { version = "0.6.2", features = ["serde"] } -bollard = "0.13.0" bytes = "1" -chrono = { version = "0.4.19", features = ["serde"] } -clap = "3.2.8" -color-eyre = "0.6.1" -cookie = "0.16.2" -cookie_store = "0.19.0" +chrono = { version = "0.4.31", features = ["serde"] } +clap = "3.2.25" +color-eyre = "0.6.2" +console = "0.15.7" +console-subscriber = { version = "0.2", optional = true } +cookie = "0.18.0" +cookie_store = "0.20.0" current_platform = "0.2.0" -digest = "0.10.3" -digest-old = { package = "digest", version = "0.9.0" } +digest = "0.10.7" divrem = "1.0.0" -ed25519 = { version = "1.5.2", features = ["pkcs8", "pem", "alloc"] } -ed25519-dalek = { version = "1.0.1", features = ["serde"] } +ed25519 = { version = "2.2.3", features = ["pkcs8", "pem", "alloc"] } +ed25519-dalek = { version = "2.0.0", features = [ + "serde", + "zeroize", + "rand_core", + "digest", +] } +ed25519-dalek-v1 = { package = "ed25519-dalek", version = "1" } +embassy_container_init = { path = "../libs/embassy_container_init" } emver = { version = "0.1.7", git = "https://github.com/Start9Labs/emver-rs.git", features = [ "serde", ] } fd-lock-rs = "0.1.4" -futures = "0.3.21" -git-version = "0.3.5" -gpt = "3.0.0" +futures = "0.3.28" +gpt = "3.1.0" helpers = { path = "../libs/helpers" } -embassy_container_init = { path = "../libs/embassy_container_init" } hex = "0.4.3" hmac = "0.12.1" -http = "0.2.8" -hyper = { version = "0.14.20", features = ["full"] } -hyper-ws-listener = "0.2.0" +http = "0.2.9" +hyper = { version = "0.14.27", features = ["full"] } +hyper-ws-listener = "0.3.0" id-pool = { version = "0.2.2", features = [ "u16", "serde", ], default-features = false } -imbl = "2.0.0" +imbl = "2.0.2" +imbl-value = { git = "https://github.com/Start9Labs/imbl-value.git" } include_dir = "0.7.3" -indexmap = { version = "1.9.1", features = ["serde"] } -ipnet = { version = "2.7.1", features = ["serde"] } +indexmap = { version = "2.0.2", features = ["serde"] } +indicatif = { version = "0.17.7", features = ["tokio"] } +ipnet = { version = "2.8.0", features = ["serde"] } iprange = { version = "0.6.7", features = ["serde"] } isocountry = "0.3.2" -itertools = "0.10.3" -jaq-core = "0.10.0" +itertools = "0.11.0" +jaq-core = "0.10.1" jaq-std = "0.10.0" -josekit = "0.8.1" +josekit = "0.8.4" js_engine = { path = '../libs/js_engine', optional = true } -jsonpath_lib = "0.3.0" +jsonpath_lib = { git = "https://github.com/Start9Labs/jsonpath.git" } lazy_static = "1.4.0" -libc = "0.2.126" -log = "0.4.17" -mbrman = "0.5.0" +libc = "0.2.149" +log = "0.4.20" +mbrman = "0.5.2" models = { version = "*", path = "../libs/models" } new_mime_guess = "4" -nix = "0.25.0" -nom = "7.1.1" -num = "0.4.0" -num_enum = "0.5.7" -openssh-keys = "0.5.0" -openssl = { version = "0.10.41", features = ["vendored"] } +nix = { version = "0.27.1", features = ["user", "process", "signal", "fs"] } +nom = "7.1.3" +num = "0.4.1" +num_enum = "0.7.0" +openssh-keys = "0.6.2" +openssl = { version = "0.10.57", features = ["vendored"] } +p256 = { version = "0.13.2", features = ["pem"] } patch-db = { version = "*", path = "../patch-db/patch-db", features = [ "trace", ] } -p256 = { version = "0.12.0", features = ["pem"] } -pbkdf2 = "0.11.0" -pin-project = "1.0.11" -pkcs8 = { version = "0.9.0", features = ["std"] } +pbkdf2 = "0.12.2" +pin-project = "1.1.3" +pkcs8 = { version = "0.10.2", features = ["std"] } prettytable-rs = "0.10.0" -proptest = "1.0.0" -proptest-derive = "0.3.0" +proptest = "1.3.1" +proptest-derive = "0.4.0" rand = { version = "0.8.5", features = ["std"] } -rand-old = { package = "rand", version = "0.7.3" } -regex = "1.6.0" -reqwest = { version = "0.11.11", features = ["stream", "json", "socks"] } -reqwest_cookie_store = "0.5.0" -rpassword = "7.0.0" +regex = "1.10.2" +reqwest = { version = "0.11.22", features = ["stream", "json", "socks"] } +reqwest_cookie_store = "0.6.0" +rpassword = "7.2.0" rpc-toolkit = "0.2.2" -rust-argon2 = "1.0.0" +rust-argon2 = "2.0.0" scopeguard = "1.1" # because avahi-sys fucks your shit up -serde = { version = "1.0.139", features = ["derive", "rc"] } -serde_cbor = { package = "ciborium", version = "0.2.0" } -serde_json = "1.0.93" -serde_toml = { package = "toml", version = "0.5.9" } -serde_with = { version = "2.0.1", features = ["macros", "json"] } -serde_yaml = "0.9.11" +serde = { version = "1.0", features = ["derive", "rc"] } +serde_cbor = { package = "ciborium", version = "0.2.1" } +serde_json = "1.0" +serde_toml = { package = "toml", version = "0.8.2" } +serde_with = { version = "3.4.0", features = ["macros", "json"] } +serde_yaml = "0.9.25" sha2 = "0.10.2" -sha2-old = { package = "sha2", version = "0.9.9" } simple-logging = "2.0.2" -sqlx = { version = "0.6.0", features = [ +sqlx = { version = "0.7.2", features = [ "chrono", - "offline", "runtime-tokio-rustls", "postgres", ] } -ssh-key = { version = "0.5.1", features = ["ed25519"] } -stderrlog = "0.5.3" -tar = "0.4.38" -thiserror = "1.0.31" -tokio = { version = "1.23", features = ["full"] } -tokio-stream = { version = "0.1.11", features = ["io-util", "sync", "net"] } -tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" } -tokio-tungstenite = { version = "0.17.1", features = ["native-tls"] } -tokio-rustls = "0.23.4" +sscanf = "0.4.1" +ssh-key = { version = "0.6.2", features = ["ed25519"] } +stderrlog = "0.5.4" +tar = "0.4.40" +thiserror = "1.0.49" +tokio = { version = "1", features = ["full"] } +tokio-rustls = "0.24.1" tokio-socks = "0.5.1" -tokio-util = { version = "0.7.3", features = ["io"] } +tokio-stream = { version = "0.1.14", features = ["io-util", "sync", "net"] } +tokio-tar = { git = "https://github.com/dr-bonez/tokio-tar.git" } +tokio-tungstenite = { version = "0.20.1", features = ["native-tls"] } +tokio-util = { version = "0.7.9", features = ["io"] } torut = "0.2.1" -tracing = "0.1.35" +tracing = "0.1.39" tracing-error = "0.2.0" tracing-futures = "0.2.5" -tracing-subscriber = { version = "0.3.14", features = ["env-filter"] } -trust-dns-server = "0.22.0" -typed-builder = "0.10.0" -url = { version = "2.2.2", features = ["serde"] } -urlencoding = "2.1.2" -uuid = { version = "1.1.2", features = ["v4"] } -zeroize = "1.5.7" +tracing-journald = "0.3.0" +tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } +trust-dns-server = "0.23.1" +typed-builder = "0.17.0" +url = { version = "2.4.1", features = ["serde"] } +urlencoding = "2.1.3" +uuid = { version = "1.4.1", features = ["v4"] } +zeroize = "1.6.0" [profile.test] opt-level = 3 diff --git a/backend/README.md b/backend/README.md index 986972efd..01d0b2a4d 100644 --- a/backend/README.md +++ b/backend/README.md @@ -5,6 +5,7 @@ - Recommended: [rust-analyzer](https://rust-analyzer.github.io/) - [Docker](https://docs.docker.com/get-docker/) - [Rust ARM64 Build Container](https://github.com/Start9Labs/rust-arm-builder) + - Mac `brew install gnu-tar` - Scripts (run within the `./backend` directory) - `build-prod.sh` - compiles a release build of the artifacts for running on ARM64 @@ -12,7 +13,7 @@ ## Structure -The StartOS backend is packed into a single binary `startbox` that is symlinked under +The StartOS backend is packed into a single binary `startbox` that is symlinked under several different names for different behaviour: - startd: This is the main workhorse of StartOS - any new functionality you diff --git a/backend/build-prod.sh b/backend/build-prod.sh index db2331eb4..d6c64eec2 100755 --- a/backend/build-prod.sh +++ b/backend/build-prod.sh @@ -3,11 +3,6 @@ set -e shopt -s expand_aliases -if [ -z "$OS_ARCH" ]; then - >&2 echo '$OS_ARCH is required' - exit 1 -fi - if [ -z "$ARCH" ]; then ARCH=$(uname -m) fi @@ -22,46 +17,28 @@ if tty -s; then USE_TTY="-it" fi -alias 'rust-gnu-builder'='docker run $USE_TTY --rm -e "OS_ARCH=$OS_ARCH" -v "$HOME/.cargo/registry":/usr/local/cargo/registry -v "$(pwd)":/home/rust/src -w /home/rust/src -P start9/rust-arm-cross:aarch64' -alias 'rust-musl-builder'='docker run $USE_TTY --rm -e "OS_ARCH=$OS_ARCH" -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src -P messense/rust-musl-cross:$ARCH-musl' - cd .. -FLAGS="" -if [[ "$ENVIRONMENT" =~ (^|-)unstable($|-) ]]; then - FLAGS="unstable,$FLAGS" -fi -if [[ "$ENVIRONMENT" =~ (^|-)dev($|-) ]]; then - FLAGS="dev,$FLAGS" -fi +FEATURES="$(echo $ENVIRONMENT | sed 's/-/,/g')" +RUSTFLAGS="" + +alias 'rust-gnu-builder'='docker run $USE_TTY --rm -e "RUSTFLAGS=$RUSTFLAGS" -v "$HOME/.cargo/registry":/usr/local/cargo/registry -v "$(pwd)":/home/rust/src -w /home/rust/src -P start9/rust-arm-cross:aarch64' +alias 'rust-musl-builder'='docker run $USE_TTY --rm -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src -P messense/rust-musl-cross:$ARCH-musl' set +e fail= -if [[ "$FLAGS" = "" ]]; then - rust-gnu-builder sh -c "(cd backend && cargo build --release --locked --target=$ARCH-unknown-linux-gnu)" - if test $? -ne 0; then - fail=true - fi - for ARCH in x86_64 aarch64 - do - rust-musl-builder sh -c "(cd libs && cargo build --release --locked --bin embassy_container_init )" - if test $? -ne 0; then - fail=true - fi - done -else - echo "FLAGS=$FLAGS" - rust-gnu-builder sh -c "(cd backend && cargo build --release --features $FLAGS --locked --target=$ARCH-unknown-linux-gnu)" - if test $? -ne 0; then - fail=true - fi - for ARCH in x86_64 aarch64 - do - rust-musl-builder sh -c "(cd libs && cargo build --release --features $FLAGS --locked --bin embassy_container_init)" - if test $? -ne 0; then - fail=true - fi - done +echo "FEATURES=\"$FEATURES\"" +echo "RUSTFLAGS=\"$RUSTFLAGS\"" +rust-gnu-builder sh -c "(cd backend && cargo build --release --features avahi-alias,$FEATURES --locked --target=$ARCH-unknown-linux-gnu)" +if test $? -ne 0; then + fail=true fi +for ARCH in x86_64 aarch64 +do + rust-musl-builder sh -c "(cd libs && cargo build --release --locked --bin embassy_container_init)" + if test $? -ne 0; then + fail=true + fi +done set -e cd backend diff --git a/backend/install-sdk.sh b/backend/install-sdk.sh index 2f5177a8d..a5d9b31b6 100755 --- a/backend/install-sdk.sh +++ b/backend/install-sdk.sh @@ -8,11 +8,14 @@ if [ "$0" != "./install-sdk.sh" ]; then exit 1 fi -if [ -z "$OS_ARCH" ]; then - export OS_ARCH=$(uname -m) +frontend="../frontend/dist/static" +[ -d "$frontend" ] || mkdir -p "$frontend" + +if [ -z "$PLATFORM" ]; then + export PLATFORM=$(uname -m) fi cargo install --path=. --no-default-features --features=js_engine,sdk,cli --locked startbox_loc=$(which startbox) ln -sf $startbox_loc $(dirname $startbox_loc)/start-cli -ln -sf $startbox_loc $(dirname $startbox_loc)/start-sdk \ No newline at end of file +ln -sf $startbox_loc $(dirname $startbox_loc)/start-sdk diff --git a/backend/sqlx-data.json b/backend/sqlx-data.json deleted file mode 100644 index 84afcfdb6..000000000 --- a/backend/sqlx-data.json +++ /dev/null @@ -1,744 +0,0 @@ -{ - "db": "PostgreSQL", - "1ce5254f27de971fd87f5ab66d300f2b22433c86617a0dbf796bf2170186dd2e": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Bytea" - ] - } - }, - "query": "INSERT INTO network_keys (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING" - }, - "21471490cdc3adb206274cc68e1ea745ffa5da4479478c1fd2158a45324b1930": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "DELETE FROM ssh_keys WHERE fingerprint = $1" - }, - "28ea34bbde836e0618c5fc9bb7c36e463c20c841a7d6a0eb15be0f24f4a928ec": { - "describe": { - "columns": [ - { - "name": "hostname", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "path", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "username", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "password", - "ordinal": 3, - "type_info": "Text" - } - ], - "nullable": [ - false, - false, - false, - true - ], - "parameters": { - "Left": [ - "Int4" - ] - } - }, - "query": "SELECT hostname, path, username, password FROM cifs_shares WHERE id = $1" - }, - "4099028a5c0de578255bf54a67cef6cb0f1e9a4e158260700f1639dd4b438997": { - "describe": { - "columns": [ - { - "name": "fingerprint", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "openssh_pubkey", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "created_at", - "ordinal": 2, - "type_info": "Text" - } - ], - "nullable": [ - false, - false, - false - ], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "SELECT * FROM ssh_keys WHERE fingerprint = $1" - }, - "4691e3a2ce80b59009ac17124f54f925f61dc5ea371903e62cdffa5d7b67ca96": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "logged_in", - "ordinal": 1, - "type_info": "Timestamp" - }, - { - "name": "logged_out", - "ordinal": 2, - "type_info": "Timestamp" - }, - { - "name": "last_active", - "ordinal": 3, - "type_info": "Timestamp" - }, - { - "name": "user_agent", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "metadata", - "ordinal": 5, - "type_info": "Text" - } - ], - "nullable": [ - false, - false, - true, - false, - true, - false - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT * FROM session WHERE logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP" - }, - "4bcfbefb1eb3181343871a1cd7fc3afb81c2be5c681cfa8b4be0ce70610e9c3a": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = $1" - }, - "629be61c3c341c131ddbbff0293a83dbc6afd07cae69d246987f62cf0cc35c2a": { - "describe": { - "columns": [ - { - "name": "password", - "ordinal": 0, - "type_info": "Text" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT password FROM account" - }, - "687688055e63d27123cdc89a5bbbd8361776290a9411d527eaf1fdb40bef399d": { - "describe": { - "columns": [ - { - "name": "key", - "ordinal": 0, - "type_info": "Bytea" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [ - "Text", - "Text" - ] - } - }, - "query": "SELECT key FROM tor WHERE package = $1 AND interface = $2" - }, - "6d35ccf780fb2bb62586dd1d3df9c1550a41ee580dad3f49d35cb843ebef10ca": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = $1 AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP" - }, - "770c1017734720453dc87b58c385b987c5af5807151ff71a59000014586752e0": { - "describe": { - "columns": [ - { - "name": "key", - "ordinal": 0, - "type_info": "Bytea" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Bytea" - ] - } - }, - "query": "INSERT INTO network_keys (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO UPDATE SET package = EXCLUDED.package RETURNING key" - }, - "7b64f032d507e8ffe37c41f4c7ad514a66c421a11ab04c26d89a7aa8f6b67210": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "package_id", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "created_at", - "ordinal": 2, - "type_info": "Timestamp" - }, - { - "name": "code", - "ordinal": 3, - "type_info": "Int4" - }, - { - "name": "level", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "title", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "message", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "data", - "ordinal": 7, - "type_info": "Text" - } - ], - "nullable": [ - false, - true, - false, - false, - false, - false, - false, - true - ], - "parameters": { - "Left": [ - "Int4", - "Int8" - ] - } - }, - "query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications WHERE id < $1 ORDER BY id DESC LIMIT $2" - }, - "7c7a3549c997eb75bf964ea65fbb98a73045adf618696cd838d79203ef5383fb": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Bytea", - "Text", - "Text" - ] - } - }, - "query": "\n INSERT INTO account (\n id,\n server_id,\n hostname,\n password,\n network_key,\n root_ca_key_pem,\n root_ca_cert_pem\n ) VALUES (\n 0, $1, $2, $3, $4, $5, $6\n ) ON CONFLICT (id) DO UPDATE SET\n server_id = EXCLUDED.server_id,\n hostname = EXCLUDED.hostname,\n password = EXCLUDED.password,\n network_key = EXCLUDED.network_key,\n root_ca_key_pem = EXCLUDED.root_ca_key_pem,\n root_ca_cert_pem = EXCLUDED.root_ca_cert_pem\n " - }, - "7e0649d839927e57fa03ee51a2c9f96a8bdb0fc97ee8a3c6df1069e1e2b98576": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "DELETE FROM tor WHERE package = $1" - }, - "8951b9126fbf60dbb5997241e11e3526b70bccf3e407327917294a993bc17ed5": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Bytea" - ] - } - }, - "query": "INSERT INTO tor (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING" - }, - "94d471bb374b4965c6cbedf8c17bbf6bea226d38efaf6559923c79a36d5ca08c": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "package_id", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "created_at", - "ordinal": 2, - "type_info": "Timestamp" - }, - { - "name": "code", - "ordinal": 3, - "type_info": "Int4" - }, - { - "name": "level", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "title", - "ordinal": 5, - "type_info": "Text" - }, - { - "name": "message", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "data", - "ordinal": 7, - "type_info": "Text" - } - ], - "nullable": [ - false, - true, - false, - false, - false, - false, - false, - true - ], - "parameters": { - "Left": [ - "Int8" - ] - } - }, - "query": "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications ORDER BY id DESC LIMIT $1" - }, - "95c4ab4c645f3302568c6ff13d85ab58252362694cf0f56999bf60194d20583a": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "hostname", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "path", - "ordinal": 2, - "type_info": "Text" - }, - { - "name": "username", - "ordinal": 3, - "type_info": "Text" - }, - { - "name": "password", - "ordinal": 4, - "type_info": "Text" - } - ], - "nullable": [ - false, - false, - false, - false, - true - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT id, hostname, path, username, password FROM cifs_shares" - }, - "a60d6e66719325b08dc4ecfacaf337527233c84eee758ac9be967906e5841d27": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Int4" - ] - } - }, - "query": "DELETE FROM cifs_shares WHERE id = $1" - }, - "a6b0c8909a3a5d6d9156aebfb359424e6b5a1d1402e028219e21726f1ebd282e": { - "describe": { - "columns": [ - { - "name": "fingerprint", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "openssh_pubkey", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "created_at", - "ordinal": 2, - "type_info": "Text" - } - ], - "nullable": [ - false, - false, - false - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT fingerprint, openssh_pubkey, created_at FROM ssh_keys" - }, - "b1147beaaabbed89f2ab8c1e13ec4393a9a8fde2833cf096af766a979d94dee6": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text", - "Int4" - ] - } - }, - "query": "UPDATE cifs_shares SET hostname = $1, path = $2, username = $3, password = $4 WHERE id = $5" - }, - "d5117054072476377f3c4f040ea429d4c9b2cf534e76f35c80a2bf60e8599cca": { - "describe": { - "columns": [ - { - "name": "openssh_pubkey", - "ordinal": 0, - "type_info": "Text" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT openssh_pubkey FROM ssh_keys" - }, - "da71f94b29798d1738d2b10b9a721ea72db8cfb362e7181c8226d9297507c62b": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Int4", - "Text", - "Text", - "Text", - "Text" - ] - } - }, - "query": "INSERT INTO notifications (package_id, code, level, title, message, data) VALUES ($1, $2, $3, $4, $5, $6)" - }, - "e185203cf84e43b801dfb23b4159e34aeaef1154dcd3d6811ab504915497ccf7": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Int4" - ] - } - }, - "query": "DELETE FROM notifications WHERE id = $1" - }, - "e545696735f202f9d13cf22a561f3ff3f9aed7f90027a9ba97634bcb47d772f0": { - "describe": { - "columns": [ - { - "name": "tor_key", - "ordinal": 0, - "type_info": "Bytea" - } - ], - "nullable": [ - true - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT tor_key FROM account WHERE id = 0" - }, - "e5843c5b0e7819b29aa1abf2266799bd4f82e761837b526a0972c3d4439a264d": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text" - ] - } - }, - "query": "INSERT INTO session (id, user_agent, metadata) VALUES ($1, $2, $3)" - }, - "e95322a8e2ae3b93f1e974b24c0b81803f1e9ec9e8ebbf15cafddfc1c5a028ed": { - "describe": { - "columns": [ - { - "name": "package", - "ordinal": 0, - "type_info": "Text" - }, - { - "name": "interface", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "key", - "ordinal": 2, - "type_info": "Bytea" - }, - { - "name": "tor_key?", - "ordinal": 3, - "type_info": "Bytea" - } - ], - "nullable": [ - false, - false, - false, - false - ], - "parameters": { - "Left": [ - "Text" - ] - } - }, - "query": "\n SELECT\n network_keys.package,\n network_keys.interface,\n network_keys.key,\n tor.key AS \"tor_key?\"\n FROM\n network_keys\n LEFT JOIN\n tor\n ON\n network_keys.package = tor.package\n AND\n network_keys.interface = tor.interface\n WHERE\n network_keys.package = $1\n " - }, - "eb750adaa305bdbf3c5b70aaf59139c7b7569602adb58f2d6b3a94da4f167b0a": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Int4" - ] - } - }, - "query": "DELETE FROM notifications WHERE id < $1" - }, - "ecc765d8205c0876956f95f76944ac6a5f34dd820c4073b7728c7067aab9fded": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [ - "Text", - "Text", - "Text", - "Text" - ] - } - }, - "query": "INSERT INTO cifs_shares (hostname, path, username, password) VALUES ($1, $2, $3, $4) RETURNING id" - }, - "f6d1c5ef0f9d9577bea8382318967b9deb46da75788c7fe6082b43821c22d556": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text" - ] - } - }, - "query": "INSERT INTO ssh_keys (fingerprint, openssh_pubkey, created_at) VALUES ($1, $2, $3)" - }, - "f7d2dae84613bcef330f7403352cc96547f3f6dbec11bf2eadfaf53ad8ab51b5": { - "describe": { - "columns": [ - { - "name": "network_key", - "ordinal": 0, - "type_info": "Bytea" - } - ], - "nullable": [ - false - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT network_key FROM account WHERE id = 0" - }, - "fe6e4f09f3028e5b6b6259e86cbad285680ce157aae9d7837ac020c8b2945e7f": { - "describe": { - "columns": [ - { - "name": "id", - "ordinal": 0, - "type_info": "Int4" - }, - { - "name": "password", - "ordinal": 1, - "type_info": "Text" - }, - { - "name": "tor_key", - "ordinal": 2, - "type_info": "Bytea" - }, - { - "name": "server_id", - "ordinal": 3, - "type_info": "Text" - }, - { - "name": "hostname", - "ordinal": 4, - "type_info": "Text" - }, - { - "name": "network_key", - "ordinal": 5, - "type_info": "Bytea" - }, - { - "name": "root_ca_key_pem", - "ordinal": 6, - "type_info": "Text" - }, - { - "name": "root_ca_cert_pem", - "ordinal": 7, - "type_info": "Text" - } - ], - "nullable": [ - false, - false, - true, - true, - true, - false, - false, - false - ], - "parameters": { - "Left": [] - } - }, - "query": "SELECT * FROM account WHERE id = 0" - } -} \ No newline at end of file diff --git a/backend/src/account.rs b/backend/src/account.rs index daae7bee7..cb08a0d53 100644 --- a/backend/src/account.rs +++ b/backend/src/account.rs @@ -1,5 +1,6 @@ -use ed25519_dalek::{ExpandedSecretKey, SecretKey}; -use models::ResultExt; +use std::time::SystemTime; + +use ed25519_dalek::SecretKey; use openssl::pkey::{PKey, Private}; use openssl::x509::X509; use sqlx::PgExecutor; @@ -7,13 +8,14 @@ use sqlx::PgExecutor; use crate::hostname::{generate_hostname, generate_id, Hostname}; use crate::net::keys::Key; use crate::net::ssl::{generate_key, make_root_cert}; -use crate::Error; +use crate::prelude::*; +use crate::util::crypto::ed25519_expand_key; fn hash_password(password: &str) -> Result { argon2::hash_encoded( password.as_bytes(), &rand::random::<[u8; 16]>()[..], - &argon2::Config::default(), + &argon2::Config::rfc9106_low_mem(), ) .with_kind(crate::ErrorKind::PasswordHashGeneration) } @@ -28,11 +30,11 @@ pub struct AccountInfo { pub root_ca_cert: X509, } impl AccountInfo { - pub fn new(password: &str) -> Result { + pub fn new(password: &str, start_time: SystemTime) -> Result { let server_id = generate_id(); let hostname = generate_hostname(); let root_ca_key = generate_key()?; - let root_ca_cert = make_root_cert(&root_ca_key, &hostname)?; + let root_ca_cert = make_root_cert(&root_ca_key, &hostname, start_time)?; Ok(Self { server_id, hostname, @@ -51,13 +53,23 @@ impl AccountInfo { let server_id = r.server_id.unwrap_or_else(generate_id); let hostname = r.hostname.map(Hostname).unwrap_or_else(generate_hostname); let password = r.password; - let network_key = SecretKey::from_bytes(&r.network_key)?; + let network_key = SecretKey::try_from(r.network_key).map_err(|e| { + Error::new( + eyre!("expected vec of len 32, got len {}", e.len()), + ErrorKind::ParseDbField, + ) + })?; let tor_key = if let Some(k) = &r.tor_key { - ExpandedSecretKey::from_bytes(k)? + <[u8; 64]>::try_from(&k[..]).map_err(|_| { + Error::new( + eyre!("expected vec of len 64, got len {}", k.len()), + ErrorKind::ParseDbField, + ) + })? } else { - ExpandedSecretKey::from(&network_key) + ed25519_expand_key(&network_key) }; - let key = Key::from_pair(None, network_key.to_bytes(), tor_key.to_bytes()); + let key = Key::from_pair(None, network_key, tor_key); let root_ca_key = PKey::private_key_from_pem(r.root_ca_key_pem.as_bytes())?; let root_ca_cert = X509::from_pem(r.root_ca_cert_pem.as_bytes())?; diff --git a/backend/src/action.rs b/backend/src/action.rs index bf9844ecf..3223aaa86 100644 --- a/backend/src/action.rs +++ b/backend/src/action.rs @@ -11,6 +11,7 @@ use tracing::instrument; use crate::config::{Config, ConfigSpec}; use crate::context::RpcContext; +use crate::prelude::*; use crate::procedure::docker::DockerContainers; use crate::procedure::{PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; @@ -59,13 +60,13 @@ impl Action { #[instrument(skip_all)] pub fn validate( &self, - container: &Option, + _container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, ) -> Result<(), Error> { self.implementation - .validate(container, eos_version, volumes, image_ids, true) + .validate(eos_version, volumes, image_ids, true) .with_ctx(|_| { ( crate::ErrorKind::ValidateS9pk, @@ -130,18 +131,17 @@ pub async fn action( #[arg(long = "format")] format: Option, ) -> Result { - let mut db = ctx.db.handle(); - let manifest = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&pkg_id) - .and_then(|p| p.installed()) - .expect(&mut db) + let manifest = ctx + .db + .peek() .await - .with_kind(crate::ErrorKind::NotFound)? - .manifest() - .get(&mut db) - .await? - .to_owned(); + .as_package_data() + .as_idx(&pkg_id) + .or_not_found(&pkg_id)? + .as_installed() + .or_not_found(&pkg_id)? + .as_manifest() + .de()?; if let Some(action) = manifest.actions.0.get(&action_id) { action diff --git a/backend/src/auth.rs b/backend/src/auth.rs index 1ccbf81df..a6ae2fff0 100644 --- a/backend/src/auth.rs +++ b/backend/src/auth.rs @@ -5,7 +5,6 @@ use chrono::{DateTime, Utc}; use clap::ArgMatches; use color_eyre::eyre::eyre; use josekit::jwk::Jwk; -use patch_db::{DbHandle, LockReceipt}; use rpc_toolkit::command; use rpc_toolkit::command_helpers::prelude::{RequestParts, ResponseParts}; use rpc_toolkit::yajrc::RpcError; @@ -17,6 +16,7 @@ use tracing::instrument; use crate::context::{CliContext, RpcContext}; use crate::middleware::auth::{AsLogoutSessionId, HasLoggedOutSessions, HashSessionToken}; use crate::middleware::encrypt::EncryptedWire; +use crate::prelude::*; use crate::util::display_none; use crate::util::serde::{display_serializable, IoFormat}; use crate::{ensure_code, Error, ResultExt}; @@ -84,7 +84,7 @@ fn gen_pwd() { argon2::hash_encoded( b"testing1234", &rand::random::<[u8; 16]>()[..], - &argon2::Config::default() + &argon2::Config::rfc9106_low_mem() ) .unwrap() ) @@ -160,7 +160,7 @@ pub async fn login( ) -> Result<(), Error> { let password = password.unwrap_or_default().decrypt(&ctx)?; let mut handle = ctx.secret_store.acquire().await?; - check_password_against_db(&mut handle, &password).await?; + check_password_against_db(handle.as_mut(), &password).await?; let hash_token = HashSessionToken::new(); let user_agent = req.headers.get("user-agent").and_then(|h| h.to_str().ok()); @@ -172,7 +172,7 @@ pub async fn login( user_agent, metadata, ) - .execute(&mut handle) + .execute(handle.as_mut()) .await?; res.headers.insert( "set-cookie", @@ -263,7 +263,7 @@ pub async fn list( sessions: sqlx::query!( "SELECT * FROM session WHERE logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP" ) - .fetch_all(&mut ctx.secret_store.acquire().await?) + .fetch_all(ctx.secret_store.acquire().await?.as_mut()) .await? .into_iter() .map(|row| { @@ -343,27 +343,6 @@ async fn cli_reset_password( Ok(()) } -pub struct SetPasswordReceipt(LockReceipt); -impl SetPasswordReceipt { - pub async fn new(db: &mut Db) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let password_hash = crate::db::DatabaseModel::new() - .server_info() - .password_hash() - .make_locker(patch_db::LockType::Write) - .add_to_keys(locks); - move |skeleton_key| Ok(Self(password_hash.verify(skeleton_key)?)) - } -} - #[command( rename = "reset-password", custom_cli(cli_reset_password(async, context(CliContext))), @@ -389,13 +368,14 @@ pub async fn reset_password( } account.set_password(&new_password)?; account.save(&ctx.secret_store).await?; - crate::db::DatabaseModel::new() - .server_info() - .password_hash() - .put(&mut ctx.db.handle(), &account.password) - .await?; - - Ok(()) + let account_password = &account.password; + ctx.db + .mutate(|d| { + d.as_server_info_mut() + .as_password_hash_mut() + .ser(account_password) + }) + .await } #[command( diff --git a/backend/src/backup/backup_bulk.rs b/backend/src/backup/backup_bulk.rs index d0ae26f52..21eedbaf2 100644 --- a/backend/src/backup/backup_bulk.rs +++ b/backend/src/backup/backup_bulk.rs @@ -1,4 +1,5 @@ -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; +use std::panic::UnwindSafe; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -6,9 +7,11 @@ use chrono::Utc; use clap::ArgMatches; use color_eyre::eyre::eyre; use helpers::AtomicFile; -use patch_db::{DbHandle, LockType, PatchDbHandle}; +use imbl::OrdSet; +use models::Version; use rpc_toolkit::command; -use tokio::{io::AsyncWriteExt, sync::Mutex}; +use tokio::io::AsyncWriteExt; +use tokio::sync::Mutex; use tracing::instrument; use super::target::BackupTargetId; @@ -18,26 +21,27 @@ use crate::backup::os::OsBackup; use crate::backup::{BackupReport, ServerBackupReport}; use crate::context::RpcContext; use crate::db::model::BackupProgress; +use crate::db::package::get_packages; use crate::disk::mount::backup::BackupMountGuard; use crate::disk::mount::filesystem::ReadWrite; use crate::disk::mount::guard::TmpMountGuard; use crate::manager::BackupReturn; use crate::notifications::NotificationLevel; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; +use crate::util::display_none; use crate::util::io::dir_copy; use crate::util::serde::IoFormat; -use crate::util::{display_none, Invoke}; use crate::version::VersionT; -use crate::{Error, ErrorKind, ResultExt}; -fn parse_comma_separated(arg: &str, _: &ArgMatches) -> Result, Error> { +fn parse_comma_separated(arg: &str, _: &ArgMatches) -> Result, Error> { arg.split(',') - .map(|s| s.trim().parse().map_err(Error::from)) + .map(|s| s.trim().parse::().map_err(Error::from)) .collect() } #[command(rename = "create", display(display_none))] -#[instrument(skip_all)] +#[instrument(skip(ctx, old_password, password))] pub async fn backup_all( #[context] ctx: RpcContext, #[arg(rename = "target-id")] target_id: BackupTargetId, @@ -49,55 +53,52 @@ pub async fn backup_all( long = "package-ids", parse(parse_comma_separated) )] - package_ids: Option>, + package_ids: Option>, #[arg] password: crate::auth::PasswordType, ) -> Result<(), Error> { - let mut db = ctx.db.handle(); + let db = ctx.db.peek().await; let old_password_decrypted = old_password .as_ref() .unwrap_or(&password) .clone() .decrypt(&ctx)?; let password = password.decrypt(&ctx)?; - check_password_against_db(&mut ctx.secret_store.acquire().await?, &password).await?; + check_password_against_db(ctx.secret_store.acquire().await?.as_mut(), &password).await?; let fs = target_id - .load(&mut ctx.secret_store.acquire().await?) + .load(ctx.secret_store.acquire().await?.as_mut()) .await?; let mut backup_guard = BackupMountGuard::mount( TmpMountGuard::mount(&fs, ReadWrite).await?, &old_password_decrypted, ) .await?; - let all_packages = crate::db::DatabaseModel::new() - .package_data() - .get(&mut db) - .await? - .0 - .keys() - .into_iter() - .cloned() - .collect(); - let package_ids = package_ids.unwrap_or(all_packages); + let package_ids = if let Some(ids) = package_ids { + ids.into_iter() + .flat_map(|package_id| { + let version = db + .as_package_data() + .as_idx(&package_id)? + .as_manifest() + .as_version() + .de() + .ok()?; + Some((package_id, version)) + }) + .collect() + } else { + get_packages(db.clone())?.into_iter().collect() + }; if old_password.is_some() { backup_guard.change_password(&password)?; } - assure_backing_up(&mut db, &package_ids).await?; + assure_backing_up(&ctx.db, &package_ids).await?; tokio::task::spawn(async move { - let backup_res = perform_backup(&ctx, &mut db, backup_guard, &package_ids).await; - let backup_progress = crate::db::DatabaseModel::new() - .server_info() - .status_info() - .backup_progress(); - backup_progress - .clone() - .lock(&mut db, LockType::Write) - .await - .expect("failed to lock server status"); + let backup_res = perform_backup(&ctx, backup_guard, &package_ids).await; match backup_res { Ok(report) if report.iter().all(|(_, rep)| rep.error.is_none()) => ctx .notification_manager .notify( - &mut db, + ctx.db.clone(), None, NotificationLevel::Success, "Backup Complete".to_owned(), @@ -107,7 +108,10 @@ pub async fn backup_all( attempted: true, error: None, }, - packages: report, + packages: report + .into_iter() + .map(|((package_id, _), value)| (package_id, value)) + .collect(), }, None, ) @@ -116,7 +120,7 @@ pub async fn backup_all( Ok(report) => ctx .notification_manager .notify( - &mut db, + ctx.db.clone(), None, NotificationLevel::Warning, "Backup Complete".to_owned(), @@ -126,7 +130,10 @@ pub async fn backup_all( attempted: true, error: None, }, - packages: report, + packages: report + .into_iter() + .map(|((package_id, _), value)| (package_id, value)) + .collect(), }, None, ) @@ -137,7 +144,7 @@ pub async fn backup_all( tracing::debug!("{:?}", e); ctx.notification_manager .notify( - &mut db, + ctx.db.clone(), None, NotificationLevel::Error, "Backup Failed".to_owned(), @@ -155,106 +162,85 @@ pub async fn backup_all( .expect("failed to send notification"); } } - backup_progress - .delete(&mut db) - .await - .expect("failed to change server status"); + ctx.db + .mutate(|v| { + v.as_server_info_mut() + .as_status_info_mut() + .as_backup_progress_mut() + .ser(&None) + }) + .await?; + Ok::<(), Error>(()) }); Ok(()) } -#[instrument(skip_all)] +#[instrument(skip(db, packages))] async fn assure_backing_up( - db: &mut PatchDbHandle, - packages: impl IntoIterator, + db: &PatchDb, + packages: impl IntoIterator + UnwindSafe + Send, ) -> Result<(), Error> { - let mut tx = db.begin().await?; - let mut backing_up = crate::db::DatabaseModel::new() - .server_info() - .status_info() - .backup_progress() - .get_mut(&mut tx) - .await?; - - if backing_up - .iter() - .flat_map(|x| x.values()) - .fold(false, |acc, x| { - if !x.complete { - return true; - } - acc - }) - { - return Err(Error::new( - eyre!("Server is already backing up!"), - crate::ErrorKind::InvalidRequest, - )); - } - *backing_up = Some( - packages - .into_iter() - .map(|x| (x.clone(), BackupProgress { complete: false })) - .collect(), - ); - backing_up.save(&mut tx).await?; - tx.commit().await?; - Ok(()) + db.mutate(|v| { + let backing_up = v + .as_server_info_mut() + .as_status_info_mut() + .as_backup_progress_mut(); + if backing_up + .clone() + .de()? + .iter() + .flat_map(|x| x.values()) + .fold(false, |acc, x| { + if !x.complete { + return true; + } + acc + }) + { + return Err(Error::new( + eyre!("Server is already backing up!"), + ErrorKind::InvalidRequest, + )); + } + backing_up.ser(&Some( + packages + .into_iter() + .map(|(x, _)| (x.clone(), BackupProgress { complete: false })) + .collect(), + ))?; + Ok(()) + }) + .await } -#[instrument(skip_all)] -async fn perform_backup( +#[instrument(skip(ctx, backup_guard))] +async fn perform_backup( ctx: &RpcContext, - mut db: Db, backup_guard: BackupMountGuard, - package_ids: &BTreeSet, -) -> Result, Error> { + package_ids: &OrdSet<(PackageId, Version)>, +) -> Result, Error> { let mut backup_report = BTreeMap::new(); let backup_guard = Arc::new(Mutex::new(backup_guard)); - for package_id in crate::db::DatabaseModel::new() - .package_data() - .keys(&mut db) - .await? - .into_iter() - .filter(|id| package_ids.contains(id)) - { - let mut tx = db.begin().await?; // for lock scope - let installed_model = if let Some(installed_model) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&package_id) - .and_then(|m| m.installed()) - .check(&mut tx) - .await? - { - installed_model - } else { - continue; - }; - let main_status_model = installed_model.clone().status().main(); - - let manifest = installed_model.clone().manifest().get(&mut tx).await?; - - let (response, report) = match ctx + for package_id in package_ids { + let (response, _report) = match ctx .managers - .get(&(manifest.id.clone(), manifest.version.clone())) + .get(package_id) .await - .ok_or_else(|| { - Error::new(eyre!("Manager not found"), crate::ErrorKind::InvalidRequest) - })? + .ok_or_else(|| Error::new(eyre!("Manager not found"), ErrorKind::InvalidRequest))? .backup(backup_guard.clone()) .await { BackupReturn::Ran { report, res } => (res, report), BackupReturn::AlreadyRunning(report) => { - backup_report.insert(package_id, report); + backup_report.insert(package_id.clone(), report); continue; } BackupReturn::Error(error) => { tracing::warn!("Backup thread error"); tracing::debug!("{error:?}"); backup_report.insert( - package_id, + package_id.clone(), PackageBackupReport { error: Some("Backup thread error".to_owned()), }, @@ -270,42 +256,16 @@ async fn perform_backup( ); if let Ok(pkg_meta) = response { - installed_model - .last_backup() - .put(&mut tx, &Some(pkg_meta.timestamp)) - .await?; backup_guard .lock() .await .metadata .package_backups - .insert(package_id.clone(), pkg_meta); + .insert(package_id.0.clone(), pkg_meta); } - - let mut backup_progress = crate::db::DatabaseModel::new() - .server_info() - .status_info() - .backup_progress() - .get_mut(&mut tx) - .await?; - if backup_progress.is_none() { - *backup_progress = Some(Default::default()); - } - if let Some(mut backup_progress) = backup_progress - .as_mut() - .and_then(|bp| bp.get_mut(&package_id)) - { - (*backup_progress).complete = true; - } - backup_progress.save(&mut tx).await?; - tx.save().await?; } - let ui = crate::db::DatabaseModel::new() - .ui() - .get(&mut db) - .await? - .into_owned(); + let ui = ctx.db.peek().await.into_ui().de()?; let mut os_backup_file = AtomicFile::new( backup_guard.lock().await.as_ref().join("os-backup.cbor"), @@ -354,10 +314,9 @@ async fn perform_backup( backup_guard.save_and_unmount().await?; - crate::db::DatabaseModel::new() - .server_info() - .last_backup() - .put(&mut db, ×tamp) + ctx.db + .mutate(|v| v.as_server_info_mut().as_last_backup_mut().ser(×tamp)) .await?; + Ok(backup_report) } diff --git a/backend/src/backup/mod.rs b/backend/src/backup/mod.rs index c2bd9bcd0..2f3f9bd8f 100644 --- a/backend/src/backup/mod.rs +++ b/backend/src/backup/mod.rs @@ -1,11 +1,11 @@ use std::collections::{BTreeMap, BTreeSet}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use chrono::{DateTime, Utc}; use color_eyre::eyre::eyre; use helpers::AtomicFile; -use models::ImageId; -use patch_db::{DbHandle, HasModel}; +use models::{ImageId, OptionExt}; use reqwest::Url; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; @@ -15,10 +15,11 @@ use tracing::instrument; use self::target::PackageBackupInfo; use crate::context::RpcContext; -use crate::dependencies::reconfigure_dependents_with_live_pointers; use crate::install::PKG_ARCHIVE_DIR; -use crate::net::interface::{InterfaceId, Interfaces}; +use crate::manager::manager_seed::ManagerSeed; +use crate::net::interface::InterfaceId; use crate::net::keys::Key; +use crate::prelude::*; use crate::procedure::docker::DockerContainers; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; @@ -71,6 +72,7 @@ struct BackupMetadata { } #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] +#[model = "Model"] pub struct BackupActions { pub create: PackageProcedure, pub restore: PackageProcedure, @@ -78,34 +80,29 @@ pub struct BackupActions { impl BackupActions { pub fn validate( &self, - container: &Option, + _container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, ) -> Result<(), Error> { self.create - .validate(container, eos_version, volumes, image_ids, false) + .validate(eos_version, volumes, image_ids, false) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Backup Create"))?; self.restore - .validate(container, eos_version, volumes, image_ids, false) + .validate(eos_version, volumes, image_ids, false) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Backup Restore"))?; Ok(()) } #[instrument(skip_all)] - pub async fn create( - &self, - ctx: &RpcContext, - db: &mut Db, - pkg_id: &PackageId, - pkg_title: &str, - pkg_version: &Version, - interfaces: &Interfaces, - volumes: &Volumes, - ) -> Result { - let mut volumes = volumes.to_readonly(); + pub async fn create(&self, seed: Arc) -> Result { + let manifest = &seed.manifest; + let mut volumes = seed.manifest.volumes.to_readonly(); + let ctx = &seed.ctx; + let pkg_id = &manifest.id; + let pkg_version = &manifest.version; volumes.insert(VolumeId::Backup, Volume::Backup { readonly: false }); - let backup_dir = backup_dir(pkg_id); + let backup_dir = backup_dir(&manifest.id); if tokio::fs::metadata(&backup_dir).await.is_err() { tokio::fs::create_dir_all(&backup_dir).await? } @@ -122,29 +119,29 @@ impl BackupActions { .await? .map_err(|e| eyre!("{}", e.1)) .with_kind(crate::ErrorKind::Backup)?; - let (network_keys, tor_keys) = Key::for_package(&ctx.secret_store, pkg_id) - .await? - .into_iter() - .filter_map(|k| { - let interface = k.interface().map(|(_, i)| i)?; - Some(( - (interface.clone(), Base64(k.as_bytes())), - (interface, Base32(k.tor_key().as_bytes())), - )) - }) - .unzip(); - let marketplace_url = crate::db::DatabaseModel::new() - .package_data() - .idx_model(pkg_id) - .expect(db) - .await? - .installed() - .expect(db) - .await? - .marketplace_url() - .get(db) - .await? - .into_owned(); + let (network_keys, tor_keys): (Vec<_>, Vec<_>) = + Key::for_package(&ctx.secret_store, pkg_id) + .await? + .into_iter() + .filter_map(|k| { + let interface = k.interface().map(|(_, i)| i)?; + Some(( + (interface.clone(), Base64(k.as_bytes())), + (interface, Base32(k.tor_key().as_bytes())), + )) + }) + .unzip(); + let marketplace_url = ctx + .db + .peek() + .await + .as_package_data() + .as_idx(&pkg_id) + .or_not_found(pkg_id)? + .expect_as_installed()? + .as_installed() + .as_marketplace_url() + .de()?; let tmp_path = Path::new(BACKUP_DIR) .join(pkg_id) .join(format!("{}.s9pk", pkg_id)); @@ -172,6 +169,8 @@ impl BackupActions { let mut outfile = AtomicFile::new(&metadata_path, None::) .await .with_kind(ErrorKind::Filesystem)?; + let network_keys = network_keys.into_iter().collect(); + let tor_keys = tor_keys.into_iter().collect(); outfile .write_all(&IoFormat::Cbor.to_vec(&BackupMetadata { timestamp, @@ -183,22 +182,20 @@ impl BackupActions { outfile.save().await.with_kind(ErrorKind::Filesystem)?; Ok(PackageBackupInfo { os_version: Current::new().semver().into(), - title: pkg_title.to_owned(), + title: manifest.title.clone(), version: pkg_version.clone(), timestamp, }) } #[instrument(skip_all)] - pub async fn restore( + pub async fn restore( &self, ctx: &RpcContext, - db: &mut Db, pkg_id: &PackageId, pkg_version: &Version, - interfaces: &Interfaces, volumes: &Volumes, - ) -> Result<(), Error> { + ) -> Result, Error> { let mut volumes = volumes.clone(); volumes.insert(VolumeId::Backup, Volume::Backup { readonly: true }); self.restore @@ -223,32 +220,7 @@ impl BackupActions { ) })?, )?; - let pde = crate::db::DatabaseModel::new() - .package_data() - .idx_model(pkg_id) - .expect(db) - .await? - .installed() - .expect(db) - .await?; - pde.marketplace_url() - .put(db, &metadata.marketplace_url) - .await?; - let entry = crate::db::DatabaseModel::new() - .package_data() - .idx_model(pkg_id) - .expect(db) - .await? - .installed() - .expect(db) - .await? - .get(db) - .await?; - - let receipts = crate::config::ConfigReceipts::new(db).await?; - reconfigure_dependents_with_live_pointers(ctx, db, &receipts, &entry).await?; - - Ok(()) + Ok(metadata.marketplace_url) } } diff --git a/backend/src/backup/os.rs b/backend/src/backup/os.rs index 74498452c..5ab8bd12e 100644 --- a/backend/src/backup/os.rs +++ b/backend/src/backup/os.rs @@ -1,13 +1,13 @@ use openssl::pkey::PKey; use openssl::x509::X509; +use patch_db::Value; use serde::{Deserialize, Serialize}; -use serde_json::Value; use crate::account::AccountInfo; use crate::hostname::{generate_hostname, generate_id, Hostname}; use crate::net::keys::Key; +use crate::prelude::*; use crate::util::serde::Base64; -use crate::Error; pub struct OsBackup { pub account: AccountInfo, @@ -20,11 +20,11 @@ impl<'de> Deserialize<'de> for OsBackup { { let tagged = OsBackupSerDe::deserialize(deserializer)?; match tagged.version { - 0 => serde_json::from_value::(tagged.rest) + 0 => patch_db::value::from_value::(tagged.rest) .map_err(serde::de::Error::custom)? .project() .map_err(serde::de::Error::custom), - 1 => serde_json::from_value::(tagged.rest) + 1 => patch_db::value::from_value::(tagged.rest) .map_err(serde::de::Error::custom)? .project() .map_err(serde::de::Error::custom), @@ -41,7 +41,7 @@ impl Serialize for OsBackup { { OsBackupSerDe { version: 1, - rest: serde_json::to_value( + rest: patch_db::value::to_value( &OsBackupV1::unproject(self).map_err(serde::ser::Error::custom)?, ) .map_err(serde::ser::Error::custom)?, diff --git a/backend/src/backup/restore.rs b/backend/src/backup/restore.rs index 2e2bad1f5..b72b319e2 100644 --- a/backend/src/backup/restore.rs +++ b/backend/src/backup/restore.rs @@ -5,11 +5,9 @@ use std::sync::Arc; use std::time::Duration; use clap::ArgMatches; -use color_eyre::eyre::eyre; use futures::future::BoxFuture; use futures::{stream, FutureExt, StreamExt}; use openssl::x509::X509; -use patch_db::{DbHandle, PatchDbHandle}; use rpc_toolkit::command; use sqlx::Connection; use tokio::fs::File; @@ -21,7 +19,7 @@ use crate::backup::os::OsBackup; use crate::backup::BackupMetadata; use crate::context::rpc::RpcContextConfig; use crate::context::{RpcContext, SetupContext}; -use crate::db::model::{PackageDataEntry, StaticFiles}; +use crate::db::model::{PackageDataEntry, PackageDataEntryRestoring, StaticFiles}; use crate::disk::mount::backup::{BackupMountGuard, PackageBackupMountGuard}; use crate::disk::mount::filesystem::ReadWrite; use crate::disk::mount::guard::TmpMountGuard; @@ -30,6 +28,7 @@ use crate::init::init; use crate::install::progress::InstallProgress; use crate::install::{download_install_s9pk, PKG_PUBLIC_DIR}; use crate::notifications::NotificationLevel; +use crate::prelude::*; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::s9pk::reader::S9pkReader; use crate::setup::SetupStatus; @@ -37,7 +36,6 @@ use crate::util::display_none; use crate::util::io::dir_size; use crate::util::serde::IoFormat; use crate::volume::{backup_dir, BACKUP_DIR, PKG_VOLUME_DIR}; -use crate::{Error, ResultExt}; fn parse_comma_separated(arg: &str, _: &ArgMatches) -> Result, Error> { arg.split(',') @@ -46,33 +44,31 @@ fn parse_comma_separated(arg: &str, _: &ArgMatches) -> Result, Er } #[command(rename = "restore", display(display_none))] -#[instrument(skip_all)] +#[instrument(skip(ctx, password))] pub async fn restore_packages_rpc( #[context] ctx: RpcContext, #[arg(parse(parse_comma_separated))] ids: Vec, #[arg(rename = "target-id")] target_id: BackupTargetId, #[arg] password: String, ) -> Result<(), Error> { - let mut db = ctx.db.handle(); let fs = target_id - .load(&mut ctx.secret_store.acquire().await?) + .load(ctx.secret_store.acquire().await?.as_mut()) .await?; let backup_guard = BackupMountGuard::mount(TmpMountGuard::mount(&fs, ReadWrite).await?, &password).await?; - let (backup_guard, tasks, _) = restore_packages(&ctx, &mut db, backup_guard, ids).await?; + let (backup_guard, tasks, _) = restore_packages(&ctx, backup_guard, ids).await?; tokio::spawn(async move { stream::iter(tasks.into_iter().map(|x| (x, ctx.clone()))) .for_each_concurrent(5, |(res, ctx)| async move { - let mut db = ctx.db.handle(); match res.await { (Ok(_), _) => (), (Err(err), package_id) => { if let Err(err) = ctx .notification_manager .notify( - &mut db, + ctx.db.clone(), Some(package_id.clone()), NotificationLevel::Error, "Restoration Failure".to_string(), @@ -169,7 +165,7 @@ impl ProgressInfo { } } -#[instrument(skip_all)] +#[instrument(skip(ctx))] pub async fn recover_full_embassy( ctx: SetupContext, disk_guid: Arc, @@ -184,20 +180,18 @@ pub async fn recover_full_embassy( .await?; let os_backup_path = backup_guard.as_ref().join("os-backup.cbor"); - let mut os_backup: OsBackup = - IoFormat::Cbor.from_slice(&tokio::fs::read(&os_backup_path).await.with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - os_backup_path.display().to_string(), - ) - })?)?; + let mut os_backup: OsBackup = IoFormat::Cbor.from_slice( + &tokio::fs::read(&os_backup_path) + .await + .with_ctx(|_| (ErrorKind::Filesystem, os_backup_path.display().to_string()))?, + )?; os_backup.account.password = argon2::hash_encoded( embassy_password.as_bytes(), &rand::random::<[u8; 16]>()[..], - &argon2::Config::default(), + &argon2::Config::rfc9106_low_mem(), ) - .with_kind(crate::ErrorKind::PasswordHashGeneration)?; + .with_kind(ErrorKind::PasswordHashGeneration)?; let secret_store = ctx.secret_store().await?; @@ -211,27 +205,24 @@ pub async fn recover_full_embassy( let rpc_ctx = RpcContext::init(ctx.config_path.clone(), disk_guid.clone()).await?; - let mut db = rpc_ctx.db.handle(); - - let ids = backup_guard + let ids: Vec<_> = backup_guard .metadata .package_backups .keys() .cloned() .collect(); let (backup_guard, tasks, progress_info) = - restore_packages(&rpc_ctx, &mut db, backup_guard, ids).await?; + restore_packages(&rpc_ctx, backup_guard, ids).await?; let task_consumer_rpc_ctx = rpc_ctx.clone(); tokio::select! { _ = async move { stream::iter(tasks.into_iter().map(|x| (x, task_consumer_rpc_ctx.clone()))) .for_each_concurrent(5, |(res, ctx)| async move { - let mut db = ctx.db.handle(); match res.await { (Ok(_), _) => (), (Err(err), package_id) => { if let Err(err) = ctx.notification_manager.notify( - &mut db, + ctx.db.clone(), Some(package_id.clone()), NotificationLevel::Error, "Restoration Failure".to_string(), format!("Error restoring package {}: {}", package_id,err), (), None).await{ @@ -261,9 +252,9 @@ pub async fn recover_full_embassy( )) } +#[instrument(skip(ctx, backup_guard))] async fn restore_packages( ctx: &RpcContext, - db: &mut PatchDbHandle, backup_guard: BackupMountGuard, ids: Vec, ) -> Result< @@ -274,7 +265,7 @@ async fn restore_packages( ), Error, > { - let guards = assure_restoring(ctx, db, ids, &backup_guard).await?; + let guards = assure_restoring(ctx, ids, &backup_guard).await?; let mut progress_info = ProgressInfo::default(); @@ -282,7 +273,9 @@ async fn restore_packages( for (manifest, guard) in guards { let id = manifest.id.clone(); let (progress, task) = restore_package(ctx.clone(), manifest, guard).await?; - progress_info.package_installs.insert(id.clone(), progress); + progress_info + .package_installs + .insert(id.clone(), progress.clone()); progress_info .src_volume_size .insert(id.clone(), dir_size(backup_dir(&id), None).await?); @@ -306,23 +299,20 @@ async fn restore_packages( Ok((backup_guard, tasks, progress_info)) } -#[instrument(skip_all)] +#[instrument(skip(ctx, backup_guard))] async fn assure_restoring( ctx: &RpcContext, - db: &mut PatchDbHandle, ids: Vec, backup_guard: &BackupMountGuard, ) -> Result, Error> { - let mut tx = db.begin().await?; - let mut guards = Vec::with_capacity(ids.len()); + let mut insert_packages = BTreeMap::new(); + for id in ids { - let mut model = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .get_mut(&mut tx) - .await?; + let peek = ctx.db.peek().await; + + let model = peek.as_package_data().as_idx(&id); if !model.is_none() { return Err(Error::new( @@ -330,14 +320,15 @@ async fn assure_restoring( crate::ErrorKind::InvalidRequest, )); } - let guard = backup_guard.mount_package_backup(&id).await?; let s9pk_path = Path::new(BACKUP_DIR).join(&id).join(format!("{}.s9pk", id)); let mut rdr = S9pkReader::open(&s9pk_path, false).await?; let manifest = rdr.manifest().await?; let version = manifest.version.clone(); - let progress = InstallProgress::new(Some(tokio::fs::metadata(&s9pk_path).await?.len())); + let progress = Arc::new(InstallProgress::new(Some( + tokio::fs::metadata(&s9pk_path).await?.len(), + ))); let public_dir_path = ctx .datadir @@ -361,22 +352,29 @@ async fn assure_restoring( let mut dst = File::create(&icon_path).await?; tokio::io::copy(&mut rdr.icon().await?, &mut dst).await?; dst.sync_all().await?; - - *model = Some(PackageDataEntry::Restoring { - install_progress: progress.clone(), - static_files: StaticFiles::local(&id, &version, manifest.assets.icon_type()), - manifest: manifest.clone(), - }); - model.save(&mut tx).await?; + insert_packages.insert( + id.clone(), + PackageDataEntry::Restoring(PackageDataEntryRestoring { + install_progress: progress.clone(), + static_files: StaticFiles::local(&id, &version, manifest.assets.icon_type()), + manifest: manifest.clone(), + }), + ); guards.push((manifest, guard)); } - - tx.commit().await?; + ctx.db + .mutate(|db| { + for (id, package) in insert_packages { + db.as_package_data_mut().insert(&id, &package)?; + } + Ok(()) + }) + .await?; Ok(guards) } -#[instrument(skip_all)] +#[instrument(skip(ctx, guard))] async fn restore_package<'a>( ctx: RpcContext, manifest: Manifest, @@ -388,13 +386,11 @@ async fn restore_package<'a>( .join(format!("{}.s9pk", id)); let metadata_path = Path::new(BACKUP_DIR).join(&id).join("metadata.cbor"); - let metadata: BackupMetadata = - IoFormat::Cbor.from_slice(&tokio::fs::read(&metadata_path).await.with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - metadata_path.display().to_string(), - ) - })?)?; + let metadata: BackupMetadata = IoFormat::Cbor.from_slice( + &tokio::fs::read(&metadata_path) + .await + .with_ctx(|_| (ErrorKind::Filesystem, metadata_path.display().to_string()))?, + )?; let mut secrets = ctx.secret_store.acquire().await?; let mut secrets_tx = secrets.begin().await?; @@ -402,48 +398,60 @@ async fn restore_package<'a>( let k = key.0.as_slice(); sqlx::query!( "INSERT INTO network_keys (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING", - *id, - *iface, + id.to_string(), + iface.to_string(), k, ) - .execute(&mut secrets_tx).await?; + .execute(secrets_tx.as_mut()).await?; } // DEPRECATED for (iface, key) in metadata.tor_keys { let k = key.0.as_slice(); sqlx::query!( "INSERT INTO tor (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING", - *id, - *iface, + id.to_string(), + iface.to_string(), k, ) - .execute(&mut secrets_tx).await?; + .execute(secrets_tx.as_mut()).await?; } secrets_tx.commit().await?; drop(secrets); let len = tokio::fs::metadata(&s9pk_path) .await - .with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - s9pk_path.display().to_string(), - ) - })? + .with_ctx(|_| (ErrorKind::Filesystem, s9pk_path.display().to_string()))? .len(); - let file = File::open(&s9pk_path).await.with_ctx(|_| { - ( - crate::ErrorKind::Filesystem, - s9pk_path.display().to_string(), - ) - })?; + let file = File::open(&s9pk_path) + .await + .with_ctx(|_| (ErrorKind::Filesystem, s9pk_path.display().to_string()))?; let progress = InstallProgress::new(Some(len)); + let marketplace_url = metadata.marketplace_url; + let progress = Arc::new(progress); + + ctx.db + .mutate(|db| { + db.as_package_data_mut().insert( + &id, + &PackageDataEntry::Restoring(PackageDataEntryRestoring { + install_progress: progress.clone(), + static_files: StaticFiles::local( + &id, + &manifest.version, + manifest.assets.icon_type(), + ), + manifest: manifest.clone(), + }), + ) + }) + .await?; Ok(( progress.clone(), async move { - download_install_s9pk(&ctx, &manifest, None, progress, file, None).await?; + download_install_s9pk(ctx, manifest, marketplace_url, progress, file, None).await?; + guard.unmount().await?; Ok(()) diff --git a/backend/src/backup/target/cifs.rs b/backend/src/backup/target/cifs.rs index 3c683ad1f..3f3251535 100644 --- a/backend/src/backup/target/cifs.rs +++ b/backend/src/backup/target/cifs.rs @@ -12,9 +12,9 @@ use crate::disk::mount::filesystem::cifs::Cifs; use crate::disk::mount::filesystem::ReadOnly; use crate::disk::mount::guard::TmpMountGuard; use crate::disk::util::{recovery_info, EmbassyOsRecoveryInfo}; +use crate::prelude::*; use crate::util::display_none; use crate::util::serde::KeyVal; -use crate::Error; #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] @@ -84,7 +84,7 @@ pub async fn update( } else { return Err(Error::new( eyre!("Backup Target ID {} Not Found", id), - crate::ErrorKind::NotFound, + ErrorKind::NotFound, )); }; let cifs = Cifs { @@ -112,7 +112,7 @@ pub async fn update( { return Err(Error::new( eyre!("Backup Target ID {} Not Found", BackupTargetId::Cifs { id }), - crate::ErrorKind::NotFound, + ErrorKind::NotFound, )); }; Ok(KeyVal { @@ -134,7 +134,7 @@ pub async fn remove(#[context] ctx: RpcContext, #[arg] id: BackupTargetId) -> Re } else { return Err(Error::new( eyre!("Backup Target ID {} Not Found", id), - crate::ErrorKind::NotFound, + ErrorKind::NotFound, )); }; if sqlx::query!("DELETE FROM cifs_shares WHERE id = $1", id) @@ -145,7 +145,7 @@ pub async fn remove(#[context] ctx: RpcContext, #[arg] id: BackupTargetId) -> Re { return Err(Error::new( eyre!("Backup Target ID {} Not Found", BackupTargetId::Cifs { id }), - crate::ErrorKind::NotFound, + ErrorKind::NotFound, )); }; Ok(()) diff --git a/backend/src/backup/target/mod.rs b/backend/src/backup/target/mod.rs index a17cf8d62..93e56c2d3 100644 --- a/backend/src/backup/target/mod.rs +++ b/backend/src/backup/target/mod.rs @@ -7,7 +7,6 @@ use clap::ArgMatches; use color_eyre::eyre::eyre; use digest::generic_array::GenericArray; use digest::OutputSizeUser; -use lazy_static::lazy_static; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; use sha2::Sha256; @@ -23,10 +22,10 @@ use crate::disk::mount::filesystem::cifs::Cifs; use crate::disk::mount::filesystem::{FileSystem, MountType, ReadWrite}; use crate::disk::mount::guard::TmpMountGuard; use crate::disk::util::PartitionInfo; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; use crate::util::serde::{deserialize_from_str, display_serializable, serialize_display}; use crate::util::{display_none, Version}; -use crate::Error; pub mod cifs; @@ -44,7 +43,7 @@ pub enum BackupTarget { Cifs(CifsBackupTarget), } -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum BackupTargetId { Disk { logicalname: PathBuf }, Cifs { id: i32 }, @@ -73,14 +72,14 @@ impl std::fmt::Display for BackupTargetId { impl std::str::FromStr for BackupTargetId { type Err = Error; fn from_str(s: &str) -> Result { - match s.split_once("-") { + match s.split_once('-') { Some(("disk", logicalname)) => Ok(BackupTargetId::Disk { logicalname: Path::new(logicalname).to_owned(), }), Some(("cifs", id)) => Ok(BackupTargetId::Cifs { id: id.parse()? }), _ => Err(Error::new( eyre!("Invalid Backup Target ID"), - crate::ErrorKind::InvalidBackupTargetId, + ErrorKind::InvalidBackupTargetId, )), } } @@ -143,7 +142,7 @@ pub async fn list( let mut sql_handle = ctx.secret_store.acquire().await?; let (disks_res, cifs) = tokio::try_join!( crate::disk::util::list(&ctx.os_partitions), - cifs::list(&mut sql_handle), + cifs::list(sql_handle.as_mut()), )?; Ok(disks_res .into_iter() @@ -214,7 +213,7 @@ fn display_backup_info(info: BackupInfo, matches: &ArgMatches) { ]); for (id, info) in info.package_backups { let row = row![ - id.as_str(), + &*id, info.version.as_str(), info.os_version.as_str(), &info.timestamp.to_string(), @@ -225,7 +224,7 @@ fn display_backup_info(info: BackupInfo, matches: &ArgMatches) { } #[command(display(display_backup_info))] -#[instrument(skip_all)] +#[instrument(skip(ctx, password))] pub async fn info( #[context] ctx: RpcContext, #[arg(rename = "target-id")] target_id: BackupTargetId, @@ -234,7 +233,7 @@ pub async fn info( let guard = BackupMountGuard::mount( TmpMountGuard::mount( &target_id - .load(&mut ctx.secret_store.acquire().await?) + .load(ctx.secret_store.acquire().await?.as_mut()) .await?, ReadWrite, ) @@ -250,7 +249,7 @@ pub async fn info( Ok(res) } -lazy_static! { +lazy_static::lazy_static! { static ref USER_MOUNTS: Mutex>> = Mutex::new(BTreeMap::new()); } @@ -272,7 +271,7 @@ pub async fn mount( TmpMountGuard::mount( &target_id .clone() - .load(&mut ctx.secret_store.acquire().await?) + .load(ctx.secret_store.acquire().await?.as_mut()) .await?, ReadWrite, ) @@ -287,11 +286,10 @@ pub async fn mount( Ok(res) } - #[command(display(display_none))] #[instrument(skip_all)] pub async fn umount( - #[context] ctx: RpcContext, + #[context] _ctx: RpcContext, #[arg(rename = "target-id")] target_id: Option, ) -> Result<(), Error> { let mut mounts = USER_MOUNTS.lock().await; diff --git a/backend/src/bins/mod.rs b/backend/src/bins/mod.rs index 76329e094..e131d22c4 100644 --- a/backend/src/bins/mod.rs +++ b/backend/src/bins/mod.rs @@ -5,6 +5,8 @@ pub mod avahi_alias; pub mod deprecated; #[cfg(feature = "cli")] pub mod start_cli; +#[cfg(feature = "js_engine")] +pub mod start_deno; #[cfg(feature = "daemon")] pub mod start_init; #[cfg(feature = "sdk")] @@ -16,6 +18,8 @@ fn select_executable(name: &str) -> Option { match name { #[cfg(feature = "avahi-alias")] "avahi-alias" => Some(avahi_alias::main), + #[cfg(feature = "js_engine")] + "start-deno" => Some(start_deno::main), #[cfg(feature = "cli")] "start-cli" => Some(start_cli::main), #[cfg(feature = "sdk")] diff --git a/backend/src/bins/start_deno.rs b/backend/src/bins/start_deno.rs new file mode 100644 index 000000000..0be507082 --- /dev/null +++ b/backend/src/bins/start_deno.rs @@ -0,0 +1,134 @@ +use rpc_toolkit::yajrc::RpcError; +use rpc_toolkit::{command, run_cli, Context}; +use serde_json::Value; + +use crate::procedure::js_scripts::ExecuteArgs; +use crate::s9pk::manifest::PackageId; +use crate::util::serde::{display_serializable, parse_stdin_deserializable}; +use crate::version::{Current, VersionT}; +use crate::Error; + +lazy_static::lazy_static! { + static ref VERSION_STRING: String = Current::new().semver().to_string(); +} + +struct DenoContext; +impl Context for DenoContext {} + +#[command(subcommands(execute, sandbox))] +fn deno_api() -> Result<(), Error> { + Ok(()) +} + +#[command(cli_only, display(display_serializable))] +async fn execute( + #[arg(stdin, parse(parse_stdin_deserializable))] arg: ExecuteArgs, +) -> Result, Error> { + let ExecuteArgs { + procedure, + directory, + pkg_id, + pkg_version, + name, + volumes, + input, + } = arg; + PackageLogger::init(&pkg_id); + procedure + .execute_impl(&directory, &pkg_id, &pkg_version, name, &volumes, input) + .await +} +#[command(cli_only, display(display_serializable))] +async fn sandbox( + #[arg(stdin, parse(parse_stdin_deserializable))] arg: ExecuteArgs, +) -> Result, Error> { + let ExecuteArgs { + procedure, + directory, + pkg_id, + pkg_version, + name, + volumes, + input, + } = arg; + PackageLogger::init(&pkg_id); + procedure + .sandboxed_impl(&directory, &pkg_id, &pkg_version, &volumes, input, name) + .await +} + +use tracing::Subscriber; +use tracing_subscriber::util::SubscriberInitExt; + +#[derive(Clone)] +struct PackageLogger {} + +impl PackageLogger { + fn base_subscriber(id: &PackageId) -> impl Subscriber { + use tracing_error::ErrorLayer; + use tracing_subscriber::prelude::*; + use tracing_subscriber::{fmt, EnvFilter}; + + let filter_layer = EnvFilter::default().add_directive( + format!("{}=warn", std::module_path!().split("::").next().unwrap()) + .parse() + .unwrap(), + ); + let fmt_layer = fmt::layer().with_writer(std::io::stderr).with_target(true); + let journald_layer = tracing_journald::layer() + .unwrap() + .with_syslog_identifier(format!("{id}.embassy")); + + let sub = tracing_subscriber::registry() + .with(filter_layer) + .with(fmt_layer) + .with(journald_layer) + .with(ErrorLayer::default()); + + sub + } + pub fn init(id: &PackageId) -> Self { + Self::base_subscriber(id).init(); + color_eyre::install().unwrap_or_else(|_| tracing::warn!("tracing too many times")); + + Self {} + } +} + +fn inner_main() -> Result<(), Error> { + run_cli!({ + command: deno_api, + app: app => app + .name("StartOS Deno Executor") + .version(&**VERSION_STRING), + context: _m => DenoContext, + exit: |e: RpcError| { + match e.data { + Some(Value::String(s)) => eprintln!("{}: {}", e.message, s), + Some(Value::Object(o)) => if let Some(Value::String(s)) = o.get("details") { + eprintln!("{}: {}", e.message, s); + if let Some(Value::String(s)) = o.get("debug") { + tracing::debug!("{}", s) + } + } + Some(a) => eprintln!("{}: {}", e.message, a), + None => eprintln!("{}", e.message), + } + + std::process::exit(e.code); + } + }); + Ok(()) +} + +pub fn main() { + match inner_main() { + Ok(_) => (), + Err(e) => { + eprintln!("{}", e.source); + tracing::debug!("{:?}", e.source); + drop(e.source); + std::process::exit(e.kind as i32) + } + } +} diff --git a/backend/src/bins/start_init.rs b/backend/src/bins/start_init.rs index 485d8e323..0440e0ad6 100644 --- a/backend/src/bins/start_init.rs +++ b/backend/src/bins/start_init.rs @@ -11,31 +11,38 @@ use crate::context::{DiagnosticContext, InstallContext, SetupContext}; use crate::disk::fsck::RepairStrategy; use crate::disk::main::DEFAULT_PASSWORD; use crate::disk::REPAIR_DISK_PATH; +use crate::firmware::update_firmware; use crate::init::STANDBY_MODE_PATH; use crate::net::web_server::WebServer; use crate::shutdown::Shutdown; use crate::sound::CHIME; -use crate::util::logger::EmbassyLogger; use crate::util::Invoke; -use crate::{Error, ErrorKind, ResultExt, OS_ARCH}; +use crate::{Error, ErrorKind, ResultExt, PLATFORM}; #[instrument(skip_all)] -async fn setup_or_init(cfg_path: Option) -> Result<(), Error> { +async fn setup_or_init(cfg_path: Option) -> Result, Error> { + if update_firmware().await?.0 { + return Ok(Some(Shutdown { + export_args: None, + restart: true, + })); + } + Command::new("ln") .arg("-sf") - .arg("/usr/lib/embassy/scripts/fake-apt") + .arg("/usr/lib/startos/scripts/fake-apt") .arg("/usr/local/bin/apt") .invoke(crate::ErrorKind::OpenSsh) .await?; Command::new("ln") .arg("-sf") - .arg("/usr/lib/embassy/scripts/fake-apt") + .arg("/usr/lib/startos/scripts/fake-apt") .arg("/usr/local/bin/apt-get") .invoke(crate::ErrorKind::OpenSsh) .await?; Command::new("ln") .arg("-sf") - .arg("/usr/lib/embassy/scripts/fake-apt") + .arg("/usr/lib/startos/scripts/fake-apt") .arg("/usr/local/bin/aptitude") .invoke(crate::ErrorKind::OpenSsh) .await?; @@ -147,7 +154,7 @@ async fn setup_or_init(cfg_path: Option) -> Result<(), Error> { crate::init::init(&cfg).await?; } - Ok(()) + Ok(None) } async fn run_script_if_exists>(path: P) { @@ -170,7 +177,7 @@ async fn run_script_if_exists>(path: P) { #[instrument(skip_all)] async fn inner_main(cfg_path: Option) -> Result, Error> { - if OS_ARCH == "raspberrypi" && tokio::fs::metadata(STANDBY_MODE_PATH).await.is_ok() { + if &*PLATFORM == "raspberrypi" && tokio::fs::metadata(STANDBY_MODE_PATH).await.is_ok() { tokio::fs::remove_file(STANDBY_MODE_PATH).await?; Command::new("sync").invoke(ErrorKind::Filesystem).await?; crate::sound::SHUTDOWN.play().await?; @@ -181,46 +188,47 @@ async fn inner_main(cfg_path: Option) -> Result, Error run_script_if_exists("/media/embassy/config/preinit.sh").await; - let res = if let Err(e) = setup_or_init(cfg_path.clone()).await { - async move { - tracing::error!("{}", e.source); - tracing::debug!("{}", e.source); - crate::sound::BEETHOVEN.play().await?; + let res = match setup_or_init(cfg_path.clone()).await { + Err(e) => { + async move { + tracing::error!("{}", e.source); + tracing::debug!("{}", e.source); + crate::sound::BEETHOVEN.play().await?; - let ctx = DiagnosticContext::init( - cfg_path, - if tokio::fs::metadata("/media/embassy/config/disk.guid") - .await - .is_ok() - { - Some(Arc::new( - tokio::fs::read_to_string("/media/embassy/config/disk.guid") // unique identifier for volume group - keeps track of the disk that goes with your embassy - .await? - .trim() - .to_owned(), - )) - } else { - None - }, - e, - ) - .await?; + let ctx = DiagnosticContext::init( + cfg_path, + if tokio::fs::metadata("/media/embassy/config/disk.guid") + .await + .is_ok() + { + Some(Arc::new( + tokio::fs::read_to_string("/media/embassy/config/disk.guid") // unique identifier for volume group - keeps track of the disk that goes with your embassy + .await? + .trim() + .to_owned(), + )) + } else { + None + }, + e, + ) + .await?; - let server = WebServer::diagnostic( - SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 80), - ctx.clone(), - ) - .await?; + let server = WebServer::diagnostic( + SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 80), + ctx.clone(), + ) + .await?; - let shutdown = ctx.shutdown.subscribe().recv().await.unwrap(); + let shutdown = ctx.shutdown.subscribe().recv().await.unwrap(); - server.shutdown().await; + server.shutdown().await; - Ok(shutdown) + Ok(shutdown) + } + .await } - .await - } else { - Ok(None) + Ok(s) => Ok(s), }; run_script_if_exists("/media/embassy/config/postinit.sh").await; diff --git a/backend/src/bins/startd.rs b/backend/src/bins/startd.rs index e6c272803..a773dd99a 100644 --- a/backend/src/bins/startd.rs +++ b/backend/src/bins/startd.rs @@ -16,7 +16,7 @@ use crate::{Error, ErrorKind, ResultExt}; #[instrument(skip_all)] async fn inner_main(cfg_path: Option) -> Result, Error> { - let (rpc_ctx, server, shutdown) = { + let (rpc_ctx, server, shutdown) = async { let rpc_ctx = RpcContext::init( cfg_path, Arc::new( @@ -91,8 +91,9 @@ async fn inner_main(cfg_path: Option) -> Result, Error sig_handler.abort(); - (rpc_ctx, server, shutdown) - }; + Ok::<_, Error>((rpc_ctx, server, shutdown)) + } + .await?; server.shutdown().await; rpc_ctx.shutdown().await?; diff --git a/backend/src/config/action.rs b/backend/src/config/action.rs index 0684d689e..27cd1683f 100644 --- a/backend/src/config/action.rs +++ b/backend/src/config/action.rs @@ -2,7 +2,6 @@ use std::collections::{BTreeMap, BTreeSet}; use color_eyre::eyre::eyre; use models::ImageId; -use nix::sys::signal::Signal; use patch_db::HasModel; use serde::{Deserialize, Serialize}; use tracing::instrument; @@ -10,6 +9,7 @@ use tracing::instrument; use super::{Config, ConfigSpec}; use crate::context::RpcContext; use crate::dependencies::Dependencies; +use crate::prelude::*; use crate::procedure::docker::DockerContainers; use crate::procedure::{PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; @@ -18,7 +18,7 @@ use crate::util::Version; use crate::volume::Volumes; use crate::{Error, ResultExt}; -#[derive(Debug, Deserialize, Serialize, HasModel)] +#[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct ConfigRes { pub config: Option, @@ -26,6 +26,7 @@ pub struct ConfigRes { } #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] +#[model = "Model"] pub struct ConfigActions { pub get: PackageProcedure, pub set: PackageProcedure, @@ -34,16 +35,16 @@ impl ConfigActions { #[instrument(skip_all)] pub fn validate( &self, - container: &Option, + _container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, ) -> Result<(), Error> { self.get - .validate(container, eos_version, volumes, image_ids, true) + .validate(eos_version, volumes, image_ids, true) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Config Get"))?; self.set - .validate(container, eos_version, volumes, image_ids, true) + .validate(eos_version, volumes, image_ids, true) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Config Set"))?; Ok(()) } @@ -99,7 +100,6 @@ impl ConfigActions { }) })?; Ok(SetResult { - signal: res.signal, depends_on: res .depends_on .into_iter() @@ -112,9 +112,5 @@ impl ConfigActions { #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "kebab-case")] pub struct SetResult { - #[serde(default)] - #[serde(deserialize_with = "crate::util::serde::deserialize_from_str_opt")] - #[serde(serialize_with = "crate::util::serde::serialize_display_opt")] - pub signal: Option, pub depends_on: BTreeMap>, } diff --git a/backend/src/config/mod.rs b/backend/src/config/mod.rs index 0cd23e88e..06e7770b0 100644 --- a/backend/src/config/mod.rs +++ b/backend/src/config/mod.rs @@ -1,42 +1,36 @@ use std::collections::BTreeMap; use std::path::PathBuf; +use std::sync::Arc; use std::time::Duration; use color_eyre::eyre::eyre; use indexmap::IndexSet; use itertools::Itertools; -use models::ErrorKind; -use patch_db::{DbHandle, LockReceipt, LockTarget, LockTargetId, LockType, Verifier}; +use models::{ErrorKind, OptionExt}; +use patch_db::value::InternedString; +use patch_db::Value; use regex::Regex; use rpc_toolkit::command; -use serde_json::Value; use tracing::instrument; use crate::context::RpcContext; -use crate::db::model::{CurrentDependencies, CurrentDependents}; -use crate::dependencies::{ - BreakTransitiveReceipts, BreakageRes, Dependencies, DependencyConfig, DependencyErrors, - DependencyReceipt, TaggedDependencyError, TryHealReceipts, -}; -use crate::install::cleanup::UpdateDependencyReceipts; -use crate::procedure::docker::DockerContainers; -use crate::s9pk::manifest::{Manifest, PackageId}; +use crate::prelude::*; +use crate::s9pk::manifest::PackageId; use crate::util::display_none; use crate::util::serde::{display_serializable, parse_stdin_deserializable, IoFormat}; use crate::Error; pub mod action; -pub mod hook; pub mod spec; pub mod util; pub use spec::{ConfigSpec, Defaultable}; use util::NumRange; -use self::action::{ConfigActions, ConfigRes}; -use self::spec::{ConfigPointerReceipts, ValueSpecPointer}; +use self::action::ConfigRes; +use self::spec::ValueSpecPointer; -pub type Config = serde_json::Map; +pub type Config = patch_db::value::InOMap; pub trait TypeOf { fn type_of(&self) -> &'static str; } @@ -80,7 +74,7 @@ pub struct TimeoutError; #[derive(Clone, Debug, thiserror::Error)] pub struct NoMatchWithPath { - pub path: Vec, + pub path: Vec, pub error: MatchError, } impl NoMatchWithPath { @@ -90,7 +84,7 @@ impl NoMatchWithPath { error, } } - pub fn prepend(mut self, seg: String) -> Self { + pub fn prepend(mut self, seg: InternedString) -> Self { self.path.push(seg); self } @@ -109,9 +103,9 @@ impl From for Error { #[derive(Clone, Debug, thiserror::Error)] pub enum MatchError { #[error("String {0:?} Does Not Match Pattern {1}")] - Pattern(String, Regex), + Pattern(Arc, Regex), #[error("String {0:?} Is Not In Enum {1:?}")] - Enum(String, IndexSet), + Enum(Arc, IndexSet), #[error("Field Is Not Nullable")] NotNullable, #[error("Length Mismatch: expected {0}, actual: {1}")] @@ -123,11 +117,11 @@ pub enum MatchError { #[error("Number Is Not Integral: {0}")] NonIntegral(f64), #[error("Variant {0:?} Is Not In Union {1:?}")] - Union(String, IndexSet), + Union(Arc, IndexSet), #[error("Variant Is Missing Tag {0:?}")] - MissingTag(String), + MissingTag(InternedString), #[error("Property {0:?} Of Variant {1:?} Conflicts With Union Tag")] - PropertyMatchesUnionTag(String, String), + PropertyMatchesUnionTag(InternedString, String), #[error("Name of Property {0:?} Conflicts With Map Tag Name")] PropertyNameMatchesMapTag(String), #[error("Pointer Is Invalid: {0}")] @@ -163,55 +157,6 @@ pub fn config(#[arg] id: PackageId) -> Result { Ok(id) } -pub struct ConfigGetReceipts { - manifest_volumes: LockReceipt, - manifest_version: LockReceipt, - manifest_config: LockReceipt, ()>, -} - -impl ConfigGetReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, id); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&Verifier) -> Result { - let manifest_version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().version()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let manifest_volumes = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().volumes()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let manifest_config = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().config()) - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - manifest_volumes: manifest_volumes.verify(skeleton_key)?, - manifest_version: manifest_version.verify(skeleton_key)?, - manifest_config: manifest_config.verify(skeleton_key)?, - }) - } - } -} - #[command(display(display_serializable))] #[instrument(skip_all)] pub async fn get( @@ -221,16 +166,21 @@ pub async fn get( #[arg(long = "format")] format: Option, ) -> Result { - let mut db = ctx.db.handle(); - let receipts = ConfigGetReceipts::new(&mut db, &id).await?; - let action = receipts - .manifest_config - .get(&mut db) - .await? + let db = ctx.db.peek().await; + let manifest = db + .as_package_data() + .as_idx(&id) + .or_not_found(&id)? + .as_installed() + .or_not_found(&id)? + .as_manifest(); + let action = manifest + .as_config() + .de()? .ok_or_else(|| Error::new(eyre!("{} has no config", id), crate::ErrorKind::NotFound))?; - let volumes = receipts.manifest_volumes.get(&mut db).await?; - let version = receipts.manifest_version.get(&mut db).await?; + let volumes = manifest.as_volumes().de()?; + let version = manifest.as_version().de()?; action.get(&ctx, &id, &version, &volumes).await } @@ -251,172 +201,12 @@ pub fn set( Ok((id, config, timeout.map(|d| *d))) } -/// So, the new locking finds all the possible locks and lifts them up into a bundle of locks. -/// Then this bundle will be passed down into the functions that will need to touch the db, and -/// instead of doing the locks down in the system, we have already done the locks and can -/// do the operation on the db. -/// An UnlockedLock has two types, the type of setting and getting from the db, and the second type -/// is the keys that we need to insert on getting/setting because we have included wild cards into the paths. -pub struct ConfigReceipts { - pub dependency_receipt: DependencyReceipt, - pub config_receipts: ConfigPointerReceipts, - pub update_dependency_receipts: UpdateDependencyReceipts, - pub try_heal_receipts: TryHealReceipts, - pub break_transitive_receipts: BreakTransitiveReceipts, - pub configured: LockReceipt, - pub config_actions: LockReceipt, - pub dependencies: LockReceipt, - pub volumes: LockReceipt, - pub version: LockReceipt, - pub manifest: LockReceipt, - pub system_pointers: LockReceipt, String>, - pub current_dependents: LockReceipt, - pub current_dependencies: LockReceipt, - pub dependency_errors: LockReceipt, - pub manifest_dependencies_config: LockReceipt, - pub docker_containers: LockReceipt, -} - -impl ConfigReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let dependency_receipt = DependencyReceipt::setup(locks); - let config_receipts = ConfigPointerReceipts::setup(locks); - let update_dependency_receipts = UpdateDependencyReceipts::setup(locks); - let break_transitive_receipts = BreakTransitiveReceipts::setup(locks); - let try_heal_receipts = TryHealReceipts::setup(locks); - - let configured: LockTarget = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status().configured()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let config_actions = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().config()) - .make_locker(LockType::Read) - .add_to_keys(locks); - - let dependencies = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().dependencies()) - .make_locker(LockType::Read) - .add_to_keys(locks); - - let volumes = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().volumes()) - .make_locker(LockType::Read) - .add_to_keys(locks); - - let version = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().version()) - .make_locker(LockType::Read) - .add_to_keys(locks); - - let manifest = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest()) - .make_locker(LockType::Read) - .add_to_keys(locks); - - let system_pointers = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.system_pointers()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let current_dependents = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependents()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let current_dependencies = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependencies()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let dependency_errors = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status().dependency_errors()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let manifest_dependencies_config = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().dependencies().star().config()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let docker_containers = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().containers()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - move |skeleton_key| { - Ok(Self { - dependency_receipt: dependency_receipt(skeleton_key)?, - config_receipts: config_receipts(skeleton_key)?, - try_heal_receipts: try_heal_receipts(skeleton_key)?, - break_transitive_receipts: break_transitive_receipts(skeleton_key)?, - update_dependency_receipts: update_dependency_receipts(skeleton_key)?, - configured: configured.verify(skeleton_key)?, - config_actions: config_actions.verify(skeleton_key)?, - dependencies: dependencies.verify(skeleton_key)?, - volumes: volumes.verify(skeleton_key)?, - version: version.verify(skeleton_key)?, - manifest: manifest.verify(skeleton_key)?, - system_pointers: system_pointers.verify(skeleton_key)?, - current_dependents: current_dependents.verify(skeleton_key)?, - current_dependencies: current_dependencies.verify(skeleton_key)?, - dependency_errors: dependency_errors.verify(skeleton_key)?, - manifest_dependencies_config: manifest_dependencies_config.verify(skeleton_key)?, - docker_containers: docker_containers.verify(skeleton_key)?, - }) - } - } -} - #[command(rename = "dry", display(display_serializable))] #[instrument(skip_all)] pub async fn set_dry( #[context] ctx: RpcContext, #[parent_data] (id, config, timeout): (PackageId, Option, Option), -) -> Result { +) -> Result, Error> { let breakages = BTreeMap::new(); let overrides = Default::default(); @@ -429,11 +219,11 @@ pub async fn set_dry( }; let breakages = configure(&ctx, &id, configure_context).await?; - Ok(BreakageRes(breakages)) + Ok(breakages) } pub struct ConfigureContext { - pub breakages: BTreeMap, + pub breakages: BTreeMap, pub timeout: Option, pub config: Option, pub overrides: BTreeMap, @@ -464,20 +254,15 @@ pub async fn configure( ctx: &RpcContext, id: &PackageId, configure_context: ConfigureContext, -) -> Result, Error> { - let mut db = ctx.db.handle(); - let version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .expect(&mut db) - .await? - .installed() - .expect(&mut db) - .await? - .manifest() - .version() - .get(&mut ctx.db.handle()) - .await?; +) -> Result, Error> { + let db = ctx.db.peek().await; + let package = db + .as_package_data() + .as_idx(id) + .or_not_found(&id)? + .as_installed() + .or_not_found(&id)?; + let version = package.as_manifest().as_version().de()?; ctx.managers .get(&(id.clone(), version.clone())) .await @@ -500,63 +285,3 @@ macro_rules! not_found { }; } pub(crate) use not_found; - -/// We want to have a double check that the paths are what we expect them to be. -/// Found that earlier the paths where not what we expected them to be. -#[tokio::test] -async fn ensure_creation_of_config_paths_makes_sense() { - let mut fake = patch_db::test_utils::NoOpDb(); - let config_locks = ConfigReceipts::new(&mut fake).await.unwrap(); - assert_eq!( - &format!("{}", config_locks.configured.lock.glob), - "/package-data/*/installed/status/configured" - ); - assert_eq!( - &format!("{}", config_locks.config_actions.lock.glob), - "/package-data/*/installed/manifest/config" - ); - assert_eq!( - &format!("{}", config_locks.dependencies.lock.glob), - "/package-data/*/installed/manifest/dependencies" - ); - assert_eq!( - &format!("{}", config_locks.volumes.lock.glob), - "/package-data/*/installed/manifest/volumes" - ); - assert_eq!( - &format!("{}", config_locks.version.lock.glob), - "/package-data/*/installed/manifest/version" - ); - assert_eq!( - &format!("{}", config_locks.volumes.lock.glob), - "/package-data/*/installed/manifest/volumes" - ); - assert_eq!( - &format!("{}", config_locks.manifest.lock.glob), - "/package-data/*/installed/manifest" - ); - assert_eq!( - &format!("{}", config_locks.manifest.lock.glob), - "/package-data/*/installed/manifest" - ); - assert_eq!( - &format!("{}", config_locks.system_pointers.lock.glob), - "/package-data/*/installed/system-pointers" - ); - assert_eq!( - &format!("{}", config_locks.current_dependents.lock.glob), - "/package-data/*/installed/current-dependents" - ); - assert_eq!( - &format!("{}", config_locks.dependency_errors.lock.glob), - "/package-data/*/installed/status/dependency-errors" - ); - assert_eq!( - &format!("{}", config_locks.manifest_dependencies_config.lock.glob), - "/package-data/*/installed/manifest/dependencies/*/config" - ); - assert_eq!( - &format!("{}", config_locks.system_pointers.lock.glob), - "/package-data/*/installed/system-pointers" - ); -} diff --git a/backend/src/config/spec.rs b/backend/src/config/spec.rs index 7aafad1b3..a98ad888d 100644 --- a/backend/src/config/spec.rs +++ b/backend/src/config/spec.rs @@ -1,4 +1,4 @@ -use std::borrow::{Borrow, Cow}; +use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet}; use std::fmt; use std::fmt::Debug; @@ -9,15 +9,16 @@ use std::sync::Arc; use std::time::Duration; use async_trait::async_trait; +use imbl::Vector; +use imbl_value::InternedString; use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; use jsonpath_lib::Compiled as CompiledJsonPath; -use patch_db::{DbHandle, LockReceipt, LockType}; +use patch_db::value::{Number, Value}; use rand::{CryptoRng, Rng}; use regex::Regex; use serde::de::{MapAccess, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_json::{Number, Value}; use sqlx::PgPool; use super::util::{self, CharSet, NumRange, UniqueBy, STATIC_NULL}; @@ -26,8 +27,8 @@ use crate::config::ConfigurationError; use crate::context::RpcContext; use crate::net::interface::InterfaceId; use crate::net::keys::Key; +use crate::prelude::*; use crate::s9pk::manifest::{Manifest, PackageId}; -use crate::Error; // Config Value Specifications #[async_trait] @@ -39,14 +40,12 @@ pub trait ValueSpec { // since not all inVariant can be checked by the type fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath>; // update is to fill in values for environment pointers recursively - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError>; // returns all pointers that are live in the provided config fn pointers(&self, value: &Value) -> Result, NoMatchWithPath>; @@ -106,7 +105,7 @@ where rng: &mut R, timeout: &Option, ) -> Result { - self.gen_with(self.default_spec().borrow(), rng, timeout) + self.gen_with(self.default_spec(), rng, timeout) } } @@ -156,17 +155,15 @@ where fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { self.inner.validate(manifest) } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { self.inner - .update(ctx, db, manifest, config_overrides, value, receipts) + .update(ctx, manifest, config_overrides, value) .await } fn pointers(&self, value: &Value) -> Result, NoMatchWithPath> { @@ -201,17 +198,15 @@ where fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { self.inner.validate(manifest) } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { self.inner - .update(ctx, db, manifest, config_overrides, value, receipts) + .update(ctx, manifest, config_overrides, value) .await } fn pointers(&self, value: &Value) -> Result, NoMatchWithPath> { @@ -279,17 +274,15 @@ where fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { self.inner.validate(manifest) } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { self.inner - .update(ctx, db, manifest, config_overrides, value, receipts) + .update(ctx, manifest, config_overrides, value) .await } fn pointers(&self, value: &Value) -> Result, NoMatchWithPath> { @@ -394,48 +387,22 @@ impl ValueSpec for ValueSpecAny { ValueSpecAny::Pointer(a) => a.validate(manifest), } } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { match self { - ValueSpecAny::Boolean(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::Enum(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::List(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::Number(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::Object(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::String(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::Union(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecAny::Pointer(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } + ValueSpecAny::Boolean(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::Enum(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::List(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::Number(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::Object(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::String(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::Union(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecAny::Pointer(a) => a.update(ctx, manifest, config_overrides, value).await, } } fn pointers(&self, value: &Value) -> Result, NoMatchWithPath> { @@ -513,14 +480,12 @@ impl ValueSpec for ValueSpecBoolean { fn validate(&self, _manifest: &Manifest) -> Result<(), NoMatchWithPath> { Ok(()) } - async fn update( + async fn update( &self, _ctx: &RpcContext, - _db: &mut Db, _manifest: &Manifest, _config_overrides: &BTreeMap, _value: &mut Value, - _receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { Ok(()) } @@ -584,7 +549,7 @@ impl ValueSpec for ValueSpecEnum { fn matches(&self, val: &Value) -> Result<(), NoMatchWithPath> { match val { Value::String(b) => { - if self.values.contains(b) { + if self.values.contains(&**b) { Ok(()) } else { Err(NoMatchWithPath::new(MatchError::Enum( @@ -603,14 +568,12 @@ impl ValueSpec for ValueSpecEnum { fn validate(&self, _manifest: &Manifest) -> Result<(), NoMatchWithPath> { Ok(()) } - async fn update( + async fn update( &self, _ctx: &RpcContext, - _db: &mut Db, _manifest: &Manifest, _config_overrides: &BTreeMap, _value: &mut Value, - _receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { Ok(()) } @@ -628,7 +591,7 @@ impl ValueSpec for ValueSpecEnum { } } impl DefaultableWith for ValueSpecEnum { - type DefaultSpec = String; + type DefaultSpec = Arc; type Error = crate::util::Never; fn gen_with( @@ -666,13 +629,13 @@ where .map(|(i, v)| { self.spec .matches(v) - .map_err(|e| e.prepend(format!("{}", i)))?; + .map_err(|e| e.prepend(InternedString::from_display(&i)))?; if l.iter() .enumerate() .any(|(i2, v2)| i != i2 && self.spec.eq(v, v2)) { Err(NoMatchWithPath::new(MatchError::ListUniquenessViolation) - .prepend(format!("{}", i))) + .prepend(InternedString::from_display(&i))) } else { Ok(()) } @@ -690,25 +653,19 @@ where fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { self.spec.validate(manifest) } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { if let Value::Array(ref mut ls) = value { - for (i, val) in ls.into_iter().enumerate() { - match self - .spec - .update(ctx, db, manifest, config_overrides, val, receipts) - .await - { - Err(ConfigurationError::NoMatch(e)) => { - Err(ConfigurationError::NoMatch(e.prepend(format!("{}", i)))) - } + for (i, val) in ls.iter_mut().enumerate() { + match self.spec.update(ctx, manifest, config_overrides, val).await { + Err(ConfigurationError::NoMatch(e)) => Err(ConfigurationError::NoMatch( + e.prepend(InternedString::from_display(&i)), + )), a => a, }?; } @@ -755,9 +712,9 @@ where rng: &mut R, timeout: &Option, ) -> Result { - let mut res = Vec::new(); + let mut res = Vector::new(); for spec_member in spec.iter() { - res.push(self.spec.gen_with(spec_member, rng, timeout)?); + res.push_back(self.spec.gen_with(spec_member, rng, timeout)?); } Ok(Value::Array(res)) } @@ -798,36 +755,19 @@ impl ValueSpec for ValueSpecList { ValueSpecList::Union(a) => a.validate(manifest), } } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { match self { - ValueSpecList::Enum(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecList::Number(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecList::Object(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecList::String(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecList::Union(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } + ValueSpecList::Enum(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecList::Number(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecList::Object(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecList::String(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecList::Union(a) => a.update(ctx, manifest, config_overrides, value).await, } } fn pointers(&self, value: &Value) -> Result, NoMatchWithPath> { @@ -885,7 +825,7 @@ impl Defaultable for ValueSpecList { ) .contains(&ret.len()) { - ret.push( + ret.push_back( a.inner .inner .spec @@ -941,14 +881,12 @@ impl ValueSpec for ValueSpecNumber { fn validate(&self, _manifest: &Manifest) -> Result<(), NoMatchWithPath> { Ok(()) } - async fn update( + async fn update( &self, _ctx: &RpcContext, - _db: &mut Db, _manifest: &Manifest, _config_overrides: &BTreeMap, _value: &mut Value, - _receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { Ok(()) } @@ -1005,19 +943,15 @@ impl ValueSpec for ValueSpecObject { fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { self.spec.validate(manifest) } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { if let Value::Object(o) = value { - self.spec - .update(ctx, db, manifest, config_overrides, o, receipts) - .await + self.spec.update(ctx, manifest, config_overrides, o).await } else { Err(ConfigurationError::NoMatch(NoMatchWithPath::new( MatchError::InvalidType("object", value.type_of()), @@ -1074,11 +1008,11 @@ impl Defaultable for ValueSpecObject { } #[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct ConfigSpec(pub IndexMap); +pub struct ConfigSpec(pub IndexMap); impl ConfigSpec { pub fn matches(&self, value: &Config) -> Result<(), NoMatchWithPath> { for (key, val) in self.0.iter() { - if let Some(v) = value.get(key) { + if let Some(v) = value.get(&**key) { val.matches(v).map_err(|e| e.prepend(key.clone()))?; } else { val.matches(&Value::Null) @@ -1108,27 +1042,21 @@ impl ConfigSpec { Ok(()) } - pub async fn update( + pub async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, cfg: &mut Config, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { for (k, vs) in self.0.iter() { match cfg.get_mut(k) { None => { let mut v = Value::Null; - vs.update(ctx, db, manifest, config_overrides, &mut v, receipts) - .await?; + vs.update(ctx, manifest, config_overrides, &mut v).await?; cfg.insert(k.clone(), v); } - Some(v) => match vs - .update(ctx, db, manifest, config_overrides, v, receipts) - .await - { + Some(v) => match vs.update(ctx, manifest, config_overrides, v).await { Err(ConfigurationError::NoMatch(e)) => { Err(ConfigurationError::NoMatch(e.prepend(k.clone()))) } @@ -1247,7 +1175,7 @@ impl<'de> Deserialize<'de> for ValueSpecString { }) } } - const FIELDS: &'static [&'static str] = &[ + const FIELDS: &[&str] = &[ "pattern", "pattern-description", "textarea", @@ -1268,7 +1196,7 @@ impl ValueSpec for ValueSpecString { Ok(()) } else { Err(NoMatchWithPath::new(MatchError::Pattern( - s.to_owned(), + s.clone(), pattern.pattern.clone(), ))) } @@ -1286,14 +1214,12 @@ impl ValueSpec for ValueSpecString { fn validate(&self, _manifest: &Manifest) -> Result<(), NoMatchWithPath> { Ok(()) } - async fn update( + async fn update( &self, _ctx: &RpcContext, - _db: &mut Db, _manifest: &Manifest, _config_overrides: &BTreeMap, _value: &mut Value, - _receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { Ok(()) } @@ -1352,11 +1278,11 @@ pub enum DefaultString { Entropy(Entropy), } impl DefaultString { - pub fn gen(&self, rng: &mut R) -> String { - match self { + pub fn gen(&self, rng: &mut R) -> Arc { + Arc::new(match self { DefaultString::Literal(s) => s.clone(), DefaultString::Entropy(e) => e.gen(rng), - } + }) } } @@ -1380,7 +1306,7 @@ impl Entropy { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub struct UnionTag { - pub id: String, + pub id: InternedString, pub name: String, pub description: Option, pub variant_names: BTreeMap, @@ -1401,7 +1327,7 @@ impl<'de> serde::de::Deserialize<'de> for ValueSpecUnion { #[serde(rename_all = "kebab-case")] #[serde(untagged)] pub enum _UnionTag { - Old(String), + Old(InternedString), New(UnionTag), } #[derive(Deserialize)] @@ -1419,7 +1345,7 @@ impl<'de> serde::de::Deserialize<'de> for ValueSpecUnion { tag: match u.tag { _UnionTag::Old(id) => UnionTag { id: id.clone(), - name: id, + name: id.to_string(), description: None, variant_names: u .variants @@ -1461,10 +1387,10 @@ impl ValueSpec for ValueSpecUnion { fn matches(&self, value: &Value) -> Result<(), NoMatchWithPath> { match value { Value::Object(o) => { - if let Some(Value::String(ref tag)) = o.get(&self.tag.id) { - if let Some(obj_spec) = self.variants.get(tag) { + if let Some(Value::String(ref tag)) = o.get(&*self.tag.id) { + if let Some(obj_spec) = self.variants.get(&**tag) { let mut without_tag = o.clone(); - without_tag.remove(&self.tag.id); + without_tag.remove(&*self.tag.id); obj_spec.matches(&without_tag) } else { Err(NoMatchWithPath::new(MatchError::Union( @@ -1487,7 +1413,7 @@ impl ValueSpec for ValueSpecUnion { } fn validate(&self, manifest: &Manifest) -> Result<(), NoMatchWithPath> { for (name, variant) in &self.variants { - if variant.0.get(&self.tag.id).is_some() { + if variant.0.get(&*self.tag.id).is_some() { return Err(NoMatchWithPath::new(MatchError::PropertyMatchesUnionTag( self.tag.id.clone(), name.clone(), @@ -1497,28 +1423,23 @@ impl ValueSpec for ValueSpecUnion { } Ok(()) } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { if let Value::Object(o) = value { - match o.get(&self.tag.id) { + match o.get(&*self.tag.id) { None => Err(ConfigurationError::NoMatch(NoMatchWithPath::new( MatchError::MissingTag(self.tag.id.clone()), ))), - Some(Value::String(tag)) => match self.variants.get(tag) { + Some(Value::String(tag)) => match self.variants.get(&**tag) { None => Err(ConfigurationError::NoMatch(NoMatchWithPath::new( MatchError::Union(tag.clone(), self.variants.keys().cloned().collect()), ))), - Some(spec) => { - spec.update(ctx, db, manifest, config_overrides, o, receipts) - .await - } + Some(spec) => spec.update(ctx, manifest, config_overrides, o).await, }, Some(other) => Err(ConfigurationError::NoMatch( NoMatchWithPath::new(MatchError::InvalidType("string", other.type_of())) @@ -1533,11 +1454,11 @@ impl ValueSpec for ValueSpecUnion { } fn pointers(&self, value: &Value) -> Result, NoMatchWithPath> { if let Value::Object(o) = value { - match o.get(&self.tag.id) { + match o.get(&*self.tag.id) { None => Err(NoMatchWithPath::new(MatchError::MissingTag( self.tag.id.clone(), ))), - Some(Value::String(tag)) => match self.variants.get(tag) { + Some(Value::String(tag)) => match self.variants.get(&**tag) { None => Err(NoMatchWithPath::new(MatchError::Union( tag.clone(), self.variants.keys().cloned().collect(), @@ -1559,8 +1480,8 @@ impl ValueSpec for ValueSpecUnion { } fn requires(&self, id: &PackageId, value: &Value) -> bool { if let Value::Object(o) = value { - match o.get(&self.tag.id) { - Some(Value::String(tag)) => match self.variants.get(tag) { + match o.get(&*self.tag.id) { + Some(Value::String(tag)) => match self.variants.get(&**tag) { None => false, Some(spec) => spec.requires(id, o), }, @@ -1578,7 +1499,7 @@ impl ValueSpec for ValueSpecUnion { } } impl DefaultableWith for ValueSpecUnion { - type DefaultSpec = String; + type DefaultSpec = Arc; type Error = ConfigurationError; fn gen_with( @@ -1587,7 +1508,7 @@ impl DefaultableWith for ValueSpecUnion { rng: &mut R, timeout: &Option, ) -> Result { - let variant = if let Some(v) = self.variants.get(spec) { + let variant = if let Some(v) = self.variants.get(&**spec) { v } else { return Err(ConfigurationError::NoMatch(NoMatchWithPath::new( @@ -1643,24 +1564,16 @@ impl ValueSpec for ValueSpecPointer { ValueSpecPointer::System(a) => a.validate(manifest), } } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { match self { - ValueSpecPointer::Package(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } - ValueSpecPointer::System(a) => { - a.update(ctx, db, manifest, config_overrides, value, receipts) - .await - } + ValueSpecPointer::Package(a) => a.update(ctx, manifest, config_overrides, value).await, + ValueSpecPointer::System(a) => a.update(ctx, manifest, config_overrides, value).await, } } fn pointers(&self, _value: &Value) -> Result, NoMatchWithPath> { @@ -1697,23 +1610,17 @@ impl PackagePointerSpec { PackagePointerSpec::Config(ConfigPointer { package_id, .. }) => package_id, } } - async fn deref( + async fn deref( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, - receipts: &ConfigPointerReceipts, ) -> Result { match &self { PackagePointerSpec::TorKey(key) => key.deref(&manifest.id, &ctx.secret_store).await, - PackagePointerSpec::TorAddress(tor) => { - tor.deref(db, &receipts.interface_addresses_receipt).await - } - PackagePointerSpec::LanAddress(lan) => { - lan.deref(db, &receipts.interface_addresses_receipt).await - } - PackagePointerSpec::Config(cfg) => cfg.deref(ctx, db, config_overrides, receipts).await, + PackagePointerSpec::TorAddress(tor) => tor.deref(ctx).await, + PackagePointerSpec::LanAddress(lan) => lan.deref(ctx).await, + PackagePointerSpec::Config(cfg) => cfg.deref(ctx, config_overrides).await, } } } @@ -1754,18 +1661,14 @@ impl ValueSpec for PackagePointerSpec { _ => Ok(()), } } - async fn update( + async fn update( &self, ctx: &RpcContext, - db: &mut Db, manifest: &Manifest, config_overrides: &BTreeMap, value: &mut Value, - receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { - *value = self - .deref(ctx, db, manifest, config_overrides, receipts) - .await?; + *value = self.deref(ctx, manifest, config_overrides).await?; Ok(()) } fn pointers(&self, _value: &Value) -> Result, NoMatchWithPath> { @@ -1788,18 +1691,19 @@ pub struct TorAddressPointer { interface: InterfaceId, } impl TorAddressPointer { - async fn deref( - &self, - db: &mut Db, - receipt: &InterfaceAddressesReceipt, - ) -> Result { - let addr = receipt - .interface_addresses - .get(db, (&self.package_id, &self.interface)) + async fn deref(&self, ctx: &RpcContext) -> Result { + let addr = ctx + .db + .peek() .await - .map_err(|e| ConfigurationError::SystemError(Error::from(e)))? - .and_then(|addresses| addresses.tor_address); - Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null)) + .as_package_data() + .as_idx(&self.package_id) + .and_then(|pde| pde.as_installed()) + .and_then(|i| i.as_interface_addresses().as_idx(&self.interface)) + .and_then(|a| a.as_tor_address().de().transpose()) + .transpose() + .map_err(|e| ConfigurationError::SystemError(e))?; + Ok(addr.map(Arc::new).map(Value::String).unwrap_or(Value::Null)) } } impl fmt::Display for TorAddressPointer { @@ -1813,39 +1717,6 @@ impl fmt::Display for TorAddressPointer { } } -pub struct InterfaceAddressesReceipt { - interface_addresses: LockReceipt, -} - -impl InterfaceAddressesReceipt { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - // let cleanup_receipts = CleanupFailedReceipts::setup(locks); - - let interface_addresses = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.interface_addresses().star()) - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - // cleanup_receipts: cleanup_receipts(skeleton_key)?, - interface_addresses: interface_addresses.verify(skeleton_key)?, - }) - } - } -} - #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub struct LanAddressPointer { @@ -1862,73 +1733,26 @@ impl fmt::Display for LanAddressPointer { } } impl LanAddressPointer { - async fn deref( - &self, - db: &mut Db, - receipts: &InterfaceAddressesReceipt, - ) -> Result { - let addr = receipts - .interface_addresses - .get(db, (&self.package_id, &self.interface)) + async fn deref(&self, ctx: &RpcContext) -> Result { + let addr = ctx + .db + .peek() .await - .ok() - .flatten() - .and_then(|x| x.lan_address); - Ok(addr.to_owned().map(Value::String).unwrap_or(Value::Null)) + .as_package_data() + .as_idx(&self.package_id) + .and_then(|pde| pde.as_installed()) + .and_then(|i| i.as_interface_addresses().as_idx(&self.interface)) + .and_then(|a| a.as_lan_address().de().transpose()) + .transpose() + .map_err(|e| ConfigurationError::SystemError(e))?; + Ok(addr + .to_owned() + .map(Arc::new) + .map(Value::String) + .unwrap_or(Value::Null)) } } -pub struct ConfigPointerReceipts { - interface_addresses_receipt: InterfaceAddressesReceipt, - manifest_volumes: LockReceipt, - manifest_version: LockReceipt, - config_actions: LockReceipt, -} - -impl ConfigPointerReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let interface_addresses_receipt = InterfaceAddressesReceipt::setup(locks); - - let manifest_volumes = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().volumes()) - .make_locker(LockType::Read) - .add_to_keys(locks); - let manifest_version = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().version()) - .make_locker(LockType::Read) - .add_to_keys(locks); - let config_actions = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().config()) - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - interface_addresses_receipt: interface_addresses_receipt(skeleton_key)?, - manifest_volumes: manifest_volumes.verify(skeleton_key)?, - config_actions: config_actions.verify(skeleton_key)?, - manifest_version: manifest_version.verify(skeleton_key)?, - }) - } - } -} #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub struct ConfigPointer { @@ -1940,25 +1764,34 @@ impl ConfigPointer { pub fn select(&self, val: &Value) -> Value { self.selector.select(self.multi, val) } - async fn deref( + async fn deref( &self, ctx: &RpcContext, - db: &mut Db, config_overrides: &BTreeMap, - receipts: &ConfigPointerReceipts, ) -> Result { if let Some(cfg) = config_overrides.get(&self.package_id) { Ok(self.select(&Value::Object(cfg.clone()))) } else { let id = &self.package_id; - let version = receipts.manifest_version.get(db, id).await.ok().flatten(); - let cfg_actions = receipts.config_actions.get(db, id).await.ok().flatten(); - let volumes = receipts.manifest_volumes.get(db, id).await.ok().flatten(); - if let (Some(version), Some(cfg_actions), Some(volumes)) = - (&version, &cfg_actions, &volumes) - { + let db = ctx.db.peek().await; + let manifest = db.as_package_data().as_idx(id).map(|pde| pde.as_manifest()); + let cfg_actions = manifest.and_then(|m| m.as_config().transpose_ref()); + if let (Some(manifest), Some(cfg_actions)) = (manifest, cfg_actions) { let cfg_res = cfg_actions - .get(ctx, &self.package_id, version, volumes) + .de() + .map_err(|e| ConfigurationError::SystemError(e))? + .get( + ctx, + &self.package_id, + &manifest + .as_version() + .de() + .map_err(|e| ConfigurationError::SystemError(e))?, + &manifest + .as_volumes() + .de() + .map_err(|e| ConfigurationError::SystemError(e))?, + ) .await .map_err(|e| ConfigurationError::SystemError(e))?; if let Some(cfg) = cfg_res.config { @@ -1990,7 +1823,7 @@ pub struct ConfigSelector { } impl ConfigSelector { fn select(&self, multi: bool, val: &Value) -> Value { - let selected = self.compiled.select(&val).ok().unwrap_or_else(Vec::new); + let selected = self.compiled.select(&val).ok().unwrap_or_else(Vector::new); if multi { Value::Array(selected.into_iter().cloned().collect()) } else { @@ -2061,18 +1894,19 @@ impl TorKeyPointer { )); } let key = Key::for_interface( - &mut secrets + secrets .acquire() .await - .map_err(|e| ConfigurationError::SystemError(e.into()))?, + .map_err(|e| ConfigurationError::SystemError(e.into()))? + .as_mut(), Some((self.package_id.clone(), self.interface.clone())), ) .await .map_err(ConfigurationError::SystemError)?; - Ok(Value::String(base32::encode( + Ok(Value::String(Arc::new(base32::encode( base32::Alphabet::RFC4648 { padding: false }, &key.tor_key().as_bytes(), - ))) + )))) } } impl fmt::Display for TorKeyPointer { @@ -2092,7 +1926,7 @@ impl fmt::Display for SystemPointerSpec { } } impl SystemPointerSpec { - async fn deref(&self, _db: &mut Db) -> Result { + async fn deref(&self, _ctx: &RpcContext) -> Result { #[allow(unreachable_code)] Ok(match *self {}) } @@ -2115,17 +1949,14 @@ impl ValueSpec for SystemPointerSpec { fn validate(&self, _manifest: &Manifest) -> Result<(), NoMatchWithPath> { Ok(()) } - async fn update( + async fn update( &self, - _ctx: &RpcContext, - db: &mut Db, + ctx: &RpcContext, _manifest: &Manifest, _config_overrides: &BTreeMap, value: &mut Value, - - _receipts: &ConfigPointerReceipts, ) -> Result<(), ConfigurationError> { - *value = self.deref(db).await?; + *value = self.deref(ctx).await?; Ok(()) } fn pointers(&self, _value: &Value) -> Result, NoMatchWithPath> { diff --git a/backend/src/config/util.rs b/backend/src/config/util.rs index f6acd092e..359c24476 100644 --- a/backend/src/config/util.rs +++ b/backend/src/config/util.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; use std::ops::{Bound, RangeBounds, RangeInclusive}; +use patch_db::Value; use rand::distributions::Distribution; use rand::Rng; -use serde_json::Value; use super::Config; @@ -321,7 +321,7 @@ impl UniqueBy { match self { UniqueBy::Any(any) => any.iter().any(|u| u.eq(lhs, rhs)), UniqueBy::All(all) => all.iter().all(|u| u.eq(lhs, rhs)), - UniqueBy::Exactly(key) => lhs.get(key) == rhs.get(key), + UniqueBy::Exactly(key) => lhs.get(&**key) == rhs.get(&**key), UniqueBy::NotUnique => false, } } diff --git a/backend/src/context/cli.rs b/backend/src/context/cli.rs index 25adecdde..020b73459 100644 --- a/backend/src/context/cli.rs +++ b/backend/src/context/cli.rs @@ -6,8 +6,7 @@ use std::sync::Arc; use clap::ArgMatches; use color_eyre::eyre::eyre; -use cookie::Cookie; -use cookie_store::CookieStore; +use cookie_store::{CookieStore, RawCookie}; use josekit::jwk::Jwk; use reqwest::Proxy; use reqwest_cookie_store::CookieStoreMutex; @@ -111,7 +110,10 @@ impl CliContext { }; if let Ok(local) = std::fs::read_to_string(LOCAL_AUTH_COOKIE_PATH) { store - .insert_raw(&Cookie::new("local", local), &"http://localhost".parse()?) + .insert_raw( + &RawCookie::new("local", local), + &"http://localhost".parse()?, + ) .with_kind(crate::ErrorKind::Network)?; } store diff --git a/backend/src/context/rpc.rs b/backend/src/context/rpc.rs index f1ab1a79e..f235572e4 100644 --- a/backend/src/context/rpc.rs +++ b/backend/src/context/rpc.rs @@ -4,38 +4,37 @@ use std::ops::Deref; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use std::time::Duration; -use bollard::Docker; use helpers::to_tmp_path; use josekit::jwk::Jwk; -use models::PackageId; use patch_db::json_ptr::JsonPointer; -use patch_db::{DbHandle, LockReceipt, LockType, PatchDb}; +use patch_db::PatchDb; use reqwest::{Client, Proxy, Url}; use rpc_toolkit::Context; use serde::Deserialize; use sqlx::postgres::PgConnectOptions; use sqlx::PgPool; use tokio::sync::{broadcast, oneshot, Mutex, RwLock}; +use tokio::time::Instant; use tracing::instrument; use super::setup::CURRENT_SECRET; use crate::account::AccountInfo; -use crate::config::hook::ConfigHook; use crate::core::rpc_continuations::{RequestGuid, RestHandler, RpcContinuation}; -use crate::db::model::{CurrentDependents, Database, InstalledPackageDataEntry, PackageDataEntry}; +use crate::db::model::{CurrentDependents, Database, PackageDataEntryMatchModelRef}; +use crate::db::prelude::PatchDbExt; +use crate::dependencies::compute_dependency_config_errs; use crate::disk::OsPartitionInfo; use crate::init::init_postgres; -use crate::install::cleanup::{cleanup_failed, uninstall, CleanupFailedReceipts}; +use crate::install::cleanup::{cleanup_failed, uninstall}; use crate::manager::ManagerMap; use crate::middleware::auth::HashSessionToken; use crate::net::net_controller::NetController; -use crate::net::ssl::SslManager; +use crate::net::ssl::{root_ca_start_time, SslManager}; use crate::net::wifi::WpaCli; use crate::notifications::NotificationManager; use crate::shutdown::Shutdown; -use crate::status::{MainStatus, Status}; +use crate::status::MainStatus; use crate::system::get_mem_info; use crate::util::config::load_config_from_paths; use crate::util::lshw::{lshw, LshwDevice}; @@ -113,7 +112,6 @@ pub struct RpcContextSeed { pub db: PatchDb, pub secret_store: PgPool, pub account: RwLock, - pub docker: Docker, pub net_controller: Arc, pub managers: ManagerMap, pub metrics_cache: RwLock>, @@ -124,9 +122,9 @@ pub struct RpcContextSeed { pub rpc_stream_continuations: Mutex>, pub wifi_manager: Option>>, pub current_secret: Arc, - pub config_hooks: Mutex>>, pub client: Client, pub hardware: Hardware, + pub start_time: Instant, } pub struct Hardware { @@ -134,49 +132,11 @@ pub struct Hardware { pub ram: u64, } -pub struct RpcCleanReceipts { - cleanup_receipts: CleanupFailedReceipts, - packages: LockReceipt, - package: LockReceipt, -} - -impl RpcCleanReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let cleanup_receipts = CleanupFailedReceipts::setup(locks); - - let packages = crate::db::DatabaseModel::new() - .package_data() - .make_locker(LockType::Write) - .add_to_keys(locks); - let package = crate::db::DatabaseModel::new() - .package_data() - .star() - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - cleanup_receipts: cleanup_receipts(skeleton_key)?, - packages: packages.verify(skeleton_key)?, - package: package.verify(skeleton_key)?, - }) - } - } -} - #[derive(Clone)] pub struct RpcContext(Arc); impl RpcContext { #[instrument(skip_all)] - pub async fn init + Send + 'static>( + pub async fn init + Send + Sync + 'static>( cfg_path: Option

, disk_guid: Arc, ) -> Result { @@ -192,19 +152,15 @@ impl RpcContext { let account = AccountInfo::load(&secret_store).await?; let db = base.db(&account).await?; tracing::info!("Opened PatchDB"); - let mut docker = Docker::connect_with_unix_defaults()?; - docker.set_timeout(Duration::from_secs(600)); - tracing::info!("Connected to Docker"); let net_controller = Arc::new( NetController::init( base.tor_control .unwrap_or(SocketAddr::from(([127, 0, 0, 1], 9051))), tor_proxy, base.dns_bind - .as_ref() - .map(|v| v.as_slice()) + .as_deref() .unwrap_or(&[SocketAddr::from(([127, 0, 0, 1], 53))]), - SslManager::new(&account)?, + SslManager::new(&account, root_ca_start_time().await?)?, &account.hostname, &account.key, ) @@ -212,7 +168,7 @@ impl RpcContext { ); tracing::info!("Initialized Net Controller"); let managers = ManagerMap::default(); - let metrics_cache = RwLock::new(None); + let metrics_cache = RwLock::>::new(None); let notification_manager = NotificationManager::new(secret_store.clone()); tracing::info!("Initialized Notification Manager"); let tor_proxy_url = format!("socks5h://{tor_proxy}"); @@ -228,7 +184,6 @@ impl RpcContext { db, secret_store, account: RwLock::new(account), - docker, net_controller, managers, metrics_cache, @@ -250,7 +205,6 @@ impl RpcContext { ) })?, ), - config_hooks: Mutex::new(BTreeMap::new()), client: Client::builder() .proxy(Proxy::custom(move |url| { if url.host_str().map_or(false, |h| h.ends_with(".onion")) { @@ -262,19 +216,12 @@ impl RpcContext { .build() .with_kind(crate::ErrorKind::ParseUrl)?, hardware: Hardware { devices, ram }, + start_time: Instant::now(), }); - let res = Self(seed); - res.cleanup().await?; + let res = Self(seed.clone()); + res.cleanup_and_initialize().await?; tracing::info!("Cleaned up transient states"); - res.managers - .init( - &res, - &mut res.db.handle(), - &mut res.secret_store.acquire().await?, - ) - .await?; - tracing::info!("Initialized Package Managers"); Ok(res) } @@ -288,118 +235,150 @@ impl RpcContext { Ok(()) } - #[instrument(skip_all)] - pub async fn cleanup(&self) -> Result<(), Error> { - let mut db = self.db.handle(); - let receipts = RpcCleanReceipts::new(&mut db).await?; - let packages = receipts.packages.get(&mut db).await?.0; - let mut current_dependents = packages - .keys() - .map(|k| (k.clone(), BTreeMap::new())) - .collect::>(); - for (package_id, package) in packages { - for (k, v) in package - .into_installed() - .into_iter() - .flat_map(|i| i.current_dependencies.0) - { - let mut entry: BTreeMap<_, _> = current_dependents.remove(&k).unwrap_or_default(); - entry.insert(package_id.clone(), v); - current_dependents.insert(k, entry); - } - } - for (package_id, current_dependents) in current_dependents { - if let Some(deps) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&package_id) - .and_then(|pde| pde.installed()) - .map::<_, CurrentDependents>(|i| i.current_dependents()) - .check(&mut db) - .await? - { - deps.put(&mut db, &CurrentDependents(current_dependents)) - .await?; - } else if let Some(deps) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&package_id) - .and_then(|pde| pde.removing()) - .map::<_, CurrentDependents>(|i| i.current_dependents()) - .check(&mut db) - .await? - { - deps.put(&mut db, &CurrentDependents(current_dependents)) - .await?; - } - } - for (package_id, package) in receipts.packages.get(&mut db).await?.0 { - if let Err(e) = async { - match package { - PackageDataEntry::Installing { .. } - | PackageDataEntry::Restoring { .. } - | PackageDataEntry::Updating { .. } => { - cleanup_failed(self, &mut db, &package_id, &receipts.cleanup_receipts) - .await?; - } - PackageDataEntry::Removing { .. } => { - uninstall( - self, - &mut db, - &mut self.secret_store.acquire().await?, - &package_id, - ) - .await?; - } - PackageDataEntry::Installed { - installed, - static_files, - manifest, - } => { - for (volume_id, volume_info) in &*manifest.volumes { - let tmp_path = to_tmp_path(volume_info.path_for( - &self.datadir, - &package_id, - &manifest.version, - &volume_id, - )) - .with_kind(ErrorKind::Filesystem)?; - if tokio::fs::metadata(&tmp_path).await.is_ok() { - tokio::fs::remove_dir_all(&tmp_path).await?; - } - } - let status = installed.status; - let main = match status.main { - MainStatus::BackingUp { started, .. } => { - if let Some(_) = started { - MainStatus::Starting - } else { - MainStatus::Stopped - } - } - MainStatus::Running { .. } => MainStatus::Starting, - a => a.clone(), - }; - let new_package = PackageDataEntry::Installed { - installed: InstalledPackageDataEntry { - status: Status { main, ..status }, - ..installed - }, - static_files, - manifest, - }; - receipts - .package - .set(&mut db, new_package, &package_id) - .await?; + #[instrument(skip(self))] + pub async fn cleanup_and_initialize(&self) -> Result<(), Error> { + self.db + .mutate(|f| { + let mut current_dependents = f + .as_package_data() + .keys()? + .into_iter() + .map(|k| (k.clone(), BTreeMap::new())) + .collect::>(); + for (package_id, package) in f.as_package_data_mut().as_entries_mut()? { + for (k, v) in package + .as_installed_mut() + .into_iter() + .flat_map(|i| i.clone().into_current_dependencies().into_entries()) + .flatten() + { + let mut entry: BTreeMap<_, _> = + current_dependents.remove(&k).unwrap_or_default(); + entry.insert(package_id.clone(), v.de()?); + current_dependents.insert(k, entry); } } - Ok::<_, Error>(()) - } - .await - { + for (package_id, current_dependents) in current_dependents { + if let Some(deps) = f + .as_package_data_mut() + .as_idx_mut(&package_id) + .and_then(|pde| pde.expect_as_installed_mut().ok()) + .map(|i| i.as_installed_mut().as_current_dependents_mut()) + { + deps.ser(&CurrentDependents(current_dependents))?; + } else if let Some(deps) = f + .as_package_data_mut() + .as_idx_mut(&package_id) + .and_then(|pde| pde.expect_as_removing_mut().ok()) + .map(|i| i.as_removing_mut().as_current_dependents_mut()) + { + deps.ser(&CurrentDependents(current_dependents))?; + } + } + Ok(()) + }) + .await?; + + let peek = self.db.peek().await; + + for (package_id, package) in peek.as_package_data().as_entries()?.into_iter() { + let action = match package.as_match() { + PackageDataEntryMatchModelRef::Installing(_) + | PackageDataEntryMatchModelRef::Restoring(_) + | PackageDataEntryMatchModelRef::Updating(_) => { + cleanup_failed(self, &package_id).await + } + PackageDataEntryMatchModelRef::Removing(_) => { + uninstall( + self, + self.secret_store.acquire().await?.as_mut(), + &package_id, + ) + .await + } + PackageDataEntryMatchModelRef::Installed(m) => { + let version = m.as_manifest().as_version().clone().de()?; + let volumes = m.as_manifest().as_volumes().de()?; + for (volume_id, volume_info) in &*volumes { + let tmp_path = to_tmp_path(volume_info.path_for( + &self.datadir, + &package_id, + &version, + volume_id, + )) + .with_kind(ErrorKind::Filesystem)?; + if tokio::fs::metadata(&tmp_path).await.is_ok() { + tokio::fs::remove_dir_all(&tmp_path).await?; + } + } + Ok(()) + } + _ => continue, + }; + if let Err(e) = action { tracing::error!("Failed to clean up package {}: {}", package_id, e); tracing::debug!("{:?}", e); } } + let peek = self + .db + .mutate(|v| { + for (_, pde) in v.as_package_data_mut().as_entries_mut()? { + let status = pde + .expect_as_installed_mut()? + .as_installed_mut() + .as_status_mut() + .as_main_mut(); + let running = status.clone().de()?.running(); + status.ser(&if running { + MainStatus::Starting + } else { + MainStatus::Stopped + })?; + } + Ok(v.clone()) + }) + .await?; + self.managers.init(self.clone(), peek.clone()).await?; + tracing::info!("Initialized Package Managers"); + + let mut all_dependency_config_errs = BTreeMap::new(); + for (package_id, package) in peek.as_package_data().as_entries()?.into_iter() { + let package = package.clone(); + if let Some(current_dependencies) = package + .as_installed() + .and_then(|x| x.as_current_dependencies().de().ok()) + { + let manifest = package.as_manifest().de()?; + all_dependency_config_errs.insert( + package_id.clone(), + compute_dependency_config_errs( + self, + &peek, + &manifest, + ¤t_dependencies, + &Default::default(), + ) + .await?, + ); + } + } + self.db + .mutate(|v| { + for (package_id, errs) in all_dependency_config_errs { + if let Some(config_errors) = v + .as_package_data_mut() + .as_idx_mut(&package_id) + .and_then(|pde| pde.as_installed_mut()) + .map(|i| i.as_status_mut().as_dependency_config_errors_mut()) + { + config_errors.ser(&errs)?; + } + } + Ok(()) + }) + .await?; + Ok(()) } @@ -457,7 +436,7 @@ impl RpcContext { } impl AsRef for RpcContext { fn as_ref(&self) -> &Jwk { - &*CURRENT_SECRET + &CURRENT_SECRET } } impl Context for RpcContext {} @@ -471,7 +450,7 @@ impl Deref for RpcContext { tracing_error::SpanTrace::capture() ); } - &*self.0 + &self.0 } } impl Drop for RpcContext { diff --git a/backend/src/context/sdk.rs b/backend/src/context/sdk.rs index 87adaee1f..7ba7a6bfa 100644 --- a/backend/src/context/sdk.rs +++ b/backend/src/context/sdk.rs @@ -7,8 +7,8 @@ use rpc_toolkit::Context; use serde::Deserialize; use tracing::instrument; +use crate::prelude::*; use crate::util::config::{load_config_from_paths, local_config_path}; -use crate::{Error, ResultExt}; #[derive(Debug, Default, Deserialize)] #[serde(rename_all = "kebab-case")] @@ -50,21 +50,21 @@ impl SdkContext { } /// BLOCKING #[instrument(skip_all)] - pub fn developer_key(&self) -> Result { + pub fn developer_key(&self) -> Result { if !self.developer_key_path.exists() { - return Err(Error::new(eyre!("Developer Key does not exist! Please run `embassy-sdk init` before running this command."), crate::ErrorKind::Uninitialized)); + return Err(Error::new(eyre!("Developer Key does not exist! Please run `start-sdk init` before running this command."), crate::ErrorKind::Uninitialized)); } let pair = ::from_pkcs8_pem( &std::fs::read_to_string(&self.developer_key_path)?, ) .with_kind(crate::ErrorKind::Pem)?; - let secret = ed25519_dalek::SecretKey::from_bytes(&pair.secret_key[..])?; - let public = if let Some(public) = pair.public_key { - ed25519_dalek::PublicKey::from_bytes(&public[..])? - } else { - (&secret).into() - }; - Ok(ed25519_dalek::Keypair { secret, public }) + let secret = ed25519_dalek::SecretKey::try_from(&pair.secret_key[..]).map_err(|_| { + Error::new( + eyre!("pkcs8 key is of incorrect length"), + ErrorKind::OpenSsl, + ) + })?; + Ok(secret.into()) } } impl std::ops::Deref for SdkContext { diff --git a/backend/src/control.rs b/backend/src/control.rs index 794afc64a..58e39ac14 100644 --- a/backend/src/control.rs +++ b/backend/src/control.rs @@ -1,220 +1,85 @@ -use std::collections::BTreeMap; - use color_eyre::eyre::eyre; -use patch_db::{DbHandle, LockReceipt, LockType}; use rpc_toolkit::command; use tracing::instrument; use crate::context::RpcContext; -use crate::dependencies::{ - break_all_dependents_transitive, heal_all_dependents_transitive, BreakageRes, DependencyError, - DependencyReceipt, TaggedDependencyError, -}; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; use crate::status::MainStatus; use crate::util::display_none; -use crate::util::serde::display_serializable; use crate::Error; -#[derive(Clone)] -pub struct StartReceipts { - dependency_receipt: DependencyReceipt, - status: LockReceipt, - version: LockReceipt, -} - -impl StartReceipts { - pub async fn new(db: &mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, id); - setup(&db.lock_all(locks).await?) - } - - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let dependency_receipt = DependencyReceipt::setup(locks); - let status = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.status().main()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().version()) - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - dependency_receipt: dependency_receipt(skeleton_key)?, - status: status.verify(skeleton_key)?, - version: version.verify(skeleton_key)?, - }) - } - } -} - #[command(display(display_none), metadata(sync_db = true))] #[instrument(skip_all)] pub async fn start(#[context] ctx: RpcContext, #[arg] id: PackageId) -> Result<(), Error> { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - let receipts = StartReceipts::new(&mut tx, &id).await?; - let version = receipts.version.get(&mut tx).await?; - receipts.status.set(&mut tx, MainStatus::Starting).await?; - heal_all_dependents_transitive(&ctx, &mut tx, &id, &receipts.dependency_receipt).await?; - - tx.commit().await?; - drop(receipts); + let peek = ctx.db.peek().await; + let version = peek + .as_package_data() + .as_idx(&id) + .or_not_found(&id)? + .as_installed() + .or_not_found(&id)? + .as_manifest() + .as_version() + .de()?; ctx.managers .get(&(id, version)) .await .ok_or_else(|| Error::new(eyre!("Manager not found"), crate::ErrorKind::InvalidRequest))? - .start(); + .start() + .await; Ok(()) } -#[derive(Clone)] -pub struct StopReceipts { - breaks: crate::dependencies::BreakTransitiveReceipts, - status: LockReceipt, -} -impl StopReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); +#[command(display(display_none), metadata(sync_db = true))] +pub async fn stop(#[context] ctx: RpcContext, #[arg] id: PackageId) -> Result { + let peek = ctx.db.peek().await; + let version = peek + .as_package_data() + .as_idx(&id) + .or_not_found(&id)? + .as_installed() + .or_not_found(&id)? + .as_manifest() + .as_version() + .de()?; - let setup = Self::setup(&mut locks, id); - setup(&db.lock_all(locks).await?) - } + let last_statuts = ctx + .db + .mutate(|v| { + v.as_package_data_mut() + .as_idx_mut(&id) + .and_then(|x| x.as_installed_mut()) + .ok_or_else(|| Error::new(eyre!("{} is not installed", id), ErrorKind::NotFound))? + .as_status_mut() + .as_main_mut() + .replace(&MainStatus::Stopping) + }) + .await?; - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let breaks = crate::dependencies::BreakTransitiveReceipts::setup(locks); - let status = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.status().main()) - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - breaks: breaks(skeleton_key)?, - status: status.verify(skeleton_key)?, - }) - } - } -} - -#[instrument(skip_all)] -pub async fn stop_common( - db: &mut Db, - id: &PackageId, - breakages: &mut BTreeMap, -) -> Result { - let mut tx = db.begin().await?; - let receipts = StopReceipts::new(&mut tx, id).await?; - let last_status = receipts.status.get(&mut tx).await?; - receipts.status.set(&mut tx, MainStatus::Stopping).await?; - - tx.save().await?; - break_all_dependents_transitive( - db, - id, - DependencyError::NotRunning, - breakages, - &receipts.breaks, - ) - .await?; - - Ok(last_status) -} - -#[command( - subcommands(self(stop_impl(async)), stop_dry), - display(display_none), - metadata(sync_db = true) -)] -pub fn stop(#[arg] id: PackageId) -> Result { - Ok(id) -} - -#[command(rename = "dry", display(display_serializable))] -#[instrument(skip_all)] -pub async fn stop_dry( - #[context] ctx: RpcContext, - #[parent_data] id: PackageId, -) -> Result { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - - let mut breakages = BTreeMap::new(); - stop_common(&mut tx, &id, &mut breakages).await?; - - tx.abort().await?; - - Ok(BreakageRes(breakages)) -} - -#[instrument(skip_all)] -pub async fn stop_impl(ctx: RpcContext, id: PackageId) -> Result { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - let version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .expect(&mut tx) - .await? - .installed() - .expect(&mut tx) - .await? - .manifest() - .version() - .get(&mut tx) - .await? - .clone(); - - let last_statuts = stop_common(&mut tx, &id, &mut BTreeMap::new()).await?; - - tx.commit().await?; ctx.managers .get(&(id, version)) .await .ok_or_else(|| Error::new(eyre!("Manager not found"), crate::ErrorKind::InvalidRequest))? - .stop(); + .stop() + .await; Ok(last_statuts) } #[command(display(display_none), metadata(sync_db = true))] pub async fn restart(#[context] ctx: RpcContext, #[arg] id: PackageId) -> Result<(), Error> { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - let version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .expect(&mut tx) - .await? - .installed() - .expect(&mut tx) - .await? - .manifest() - .version() - .get(&mut tx) - .await? - .clone(); - - tx.commit().await?; + let peek = ctx.db.peek().await; + let version = peek + .as_package_data() + .as_idx(&id) + .or_not_found(&id)? + .expect_as_installed()? + .as_manifest() + .as_version() + .de()?; ctx.managers .get(&(id, version)) diff --git a/backend/src/db/mod.rs b/backend/src/db/mod.rs index a8cc11d1f..03ad94338 100644 --- a/backend/src/db/mod.rs +++ b/backend/src/db/mod.rs @@ -1,13 +1,14 @@ pub mod model; pub mod package; +pub mod prelude; use std::future::Future; +use std::path::PathBuf; use std::sync::Arc; -use color_eyre::eyre::eyre; use futures::{FutureExt, SinkExt, StreamExt}; use patch_db::json_ptr::JsonPointer; -use patch_db::{DbHandle, Dump, LockType, Revision}; +use patch_db::{Dump, Revision}; use rpc_toolkit::command; use rpc_toolkit::hyper::upgrade::Upgraded; use rpc_toolkit::hyper::{Body, Error as HyperError, Request, Response}; @@ -22,12 +23,11 @@ use tokio_tungstenite::tungstenite::Message; use tokio_tungstenite::WebSocketStream; use tracing::instrument; -pub use self::model::DatabaseModel; -use crate::context::RpcContext; +use crate::context::{CliContext, RpcContext}; use crate::middleware::auth::{HasValidSession, HashSessionToken}; +use crate::prelude::*; use crate::util::display_none; use crate::util::serde::{display_serializable, IoFormat}; -use crate::{Error, ResultExt}; #[instrument(skip_all)] async fn ws_handler< @@ -37,11 +37,11 @@ async fn ws_handler< session: Option<(HasValidSession, HashSessionToken)>, ws_fut: WSFut, ) -> Result<(), Error> { - let (dump, sub) = ctx.db.dump_and_sub().await?; + let (dump, sub) = ctx.db.dump_and_sub().await; let mut stream = ws_fut .await - .with_kind(crate::ErrorKind::Network)? - .with_kind(crate::ErrorKind::Unknown)?; + .with_kind(ErrorKind::Network)? + .with_kind(ErrorKind::Unknown)?; if let Some((session, token)) = session { let kill = subscribe_to_session_kill(&ctx, token).await; @@ -55,7 +55,7 @@ async fn ws_handler< reason: "UNAUTHORIZED".into(), })) .await - .with_kind(crate::ErrorKind::Network)?; + .with_kind(ErrorKind::Network)?; } Ok(()) @@ -82,6 +82,8 @@ async fn deal_with_messages( mut sub: patch_db::Subscriber, mut stream: WebSocketStream, ) -> Result<(), Error> { + let mut timer = tokio::time::interval(tokio::time::Duration::from_secs(5)); + loop { futures::select! { _ = (&mut kill).fuse() => { @@ -92,18 +94,18 @@ async fn deal_with_messages( reason: "UNAUTHORIZED".into(), })) .await - .with_kind(crate::ErrorKind::Network)?; + .with_kind(ErrorKind::Network)?; return Ok(()) } new_rev = sub.recv().fuse() => { let rev = new_rev.expect("UNREACHABLE: patch-db is dropped"); stream - .send(Message::Text(serde_json::to_string(&rev).with_kind(crate::ErrorKind::Serialization)?)) + .send(Message::Text(serde_json::to_string(&rev).with_kind(ErrorKind::Serialization)?)) .await - .with_kind(crate::ErrorKind::Network)?; + .with_kind(ErrorKind::Network)?; } message = stream.next().fuse() => { - let message = message.transpose().with_kind(crate::ErrorKind::Network)?; + let message = message.transpose().with_kind(ErrorKind::Network)?; match message { None => { tracing::info!("Closing WebSocket: Stream Finished"); @@ -112,6 +114,13 @@ async fn deal_with_messages( _ => (), } } + // This is trying to give a health checks to the home to keep the ui alive. + _ = timer.tick().fuse() => { + stream + .send(Message::Ping(vec![])) + .await + .with_kind(crate::ErrorKind::Network)?; + } } } } @@ -123,10 +132,10 @@ async fn send_dump( ) -> Result<(), Error> { stream .send(Message::Text( - serde_json::to_string(&dump).with_kind(crate::ErrorKind::Serialization)?, + serde_json::to_string(&dump).with_kind(ErrorKind::Serialization)?, )) .await - .with_kind(crate::ErrorKind::Network)?; + .with_kind(ErrorKind::Network)?; Ok(()) } @@ -141,7 +150,7 @@ pub async fn subscribe(ctx: RpcContext, req: Request) -> Result Some(a), Err(e) => { - if e.kind != crate::ErrorKind::Authorization { + if e.kind != ErrorKind::Authorization { tracing::error!("Error Authenticating Websocket: {}", e); tracing::debug!("{:?}", e); } @@ -149,7 +158,7 @@ pub async fn subscribe(ctx: RpcContext, req: Request) -> Result) -> Result Result<(), RpcError> { Ok(()) } @@ -177,28 +186,42 @@ pub enum RevisionsRes { Dump(Dump), } -#[command(display(display_serializable))] -pub async fn revisions( - #[context] ctx: RpcContext, - #[arg] since: u64, - #[allow(unused_variables)] - #[arg(long = "format")] - format: Option, -) -> Result { - Ok(match ctx.db.sync(since).await? { - Ok(revs) => RevisionsRes::Revisions(revs), - Err(dump) => RevisionsRes::Dump(dump), - }) +#[instrument(skip_all)] +async fn cli_dump( + ctx: CliContext, + _format: Option, + path: Option, +) -> Result { + let dump = if let Some(path) = path { + PatchDb::open(path).await?.dump().await + } else { + rpc_toolkit::command_helpers::call_remote( + ctx, + "db.dump", + serde_json::json!({}), + std::marker::PhantomData::, + ) + .await? + .result? + }; + + Ok(dump) } -#[command(display(display_serializable))] +#[command( + custom_cli(cli_dump(async, context(CliContext))), + display(display_serializable) +)] pub async fn dump( #[context] ctx: RpcContext, #[allow(unused_variables)] #[arg(long = "format")] format: Option, + #[allow(unused_variables)] + #[arg] + path: Option, ) -> Result { - Ok(ctx.db.dump().await?) + Ok(ctx.db.dump().await) } fn apply_expr(input: jaq_core::Val, expr: &str) -> Result { @@ -252,34 +275,77 @@ fn apply_expr(input: jaq_core::Val, expr: &str) -> Result Ok(res) } -#[command(display(display_none))] -pub async fn apply(#[context] ctx: RpcContext, #[arg] expr: String) -> Result<(), Error> { - let mut db = ctx.db.handle(); +#[instrument(skip_all)] +async fn cli_apply(ctx: CliContext, expr: String, path: Option) -> Result<(), RpcError> { + if let Some(path) = path { + PatchDb::open(path) + .await? + .mutate(|db| { + let res = apply_expr( + serde_json::to_value(patch_db::Value::from(db.clone())) + .with_kind(ErrorKind::Deserialization)? + .into(), + &expr, + )?; - DatabaseModel::new().lock(&mut db, LockType::Write).await?; - - let root_ptr = JsonPointer::::default(); - - let input = db.get_value(&root_ptr, None).await?; - - let res = (|| { - let res = apply_expr(input.into(), &expr)?; - - serde_json::from_value::(res.clone().into()).with_ctx(|_| { - ( - crate::ErrorKind::Deserialization, - "result does not match database model", - ) - })?; - - Ok::(res.into()) - })()?; - - db.put_value(&root_ptr, &res).await?; + db.ser( + &serde_json::from_value::(res.clone().into()).with_ctx( + |_| { + ( + crate::ErrorKind::Deserialization, + "result does not match database model", + ) + }, + )?, + ) + }) + .await?; + } else { + rpc_toolkit::command_helpers::call_remote( + ctx, + "db.apply", + serde_json::json!({ "expr": expr }), + std::marker::PhantomData::<()>, + ) + .await? + .result?; + } Ok(()) } +#[command( + custom_cli(cli_apply(async, context(CliContext))), + display(display_none) +)] +pub async fn apply( + #[context] ctx: RpcContext, + #[arg] expr: String, + #[allow(unused_variables)] + #[arg] + path: Option, +) -> Result<(), Error> { + ctx.db + .mutate(|db| { + let res = apply_expr( + serde_json::to_value(patch_db::Value::from(db.clone())) + .with_kind(ErrorKind::Deserialization)? + .into(), + &expr, + )?; + + db.ser( + &serde_json::from_value::(res.clone().into()).with_ctx(|_| { + ( + crate::ErrorKind::Deserialization, + "result does not match database model", + ) + })?, + ) + }) + .await +} + #[command(subcommands(ui))] pub fn put() -> Result<(), RpcError> { Ok(()) @@ -297,7 +363,7 @@ pub async fn ui( ) -> Result<(), Error> { let ptr = "/ui" .parse::() - .with_kind(crate::ErrorKind::Database)? + .with_kind(ErrorKind::Database)? + &pointer; ctx.db.put(&ptr, &value).await?; Ok(()) diff --git a/backend/src/db/model.rs b/backend/src/db/model.rs index 6aa1e07cc..e6b091be1 100644 --- a/backend/src/db/model.rs +++ b/backend/src/db/model.rs @@ -4,36 +4,35 @@ use std::sync::Arc; use chrono::{DateTime, Utc}; use emver::VersionRange; +use imbl_value::InternedString; use ipnet::{Ipv4Net, Ipv6Net}; use isocountry::CountryCode; use itertools::Itertools; +use models::{DataUrl, HealthCheckId, InterfaceId}; use openssl::hash::MessageDigest; -use patch_db::json_ptr::JsonPointer; -use patch_db::{HasModel, Map, MapModel, OptionModel}; +use patch_db::{HasModel, Value}; use reqwest::Url; use serde::{Deserialize, Serialize}; -use serde_json::Value; use ssh_key::public::Ed25519PublicKey; use crate::account::AccountInfo; -use crate::config::spec::{PackagePointerSpec, SystemPointerSpec}; +use crate::config::spec::PackagePointerSpec; use crate::install::progress::InstallProgress; use crate::net::forward::LanPortForwards; -use crate::net::interface::InterfaceId; use crate::net::utils::{get_iface_ipv4_addr, get_iface_ipv6_addr}; -use crate::s9pk::manifest::{Manifest, ManifestModel, PackageId}; -use crate::status::health_check::HealthCheckId; +use crate::prelude::*; +use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::Status; use crate::util::Version; use crate::version::{Current, VersionT}; -use crate::Error; +use crate::{ARCH, PLATFORM}; #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] +// #[macro_debug] pub struct Database { - #[model] pub server_info: ServerInfo, - #[model] pub package_data: AllPackageData, pub lan_port_forwards: LanPortForwards, pub ui: Value, @@ -41,9 +40,10 @@ pub struct Database { impl Database { pub fn init(account: &AccountInfo) -> Self { let lan_address = account.hostname.lan_address().parse().unwrap(); - // TODO Database { server_info: ServerInfo { + arch: get_arch(), + platform: get_platform(), id: account.server_id.clone(), version: Current::new().semver().into(), hostname: account.hostname.no_dot_host_name(), @@ -59,6 +59,8 @@ impl Database { backup_progress: None, updated: false, update_progress: None, + shutting_down: false, + restarting: false, }, wifi: WifiInfo { ssids: Vec::new(), @@ -81,8 +83,8 @@ impl Database { .iter() .map(|x| format!("{x:X}")) .join(":"), - system_start_time: Utc::now().to_rfc3339(), - zram: false, + ntp_synced: false, + zram: true, }, package_data: AllPackageData::default(), lan_port_forwards: LanPortForwards::new(), @@ -91,15 +93,25 @@ impl Database { } } } -impl DatabaseModel { - pub fn new() -> Self { - Self::from(JsonPointer::default()) - } + +pub type DatabaseModel = Model; + +fn get_arch() -> InternedString { + (*ARCH).into() +} + +fn get_platform() -> InternedString { + (&*PLATFORM).into() } #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct ServerInfo { + #[serde(default = "get_arch")] + pub arch: InternedString, + #[serde(default = "get_platform")] + pub platform: InternedString, pub id: String, pub hostname: String, pub version: Version, @@ -109,10 +121,7 @@ pub struct ServerInfo { pub eos_version_compat: VersionRange, pub lan_address: Url, pub tor_address: Url, - #[model] - #[serde(default)] pub ip_info: BTreeMap, - #[model] #[serde(default)] pub status_info: ServerStatus, pub wifi: WifiInfo, @@ -121,13 +130,15 @@ pub struct ServerInfo { pub password_hash: String, pub pubkey: String, pub ca_fingerprint: String, - pub system_start_time: String, + #[serde(default)] + pub ntp_synced: bool, #[serde(default)] pub zram: bool, } #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct IpInfo { pub ipv4_range: Option, pub ipv4: Option, @@ -148,29 +159,35 @@ impl IpInfo { } #[derive(Debug, Default, Deserialize, Serialize, HasModel)] +#[model = "Model"] pub struct BackupProgress { pub complete: bool, } #[derive(Debug, Default, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct ServerStatus { - #[model] pub backup_progress: Option>, pub updated: bool, - #[model] pub update_progress: Option, + #[serde(default)] + pub shutting_down: bool, + #[serde(default)] + pub restarting: bool, } #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct UpdateProgress { pub size: Option, pub downloaded: u64, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct WifiInfo { pub ssids: Vec, pub selected: Option, @@ -197,16 +214,11 @@ pub struct AllPackageData(pub BTreeMap); impl Map for AllPackageData { type Key = PackageId; type Value = PackageDataEntry; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -impl HasModel for AllPackageData { - type Model = MapModel; } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct StaticFiles { license: String, instructions: String, @@ -222,120 +234,231 @@ impl StaticFiles { } } +#[derive(Debug, Deserialize, Serialize, HasModel)] +#[serde(rename_all = "kebab-case")] +#[model = "Model"] +pub struct PackageDataEntryInstalling { + pub static_files: StaticFiles, + pub manifest: Manifest, + pub install_progress: Arc, +} + +#[derive(Debug, Deserialize, Serialize, HasModel)] +#[serde(rename_all = "kebab-case")] +#[model = "Model"] +pub struct PackageDataEntryUpdating { + pub static_files: StaticFiles, + pub manifest: Manifest, + pub installed: InstalledPackageInfo, + pub install_progress: Arc, +} + +#[derive(Debug, Deserialize, Serialize, HasModel)] +#[serde(rename_all = "kebab-case")] +#[model = "Model"] +pub struct PackageDataEntryRestoring { + pub static_files: StaticFiles, + pub manifest: Manifest, + pub install_progress: Arc, +} + +#[derive(Debug, Deserialize, Serialize, HasModel)] +#[serde(rename_all = "kebab-case")] +#[model = "Model"] +pub struct PackageDataEntryRemoving { + pub static_files: StaticFiles, + pub manifest: Manifest, + pub removing: InstalledPackageInfo, +} + +#[derive(Debug, Deserialize, Serialize, HasModel)] +#[serde(rename_all = "kebab-case")] +#[model = "Model"] +pub struct PackageDataEntryInstalled { + pub static_files: StaticFiles, + pub manifest: Manifest, + pub installed: InstalledPackageInfo, +} + #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(tag = "state")] #[serde(rename_all = "kebab-case")] +#[model = "Model"] +// #[macro_debug] pub enum PackageDataEntry { - #[serde(rename_all = "kebab-case")] - Installing { - static_files: StaticFiles, - manifest: Manifest, - install_progress: Arc, - }, - #[serde(rename_all = "kebab-case")] - Updating { - static_files: StaticFiles, - manifest: Manifest, - installed: InstalledPackageDataEntry, - install_progress: Arc, - }, - #[serde(rename_all = "kebab-case")] - Restoring { - static_files: StaticFiles, - manifest: Manifest, - install_progress: Arc, - }, - #[serde(rename_all = "kebab-case")] - Removing { - static_files: StaticFiles, - manifest: Manifest, - removing: InstalledPackageDataEntry, - }, - #[serde(rename_all = "kebab-case")] - Installed { - static_files: StaticFiles, - manifest: Manifest, - installed: InstalledPackageDataEntry, - }, + Installing(PackageDataEntryInstalling), + Updating(PackageDataEntryUpdating), + Restoring(PackageDataEntryRestoring), + Removing(PackageDataEntryRemoving), + Installed(PackageDataEntryInstalled), } -impl PackageDataEntry { - pub fn installed(&self) -> Option<&InstalledPackageDataEntry> { - match self { - Self::Installing { .. } | Self::Restoring { .. } | Self::Removing { .. } => None, - Self::Updating { installed, .. } | Self::Installed { installed, .. } => Some(installed), +impl Model { + pub fn expect_into_installed(self) -> Result, Error> { + if let PackageDataEntryMatchModel::Installed(a) = self.into_match() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in installed state"), + ErrorKind::InvalidRequest, + )) } } - pub fn installed_mut(&mut self) -> Option<&mut InstalledPackageDataEntry> { - match self { - Self::Installing { .. } | Self::Restoring { .. } | Self::Removing { .. } => None, - Self::Updating { installed, .. } | Self::Installed { installed, .. } => Some(installed), + pub fn expect_as_installed(&self) -> Result<&Model, Error> { + if let PackageDataEntryMatchModelRef::Installed(a) = self.as_match() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in installed state"), + ErrorKind::InvalidRequest, + )) } } - pub fn into_installed(self) -> Option { - match self { - Self::Installing { .. } | Self::Restoring { .. } | Self::Removing { .. } => None, - Self::Updating { installed, .. } | Self::Installed { installed, .. } => Some(installed), + pub fn expect_as_installed_mut( + &mut self, + ) -> Result<&mut Model, Error> { + if let PackageDataEntryMatchModelMut::Installed(a) = self.as_match_mut() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in installed state"), + ErrorKind::InvalidRequest, + )) } } - pub fn manifest(self) -> Manifest { - match self { - PackageDataEntry::Installing { manifest, .. } => manifest, - PackageDataEntry::Updating { manifest, .. } => manifest, - PackageDataEntry::Restoring { manifest, .. } => manifest, - PackageDataEntry::Removing { manifest, .. } => manifest, - PackageDataEntry::Installed { manifest, .. } => manifest, + pub fn expect_into_removing(self) -> Result, Error> { + if let PackageDataEntryMatchModel::Removing(a) = self.into_match() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in removing state"), + ErrorKind::InvalidRequest, + )) } } - pub fn manifest_borrow(&self) -> &Manifest { - match self { - PackageDataEntry::Installing { manifest, .. } => manifest, - PackageDataEntry::Updating { manifest, .. } => manifest, - PackageDataEntry::Restoring { manifest, .. } => manifest, - PackageDataEntry::Removing { manifest, .. } => manifest, - PackageDataEntry::Installed { manifest, .. } => manifest, + pub fn expect_as_removing(&self) -> Result<&Model, Error> { + if let PackageDataEntryMatchModelRef::Removing(a) = self.as_match() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in removing state"), + ErrorKind::InvalidRequest, + )) } } -} -impl PackageDataEntryModel { - pub fn installed(self) -> OptionModel { - self.0.child("installed").into() + pub fn expect_as_removing_mut( + &mut self, + ) -> Result<&mut Model, Error> { + if let PackageDataEntryMatchModelMut::Removing(a) = self.as_match_mut() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in removing state"), + ErrorKind::InvalidRequest, + )) + } } - pub fn removing(self) -> OptionModel { - self.0.child("removing").into() + pub fn expect_as_installing_mut( + &mut self, + ) -> Result<&mut Model, Error> { + if let PackageDataEntryMatchModelMut::Installing(a) = self.as_match_mut() { + Ok(a) + } else { + Err(Error::new( + eyre!("package is not in installing state"), + ErrorKind::InvalidRequest, + )) + } } - pub fn install_progress(self) -> OptionModel { - self.0.child("install-progress").into() + pub fn into_manifest(self) -> Model { + match self.into_match() { + PackageDataEntryMatchModel::Installing(a) => a.into_manifest(), + PackageDataEntryMatchModel::Updating(a) => a.into_installed().into_manifest(), + PackageDataEntryMatchModel::Restoring(a) => a.into_manifest(), + PackageDataEntryMatchModel::Removing(a) => a.into_manifest(), + PackageDataEntryMatchModel::Installed(a) => a.into_manifest(), + PackageDataEntryMatchModel::Error(_) => Model::from(Value::Null), + } } - pub fn manifest(self) -> ManifestModel { - self.0.child("manifest").into() + pub fn as_manifest(&self) -> &Model { + match self.as_match() { + PackageDataEntryMatchModelRef::Installing(a) => a.as_manifest(), + PackageDataEntryMatchModelRef::Updating(a) => a.as_installed().as_manifest(), + PackageDataEntryMatchModelRef::Restoring(a) => a.as_manifest(), + PackageDataEntryMatchModelRef::Removing(a) => a.as_manifest(), + PackageDataEntryMatchModelRef::Installed(a) => a.as_manifest(), + PackageDataEntryMatchModelRef::Error(_) => (&Value::Null).into(), + } + } + pub fn into_installed(self) -> Option> { + match self.into_match() { + PackageDataEntryMatchModel::Installing(_) => None, + PackageDataEntryMatchModel::Updating(a) => Some(a.into_installed()), + PackageDataEntryMatchModel::Restoring(_) => None, + PackageDataEntryMatchModel::Removing(_) => None, + PackageDataEntryMatchModel::Installed(a) => Some(a.into_installed()), + PackageDataEntryMatchModel::Error(_) => None, + } + } + pub fn as_installed(&self) -> Option<&Model> { + match self.as_match() { + PackageDataEntryMatchModelRef::Installing(_) => None, + PackageDataEntryMatchModelRef::Updating(a) => Some(a.as_installed()), + PackageDataEntryMatchModelRef::Restoring(_) => None, + PackageDataEntryMatchModelRef::Removing(_) => None, + PackageDataEntryMatchModelRef::Installed(a) => Some(a.as_installed()), + PackageDataEntryMatchModelRef::Error(_) => None, + } + } + pub fn as_installed_mut(&mut self) -> Option<&mut Model> { + match self.as_match_mut() { + PackageDataEntryMatchModelMut::Installing(_) => None, + PackageDataEntryMatchModelMut::Updating(a) => Some(a.as_installed_mut()), + PackageDataEntryMatchModelMut::Restoring(_) => None, + PackageDataEntryMatchModelMut::Removing(_) => None, + PackageDataEntryMatchModelMut::Installed(a) => Some(a.as_installed_mut()), + PackageDataEntryMatchModelMut::Error(_) => None, + } + } + pub fn as_install_progress(&self) -> Option<&Model>> { + match self.as_match() { + PackageDataEntryMatchModelRef::Installing(a) => Some(a.as_install_progress()), + PackageDataEntryMatchModelRef::Updating(a) => Some(a.as_install_progress()), + PackageDataEntryMatchModelRef::Restoring(a) => Some(a.as_install_progress()), + PackageDataEntryMatchModelRef::Removing(_) => None, + PackageDataEntryMatchModelRef::Installed(_) => None, + PackageDataEntryMatchModelRef::Error(_) => None, + } + } + pub fn as_install_progress_mut(&mut self) -> Option<&mut Model>> { + match self.as_match_mut() { + PackageDataEntryMatchModelMut::Installing(a) => Some(a.as_install_progress_mut()), + PackageDataEntryMatchModelMut::Updating(a) => Some(a.as_install_progress_mut()), + PackageDataEntryMatchModelMut::Restoring(a) => Some(a.as_install_progress_mut()), + PackageDataEntryMatchModelMut::Removing(_) => None, + PackageDataEntryMatchModelMut::Installed(_) => None, + PackageDataEntryMatchModelMut::Error(_) => None, + } } } #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] -pub struct InstalledPackageDataEntry { - #[model] +#[model = "Model"] +pub struct InstalledPackageInfo { pub status: Status, pub marketplace_url: Option, #[serde(default)] #[serde(with = "crate::util::serde::ed25519_pubkey")] - pub developer_key: ed25519_dalek::PublicKey, - #[model] + pub developer_key: ed25519_dalek::VerifyingKey, pub manifest: Manifest, pub last_backup: Option>, - #[model] - pub system_pointers: Vec, - #[model] pub dependency_info: BTreeMap, - #[model] pub current_dependents: CurrentDependents, - #[model] pub current_dependencies: CurrentDependencies, - #[model] pub interface_addresses: InterfaceAddressMap, } -#[derive(Debug, Clone, Deserialize, Serialize)] +#[derive(Debug, Clone, Default, Deserialize, Serialize)] pub struct CurrentDependents(pub BTreeMap); impl CurrentDependents { pub fn map( @@ -351,12 +474,6 @@ impl CurrentDependents { impl Map for CurrentDependents { type Key = PackageId; type Value = CurrentDependencyInfo; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -impl HasModel for CurrentDependents { - type Model = MapModel; } #[derive(Debug, Clone, Default, Deserialize, Serialize)] @@ -375,25 +492,22 @@ impl CurrentDependencies { impl Map for CurrentDependencies { type Key = PackageId; type Value = CurrentDependencyInfo; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -impl HasModel for CurrentDependencies { - type Model = MapModel; } -#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)] +#[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct StaticDependencyInfo { - pub manifest: Option, - pub icon: String, + pub title: String, + pub icon: DataUrl<'static>, } #[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct CurrentDependencyInfo { - pub pointers: Vec, + #[serde(default)] + pub pointers: BTreeSet, pub health_checks: BTreeSet, } @@ -402,27 +516,12 @@ pub struct InterfaceAddressMap(pub BTreeMap); impl Map for InterfaceAddressMap { type Key = InterfaceId; type Value = InterfaceAddresses; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -impl HasModel for InterfaceAddressMap { - type Model = MapModel; } #[derive(Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct InterfaceAddresses { - #[model] pub tor_address: Option, - #[model] pub lan_address: Option, } - -#[derive(Debug, Deserialize, Serialize, HasModel)] -#[serde(rename_all = "kebab-case")] -pub struct RecoveredPackageInfo { - pub title: String, - pub icon: String, - pub version: Version, -} diff --git a/backend/src/db/package.rs b/backend/src/db/package.rs index dd167c160..fe6f93809 100644 --- a/backend/src/db/package.rs +++ b/backend/src/db/package.rs @@ -1,75 +1,22 @@ -use patch_db::{DbHandle, LockReceipt, LockTargetId, LockType, Verifier}; +use models::Version; -use crate::s9pk::manifest::{Manifest, PackageId}; -use crate::Error; +use crate::prelude::*; +use crate::s9pk::manifest::PackageId; -pub struct PackageReceipts { - package_data: LockReceipt, -} - -impl PackageReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let package_data = crate::db::DatabaseModel::new() - .package_data() - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - package_data: package_data.verify(&skeleton_key)?, - }) - } - } -} - -pub async fn get_packages( - db: &mut Db, - receipts: &PackageReceipts, -) -> Result, Error> { - let packages = receipts.package_data.get(db).await?; - Ok(packages.0.keys().cloned().collect()) -} - -pub struct ManifestReceipts { - manifest: LockReceipt, -} - -impl ManifestReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, id); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - _id: &PackageId, - ) -> impl FnOnce(&Verifier) -> Result { - let manifest = crate::db::DatabaseModel::new() - .package_data() - .star() - .manifest() - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - manifest: manifest.verify(&skeleton_key)?, - }) - } - } -} - -pub async fn get_manifest( - db: &mut Db, - pkg: &PackageId, - receipts: &ManifestReceipts, -) -> Result, Error> { - Ok(receipts.manifest.get(db, pkg).await?) +pub fn get_packages(db: Peeked) -> Result, Error> { + Ok(db + .as_package_data() + .keys()? + .into_iter() + .flat_map(|package_id| { + let version = db + .as_package_data() + .as_idx(&package_id)? + .as_manifest() + .as_version() + .de() + .ok()?; + Some((package_id, version)) + }) + .collect()) } diff --git a/backend/src/db/prelude.rs b/backend/src/db/prelude.rs new file mode 100644 index 000000000..922a47500 --- /dev/null +++ b/backend/src/db/prelude.rs @@ -0,0 +1,382 @@ +use std::collections::BTreeMap; +use std::marker::PhantomData; +use std::panic::UnwindSafe; + +use patch_db::value::InternedString; +pub use patch_db::{HasModel, PatchDb, Value}; +use serde::de::DeserializeOwned; +use serde::Serialize; + +use crate::db::model::DatabaseModel; +use crate::prelude::*; + +pub type Peeked = Model; + +pub fn to_value(value: &T) -> Result +where + T: Serialize, +{ + patch_db::value::to_value(value).with_kind(ErrorKind::Serialization) +} + +pub fn from_value(value: Value) -> Result +where + T: DeserializeOwned, +{ + patch_db::value::from_value(value).with_kind(ErrorKind::Deserialization) +} + +#[async_trait::async_trait] +pub trait PatchDbExt { + async fn peek(&self) -> DatabaseModel; + async fn mutate( + &self, + f: impl FnOnce(&mut DatabaseModel) -> Result + UnwindSafe + Send, + ) -> Result; + async fn map_mutate( + &self, + f: impl FnOnce(DatabaseModel) -> Result + UnwindSafe + Send, + ) -> Result; +} +#[async_trait::async_trait] +impl PatchDbExt for PatchDb { + async fn peek(&self) -> DatabaseModel { + DatabaseModel::from(self.dump().await.value) + } + async fn mutate( + &self, + f: impl FnOnce(&mut DatabaseModel) -> Result + UnwindSafe + Send, + ) -> Result { + Ok(self + .apply_function(|mut v| { + let model = <&mut DatabaseModel>::from(&mut v); + let res = f(model)?; + Ok::<_, Error>((v, res)) + }) + .await? + .1) + } + async fn map_mutate( + &self, + f: impl FnOnce(DatabaseModel) -> Result + UnwindSafe + Send, + ) -> Result { + Ok(DatabaseModel::from( + self.apply_function(|v| f(DatabaseModel::from(v)).map(|a| (a.into(), ()))) + .await? + .0, + )) + } +} + +/// &mut Model <=> &mut Value +#[repr(transparent)] +#[derive(Debug)] +pub struct Model { + value: Value, + phantom: PhantomData, +} +impl Model { + pub fn de(&self) -> Result { + from_value(self.value.clone()) + } +} +impl Model { + pub fn new(value: &T) -> Result { + Ok(Self::from(to_value(value)?)) + } + pub fn ser(&mut self, value: &T) -> Result<(), Error> { + self.value = to_value(value)?; + Ok(()) + } +} + +impl Model { + pub fn replace(&mut self, value: &T) -> Result { + let orig = self.de()?; + self.ser(value)?; + Ok(orig) + } +} +impl Clone for Model { + fn clone(&self) -> Self { + Self { + value: self.value.clone(), + phantom: PhantomData, + } + } +} +impl From for Model { + fn from(value: Value) -> Self { + Self { + value, + phantom: PhantomData, + } + } +} +impl From> for Value { + fn from(value: Model) -> Self { + value.value + } +} +impl<'a, T> From<&'a Value> for &'a Model { + fn from(value: &'a Value) -> Self { + unsafe { std::mem::transmute(value) } + } +} +impl<'a, T> From<&'a Model> for &'a Value { + fn from(value: &'a Model) -> Self { + unsafe { std::mem::transmute(value) } + } +} +impl<'a, T> From<&'a mut Value> for &mut Model { + fn from(value: &'a mut Value) -> Self { + unsafe { std::mem::transmute(value) } + } +} +impl<'a, T> From<&'a mut Model> for &mut Value { + fn from(value: &'a mut Model) -> Self { + unsafe { std::mem::transmute(value) } + } +} +impl patch_db::Model for Model { + type Model = Model; +} + +impl Model> { + pub fn transpose(self) -> Option> { + use patch_db::ModelExt; + if self.value.is_null() { + None + } else { + Some(self.transmute(|a| a)) + } + } + pub fn transpose_ref(&self) -> Option<&Model> { + use patch_db::ModelExt; + if self.value.is_null() { + None + } else { + Some(self.transmute_ref(|a| a)) + } + } + pub fn transpose_mut(&mut self) -> Option<&mut Model> { + use patch_db::ModelExt; + if self.value.is_null() { + None + } else { + Some(self.transmute_mut(|a| a)) + } + } + pub fn from_option(opt: Option>) -> Self { + use patch_db::ModelExt; + match opt { + Some(a) => a.transmute(|a| a), + None => Self::from_value(Value::Null), + } + } +} + +pub trait Map: DeserializeOwned + Serialize { + type Key; + type Value; +} + +impl Map for BTreeMap +where + A: serde::Serialize + serde::de::DeserializeOwned + Ord, + B: serde::Serialize + serde::de::DeserializeOwned, +{ + type Key = A; + type Value = B; +} + +impl Model +where + T::Key: AsRef, + T::Value: Serialize, +{ + pub fn insert(&mut self, key: &T::Key, value: &T::Value) -> Result<(), Error> { + use serde::ser::Error; + let v = patch_db::value::to_value(value)?; + match &mut self.value { + Value::Object(o) => { + o.insert(InternedString::intern(key.as_ref()), v); + Ok(()) + } + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Serialization, + } + .into()), + } + } + pub fn insert_model(&mut self, key: &T::Key, value: Model) -> Result<(), Error> { + use patch_db::ModelExt; + use serde::ser::Error; + let v = value.into_value(); + match &mut self.value { + Value::Object(o) => { + o.insert(InternedString::intern(key.as_ref()), v); + Ok(()) + } + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Serialization, + } + .into()), + } + } +} + +impl Model +where + T::Key: DeserializeOwned + Ord + Clone, +{ + pub fn keys(&self) -> Result, Error> { + use serde::de::Error; + use serde::Deserialize; + match &self.value { + Value::Object(o) => o + .keys() + .cloned() + .map(|k| { + T::Key::deserialize(patch_db::value::de::InternedStringDeserializer::from(k)) + .map_err(|e| { + patch_db::value::Error { + kind: patch_db::value::ErrorKind::Deserialization, + source: e, + } + .into() + }) + }) + .collect(), + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Deserialization, + } + .into()), + } + } + + pub fn into_entries(self) -> Result)>, Error> { + use patch_db::ModelExt; + use serde::de::Error; + use serde::Deserialize; + match self.value { + Value::Object(o) => o + .into_iter() + .map(|(k, v)| { + Ok(( + T::Key::deserialize(patch_db::value::de::InternedStringDeserializer::from( + k, + )) + .with_kind(ErrorKind::Deserialization)?, + Model::from_value(v), + )) + }) + .collect(), + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Deserialization, + } + .into()), + } + } + pub fn as_entries(&self) -> Result)>, Error> { + use patch_db::ModelExt; + use serde::de::Error; + use serde::Deserialize; + match &self.value { + Value::Object(o) => o + .iter() + .map(|(k, v)| { + Ok(( + T::Key::deserialize(patch_db::value::de::InternedStringDeserializer::from( + k.clone(), + )) + .with_kind(ErrorKind::Deserialization)?, + Model::value_as(v), + )) + }) + .collect(), + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Deserialization, + } + .into()), + } + } + pub fn as_entries_mut(&mut self) -> Result)>, Error> { + use patch_db::ModelExt; + use serde::de::Error; + use serde::Deserialize; + match &mut self.value { + Value::Object(o) => o + .iter_mut() + .map(|(k, v)| { + Ok(( + T::Key::deserialize(patch_db::value::de::InternedStringDeserializer::from( + k.clone(), + )) + .with_kind(ErrorKind::Deserialization)?, + Model::value_as_mut(v), + )) + }) + .collect(), + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Deserialization, + } + .into()), + } + } +} +impl Model +where + T::Key: AsRef, +{ + pub fn into_idx(self, key: &T::Key) -> Option> { + use patch_db::ModelExt; + match &self.value { + Value::Object(o) if o.contains_key(key.as_ref()) => Some(self.transmute(|v| { + use patch_db::value::index::Index; + key.as_ref().index_into_owned(v).unwrap() + })), + _ => None, + } + } + pub fn as_idx<'a>(&'a self, key: &T::Key) -> Option<&'a Model> { + use patch_db::ModelExt; + match &self.value { + Value::Object(o) if o.contains_key(key.as_ref()) => Some(self.transmute_ref(|v| { + use patch_db::value::index::Index; + key.as_ref().index_into(v).unwrap() + })), + _ => None, + } + } + pub fn as_idx_mut<'a>(&'a mut self, key: &T::Key) -> Option<&'a mut Model> { + use patch_db::ModelExt; + match &mut self.value { + Value::Object(o) if o.contains_key(key.as_ref()) => Some(self.transmute_mut(|v| { + use patch_db::value::index::Index; + key.as_ref().index_or_insert(v) + })), + _ => None, + } + } + pub fn remove(&mut self, key: &T::Key) -> Result>, Error> { + use serde::ser::Error; + match &mut self.value { + Value::Object(o) => { + let v = o.remove(key.as_ref()); + Ok(v.map(patch_db::ModelExt::from_value)) + } + v => Err(patch_db::value::Error { + source: patch_db::value::ErrorSource::custom(format!("expected object found {v}")), + kind: patch_db::value::ErrorKind::Serialization, + } + .into()), + } + } +} diff --git a/backend/src/dependencies.rs b/backend/src/dependencies.rs index 6a79b4bce..dfddecd93 100644 --- a/backend/src/dependencies.rs +++ b/backend/src/dependencies.rs @@ -1,29 +1,23 @@ -use std::cmp::Ordering; use std::collections::BTreeMap; use std::time::Duration; use color_eyre::eyre::eyre; use emver::VersionRange; -use futures::future::BoxFuture; -use futures::FutureExt; -use patch_db::{ - DbHandle, HasModel, LockReceipt, LockTargetId, LockType, Map, MapModel, PatchDbHandle, Verifier, -}; +use models::OptionExt; use rand::SeedableRng; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; use tracing::instrument; -use crate::config::action::{ConfigActions, ConfigRes}; +use crate::config::action::ConfigRes; use crate::config::spec::PackagePointerSpec; -use crate::config::{not_found, Config, ConfigReceipts, ConfigSpec, ConfigureContext}; +use crate::config::{not_found, Config, ConfigSpec, ConfigureContext}; use crate::context::RpcContext; -use crate::db::model::{CurrentDependencies, CurrentDependents, InstalledPackageDataEntry}; -use crate::procedure::docker::DockerContainers; +use crate::db::model::{CurrentDependencies, Database}; +use crate::prelude::*; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::{Manifest, PackageId}; -use crate::status::health_check::{HealthCheckId, HealthCheckResult}; -use crate::status::{MainStatus, Status}; +use crate::status::DependencyConfigErrors; use crate::util::serde::display_serializable; use crate::util::{display_none, Version}; use crate::volume::Volumes; @@ -34,414 +28,12 @@ pub fn dependency() -> Result<(), Error> { Ok(()) } -#[derive(Clone, Debug, thiserror::Error, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -#[serde(tag = "type")] -pub enum DependencyError { - NotInstalled, // { "type": "not-installed" } - #[serde(rename_all = "kebab-case")] - IncorrectVersion { - expected: VersionRange, - received: Version, - }, // { "type": "incorrect-version", "expected": "0.1.0", "received": "^0.2.0" } - #[serde(rename_all = "kebab-case")] - ConfigUnsatisfied { - error: String, - }, // { "type": "config-unsatisfied", "error": "Bitcoin Core must have pruning set to manual." } - NotRunning, // { "type": "not-running" } - #[serde(rename_all = "kebab-case")] - HealthChecksFailed { - failures: BTreeMap, - }, // { "type": "health-checks-failed", "checks": { "rpc": { "time": "2021-05-11T18:21:29Z", "result": "starting" } } } - #[serde(rename_all = "kebab-case")] - Transitive, // { "type": "transitive" } -} - -#[derive(Clone)] -pub struct TryHealReceipts { - status: LockReceipt, - manifest: LockReceipt, - manifest_version: LockReceipt, - current_dependencies: LockReceipt, - dependency_errors: LockReceipt, - docker_containers: LockReceipt, -} - -impl TryHealReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let manifest_version = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().version()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let status = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let manifest = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let current_dependencies = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependencies()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let dependency_errors = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status().dependency_errors()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let docker_containers = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().containers()) - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - status: status.verify(skeleton_key)?, - manifest_version: manifest_version.verify(skeleton_key)?, - current_dependencies: current_dependencies.verify(skeleton_key)?, - manifest: manifest.verify(skeleton_key)?, - dependency_errors: dependency_errors.verify(skeleton_key)?, - docker_containers: docker_containers.verify(skeleton_key)?, - }) - } - } -} - -impl DependencyError { - pub fn cmp_priority(&self, other: &DependencyError) -> std::cmp::Ordering { - use std::cmp::Ordering::*; - - use DependencyError::*; - match (self, other) { - (NotInstalled, NotInstalled) => Equal, - (NotInstalled, _) => Greater, - (_, NotInstalled) => Less, - (IncorrectVersion { .. }, IncorrectVersion { .. }) => Equal, - (IncorrectVersion { .. }, _) => Greater, - (_, IncorrectVersion { .. }) => Less, - (ConfigUnsatisfied { .. }, ConfigUnsatisfied { .. }) => Equal, - (ConfigUnsatisfied { .. }, _) => Greater, - (_, ConfigUnsatisfied { .. }) => Less, - (NotRunning, NotRunning) => Equal, - (NotRunning, _) => Greater, - (_, NotRunning) => Less, - (HealthChecksFailed { .. }, HealthChecksFailed { .. }) => Equal, - (HealthChecksFailed { .. }, _) => Greater, - (_, HealthChecksFailed { .. }) => Less, - (Transitive, Transitive) => Equal, - } - } - pub fn merge_with(self, other: DependencyError) -> DependencyError { - match (self, other) { - (DependencyError::NotInstalled, _) | (_, DependencyError::NotInstalled) => { - DependencyError::NotInstalled - } - (DependencyError::IncorrectVersion { expected, received }, _) - | (_, DependencyError::IncorrectVersion { expected, received }) => { - DependencyError::IncorrectVersion { expected, received } - } - ( - DependencyError::ConfigUnsatisfied { error: e0 }, - DependencyError::ConfigUnsatisfied { error: e1 }, - ) => DependencyError::ConfigUnsatisfied { - error: e0 + "\n" + &e1, - }, - (DependencyError::ConfigUnsatisfied { error }, _) - | (_, DependencyError::ConfigUnsatisfied { error }) => { - DependencyError::ConfigUnsatisfied { error } - } - (DependencyError::NotRunning, _) | (_, DependencyError::NotRunning) => { - DependencyError::NotRunning - } - ( - DependencyError::HealthChecksFailed { failures: f0 }, - DependencyError::HealthChecksFailed { failures: f1 }, - ) => DependencyError::HealthChecksFailed { - failures: f0.into_iter().chain(f1.into_iter()).collect(), - }, - (DependencyError::HealthChecksFailed { failures }, _) - | (_, DependencyError::HealthChecksFailed { failures }) => { - DependencyError::HealthChecksFailed { failures } - } - (DependencyError::Transitive, _) => DependencyError::Transitive, - } - } - #[instrument(skip_all)] - pub fn try_heal<'a, Db: DbHandle>( - self, - ctx: &'a RpcContext, - db: &'a mut Db, - id: &'a PackageId, - dependency: &'a PackageId, - mut dependency_config: Option, - info: &'a DepInfo, - receipts: &'a TryHealReceipts, - ) -> BoxFuture<'a, Result, Error>> { - async move { - let container = receipts.docker_containers.get(db, id).await?; - Ok(match self { - DependencyError::NotInstalled => { - if receipts.status.get(db, dependency).await?.is_some() { - DependencyError::IncorrectVersion { - expected: info.version.clone(), - received: Default::default(), - } - .try_heal(ctx, db, id, dependency, dependency_config, info, receipts) - .await? - } else { - Some(DependencyError::NotInstalled) - } - } - DependencyError::IncorrectVersion { expected, .. } => { - let version: Version = receipts - .manifest_version - .get(db, dependency) - .await? - .unwrap_or_default(); - if version.satisfies(&expected) { - DependencyError::ConfigUnsatisfied { - error: String::new(), - } - .try_heal(ctx, db, id, dependency, dependency_config, info, receipts) - .await? - } else { - Some(DependencyError::IncorrectVersion { - expected, - received: version, - }) - } - } - DependencyError::ConfigUnsatisfied { .. } => { - let dependent_manifest = receipts - .manifest - .get(db, id) - .await? - .ok_or_else(|| not_found!(id))?; - let dependency_manifest = receipts - .manifest - .get(db, dependency) - .await? - .ok_or_else(|| not_found!(dependency))?; - - let dependency_config = if let Some(cfg) = dependency_config.take() { - cfg - } else if let Some(cfg_info) = &dependency_manifest.config { - cfg_info - .get( - ctx, - dependency, - &dependency_manifest.version, - &dependency_manifest.volumes, - ) - .await? - .config - .unwrap_or_default() - } else { - Config::default() - }; - if let Some(cfg_req) = &info.config { - if let Err(error) = cfg_req - .check( - ctx, - &container, - id, - &dependent_manifest.version, - &dependent_manifest.volumes, - dependency, - &dependency_config, - ) - .await? - { - return Ok(Some(DependencyError::ConfigUnsatisfied { error })); - } - } - DependencyError::NotRunning - .try_heal( - ctx, - db, - id, - dependency, - Some(dependency_config), - info, - receipts, - ) - .await? - } - DependencyError::NotRunning => { - let status = receipts - .status - .get(db, dependency) - .await? - .ok_or_else(|| not_found!(dependency))?; - if status.main.running() { - DependencyError::HealthChecksFailed { - failures: BTreeMap::new(), - } - .try_heal(ctx, db, id, dependency, dependency_config, info, receipts) - .await? - } else { - Some(DependencyError::NotRunning) - } - } - DependencyError::HealthChecksFailed { .. } => { - let status = receipts - .status - .get(db, dependency) - .await? - .ok_or_else(|| not_found!(dependency))?; - match status.main { - MainStatus::BackingUp { - started: Some(_), - health, - } - | MainStatus::Running { health, .. } => { - let mut failures = BTreeMap::new(); - for (check, res) in health { - if !matches!(res, HealthCheckResult::Success) - && receipts - .current_dependencies - .get(db, id) - .await? - .ok_or_else(|| not_found!(id))? - .get(dependency) - .map(|x| x.health_checks.contains(&check)) - .unwrap_or(false) - { - failures.insert(check.clone(), res.clone()); - } - } - if !failures.is_empty() { - Some(DependencyError::HealthChecksFailed { failures }) - } else { - DependencyError::Transitive - .try_heal( - ctx, - db, - id, - dependency, - dependency_config, - info, - receipts, - ) - .await? - } - } - MainStatus::Starting { .. } | MainStatus::Restarting => { - DependencyError::Transitive - .try_heal( - ctx, - db, - id, - dependency, - dependency_config, - info, - receipts, - ) - .await? - } - _ => return Ok(Some(DependencyError::NotRunning)), - } - } - DependencyError::Transitive => { - if receipts - .dependency_errors - .get(db, dependency) - .await? - .unwrap_or_default() - .0 - .is_empty() - { - None - } else { - Some(DependencyError::Transitive) - } - } - }) - } - .boxed() - } -} -impl std::fmt::Display for DependencyError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - DependencyError::NotInstalled => write!(f, "Not Installed"), - DependencyError::IncorrectVersion { expected, received } => write!( - f, - "Incorrect Version: Expected {}, Received {}", - expected, - received.as_str() - ), - DependencyError::ConfigUnsatisfied { error } => { - write!(f, "Configuration Requirements Not Satisfied: {}", error) - } - DependencyError::NotRunning => write!(f, "Not Running"), - DependencyError::HealthChecksFailed { failures } => { - write!(f, "Failed Health Check(s): ")?; - let mut comma = false; - for (check, res) in failures { - if !comma { - comma = true; - } else { - write!(f, ", ")?; - } - write!(f, "{}: {}", check, res)?; - } - Ok(()) - } - DependencyError::Transitive => { - write!(f, "Dependency Error(s)") - } - } - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub struct TaggedDependencyError { - pub dependency: PackageId, - pub error: DependencyError, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub struct BreakageRes(pub BTreeMap); - -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)] +#[model = "Model"] pub struct Dependencies(pub BTreeMap); impl Map for Dependencies { type Key = PackageId; type Value = DepInfo; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -impl HasModel for Dependencies { - type Model = MapModel; } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -460,47 +52,18 @@ impl DependencyRequirement { #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct DepInfo { pub version: VersionRange, pub requirement: DependencyRequirement, pub description: Option, #[serde(default)] - #[model] pub config: Option, } -impl DepInfo { - pub async fn satisfied( - &self, - ctx: &RpcContext, - db: &mut Db, - dependency_id: &PackageId, - dependency_config: Option, // fetch if none - dependent_id: &PackageId, - receipts: &TryHealReceipts, - ) -> Result, Error> { - Ok( - if let Some(err) = DependencyError::NotInstalled - .try_heal( - ctx, - db, - dependent_id, - dependency_id, - dependency_config, - self, - receipts, - ) - .await? - { - Err(err) - } else { - Ok(()) - }, - ) - } -} #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct DependencyConfig { check: PackageProcedure, auto_configure: PackageProcedure, @@ -509,7 +72,6 @@ impl DependencyConfig { pub async fn check( &self, ctx: &RpcContext, - container: &Option, dependent_id: &PackageId, dependent_version: &Version, dependent_volumes: &Volumes, @@ -519,7 +81,6 @@ impl DependencyConfig { Ok(self .check .sandboxed( - container, ctx, dependent_id, dependent_version, @@ -534,7 +95,6 @@ impl DependencyConfig { pub async fn auto_configure( &self, ctx: &RpcContext, - container: &Option, dependent_id: &PackageId, dependent_version: &Version, dependent_volumes: &Volumes, @@ -542,7 +102,6 @@ impl DependencyConfig { ) -> Result { self.auto_configure .sandboxed( - container, ctx, dependent_id, dependent_version, @@ -556,99 +115,6 @@ impl DependencyConfig { } } -pub struct DependencyConfigReceipts { - config: ConfigReceipts, - dependencies: LockReceipt, - dependency_volumes: LockReceipt, - dependency_version: LockReceipt, - dependency_config_action: LockReceipt, - package_volumes: LockReceipt, - package_version: LockReceipt, - docker_containers: LockReceipt, -} - -impl DependencyConfigReceipts { - pub async fn new<'a>( - db: &'a mut impl DbHandle, - package_id: &PackageId, - dependency_id: &PackageId, - ) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, package_id, dependency_id); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - package_id: &PackageId, - dependency_id: &PackageId, - ) -> impl FnOnce(&Verifier) -> Result { - let config = ConfigReceipts::setup(locks); - let dependencies = crate::db::DatabaseModel::new() - .package_data() - .idx_model(package_id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().dependencies()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let dependency_volumes = crate::db::DatabaseModel::new() - .package_data() - .idx_model(dependency_id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().volumes()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let dependency_version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(dependency_id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().version()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let dependency_config_action = crate::db::DatabaseModel::new() - .package_data() - .idx_model(dependency_id) - .and_then(|x| x.installed()) - .and_then(|x| x.manifest().config()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let package_volumes = crate::db::DatabaseModel::new() - .package_data() - .idx_model(package_id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().volumes()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let package_version = crate::db::DatabaseModel::new() - .package_data() - .idx_model(package_id) - .and_then(|x| x.installed()) - .map(|x| x.manifest().version()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let docker_containers = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .and_then(|x| x.manifest().containers()) - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - config: config(skeleton_key)?, - dependencies: dependencies.verify(&skeleton_key)?, - dependency_volumes: dependency_volumes.verify(&skeleton_key)?, - dependency_version: dependency_version.verify(&skeleton_key)?, - dependency_config_action: dependency_config_action.verify(&skeleton_key)?, - package_volumes: package_volumes.verify(&skeleton_key)?, - package_version: package_version.verify(&skeleton_key)?, - docker_containers: docker_containers.verify(&skeleton_key)?, - }) - } - } -} - #[command( subcommands(self(configure_impl(async)), configure_dry), display(display_none) @@ -664,15 +130,13 @@ pub async fn configure_impl( ctx: RpcContext, (pkg_id, dep_id): (PackageId, PackageId), ) -> Result<(), Error> { - let mut db = ctx.db.handle(); let breakages = BTreeMap::new(); let overrides = Default::default(); - let receipts = DependencyConfigReceipts::new(&mut db, &pkg_id, &dep_id).await?; let ConfigDryRes { old_config: _, new_config, spec: _, - } = configure_logic(ctx.clone(), &mut db, (pkg_id, dep_id.clone()), &receipts).await?; + } = configure_logic(ctx.clone(), (pkg_id, dep_id.clone())).await?; let configure_context = ConfigureContext { breakages, @@ -699,50 +163,41 @@ pub async fn configure_dry( #[context] ctx: RpcContext, #[parent_data] (pkg_id, dependency_id): (PackageId, PackageId), ) -> Result { - let mut db = ctx.db.handle(); - let receipts = DependencyConfigReceipts::new(&mut db, &pkg_id, &dependency_id).await?; - configure_logic(ctx, &mut db, (pkg_id, dependency_id), &receipts).await + configure_logic(ctx, (pkg_id, dependency_id)).await } pub async fn configure_logic( ctx: RpcContext, - db: &mut PatchDbHandle, (pkg_id, dependency_id): (PackageId, PackageId), - receipts: &DependencyConfigReceipts, ) -> Result { - let pkg_version = receipts.package_version.get(db).await?; - let pkg_volumes = receipts.package_volumes.get(db).await?; - let dependency_config_action = receipts.dependency_config_action.get(db).await?; - let dependency_version = receipts.dependency_version.get(db).await?; - let dependency_volumes = receipts.dependency_volumes.get(db).await?; - let dependencies = receipts.dependencies.get(db).await?; - let pkg_docker_container = receipts.docker_containers.get(db, &*pkg_id).await?; + let db = ctx.db.peek().await; + let pkg = db + .as_package_data() + .as_idx(&pkg_id) + .or_not_found(&pkg_id)? + .as_installed() + .or_not_found(&pkg_id)?; + let pkg_version = pkg.as_manifest().as_version().de()?; + let pkg_volumes = pkg.as_manifest().as_volumes().de()?; + let dependency = db + .as_package_data() + .as_idx(&dependency_id) + .or_not_found(&dependency_id)? + .as_installed() + .or_not_found(&dependency_id)?; + let dependency_config_action = dependency + .as_manifest() + .as_config() + .de()? + .ok_or_else(|| not_found!("Manifest Config"))?; + let dependency_version = dependency.as_manifest().as_version().de()?; + let dependency_volumes = dependency.as_manifest().as_volumes().de()?; + let dependency = pkg + .as_manifest() + .as_dependencies() + .as_idx(&dependency_id) + .or_not_found(&dependency_id)?; - let dependency = dependencies - .0 - .get(&dependency_id) - .ok_or_else(|| { - Error::new( - eyre!( - "dependency for {} not found in the manifest for {}", - dependency_id, - pkg_id - ), - crate::ErrorKind::NotFound, - ) - })? - .config - .as_ref() - .ok_or_else(|| { - Error::new( - eyre!( - "dependency config for {} not found on {}", - dependency_id, - pkg_id - ), - crate::ErrorKind::NotFound, - ) - })?; let ConfigRes { config: maybe_config, spec, @@ -765,9 +220,11 @@ pub async fn configure_logic( }; let new_config = dependency + .as_config() + .de()? + .ok_or_else(|| not_found!("Config"))? .auto_configure .sandboxed( - &pkg_docker_container, &ctx, &pkg_id, &pkg_version, @@ -785,345 +242,122 @@ pub async fn configure_logic( spec, }) } + #[instrument(skip_all)] -pub async fn add_dependent_to_current_dependents_lists<'a, Db: DbHandle>( - db: &mut Db, +pub fn add_dependent_to_current_dependents_lists( + db: &mut Model, dependent_id: &PackageId, current_dependencies: &CurrentDependencies, - current_dependent_receipt: &LockReceipt, ) -> Result<(), Error> { for (dependency, dep_info) in ¤t_dependencies.0 { - if let Some(mut dependency_dependents) = - current_dependent_receipt.get(db, dependency).await? + if let Some(dependency_dependents) = db + .as_package_data_mut() + .as_idx_mut(dependency) + .and_then(|pde| pde.as_installed_mut()) + .map(|i| i.as_current_dependents_mut()) { - dependency_dependents - .0 - .insert(dependent_id.clone(), dep_info.clone()); - current_dependent_receipt - .set(db, dependency_dependents, dependency) - .await?; + dependency_dependents.insert(dependent_id, dep_info)?; } } Ok(()) } -#[derive(Debug, Clone, Default, Deserialize, Serialize)] -pub struct DependencyErrors(pub BTreeMap); -impl Map for DependencyErrors { - type Key = PackageId; - type Value = DependencyError; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -impl HasModel for DependencyErrors { - type Model = MapModel; -} -impl DependencyErrors { - pub async fn init( - ctx: &RpcContext, - db: &mut Db, - manifest: &Manifest, - current_dependencies: &CurrentDependencies, - receipts: &TryHealReceipts, - ) -> Result { - let mut res = BTreeMap::new(); - for (dependency_id, info) in current_dependencies.0.keys().filter_map(|dependency_id| { - manifest - .dependencies - .0 - .get(dependency_id) - .map(|info| (dependency_id, info)) - }) { - if let Err(e) = info - .satisfied(ctx, db, dependency_id, None, &manifest.id, receipts) - .await? - { - res.insert(dependency_id.clone(), e); - } - } - Ok(DependencyErrors(res)) - } -} -impl std::fmt::Display for DependencyErrors { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{{ ")?; - for (idx, (id, err)) in self.0.iter().enumerate() { - write!(f, "{}: {}", id, err)?; - if idx < self.0.len() - 1 { - // not last - write!(f, ", ")?; - } - } - write!(f, " }}") - } -} - -pub async fn break_all_dependents_transitive<'a, Db: DbHandle>( - db: &'a mut Db, - id: &'a PackageId, - error: DependencyError, - breakages: &'a mut BTreeMap, - receipts: &'a BreakTransitiveReceipts, -) -> Result<(), Error> { - for dependent in receipts - .current_dependents - .get(db, id) - .await? - .iter() - .flat_map(|x| x.0.keys()) - .filter(|dependent| id != *dependent) +pub fn set_dependents_with_live_pointers_to_needs_config( + db: &mut Peeked, + id: &PackageId, +) -> Result, Error> { + let mut res = Vec::new(); + for (dep, info) in db + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .as_installed() + .or_not_found(id)? + .as_current_dependents() + .de()? + .0 { - break_transitive(db, dependent, id, error.clone(), breakages, receipts).await?; - } - Ok(()) -} - -#[derive(Clone)] -pub struct BreakTransitiveReceipts { - pub dependency_receipt: DependencyReceipt, - dependency_errors: LockReceipt, - current_dependents: LockReceipt, -} - -impl BreakTransitiveReceipts { - pub async fn new(db: &'_ mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let dependency_receipt = DependencyReceipt::setup(locks); - let dependency_errors = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status().dependency_errors()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let current_dependents = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependents()) - .make_locker(LockType::Exist) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - dependency_receipt: dependency_receipt(skeleton_key)?, - dependency_errors: dependency_errors.verify(skeleton_key)?, - current_dependents: current_dependents.verify(skeleton_key)?, - }) - } - } -} - -#[instrument(skip_all)] -pub fn break_transitive<'a, Db: DbHandle>( - db: &'a mut Db, - id: &'a PackageId, - dependency: &'a PackageId, - error: DependencyError, - breakages: &'a mut BTreeMap, - receipts: &'a BreakTransitiveReceipts, -) -> BoxFuture<'a, Result<(), Error>> { - async move { - let mut tx = db.begin().await?; - let mut dependency_errors = receipts - .dependency_errors - .get(&mut tx, id) - .await? - .ok_or_else(|| not_found!(id))?; - - let old = dependency_errors.0.remove(dependency); - let newly_broken = if let Some(e) = &old { - error.cmp_priority(&e) == Ordering::Greater - } else { - true - }; - dependency_errors.0.insert( - dependency.clone(), - if let Some(old) = old { - old.merge_with(error.clone()) - } else { - error.clone() - }, - ); - if newly_broken { - breakages.insert( - id.clone(), - TaggedDependencyError { - dependency: dependency.clone(), - error: error.clone(), - }, - ); - receipts - .dependency_errors - .set(&mut tx, dependency_errors, id) - .await?; - - tx.save().await?; - break_all_dependents_transitive( - db, - id, - DependencyError::Transitive, - breakages, - receipts, - ) - .await?; - } else { - receipts - .dependency_errors - .set(&mut tx, dependency_errors, id) - .await?; - - tx.save().await?; - } - - Ok(()) - } - .boxed() -} - -#[instrument(skip_all)] -pub async fn heal_all_dependents_transitive<'a, Db: DbHandle>( - ctx: &'a RpcContext, - db: &'a mut Db, - id: &'a PackageId, - locks: &'a DependencyReceipt, -) -> Result<(), Error> { - let dependents = locks - .current_dependents - .get(db, id) - .await? - .ok_or_else(|| not_found!(id))?; - for dependent in dependents.0.keys().filter(|dependent| id != *dependent) { - heal_transitive(ctx, db, dependent, id, locks).await?; - } - Ok(()) -} - -#[instrument(skip_all)] -pub fn heal_transitive<'a, Db: DbHandle>( - ctx: &'a RpcContext, - db: &'a mut Db, - id: &'a PackageId, - dependency: &'a PackageId, - receipts: &'a DependencyReceipt, -) -> BoxFuture<'a, Result<(), Error>> { - async move { - let mut status = receipts - .status - .get(db, id) - .await? - .ok_or_else(|| not_found!(id))?; - - let old = status.dependency_errors.0.remove(dependency); - - if let Some(old) = old { - let info = receipts - .dependency - .get(db, (id, dependency)) - .await? - .ok_or_else(|| not_found!(format!("{id}'s dependency: {dependency}")))?; - if let Some(new) = old - .try_heal(ctx, db, id, dependency, None, &info, &receipts.try_heal) - .await? - { - status.dependency_errors.0.insert(dependency.clone(), new); - receipts.status.set(db, status, id).await?; - } else { - receipts.status.set(db, status, id).await?; - heal_all_dependents_transitive(ctx, db, id, receipts).await?; - } - } - - Ok(()) - } - .boxed() -} - -pub async fn reconfigure_dependents_with_live_pointers( - ctx: &RpcContext, - tx: impl DbHandle, - receipts: &ConfigReceipts, - pde: &InstalledPackageDataEntry, -) -> Result<(), Error> { - let dependents = &pde.current_dependents; - let me = &pde.manifest.id; - for (dependent_id, dependency_info) in &dependents.0 { - if dependency_info.pointers.iter().any(|ptr| match ptr { + if info.pointers.iter().any(|ptr| match ptr { // dependency id matches the package being uninstalled - PackagePointerSpec::TorAddress(ptr) => &ptr.package_id == me && dependent_id != me, - PackagePointerSpec::LanAddress(ptr) => &ptr.package_id == me && dependent_id != me, + PackagePointerSpec::TorAddress(ptr) => &ptr.package_id == id && &dep != id, + PackagePointerSpec::LanAddress(ptr) => &ptr.package_id == id && &dep != id, // we never need to retarget these PackagePointerSpec::TorKey(_) => false, PackagePointerSpec::Config(_) => false, }) { - let breakages = BTreeMap::new(); - let overrides = Default::default(); - - let configure_context = ConfigureContext { - breakages, - timeout: None, - config: None, - dry_run: false, - overrides, - }; - crate::config::configure(&ctx, dependent_id, configure_context).await?; + let installed = db + .as_package_data_mut() + .as_idx_mut(&dep) + .or_not_found(&dep)? + .as_installed_mut() + .or_not_found(&dep)?; + let version = installed.as_manifest().as_version().de()?; + let configured = installed.as_status_mut().as_configured_mut(); + if configured.de()? { + configured.ser(&false)?; + res.push((dep, version)); + } } } - Ok(()) + Ok(res) } -#[derive(Clone)] -pub struct DependencyReceipt { - pub try_heal: TryHealReceipts, - current_dependents: LockReceipt, - status: LockReceipt, - dependency: LockReceipt, -} - -impl DependencyReceipt { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let try_heal = TryHealReceipts::setup(locks); - let dependency = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().dependencies().star()) - .make_locker(LockType::Read) - .add_to_keys(locks); - let current_dependents = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependents()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let status = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status()) - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - try_heal: try_heal(skeleton_key)?, - current_dependents: current_dependents.verify(skeleton_key)?, - status: status.verify(skeleton_key)?, - dependency: dependency.verify(skeleton_key)?, - }) +#[instrument(skip_all)] +pub async fn compute_dependency_config_errs( + ctx: &RpcContext, + db: &Peeked, + manifest: &Manifest, + current_dependencies: &CurrentDependencies, + dependency_config: &BTreeMap, +) -> Result { + let mut dependency_config_errs = BTreeMap::new(); + for (dependency, _dep_info) in current_dependencies + .0 + .iter() + .filter(|(dep_id, _)| dep_id != &&manifest.id) + { + // check if config passes dependency check + if let Some(cfg) = &manifest + .dependencies + .0 + .get(dependency) + .or_not_found(dependency)? + .config + { + if let Err(error) = cfg + .check( + ctx, + &manifest.id, + &manifest.version, + &manifest.volumes, + dependency, + &if let Some(config) = dependency_config.get(dependency) { + config.clone() + } else if let Some(manifest) = db + .as_package_data() + .as_idx(dependency) + .and_then(|pde| pde.as_installed()) + .map(|i| i.as_manifest().de()) + .transpose()? + { + if let Some(config) = &manifest.config { + config + .get(ctx, &manifest.id, &manifest.version, &manifest.volumes) + .await? + .config + .unwrap_or_default() + } else { + Config::default() + } + } else { + Config::default() + }, + ) + .await? + { + dependency_config_errs.insert(dependency.clone(), error); + } } } + Ok(DependencyConfigErrors(dependency_config_errs)) } diff --git a/backend/src/developer/mod.rs b/backend/src/developer/mod.rs index 70b40699e..8722a4a11 100644 --- a/backend/src/developer/mod.rs +++ b/backend/src/developer/mod.rs @@ -3,7 +3,8 @@ use std::io::Write; use std::path::Path; use ed25519::pkcs8::EncodePrivateKey; -use ed25519_dalek::Keypair; +use ed25519::PublicKeyBytes; +use ed25519_dalek::{SigningKey, VerifyingKey}; use rpc_toolkit::command; use tracing::instrument; @@ -21,11 +22,11 @@ pub fn init(#[context] ctx: SdkContext) -> Result<(), Error> { .with_ctx(|_| (crate::ErrorKind::Filesystem, parent.display().to_string()))?; } tracing::info!("Generating new developer key..."); - let keypair = Keypair::generate(&mut rand_old::thread_rng()); + let secret = SigningKey::generate(&mut rand::thread_rng()); tracing::info!("Writing key to {}", ctx.developer_key_path.display()); let keypair_bytes = ed25519::KeypairBytes { - secret_key: keypair.secret.to_bytes(), - public_key: Some(keypair.public.to_bytes()), + secret_key: secret.to_bytes(), + public_key: Some(PublicKeyBytes(VerifyingKey::from(&secret).to_bytes())), }; let mut dev_key_file = File::create(&ctx.developer_key_path)?; dev_key_file.write_all( @@ -35,6 +36,15 @@ pub fn init(#[context] ctx: SdkContext) -> Result<(), Error> { .as_bytes(), )?; dev_key_file.sync_all()?; + println!( + "New developer key generated at {}", + ctx.developer_key_path.display() + ); + } else { + println!( + "Developer key already exists at {}", + ctx.developer_key_path.display() + ); } Ok(()) } diff --git a/backend/src/diagnostic.rs b/backend/src/diagnostic.rs index 1d4c3bcf5..aad95a5e5 100644 --- a/backend/src/diagnostic.rs +++ b/backend/src/diagnostic.rs @@ -9,7 +9,6 @@ use crate::disk::repair; use crate::init::SYSTEM_REBUILD_PATH; use crate::logs::{fetch_logs, LogResponse, LogSource}; use crate::shutdown::Shutdown; -use crate::system::SYSTEMD_UNIT; use crate::util::display_none; use crate::Error; @@ -29,7 +28,7 @@ pub async fn logs( #[arg] cursor: Option, #[arg] before: bool, ) -> Result { - Ok(fetch_logs(LogSource::Service(SYSTEMD_UNIT), limit, cursor, before).await?) + Ok(fetch_logs(LogSource::System, limit, cursor, before).await?) } #[command(display(display_none))] @@ -42,8 +41,10 @@ pub fn exit(#[context] ctx: DiagnosticContext) -> Result<(), Error> { pub fn restart(#[context] ctx: DiagnosticContext) -> Result<(), Error> { ctx.shutdown .send(Some(Shutdown { - datadir: ctx.datadir.clone(), - disk_guid: ctx.disk_guid.clone(), + export_args: ctx + .disk_guid + .clone() + .map(|guid| (guid, ctx.datadir.clone())), restart: true, })) .expect("receiver dropped"); diff --git a/backend/src/disk/fsck/btrfs.rs b/backend/src/disk/fsck/btrfs.rs index ce4e89f75..fe0cf3c33 100644 --- a/backend/src/disk/fsck/btrfs.rs +++ b/backend/src/disk/fsck/btrfs.rs @@ -23,6 +23,7 @@ pub async fn btrfs_check_repair(logicalname: impl AsRef) -> Result>( Command::new("cryptsetup") .arg("-q") .arg("luksOpen") + .arg("--allow-discards") .arg(format!("--key-file={}", PASSWORD_PATH)) .arg(format!("--keyfile-size={}", password.len())) .arg(&blockdev_path) diff --git a/backend/src/disk/mount/backup.rs b/backend/src/disk/mount/backup.rs index a3e239b2b..a19056241 100644 --- a/backend/src/disk/mount/backup.rs +++ b/backend/src/disk/mount/backup.rs @@ -84,7 +84,7 @@ impl BackupMountGuard { argon2::hash_encoded( password.as_bytes(), &rand::random::<[u8; 16]>()[..], - &argon2::Config::default(), + &argon2::Config::rfc9106_low_mem(), ) .with_kind(crate::ErrorKind::PasswordHashGeneration)?, ); @@ -134,7 +134,7 @@ impl BackupMountGuard { argon2::hash_encoded( new_password.as_bytes(), &rand::random::<[u8; 16]>()[..], - &argon2::Config::default(), + &argon2::Config::rfc9106_low_mem(), ) .with_kind(crate::ErrorKind::PasswordHashGeneration)?, ); diff --git a/backend/src/disk/mount/filesystem/cifs.rs b/backend/src/disk/mount/filesystem/cifs.rs index c456bce63..91b477fcf 100644 --- a/backend/src/disk/mount/filesystem/cifs.rs +++ b/backend/src/disk/mount/filesystem/cifs.rs @@ -19,7 +19,6 @@ async fn resolve_hostname(hostname: &str) -> Result { if let Ok(addr) = hostname.parse() { return Ok(addr); } - #[cfg(feature = "avahi")] if hostname.ends_with(".local") { return Ok(IpAddr::V4(crate::net::mdns::resolve_mdns(hostname).await?)); } diff --git a/backend/src/disk/mount/filesystem/ecryptfs.rs b/backend/src/disk/mount/filesystem/ecryptfs.rs index 3c828f4c7..78570f49b 100644 --- a/backend/src/disk/mount/filesystem/ecryptfs.rs +++ b/backend/src/disk/mount/filesystem/ecryptfs.rs @@ -2,13 +2,12 @@ use std::os::unix::ffi::OsStrExt; use std::path::Path; use async_trait::async_trait; -use color_eyre::eyre::eyre; use digest::generic_array::GenericArray; use digest::{Digest, OutputSizeUser}; use sha2::Sha256; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; use super::{FileSystem, MountType}; +use crate::util::Invoke; use crate::{Error, ResultExt}; pub async fn mount_ecryptfs, P1: AsRef>( @@ -17,7 +16,7 @@ pub async fn mount_ecryptfs, P1: AsRef>( key: &str, ) -> Result<(), Error> { tokio::fs::create_dir_all(dst.as_ref()).await?; - let mut ecryptfs = tokio::process::Command::new("mount") + tokio::process::Command::new("mount") .arg("-t") .arg("ecryptfs") .arg(src.as_ref()) @@ -25,22 +24,9 @@ pub async fn mount_ecryptfs, P1: AsRef>( .arg("-o") // for more information `man ecryptfs` .arg(format!("key=passphrase:passphrase_passwd={},ecryptfs_cipher=aes,ecryptfs_key_bytes=32,ecryptfs_passthrough=n,ecryptfs_enable_filename_crypto=y,no_sig_cache", key)) - .stdin(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .spawn()?; - let mut stdin = ecryptfs.stdin.take().unwrap(); - let mut stderr = ecryptfs.stderr.take().unwrap(); - stdin.write_all(b"\n").await?; - stdin.flush().await?; - stdin.shutdown().await?; - drop(stdin); - let mut err = String::new(); - stderr.read_to_string(&mut err).await?; - if !ecryptfs.wait().await?.success() { - Err(Error::new(eyre!("{}", err), crate::ErrorKind::Filesystem)) - } else { - Ok(()) - } + .input(Some(&mut std::io::Cursor::new(b"\n"))) + .invoke(crate::ErrorKind::Filesystem).await?; + Ok(()) } pub struct EcryptFS, Key: AsRef> { diff --git a/backend/src/disk/mount/filesystem/efivarfs.rs b/backend/src/disk/mount/filesystem/efivarfs.rs index 3b2bae3ba..ad9d79941 100644 --- a/backend/src/disk/mount/filesystem/efivarfs.rs +++ b/backend/src/disk/mount/filesystem/efivarfs.rs @@ -7,7 +7,7 @@ use sha2::Sha256; use super::{FileSystem, MountType, ReadOnly}; use crate::util::Invoke; -use crate::{Error, ResultExt}; +use crate::Error; pub struct EfiVarFs; #[async_trait] diff --git a/backend/src/disk/mount/util.rs b/backend/src/disk/mount/util.rs index 18fbcbe05..392e5d67a 100644 --- a/backend/src/disk/mount/util.rs +++ b/backend/src/disk/mount/util.rs @@ -3,7 +3,7 @@ use std::path::Path; use tracing::instrument; use crate::util::Invoke; -use crate::{Error, ResultExt}; +use crate::Error; #[instrument(skip_all)] pub async fn bind, P1: AsRef>( diff --git a/backend/src/disk/util.rs b/backend/src/disk/util.rs index 27b2bb5f0..7051026cd 100644 --- a/backend/src/disk/util.rs +++ b/backend/src/disk/util.rs @@ -3,7 +3,6 @@ use std::path::{Path, PathBuf}; use color_eyre::eyre::{self, eyre}; use futures::TryStreamExt; -use indexmap::IndexSet; use nom::bytes::complete::{tag, take_till1}; use nom::character::complete::multispace1; use nom::character::is_space; @@ -62,8 +61,8 @@ pub struct EmbassyOsRecoveryInfo { pub wrapped_key: Option, } -const DISK_PATH: &'static str = "/dev/disk/by-path"; -const SYS_BLOCK_PATH: &'static str = "/sys/block"; +const DISK_PATH: &str = "/dev/disk/by-path"; +const SYS_BLOCK_PATH: &str = "/sys/block"; lazy_static::lazy_static! { static ref PARTITION_REGEX: Regex = Regex::new("-part[0-9]+$").unwrap(); diff --git a/backend/src/error.rs b/backend/src/error.rs index d4286339d..2b769b03a 100644 --- a/backend/src/error.rs +++ b/backend/src/error.rs @@ -1,5 +1,5 @@ use color_eyre::eyre::eyre; -pub use models::{Error, ErrorKind, ResultExt}; +pub use models::{Error, ErrorKind, OptionExt, ResultExt}; #[derive(Debug, Default)] pub struct ErrorCollection(Vec); @@ -54,7 +54,7 @@ impl std::fmt::Display for ErrorCollection { macro_rules! ensure_code { ($x:expr, $c:expr, $fmt:expr $(, $arg:expr)*) => { if !($x) { - return Err(crate::Error::new(color_eyre::eyre::eyre!($fmt, $($arg, )*), $c)); + return Err(crate::error::Error::new(color_eyre::eyre::eyre!($fmt, $($arg, )*), $c)); } }; } diff --git a/backend/src/firmware.rs b/backend/src/firmware.rs new file mode 100644 index 000000000..9f3e3c52c --- /dev/null +++ b/backend/src/firmware.rs @@ -0,0 +1,70 @@ +use std::path::Path; + +use async_compression::tokio::bufread::GzipDecoder; +use tokio::fs::File; +use tokio::io::{AsyncRead, BufReader}; +use tokio::process::Command; + +use crate::disk::fsck::RequiresReboot; +use crate::prelude::*; +use crate::util::Invoke; + +pub async fn update_firmware() -> Result { + let product_name = String::from_utf8( + Command::new("dmidecode") + .arg("-s") + .arg("system-product-name") + .invoke(ErrorKind::Firmware) + .await?, + )? + .trim() + .to_owned(); + if product_name.is_empty() { + return Ok(RequiresReboot(false)); + } + let firmware_dir = Path::new("/usr/lib/startos/firmware").join(&product_name); + if tokio::fs::metadata(&firmware_dir).await.is_ok() { + let current_firmware = String::from_utf8( + Command::new("dmidecode") + .arg("-s") + .arg("bios-version") + .invoke(ErrorKind::Firmware) + .await?, + )? + .trim() + .to_owned(); + if tokio::fs::metadata(firmware_dir.join(format!("{current_firmware}.rom.gz"))) + .await + .is_err() + && tokio::fs::metadata(firmware_dir.join(format!("{current_firmware}.rom"))) + .await + .is_err() + { + let mut firmware_read_dir = tokio::fs::read_dir(&firmware_dir).await?; + while let Some(entry) = firmware_read_dir.next_entry().await? { + let filename = entry.file_name().to_string_lossy().into_owned(); + let rdr: Option> = + if filename.ends_with(".rom.gz") { + Some(Box::new(GzipDecoder::new(BufReader::new( + File::open(entry.path()).await?, + )))) + } else if filename.ends_with(".rom") { + Some(Box::new(File::open(entry.path()).await?)) + } else { + None + }; + if let Some(mut rdr) = rdr { + Command::new("flashrom") + .arg("-p") + .arg("internal") + .arg("-w-") + .input(Some(&mut rdr)) + .invoke(ErrorKind::Firmware) + .await?; + return Ok(RequiresReboot(true)); + } + } + } + } + Ok(RequiresReboot(false)) +} diff --git a/backend/src/hostname.rs b/backend/src/hostname.rs index 91e4ea71f..f68d5c9d8 100644 --- a/backend/src/hostname.rs +++ b/backend/src/hostname.rs @@ -1,9 +1,7 @@ -use patch_db::DbHandle; use rand::{thread_rng, Rng}; use tokio::process::Command; use tracing::instrument; -use crate::account::AccountInfo; use crate::util::Invoke; use crate::{Error, ErrorKind}; #[derive(Clone, serde::Deserialize, serde::Serialize, Debug)] @@ -62,6 +60,14 @@ pub async fn set_hostname(hostname: &Hostname) -> Result<(), Error> { .arg(hostname) .invoke(ErrorKind::ParseSysInfo) .await?; + Command::new("sed") + .arg("-i") + .arg(format!( + "s/\\(\\s\\)localhost\\( {hostname}\\)\\?/\\1localhost {hostname}/g" + )) + .arg("/etc/hosts") + .invoke(ErrorKind::ParseSysInfo) + .await?; Ok(()) } diff --git a/backend/src/init.rs b/backend/src/init.rs index 3cacc0726..288149f37 100644 --- a/backend/src/init.rs +++ b/backend/src/init.rs @@ -1,25 +1,28 @@ -use std::collections::HashMap; use std::fs::Permissions; use std::os::unix::fs::PermissionsExt; use std::path::Path; -use std::time::Duration; +use std::time::{Duration, SystemTime}; use color_eyre::eyre::eyre; use helpers::NonDetachingJoinHandle; use models::ResultExt; -use patch_db::{DbHandle, LockReceipt, LockType}; use rand::random; use sqlx::{Pool, Postgres}; use tokio::process::Command; +use tracing::instrument; use crate::account::AccountInfo; use crate::context::rpc::RpcContextConfig; -use crate::db::model::{ServerInfo, ServerStatus}; +use crate::db::model::ServerStatus; use crate::disk::mount::util::unmount; use crate::install::PKG_ARCHIVE_DIR; use crate::middleware::auth::LOCAL_AUTH_COOKIE_PATH; +use crate::prelude::*; use crate::sound::BEP; -use crate::system::time; +use crate::util::cpupower::{ + current_governor, get_available_governors, set_governor, GOVERNOR_PERFORMANCE, +}; +use crate::util::docker::{create_bridge_network, CONTAINER_DATADIR, CONTAINER_TOOL}; use crate::util::Invoke; use crate::{Error, ARCH}; @@ -39,40 +42,8 @@ pub async fn check_time_is_synchronized() -> Result { == "NTPSynchronized=yes") } -pub struct InitReceipts { - pub server_info: LockReceipt, - pub server_version: LockReceipt, - pub version_range: LockReceipt, -} -impl InitReceipts { - pub async fn new(db: &mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let server_info = crate::db::DatabaseModel::new() - .server_info() - .make_locker(LockType::Write) - .add_to_keys(&mut locks); - let server_version = crate::db::DatabaseModel::new() - .server_info() - .version() - .make_locker(LockType::Write) - .add_to_keys(&mut locks); - let version_range = crate::db::DatabaseModel::new() - .server_info() - .eos_version_compat() - .make_locker(LockType::Write) - .add_to_keys(&mut locks); - - let skeleton_key = db.lock_all(locks).await?; - Ok(Self { - server_info: server_info.verify(&skeleton_key)?, - server_version: server_version.verify(&skeleton_key)?, - version_range: version_range.verify(&skeleton_key)?, - }) - } -} - // must be idempotent +#[tracing::instrument(skip_all)] pub async fn init_postgres(datadir: impl AsRef) -> Result<(), Error> { let db_dir = datadir.as_ref().join("main/postgresql"); if tokio::process::Command::new("mountpoint") @@ -133,7 +104,11 @@ pub async fn init_postgres(datadir: impl AsRef) -> Result<(), Error> { tmp }; if tokio::fs::metadata(&conf_dir).await.is_ok() { - tokio::fs::rename(&conf_dir, &conf_dir_tmp).await?; + Command::new("mv") + .arg(&conf_dir) + .arg(&conf_dir_tmp) + .invoke(ErrorKind::Filesystem) + .await?; } let mut old_version = pg_version; while old_version > 13 @@ -154,7 +129,11 @@ pub async fn init_postgres(datadir: impl AsRef) -> Result<(), Error> { if tokio::fs::metadata(&conf_dir).await.is_ok() { tokio::fs::remove_dir_all(&conf_dir).await?; } - tokio::fs::rename(&conf_dir_tmp, &conf_dir).await?; + Command::new("mv") + .arg(&conf_dir_tmp) + .arg(&conf_dir) + .invoke(ErrorKind::Filesystem) + .await?; } } @@ -190,6 +169,7 @@ pub struct InitResult { pub db: patch_db::PatchDb, } +#[instrument(skip_all)] pub async fn init(cfg: &RpcContextConfig) -> Result { tokio::fs::create_dir_all("/run/embassy") .await @@ -223,12 +203,8 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { let account = AccountInfo::load(&secret_store).await?; let db = cfg.db(&account).await?; tracing::info!("Opened PatchDB"); - let mut handle = db.handle(); - let mut server_info = crate::db::DatabaseModel::new() - .server_info() - .get_mut(&mut handle) - .await?; - let receipts = InitReceipts::new(&mut handle).await?; + let peek = db.peek().await; + let mut server_info = peek.as_server_info().de()?; // write to ca cert store tokio::fs::write( @@ -278,6 +254,17 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { } } crate::disk::mount::util::bind(&log_dir, "/var/log/journal", false).await?; + match Command::new("chattr") + .arg("-R") + .arg("+C") + .arg("/var/log/journal") + .invoke(ErrorKind::Filesystem) + .await + { + Ok(_) => Ok(()), + Err(e) if e.source.to_string().contains("Operation not supported") => Ok(()), + Err(e) => Err(e), + }?; Command::new("systemctl") .arg("restart") .arg("systemd-journald") @@ -286,57 +273,53 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { tracing::info!("Mounted Logs"); let tmp_dir = cfg.datadir().join("package-data/tmp"); + if should_rebuild && tokio::fs::metadata(&tmp_dir).await.is_ok() { + tokio::fs::remove_dir_all(&tmp_dir).await?; + } if tokio::fs::metadata(&tmp_dir).await.is_err() { tokio::fs::create_dir_all(&tmp_dir).await?; } - let tmp_docker = cfg.datadir().join("package-data/tmp/docker"); - let tmp_docker_exists = tokio::fs::metadata(&tmp_docker).await.is_ok(); - if should_rebuild && tmp_docker_exists { - tokio::fs::remove_dir_all(&tmp_docker).await?; + let tmp_var = cfg.datadir().join(format!("package-data/tmp/var")); + if tokio::fs::metadata(&tmp_var).await.is_ok() { + tokio::fs::remove_dir_all(&tmp_var).await?; + } + crate::disk::mount::util::bind(&tmp_var, "/var/tmp", false).await?; + let tmp_docker = cfg + .datadir() + .join(format!("package-data/tmp/{CONTAINER_TOOL}")); + let tmp_docker_exists = tokio::fs::metadata(&tmp_docker).await.is_ok(); + if CONTAINER_TOOL == "docker" { + Command::new("systemctl") + .arg("stop") + .arg("docker") + .invoke(crate::ErrorKind::Docker) + .await?; + } + crate::disk::mount::util::bind(&tmp_docker, CONTAINER_DATADIR, false).await?; + + if CONTAINER_TOOL == "docker" { + Command::new("systemctl") + .arg("reset-failed") + .arg("docker") + .invoke(crate::ErrorKind::Docker) + .await?; + Command::new("systemctl") + .arg("start") + .arg("docker") + .invoke(crate::ErrorKind::Docker) + .await?; } - Command::new("systemctl") - .arg("stop") - .arg("docker") - .invoke(crate::ErrorKind::Docker) - .await?; - crate::disk::mount::util::bind(&tmp_docker, "/var/lib/docker", false).await?; - Command::new("systemctl") - .arg("reset-failed") - .arg("docker") - .invoke(crate::ErrorKind::Docker) - .await?; - Command::new("systemctl") - .arg("start") - .arg("docker") - .invoke(crate::ErrorKind::Docker) - .await?; tracing::info!("Mounted Docker Data"); if should_rebuild || !tmp_docker_exists { - tracing::info!("Creating Docker Network"); - bollard::Docker::connect_with_unix_defaults()? - .create_network(bollard::network::CreateNetworkOptions { - name: "start9", - driver: "bridge", - ipam: bollard::models::Ipam { - config: Some(vec![bollard::models::IpamConfig { - subnet: Some("172.18.0.1/24".into()), - ..Default::default() - }]), - ..Default::default() - }, - options: { - let mut m = HashMap::new(); - m.insert("com.docker.network.bridge.name", "br-start9"); - m - }, - ..Default::default() - }) - .await?; - tracing::info!("Created Docker Network"); + if CONTAINER_TOOL == "docker" { + tracing::info!("Creating Docker Network"); + create_bridge_network("start9", "172.18.0.1/24", "br-start9").await?; + tracing::info!("Created Docker Network"); + } tracing::info!("Loading System Docker Images"); - crate::install::load_images("/usr/lib/embassy/system-images").await?; + crate::install::load_images("/usr/lib/startos/system-images").await?; tracing::info!("Loaded System Docker Images"); tracing::info!("Loading Package Docker Images"); @@ -344,8 +327,23 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { tracing::info!("Loaded Package Docker Images"); } + if CONTAINER_TOOL == "podman" { + crate::util::docker::remove_container("netdummy", true).await?; + Command::new("podman") + .arg("run") + .arg("-d") + .arg("--rm") + .arg("--network=start9") + .arg("--name=netdummy") + .arg("start9/x_system/utils:latest") + .arg("sleep") + .arg("infinity") + .invoke(crate::ErrorKind::Docker) + .await?; + } + tracing::info!("Enabling Docker QEMU Emulation"); - Command::new("docker") + Command::new(CONTAINER_TOOL) .arg("run") .arg("--privileged") .arg("--rm") @@ -356,15 +354,45 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { .await?; tracing::info!("Enabled Docker QEMU Emulation"); - let mut warn_time_not_synced = true; - for _ in 0..60 { + if current_governor() + .await? + .map(|g| &g != &GOVERNOR_PERFORMANCE) + .unwrap_or(false) + { + tracing::info!("Setting CPU Governor to \"{}\"", GOVERNOR_PERFORMANCE); + if get_available_governors() + .await? + .contains(&GOVERNOR_PERFORMANCE) + { + set_governor(&GOVERNOR_PERFORMANCE).await?; + tracing::info!("Set CPU Governor"); + } else { + tracing::warn!("CPU Governor \"{}\" Not Available", GOVERNOR_PERFORMANCE) + } + } + + let mut time_not_synced = true; + let mut not_made_progress = 0u32; + for _ in 0..1800 { if check_time_is_synchronized().await? { - warn_time_not_synced = false; + time_not_synced = false; break; } + let t = SystemTime::now(); tokio::time::sleep(Duration::from_secs(1)).await; + if t.elapsed() + .map(|t| t > Duration::from_secs_f64(1.1)) + .unwrap_or(true) + { + not_made_progress = 0; + } else { + not_made_progress += 1; + } + if not_made_progress > 30 { + break; + } } - if warn_time_not_synced { + if time_not_synced { tracing::warn!("Timed out waiting for system time to synchronize"); } else { tracing::info!("Syncronized system clock"); @@ -378,13 +406,38 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { updated: false, update_progress: None, backup_progress: None, + shutting_down: false, + restarting: false, }; - server_info.system_start_time = time().await?; + server_info.ntp_synced = if time_not_synced { + let db = db.clone(); + tokio::spawn(async move { + while !check_time_is_synchronized().await.unwrap() { + tokio::time::sleep(Duration::from_secs(30)).await; + } + db.mutate(|v| v.as_server_info_mut().as_ntp_synced_mut().ser(&true)) + .await + .unwrap() + }); + false + } else { + true + }; - server_info.save(&mut handle).await?; + db.mutate(|v| { + v.as_server_info_mut().ser(&server_info)?; + Ok(()) + }) + .await?; - crate::version::init(&mut handle, &secret_store, &receipts).await?; + crate::version::init(&db, &secret_store).await?; + + db.mutate(|d| { + let model = d.de()?; + d.ser(&model) + }) + .await?; if should_rebuild { match tokio::fs::remove_file(SYSTEM_REBUILD_PATH).await { diff --git a/backend/src/install/cleanup.rs b/backend/src/install/cleanup.rs index 8d4b4c908..d90ec502c 100644 --- a/backend/src/install/cleanup.rs +++ b/backend/src/install/cleanup.rs @@ -1,149 +1,34 @@ -use std::collections::HashMap; use std::path::PathBuf; use std::sync::Arc; -use bollard::image::{ListImagesOptions, RemoveImageOptions}; -use patch_db::{DbHandle, LockReceipt, LockTargetId, LockType, PatchDbHandle, Verifier}; +use models::OptionExt; use sqlx::{Executor, Postgres}; use tracing::instrument; use super::PKG_ARCHIVE_DIR; -use crate::config::{not_found, ConfigReceipts}; use crate::context::RpcContext; use crate::db::model::{ - AllPackageData, CurrentDependencies, CurrentDependents, InstalledPackageDataEntry, - PackageDataEntry, -}; -use crate::dependencies::{ - reconfigure_dependents_with_live_pointers, DependencyErrors, TryHealReceipts, + CurrentDependencies, Database, PackageDataEntry, PackageDataEntryInstalled, + PackageDataEntryMatchModelRef, }; use crate::error::ErrorCollection; -use crate::s9pk::manifest::{Manifest, PackageId}; +use crate::prelude::*; +use crate::s9pk::manifest::PackageId; use crate::util::{Apply, Version}; use crate::volume::{asset_dir, script_dir}; use crate::Error; -pub struct UpdateDependencyReceipts { - try_heal: TryHealReceipts, - dependency_errors: LockReceipt, - manifest: LockReceipt, -} -impl UpdateDependencyReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let dependency_errors = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.status().dependency_errors()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let manifest = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let try_heal = TryHealReceipts::setup(locks); - move |skeleton_key| { - Ok(Self { - dependency_errors: dependency_errors.verify(skeleton_key)?, - manifest: manifest.verify(skeleton_key)?, - try_heal: try_heal(skeleton_key)?, - }) - } - } -} - -#[instrument(skip_all)] -pub async fn update_dependency_errors_of_dependents<'a, Db: DbHandle>( - ctx: &RpcContext, - db: &mut Db, - id: &PackageId, - deps: &CurrentDependents, - receipts: &UpdateDependencyReceipts, -) -> Result<(), Error> { - for dep in deps.0.keys() { - if let Some(man) = receipts.manifest.get(db, dep).await? { - if let Err(e) = if let Some(info) = man.dependencies.0.get(id) { - info.satisfied(ctx, db, id, None, dep, &receipts.try_heal) - .await? - } else { - Ok(()) - } { - let mut errs = receipts - .dependency_errors - .get(db, dep) - .await? - .ok_or_else(|| not_found!(dep))?; - errs.0.insert(id.clone(), e); - receipts.dependency_errors.set(db, errs, dep).await? - } else { - let mut errs = receipts - .dependency_errors - .get(db, dep) - .await? - .ok_or_else(|| not_found!(dep))?; - errs.0.remove(id); - receipts.dependency_errors.set(db, errs, dep).await? - } - } - } - Ok(()) -} - #[instrument(skip_all)] pub async fn cleanup(ctx: &RpcContext, id: &PackageId, version: &Version) -> Result<(), Error> { let mut errors = ErrorCollection::new(); ctx.managers.remove(&(id.clone(), version.clone())).await; // docker images start9/$APP_ID/*:$VERSION -q | xargs docker rmi - let images = ctx - .docker - .list_images(Some(ListImagesOptions { - all: false, - filters: { - let mut f = HashMap::new(); - f.insert( - "reference".to_owned(), - vec![format!("start9/{}/*:{}", id, version)], - ); - f - }, - digests: false, - })) - .await - .apply(|res| errors.handle(res)); + let images = crate::util::docker::images_for(id, version).await?; errors.extend( - futures::future::join_all( - images - .into_iter() - .flatten() - .flat_map(|image| image.repo_tags) - .filter(|tag| { - tag.starts_with(&format!("start9/{}/", id)) - && tag.ends_with(&format!(":{}", version)) - }) - .map(|tag| async { - let tag = tag; // move into future - ctx.docker - .remove_image( - &tag, - Some(RemoveImageOptions { - force: true, - noprune: false, - }), - None, - ) - .await - }), - ) + futures::future::join_all(images.into_iter().map(|sha| async { + let sha = sha; // move into future + crate::util::docker::remove_image(&sha).await + })) .await, ); let pkg_archive_dir = ctx @@ -172,66 +57,26 @@ pub async fn cleanup(ctx: &RpcContext, id: &PackageId, version: &Version) -> Res errors.into_result() } -pub struct CleanupFailedReceipts { - package_data_entry: LockReceipt, - package_entries: LockReceipt, -} - -impl CleanupFailedReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let package_data_entry = crate::db::DatabaseModel::new() - .package_data() - .star() - .make_locker(LockType::Write) - .add_to_keys(locks); - let package_entries = crate::db::DatabaseModel::new() - .package_data() - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - package_data_entry: package_data_entry.verify(skeleton_key).unwrap(), - package_entries: package_entries.verify(skeleton_key).unwrap(), - }) - } - } -} - #[instrument(skip_all)] -pub async fn cleanup_failed( - ctx: &RpcContext, - db: &mut Db, - id: &PackageId, - receipts: &CleanupFailedReceipts, -) -> Result<(), Error> { - let pde = receipts - .package_data_entry - .get(db, id) - .await? - .ok_or_else(|| not_found!(id))?; - if let Some(manifest) = match &pde { - PackageDataEntry::Installing { manifest, .. } - | PackageDataEntry::Restoring { manifest, .. } => Some(manifest), - PackageDataEntry::Updating { - manifest, - installed: - InstalledPackageDataEntry { - manifest: installed_manifest, - .. - }, - .. - } => { - if &manifest.version != &installed_manifest.version { - Some(manifest) +pub async fn cleanup_failed(ctx: &RpcContext, id: &PackageId) -> Result<(), Error> { + if let Some(version) = match ctx + .db + .peek() + .await + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .as_match() + { + PackageDataEntryMatchModelRef::Installing(m) => Some(m.as_manifest().as_version().de()?), + PackageDataEntryMatchModelRef::Restoring(m) => Some(m.as_manifest().as_version().de()?), + PackageDataEntryMatchModelRef::Updating(m) => { + let manifest_version = m.as_manifest().as_version().de()?; + let installed = m.as_installed().as_manifest().as_version().de()?; + if manifest_version != installed { + Some(manifest_version) } else { - None + None // do not remove existing data } } _ => { @@ -239,179 +84,119 @@ pub async fn cleanup_failed( None } } { - cleanup(ctx, id, &manifest.version).await?; + cleanup(ctx, id, &version).await?; } - match pde { - PackageDataEntry::Installing { .. } | PackageDataEntry::Restoring { .. } => { - let mut entries = receipts.package_entries.get(db).await?; - entries.0.remove(id); - receipts.package_entries.set(db, entries).await?; - } - PackageDataEntry::Updating { - installed, - static_files, - .. - } => { - receipts - .package_data_entry - .set( - db, - PackageDataEntry::Installed { - manifest: installed.manifest.clone(), - installed, - static_files, - }, - id, - ) - .await?; - } - _ => (), - } - - Ok(()) + ctx.db + .mutate(|v| { + match v + .clone() + .into_package_data() + .into_idx(id) + .or_not_found(id)? + .as_match() + { + PackageDataEntryMatchModelRef::Installing(_) + | PackageDataEntryMatchModelRef::Restoring(_) => { + v.as_package_data_mut().remove(id)?; + } + PackageDataEntryMatchModelRef::Updating(pde) => { + v.as_package_data_mut() + .as_idx_mut(id) + .or_not_found(id)? + .ser(&PackageDataEntry::Installed(PackageDataEntryInstalled { + manifest: pde.as_installed().as_manifest().de()?, + static_files: pde.as_static_files().de()?, + installed: pde.as_installed().de()?, + }))?; + } + _ => (), + } + Ok(()) + }) + .await } #[instrument(skip_all)] -pub async fn remove_from_current_dependents_lists<'a, Db: DbHandle>( - db: &mut Db, - id: &'a PackageId, - current_dependencies: &'a CurrentDependencies, - current_dependent_receipt: &LockReceipt, +pub fn remove_from_current_dependents_lists( + db: &mut Model, + id: &PackageId, + current_dependencies: &CurrentDependencies, ) -> Result<(), Error> { for dep in current_dependencies.0.keys().chain(std::iter::once(id)) { - if let Some(mut current_dependents) = current_dependent_receipt.get(db, dep).await? { - if current_dependents.0.remove(id).is_some() { - current_dependent_receipt - .set(db, current_dependents, dep) - .await?; - } + if let Some(current_dependents) = db + .as_package_data_mut() + .as_idx_mut(dep) + .and_then(|d| d.as_installed_mut()) + .map(|i| i.as_current_dependents_mut()) + { + current_dependents.remove(id)?; } } Ok(()) } -pub struct UninstallReceipts { - config: ConfigReceipts, - removing: LockReceipt, - packages: LockReceipt, - current_dependents: LockReceipt, - update_depenency_receipts: UpdateDependencyReceipts, -} -impl UninstallReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - let setup = Self::setup(&mut locks, id); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&Verifier) -> Result { - let config = ConfigReceipts::setup(locks); - let removing = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|pde| pde.removing()) - .make_locker(LockType::Write) - .add_to_keys(locks); - - let current_dependents = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependents()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let packages = crate::db::DatabaseModel::new() - .package_data() - .make_locker(LockType::Write) - .add_to_keys(locks); - let update_depenency_receipts = UpdateDependencyReceipts::setup(locks); - move |skeleton_key| { - Ok(Self { - config: config(skeleton_key)?, - removing: removing.verify(skeleton_key)?, - current_dependents: current_dependents.verify(skeleton_key)?, - update_depenency_receipts: update_depenency_receipts(skeleton_key)?, - packages: packages.verify(skeleton_key)?, - }) - } - } -} #[instrument(skip_all)] -pub async fn uninstall( - ctx: &RpcContext, - db: &mut PatchDbHandle, - secrets: &mut Ex, - id: &PackageId, -) -> Result<(), Error> +pub async fn uninstall(ctx: &RpcContext, secrets: &mut Ex, id: &PackageId) -> Result<(), Error> where for<'a> &'a mut Ex: Executor<'a, Database = Postgres>, { - let mut tx = db.begin().await?; - crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .lock(&mut tx, LockType::Write) - .await?; - let receipts = UninstallReceipts::new(&mut tx, id).await?; - let entry = receipts.removing.get(&mut tx).await?; - cleanup(ctx, &entry.manifest.id, &entry.manifest.version).await?; + let db = ctx.db.peek().await; + let entry = db + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .expect_as_removing()?; - let packages = { - let mut packages = receipts.packages.get(&mut tx).await?; - packages.0.remove(id); - packages - }; let dependents_paths: Vec = entry - .current_dependents - .0 - .keys() - .flat_map(|x| packages.0.get(x)) - .flat_map(|x| x.manifest_borrow().volumes.values()) + .as_removing() + .as_current_dependents() + .keys()? + .into_iter() + .filter(|x| x != id) + .flat_map(|x| db.as_package_data().as_idx(&x)) + .flat_map(|x| x.as_installed()) + .flat_map(|x| x.as_manifest().as_volumes().de()) + .flat_map(|x| x.values().cloned().collect::>()) .flat_map(|x| x.pointer_path(&ctx.datadir)) .collect(); - receipts.packages.set(&mut tx, packages).await?; - // once we have removed the package entry, we can change all the dependent pointers to null - reconfigure_dependents_with_live_pointers(ctx, &mut tx, &receipts.config, &entry).await?; - remove_from_current_dependents_lists( - &mut tx, - &entry.manifest.id, - &entry.current_dependencies, - &receipts.current_dependents, - ) - .await?; - update_dependency_errors_of_dependents( - ctx, - &mut tx, - &entry.manifest.id, - &entry.current_dependents, - &receipts.update_depenency_receipts, - ) - .await?; - let volumes = ctx + let volume_dir = ctx .datadir .join(crate::volume::PKG_VOLUME_DIR) - .join(&entry.manifest.id); + .join(&*entry.as_manifest().as_id().de()?); + let version = entry.as_removing().as_manifest().as_version().de()?; + tracing::debug!( + "Cleaning up {:?} except for {:?}", + volume_dir, + dependents_paths + ); + cleanup(ctx, id, &version).await?; + cleanup_folder(volume_dir, Arc::new(dependents_paths)).await; + remove_network_keys(secrets, id).await?; - tracing::debug!("Cleaning up {:?} at {:?}", volumes, dependents_paths); - cleanup_folder(volumes, Arc::new(dependents_paths)).await; - remove_tor_keys(secrets, &entry.manifest.id).await?; - tx.commit().await?; - Ok(()) + ctx.db + .mutate(|d| { + d.as_package_data_mut().remove(id)?; + remove_from_current_dependents_lists( + d, + id, + &entry.as_removing().as_current_dependencies().de()?, + ) + }) + .await } #[instrument(skip_all)] -pub async fn remove_tor_keys(secrets: &mut Ex, id: &PackageId) -> Result<(), Error> +pub async fn remove_network_keys(secrets: &mut Ex, id: &PackageId) -> Result<(), Error> where for<'a> &'a mut Ex: Executor<'a, Database = Postgres>, { - let id_str = id.as_str(); - sqlx::query!("DELETE FROM tor WHERE package = $1", id_str) - .execute(secrets) + sqlx::query!("DELETE FROM network_keys WHERE package = $1", &*id) + .execute(&mut *secrets) + .await?; + sqlx::query!("DELETE FROM tor WHERE package = $1", &*id) + .execute(&mut *secrets) .await?; Ok(()) } diff --git a/backend/src/install/mod.rs b/backend/src/install/mod.rs index e57e61afb..e2089608e 100644 --- a/backend/src/install/mod.rs +++ b/backend/src/install/mod.rs @@ -2,7 +2,6 @@ use std::collections::BTreeMap; use std::io::SeekFrom; use std::marker::PhantomData; use std::path::{Path, PathBuf}; -use std::process::Stdio; use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Duration; @@ -14,48 +13,49 @@ use futures::{FutureExt, StreamExt, TryStreamExt}; use http::header::CONTENT_LENGTH; use http::{Request, Response, StatusCode}; use hyper::Body; -use patch_db::{DbHandle, LockType}; +use models::{mime, DataUrl}; use reqwest::Url; use rpc_toolkit::command; use rpc_toolkit::yajrc::RpcError; use serde_json::{json, Value}; use tokio::fs::{File, OpenOptions}; -use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt}; +use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWriteExt}; use tokio::process::Command; use tokio::sync::oneshot; use tokio_stream::wrappers::ReadDirStream; use tracing::instrument; use self::cleanup::{cleanup_failed, remove_from_current_dependents_lists}; -use crate::config::{ConfigReceipts, ConfigureContext}; +use crate::config::ConfigureContext; use crate::context::{CliContext, RpcContext}; use crate::core::rpc_continuations::{RequestGuid, RpcContinuation}; use crate::db::model::{ - CurrentDependencies, CurrentDependencyInfo, CurrentDependents, InstalledPackageDataEntry, - PackageDataEntry, StaticDependencyInfo, StaticFiles, + CurrentDependencies, CurrentDependencyInfo, CurrentDependents, InstalledPackageInfo, + PackageDataEntry, PackageDataEntryInstalled, PackageDataEntryInstalling, + PackageDataEntryMatchModelRef, PackageDataEntryRemoving, PackageDataEntryRestoring, + PackageDataEntryUpdating, StaticDependencyInfo, StaticFiles, }; use crate::dependencies::{ - add_dependent_to_current_dependents_lists, break_all_dependents_transitive, - reconfigure_dependents_with_live_pointers, BreakTransitiveReceipts, BreakageRes, - DependencyError, DependencyErrors, + add_dependent_to_current_dependents_lists, compute_dependency_config_errs, + set_dependents_with_live_pointers_to_needs_config, }; -use crate::install::cleanup::{cleanup, update_dependency_errors_of_dependents}; +use crate::install::cleanup::cleanup; use crate::install::progress::{InstallProgress, InstallProgressTracker}; -use crate::marketplace::with_query_params; use crate::notifications::NotificationLevel; +use crate::prelude::*; +use crate::registry::marketplace::with_query_params; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::s9pk::reader::S9pkReader; use crate::status::{MainStatus, Status}; -use crate::util::io::{copy_and_shutdown, response_to_reader}; +use crate::util::docker::CONTAINER_TOOL; +use crate::util::io::response_to_reader; use crate::util::serde::{display_serializable, Port}; -use crate::util::{display_none, AsyncFileExt, Version}; -use crate::version::{Current, VersionT}; +use crate::util::{display_none, AsyncFileExt, Invoke, Version}; use crate::volume::{asset_dir, script_dir}; use crate::{Error, ErrorKind, ResultExt}; pub mod cleanup; pub mod progress; -pub mod update; pub const PKG_ARCHIVE_DIR: &str = "package-data/archive"; pub const PKG_PUBLIC_DIR: &str = "package-data/public"; @@ -63,33 +63,30 @@ pub const PKG_WASM_DIR: &str = "package-data/wasm"; #[command(display(display_serializable))] pub async fn list(#[context] ctx: RpcContext) -> Result { - let mut hdl = ctx.db.handle(); - let package_data = crate::db::DatabaseModel::new() - .package_data() - .get(&mut hdl) - .await?; - - Ok(package_data - .0 + Ok(ctx.db.peek().await.as_package_data().as_entries()? .iter() .filter_map(|(id, pde)| { - serde_json::to_value(match pde { - PackageDataEntry::Installed { installed, .. } => { - json!({ "status":"installed","id": id.clone(), "version": installed.manifest.version.clone()}) + let status = match pde.as_match() { + PackageDataEntryMatchModelRef::Installed(_) => { + "installed" } - PackageDataEntry::Installing { manifest, install_progress, .. } => { - json!({ "status":"installing","id": id.clone(), "version": manifest.version.clone(), "progress": install_progress.clone()}) + PackageDataEntryMatchModelRef::Installing(_) => { + "installing" } - PackageDataEntry::Updating { manifest, installed, install_progress, .. } => { - json!({ "status":"updating","id": id.clone(), "version": installed.manifest.version.clone(), "progress": install_progress.clone()}) + PackageDataEntryMatchModelRef::Updating(_) => { + "updating" } - PackageDataEntry::Restoring { manifest, install_progress, .. } => { - json!({ "status":"restoring","id": id.clone(), "version": manifest.version.clone(), "progress": install_progress.clone()}) + PackageDataEntryMatchModelRef::Restoring(_) => { + "restoring" } - PackageDataEntry::Removing { manifest, .. } => { - json!({ "status":"removing", "id": id.clone(), "version": manifest.version.clone()}) + PackageDataEntryMatchModelRef::Removing(_) => { + "removing" } - }) + PackageDataEntryMatchModelRef::Error(_) => { + "error" + } + }; + serde_json::to_value(json!({ "status":status, "id": id.clone(), "version": pde.as_manifest().as_version().de().ok()?})) .ok() }) .collect()) @@ -155,7 +152,7 @@ pub async fn install( let man: Manifest = ctx .client .get(with_query_params( - &ctx, + ctx.clone(), format!( "{}/package/v0/manifest/{}?spec={}&version-priority={}", marketplace_url, id, version, version_priority, @@ -173,7 +170,7 @@ pub async fn install( let s9pk = ctx .client .get(with_query_params( - &ctx, + ctx.clone(), format!( "{}/package/v0/{}.s9pk?spec=={}&version-priority={}", marketplace_url, id, man.version, version_priority, @@ -183,10 +180,9 @@ pub async fn install( .send() .await .with_kind(crate::ErrorKind::Registry)? - .error_for_status() - .with_kind(crate::ErrorKind::Registry)?; + .error_for_status()?; - if man.id.as_str() != id || !man.version.satisfies(&version) { + if *man.id != *id || !man.version.satisfies(&version) { return Err(Error::new( eyre!("Fetched package does not match requested id and version"), ErrorKind::Registry, @@ -207,7 +203,7 @@ pub async fn install( &mut response_to_reader( ctx.client .get(with_query_params( - &ctx, + ctx.clone(), format!( "{}/package/v0/license/{}?spec=={}", marketplace_url, id, man.version, @@ -228,7 +224,7 @@ pub async fn install( &mut response_to_reader( ctx.client .get(with_query_params( - &ctx, + ctx.clone(), format!( "{}/package/v0/instructions/{}?spec=={}", marketplace_url, id, man.version, @@ -249,7 +245,7 @@ pub async fn install( &mut response_to_reader( ctx.client .get(with_query_params( - &ctx, + ctx.clone(), format!( "{}/package/v0/icon/{}?spec=={}", marketplace_url, id, man.version, @@ -276,65 +272,59 @@ pub async fn install( tracing::warn!("Failed to pre-download icon: {}", e); } - let progress = InstallProgress::new(s9pk.content_length()); + let progress = Arc::new(InstallProgress::new(s9pk.content_length())); let static_files = StaticFiles::local(&man.id, &man.version, icon_type); - let mut db_handle = ctx.db.handle(); - let mut tx = db_handle.begin().await?; - let mut pde = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&man.id) - .get_mut(&mut tx) + ctx.db + .mutate(|db| { + let pde = match db + .as_package_data() + .as_idx(&man.id) + .map(|x| x.de()) + .transpose()? + { + Some(PackageDataEntry::Installed(PackageDataEntryInstalled { + installed, + static_files, + .. + })) => PackageDataEntry::Updating(PackageDataEntryUpdating { + install_progress: progress.clone(), + static_files, + installed, + manifest: man.clone(), + }), + None => PackageDataEntry::Installing(PackageDataEntryInstalling { + install_progress: progress.clone(), + static_files, + manifest: man.clone(), + }), + _ => { + return Err(Error::new( + eyre!("Cannot install over a package in a transient state"), + crate::ErrorKind::InvalidRequest, + )) + } + }; + db.as_package_data_mut().insert(&man.id, &pde) + }) .await?; - match pde.take() { - Some(PackageDataEntry::Installed { - installed, - static_files, - .. - }) => { - *pde = Some(PackageDataEntry::Updating { - install_progress: progress.clone(), - static_files, - installed, - manifest: man.clone(), - }) - } - None => { - *pde = Some(PackageDataEntry::Installing { - install_progress: progress.clone(), - static_files, - manifest: man.clone(), - }) - } - _ => { - return Err(Error::new( - eyre!("Cannot install over a package in a transient state"), - crate::ErrorKind::InvalidRequest, - )) - } - } - pde.save(&mut tx).await?; - tx.commit().await?; - drop(db_handle); + let downloading = download_install_s9pk( + ctx.clone(), + man.clone(), + Some(marketplace_url), + Arc::new(InstallProgress::new(s9pk.content_length())), + response_to_reader(s9pk), + None, + ); tokio::spawn(async move { - let mut db_handle = ctx.db.handle(); - if let Err(e) = download_install_s9pk( - &ctx, - &man, - Some(marketplace_url), - InstallProgress::new(s9pk.content_length()), - response_to_reader(s9pk), - None, - ) - .await - { + if let Err(e) = downloading.await { let err_str = format!("Install of {}@{} Failed: {}", man.id, man.version, e); tracing::error!("{}", err_str); tracing::debug!("{:?}", e); if let Err(e) = ctx .notification_manager .notify( - &mut db_handle, + ctx.db.clone(), Some(man.id), NotificationLevel::Error, String::from("Install Failed"), @@ -348,11 +338,11 @@ pub async fn install( tracing::debug!("{:?}", e); } } + Ok::<_, String>(()) }); Ok(()) } - #[command(rpc_only, display(display_none))] #[instrument(skip_all)] pub async fn sideload( @@ -409,56 +399,54 @@ pub async fn sideload( Ok(a) => Some(a), }, }; - let progress = InstallProgress::new(content_length); + let progress = Arc::new(InstallProgress::new(content_length)); + let install_progress = progress.clone(); - let mut hdl = new_ctx.db.handle(); - let mut tx = hdl.begin().await?; - - let mut pde = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&manifest.id) - .get_mut(&mut tx) + new_ctx + .db + .mutate(|db| { + let pde = match db + .as_package_data() + .as_idx(&manifest.id) + .map(|x| x.de()) + .transpose()? + { + Some(PackageDataEntry::Installed(PackageDataEntryInstalled { + installed, + static_files, + .. + })) => PackageDataEntry::Updating(PackageDataEntryUpdating { + install_progress, + installed, + manifest: manifest.clone(), + static_files, + }), + None => PackageDataEntry::Installing(PackageDataEntryInstalling { + install_progress, + static_files: StaticFiles::local( + &manifest.id, + &manifest.version, + &manifest.assets.icon_type(), + ), + manifest: manifest.clone(), + }), + _ => { + return Err(Error::new( + eyre!("Cannot install over a package in a transient state"), + crate::ErrorKind::InvalidRequest, + )) + } + }; + db.as_package_data_mut().insert(&manifest.id, &pde) + }) .await?; - match pde.take() { - Some(PackageDataEntry::Installed { - installed, - static_files, - .. - }) => { - *pde = Some(PackageDataEntry::Updating { - install_progress: progress.clone(), - installed, - manifest: manifest.clone(), - static_files, - }) - } - None => { - *pde = Some(PackageDataEntry::Installing { - install_progress: progress.clone(), - static_files: StaticFiles::local( - &manifest.id, - &manifest.version, - &manifest.assets.icon_type(), - ), - manifest: manifest.clone(), - }) - } - _ => { - return Err(Error::new( - eyre!("Cannot install over a package in a transient state"), - crate::ErrorKind::InvalidRequest, - )) - } - } - pde.save(&mut tx).await?; - tx.commit().await?; let (send, recv) = oneshot::channel(); tokio::spawn(async move { if let Err(e) = download_install_s9pk( - &new_ctx, - &manifest, + new_ctx.clone(), + manifest.clone(), None, progress, tokio_util::io::StreamReader::new(req.into_body().map_err(|e| { @@ -484,8 +472,8 @@ pub async fn sideload( if let Err(e) = new_ctx .notification_manager .notify( - &mut hdl, - Some(manifest.id), + new_ctx.db.clone(), + Some(manifest.id.clone()), NotificationLevel::Error, String::from("Install Failed"), err_str, @@ -604,85 +592,41 @@ async fn cli_install( Ok(()) } -#[command( - subcommands(self(uninstall_impl(async)), uninstall_dry), - display(display_none), - metadata(sync_db = true) -)] -pub async fn uninstall(#[arg] id: PackageId) -> Result { - Ok(id) -} - -#[command(rename = "dry", display(display_serializable))] -#[instrument(skip_all)] -pub async fn uninstall_dry( +#[command(display(display_none), metadata(sync_db = true))] +pub async fn uninstall( #[context] ctx: RpcContext, - #[parent_data] id: PackageId, -) -> Result { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - let mut breakages = BTreeMap::new(); - let receipts = BreakTransitiveReceipts::new(&mut tx).await?; - break_all_dependents_transitive( - &mut tx, - &id, - DependencyError::NotInstalled, - &mut breakages, - &receipts, - ) - .await?; - - tx.abort().await?; - - Ok(BreakageRes(breakages)) -} - -#[instrument(skip_all)] -pub async fn uninstall_impl(ctx: RpcContext, id: PackageId) -> Result<(), Error> { - let mut handle = ctx.db.handle(); - let mut tx = handle.begin().await?; - crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .lock(&mut tx, LockType::Write) + #[arg] id: PackageId, +) -> Result { + ctx.db + .mutate(|db| { + let (manifest, static_files, installed) = + match db.as_package_data().as_idx(&id).or_not_found(&id)?.de()? { + PackageDataEntry::Installed(PackageDataEntryInstalled { + manifest, + static_files, + installed, + }) => (manifest, static_files, installed), + _ => { + return Err(Error::new( + eyre!("Package is not installed."), + crate::ErrorKind::NotFound, + )); + } + }; + let pde = PackageDataEntry::Removing(PackageDataEntryRemoving { + manifest, + static_files, + removing: installed, + }); + db.as_package_data_mut().insert(&id, &pde) + }) .await?; - let mut pde = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .get_mut(&mut tx) - .await?; - let (manifest, static_files, installed) = match pde.take() { - Some(PackageDataEntry::Installed { - manifest, - static_files, - installed, - }) => (manifest, static_files, installed), - _ => { - return Err(Error::new( - eyre!("Package is not installed."), - crate::ErrorKind::NotFound, - )); - } - }; - *pde = Some(PackageDataEntry::Removing { - manifest, - static_files, - removing: installed, - }); - pde.save(&mut tx).await?; - tx.commit().await?; - drop(handle); + let return_id = id.clone(); tokio::spawn(async move { if let Err(e) = async { - cleanup::uninstall( - &ctx, - &mut ctx.db.handle(), - &mut ctx.secret_store.acquire().await?, - &id, - ) - .await + cleanup::uninstall(&ctx, ctx.secret_store.acquire().await?.as_mut(), &id).await } .await { @@ -692,7 +636,7 @@ pub async fn uninstall_impl(ctx: RpcContext, id: PackageId) -> Result<(), Error> if let Err(e) = ctx .notification_manager .notify( - &mut ctx.db.handle(), // allocating separate handle here because the lifetime of the previous one is the expression + ctx.db.clone(), // allocating separate handle here because the lifetime of the previous one is the expression Some(id), NotificationLevel::Error, String::from("Uninstall Failed"), @@ -708,42 +652,13 @@ pub async fn uninstall_impl(ctx: RpcContext, id: PackageId) -> Result<(), Error> } }); - Ok(()) -} - -pub struct DownloadInstallReceipts { - package_receipts: crate::db::package::PackageReceipts, - manifest_receipts: crate::db::package::ManifestReceipts, -} - -impl DownloadInstallReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, id); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let package_receipts = crate::db::package::PackageReceipts::setup(locks); - let manifest_receipts = crate::db::package::ManifestReceipts::setup(locks, id); - - move |skeleton_key| { - Ok(Self { - package_receipts: package_receipts(skeleton_key)?, - manifest_receipts: manifest_receipts(skeleton_key)?, - }) - } - } + Ok(return_id) } #[instrument(skip_all)] pub async fn download_install_s9pk( - ctx: &RpcContext, - temp_manifest: &Manifest, + ctx: RpcContext, + temp_manifest: Manifest, marketplace_url: Option, progress: Arc, mut s9pk: impl AsyncRead + Unpin, @@ -751,175 +666,116 @@ pub async fn download_install_s9pk( ) -> Result<(), Error> { let pkg_id = &temp_manifest.id; let version = &temp_manifest.version; - let mut previous_state: Option = None; + let db = ctx.db.peek().await; - if let Err(e) = async { - if crate::db::DatabaseModel::new() - .package_data() - .idx_model(&pkg_id) - .and_then(|x| x.installed()) - .exists(&mut ctx.db.handle()) - .await - .unwrap_or(false) - { - previous_state = crate::control::stop_impl(ctx.clone(), pkg_id.clone()) - .await - .ok(); - } - let mut db_handle = ctx.db.handle(); - let mut tx = db_handle.begin().await?; - let receipts = DownloadInstallReceipts::new(&mut tx, &pkg_id).await?; - // Build set of existing manifests - let mut manifests = Vec::new(); - for pkg in crate::db::package::get_packages(&mut tx, &receipts.package_receipts).await? { - if let Some(m) = - crate::db::package::get_manifest(&mut tx, &pkg, &receipts.manifest_receipts).await? - { + if let Result::<(), Error>::Err(e) = { + let ctx = ctx.clone(); + async move { + // // Build set of existing manifests + let mut manifests = Vec::new(); + for (_id, pkg) in db.as_package_data().as_entries()? { + let m = pkg.as_manifest().de()?; manifests.push(m); } - } - // Build map of current port -> ssl mappings - let port_map = ssl_port_status(&manifests); - tracing::info!("SSL Port Map: {:?}", &port_map); + // Build map of current port -> ssl mappings + let port_map = ssl_port_status(&manifests); + tracing::info!("SSL Port Map: {:?}", &port_map); - // if any of the requested interface lan configs conflict with current state, fail the install - for (_id, iface) in &temp_manifest.interfaces.0 { - if let Some(cfg) = &iface.lan_config { - for (p, lan) in cfg { - if p.0 == 80 && lan.ssl || p.0 == 443 && !lan.ssl { - return Err(Error::new( - eyre!("SSL Conflict with embassyOS"), - ErrorKind::LanPortConflict, - )); - } - match port_map.get(&p) { - Some((ssl, pkg)) => { - if *ssl != lan.ssl { - return Err(Error::new( - eyre!("SSL Conflict with package: {}", pkg), - ErrorKind::LanPortConflict, - )); - } + // if any of the requested interface lan configs conflict with current state, fail the install + for (_id, iface) in &temp_manifest.interfaces.0 { + if let Some(cfg) = &iface.lan_config { + for (p, lan) in cfg { + if p.0 == 80 && lan.ssl || p.0 == 443 && !lan.ssl { + return Err(Error::new( + eyre!("SSL Conflict with StartOS"), + ErrorKind::LanPortConflict, + )); } - None => { - continue; + match port_map.get(&p) { + Some((ssl, pkg)) => { + if *ssl != lan.ssl { + return Err(Error::new( + eyre!("SSL Conflict with package: {}", pkg), + ErrorKind::LanPortConflict, + )); + } + } + None => { + continue; + } } } } } + + let pkg_archive_dir = ctx + .datadir + .join(PKG_ARCHIVE_DIR) + .join(pkg_id) + .join(version.as_str()); + tokio::fs::create_dir_all(&pkg_archive_dir).await?; + let pkg_archive = + pkg_archive_dir.join(AsRef::::as_ref(pkg_id).with_extension("s9pk")); + + File::delete(&pkg_archive).await?; + let mut dst = OpenOptions::new() + .create(true) + .write(true) + .read(true) + .open(&pkg_archive) + .await?; + + progress + .track_download_during(ctx.db.clone(), pkg_id, || async { + let mut progress_writer = + InstallProgressTracker::new(&mut dst, progress.clone()); + tokio::io::copy(&mut s9pk, &mut progress_writer).await?; + progress.download_complete(); + if let Some(complete) = download_complete { + complete.send(()).unwrap_or_default(); + } + Ok(()) + }) + .await?; + + dst.seek(SeekFrom::Start(0)).await?; + + let progress_reader = InstallProgressTracker::new(dst, progress.clone()); + let mut s9pk_reader = progress + .track_read_during(ctx.db.clone(), pkg_id, || { + S9pkReader::from_reader(progress_reader, true) + }) + .await?; + + install_s9pk( + ctx.clone(), + pkg_id, + version, + marketplace_url, + &mut s9pk_reader, + progress, + ) + .await?; + + Ok(()) } - drop(receipts); - tx.save().await?; - drop(db_handle); - - let pkg_archive_dir = ctx - .datadir - .join(PKG_ARCHIVE_DIR) - .join(pkg_id) - .join(version.as_str()); - tokio::fs::create_dir_all(&pkg_archive_dir).await?; - let pkg_archive = - pkg_archive_dir.join(AsRef::::as_ref(pkg_id).with_extension("s9pk")); - - let pkg_data_entry = crate::db::DatabaseModel::new() - .package_data() - .idx_model(pkg_id); - - let progress_model = pkg_data_entry.and_then(|pde| pde.install_progress()); - - File::delete(&pkg_archive).await?; - let mut dst = OpenOptions::new() - .create(true) - .write(true) - .read(true) - .open(&pkg_archive) - .await?; - - progress - .track_download_during(progress_model.clone(), &ctx.db, || async { - let mut progress_writer = InstallProgressTracker::new(&mut dst, progress.clone()); - tokio::io::copy(&mut s9pk, &mut progress_writer).await?; - progress.download_complete(); - if let Some(complete) = download_complete { - complete.send(()).unwrap_or_default(); - } - Ok(()) - }) - .await?; - - dst.seek(SeekFrom::Start(0)).await?; - - let progress_reader = InstallProgressTracker::new(dst, progress.clone()); - let mut s9pk_reader = progress - .track_read_during(progress_model.clone(), &ctx.db, || { - S9pkReader::from_reader(progress_reader, true) - }) - .await?; - - install_s9pk( - &ctx, - pkg_id, - version, - marketplace_url, - &mut s9pk_reader, - progress, - ) - .await?; - - Ok(()) } .await { - if previous_state.map(|x| x.running()).unwrap_or(false) { - crate::control::start(ctx.clone(), pkg_id.clone()).await?; - } - - let mut handle = ctx.db.handle(); - let mut tx = handle.begin().await?; - let receipts = cleanup::CleanupFailedReceipts::new(&mut tx).await?; - - if let Err(e) = cleanup_failed(&ctx, &mut tx, pkg_id, &receipts).await { + if let Err(e) = cleanup_failed(&ctx, pkg_id).await { tracing::error!("Failed to clean up {}@{}: {}", pkg_id, version, e); tracing::debug!("{:?}", e); - } else { - tx.commit().await?; } + Err(e) } else { - if previous_state.map(|x| x.running()).unwrap_or(false) { - crate::control::start(ctx.clone(), pkg_id.clone()).await?; - } - Ok(()) - } -} - -pub struct InstallS9Receipts { - config: ConfigReceipts, -} - -impl InstallS9Receipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup( - locks: &mut Vec, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let config = ConfigReceipts::setup(locks); - move |skeleton_key| { - Ok(Self { - config: config(skeleton_key)?, - }) - } + Ok::<_, Error>(()) } } #[instrument(skip_all)] pub async fn install_s9pk( - ctx: &RpcContext, + ctx: RpcContext, pkg_id: &PackageId, version: &Version, marketplace_url: Option, @@ -930,34 +786,28 @@ pub async fn install_s9pk( rdr.validated(); let developer_key = rdr.developer_key().clone(); rdr.reset().await?; - let model = crate::db::DatabaseModel::new() - .package_data() - .idx_model(pkg_id); - let progress_model = model.clone().and_then(|m| m.install_progress()); + let db = ctx.db.peek().await; tracing::info!("Install {}@{}: Unpacking Manifest", pkg_id, version); let manifest = progress - .track_read_during(progress_model.clone(), &ctx.db, || rdr.manifest()) + .track_read_during(ctx.db.clone(), pkg_id, || rdr.manifest()) .await?; tracing::info!("Install {}@{}: Unpacked Manifest", pkg_id, version); tracing::info!("Install {}@{}: Fetching Dependency Info", pkg_id, version); let mut dependency_info = BTreeMap::new(); for (dep, info) in &manifest.dependencies.0 { - let manifest: Option = if let Some(local_man) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(dep) - .map::<_, Manifest>(|pde| pde.manifest()) - .get(&mut ctx.db.handle()) - .await? - .into_owned() + let manifest: Option = if let Some(local_man) = db + .as_package_data() + .as_idx(dep) + .map(|pde| pde.as_manifest().de()) { - Some(local_man) + Some(local_man?) } else if let Some(marketplace_url) = &marketplace_url { match ctx .client .get(with_query_params( - ctx, + ctx.clone(), format!( "{}/package/v0/manifest/{}?spec={}", marketplace_url, dep, info.version, @@ -974,7 +824,12 @@ pub async fn install_s9pk( .await .with_kind(crate::ErrorKind::Deserialization)?, )), - Err(e) if e.status() == Some(StatusCode::BAD_REQUEST) => Ok(None), + Err(e) + if e.status() == Some(StatusCode::BAD_REQUEST) + || e.status() == Some(StatusCode::NOT_FOUND) => + { + Ok(None) + } Err(e) => Err(e), } .with_kind(crate::ErrorKind::Registry)? @@ -982,20 +837,20 @@ pub async fn install_s9pk( None }; - if let Some(marketplace_url) = &marketplace_url { - if let Some(manifest) = &manifest { - let dir = ctx - .datadir - .join(PKG_PUBLIC_DIR) - .join(&manifest.id) - .join(manifest.version.as_str()); - let icon_path = dir.join(format!("icon.{}", manifest.assets.icon_type())); - if tokio::fs::metadata(&icon_path).await.is_err() { + let icon_path = if let Some(manifest) = &manifest { + let dir = ctx + .datadir + .join(PKG_PUBLIC_DIR) + .join(&manifest.id) + .join(manifest.version.as_str()); + let icon_path = dir.join(format!("icon.{}", manifest.assets.icon_type())); + if tokio::fs::metadata(&icon_path).await.is_err() { + if let Some(marketplace_url) = &marketplace_url { tokio::fs::create_dir_all(&dir).await?; let icon = ctx .client .get(with_query_params( - ctx, + ctx.clone(), format!( "{}/package/v0/icon/{}?spec={}", marketplace_url, dep, info.version, @@ -1008,24 +863,29 @@ pub async fn install_s9pk( let mut dst = File::create(&icon_path).await?; tokio::io::copy(&mut response_to_reader(icon), &mut dst).await?; dst.sync_all().await?; + Some(icon_path) + } else { + None } + } else { + Some(icon_path) } - } + } else { + None + }; dependency_info.insert( dep.clone(), StaticDependencyInfo { - icon: if let Some(manifest) = &manifest { - format!( - "/public/package-data/{}/{}/icon.{}", - manifest.id, - manifest.version, - manifest.assets.icon_type() - ) + title: manifest + .as_ref() + .map(|x| x.title.clone()) + .unwrap_or_else(|| dep.to_string()), + icon: if let Some(icon_path) = &icon_path { + DataUrl::from_path(icon_path).await? } else { - "/assets/img/package-icon.png".to_owned() + DataUrl::from_slice("image/png", include_bytes!("./package-icon.png")) }, - manifest, }, ); } @@ -1040,7 +900,7 @@ pub async fn install_s9pk( tracing::info!("Install {}@{}: Unpacking LICENSE.md", pkg_id, version); progress - .track_read_during(progress_model.clone(), &ctx.db, || async { + .track_read_during(ctx.db.clone(), pkg_id, || async { let license_path = public_dir_path.join("LICENSE.md"); let mut dst = File::create(&license_path).await?; tokio::io::copy(&mut rdr.license().await?, &mut dst).await?; @@ -1052,7 +912,7 @@ pub async fn install_s9pk( tracing::info!("Install {}@{}: Unpacking INSTRUCTIONS.md", pkg_id, version); progress - .track_read_during(progress_model.clone(), &ctx.db, || async { + .track_read_during(ctx.db.clone(), pkg_id, || async { let instructions_path = public_dir_path.join("INSTRUCTIONS.md"); let mut dst = File::create(&instructions_path).await?; tokio::io::copy(&mut rdr.instructions().await?, &mut dst).await?; @@ -1062,65 +922,48 @@ pub async fn install_s9pk( .await?; tracing::info!("Install {}@{}: Unpacked INSTRUCTIONS.md", pkg_id, version); - let icon_path = Path::new("icon").with_extension(&manifest.assets.icon_type()); + let icon_filename = Path::new("icon").with_extension(manifest.assets.icon_type()); + let icon_path = public_dir_path.join(&icon_filename); tracing::info!( "Install {}@{}: Unpacking {}", pkg_id, version, icon_path.display() ); - progress - .track_read_during(progress_model.clone(), &ctx.db, || async { - let icon_path = public_dir_path.join(&icon_path); - let mut dst = File::create(&icon_path).await?; - tokio::io::copy(&mut rdr.icon().await?, &mut dst).await?; - dst.sync_all().await?; - Ok(()) + let icon_buf = progress + .track_read_during(ctx.db.clone(), pkg_id, || async { + Ok(rdr.icon().await?.to_vec().await?) }) .await?; + let mut dst = File::create(&icon_path).await?; + dst.write_all(&icon_buf).await?; + dst.sync_all().await?; + let icon = DataUrl::from_vec( + mime(manifest.assets.icon_type()).unwrap_or("image/png"), + icon_buf, + ); tracing::info!( "Install {}@{}: Unpacked {}", pkg_id, version, - icon_path.display() + icon_filename.display() ); tracing::info!("Install {}@{}: Unpacking Docker Images", pkg_id, version); progress - .track_read_during(progress_model.clone(), &ctx.db, || async { - let mut load = Command::new("docker") + .track_read_during(ctx.db.clone(), pkg_id, || async { + Command::new(CONTAINER_TOOL) .arg("load") - .stdin(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - let load_in = load.stdin.take().ok_or_else(|| { - Error::new( - eyre!("Could not write to stdin of docker load"), - crate::ErrorKind::Docker, - ) - })?; - let mut docker_rdr = rdr.docker_images().await?; - copy_and_shutdown(&mut docker_rdr, load_in).await?; - let res = load.wait_with_output().await?; - if !res.status.success() { - Err(Error::new( - eyre!( - "{}", - String::from_utf8(res.stderr) - .unwrap_or_else(|e| format!("Could not parse stderr: {}", e)) - ), - crate::ErrorKind::Docker, - )) - } else { - Ok(()) - } + .input(Some(&mut rdr.docker_images().await?)) + .invoke(ErrorKind::Docker) + .await }) .await?; tracing::info!("Install {}@{}: Unpacked Docker Images", pkg_id, version,); tracing::info!("Install {}@{}: Unpacking Assets", pkg_id, version); progress - .track_read_during(progress_model.clone(), &ctx.db, || async { + .track_read_during(ctx.db.clone(), pkg_id, || async { let asset_dir = asset_dir(&ctx.datadir, pkg_id, version); if tokio::fs::metadata(&asset_dir).await.is_err() { tokio::fs::create_dir_all(&asset_dir).await?; @@ -1147,26 +990,37 @@ pub async fn install_s9pk( progress.unpack_complete.store(true, Ordering::SeqCst); - progress_model.put(&mut ctx.db.handle(), &progress).await?; - - let mut handle = ctx.db.handle(); - let mut tx = handle.begin().await?; - let mut sql_tx = ctx.secret_store.begin().await?; - crate::db::DatabaseModel::new() - .package_data() - .lock(&mut tx, LockType::Write) + progress + .track_read( + ctx.db.clone(), + pkg_id.clone(), + Arc::new(::std::sync::atomic::AtomicBool::new(true)), + ) .await?; + let peek = ctx.db.peek().await; + let prev = peek + .as_package_data() + .as_idx(pkg_id) + .or_not_found(pkg_id)? + .de()?; + let mut sql_tx = ctx.secret_store.begin().await?; + tracing::info!("Install {}@{}: Creating volumes", pkg_id, version); - manifest.volumes.install(ctx, pkg_id, version).await?; + manifest.volumes.install(&ctx, pkg_id, version).await?; tracing::info!("Install {}@{}: Created volumes", pkg_id, version); tracing::info!("Install {}@{}: Installing interfaces", pkg_id, version); - let interface_addresses = manifest.interfaces.install(&mut sql_tx, pkg_id).await?; - tracing::info!("Install {}@{}: Installed interfaces", pkg_id, version); + let interface_addresses = manifest.interfaces.install(sql_tx.as_mut(), pkg_id).await?; + tracing::info!( + "Install {}@{}: Installed interfaces {:?}", + pkg_id, + version, + interface_addresses + ); tracing::info!("Install {}@{}: Creating manager", pkg_id, version); - ctx.managers.add(ctx.clone(), manifest.clone()).await?; + let manager = ctx.managers.add(ctx.clone(), manifest.clone()).await?; tracing::info!("Install {}@{}: Created manager", pkg_id, version); let static_files = StaticFiles::local(pkg_id, version, manifest.assets.icon_type()); @@ -1184,126 +1038,85 @@ pub async fn install_s9pk( }) .collect(), ); + let mut dependents_static_dependency_info = BTreeMap::new(); let current_dependents = { let mut deps = BTreeMap::new(); - for package in crate::db::DatabaseModel::new() - .package_data() - .keys(&mut tx) - .await? - { - // update dependency_info on dependents - if let Some(dep_info_model) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&package) - .expect(&mut tx) - .await? - .installed() - .and_then(|i| i.dependency_info().idx_model(pkg_id)) - .check(&mut tx) - .await? + for package in db.as_package_data().keys()? { + if db + .as_package_data() + .as_idx(&package) + .or_not_found(&package)? + .as_installed() + .and_then(|i| i.as_dependency_info().as_idx(&pkg_id)) + .is_some() { - let mut dep_info = dep_info_model.get_mut(&mut tx).await?; - *dep_info = StaticDependencyInfo { - icon: format!( - "/public/package-data/{}/{}/icon.{}", - manifest.id, - manifest.version, - manifest.assets.icon_type() - ), - manifest: Some(manifest.clone()), - }; + dependents_static_dependency_info.insert(package.clone(), icon.clone()); } - - // search required dependencies - if let Some(dep) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&package) - .expect(&mut tx) - .await? - .installed() - .and_then(|i| i.current_dependencies().idx_model(pkg_id)) - .get(&mut tx) - .await? - .to_owned() + if let Some(dep) = db + .as_package_data() + .as_idx(&package) + .or_not_found(&package)? + .as_installed() + .and_then(|i| i.as_current_dependencies().as_idx(pkg_id)) { - deps.insert(package, dep); + deps.insert(package, dep.de()?); } } + CurrentDependents(deps) }; - let mut pde = model - .clone() - .expect(&mut tx) - .await? - .get_mut(&mut tx) - .await?; - let installed = InstalledPackageDataEntry { + + let installed = InstalledPackageInfo { status: Status { configured: manifest.config.is_none(), main: MainStatus::Stopped, - dependency_errors: DependencyErrors::default(), + dependency_config_errors: compute_dependency_config_errs( + &ctx, + &peek, + &manifest, + ¤t_dependencies, + &Default::default(), + ) + .await?, }, marketplace_url, developer_key, manifest: manifest.clone(), - last_backup: match &*pde { - PackageDataEntry::Updating { + last_backup: match prev { + PackageDataEntry::Updating(PackageDataEntryUpdating { installed: - InstalledPackageDataEntry { + InstalledPackageInfo { last_backup: Some(time), .. }, .. - } => Some(*time), + }) => Some(time), _ => None, }, - system_pointers: Vec::new(), dependency_info, current_dependents: current_dependents.clone(), current_dependencies: current_dependencies.clone(), interface_addresses, }; - let prev = std::mem::replace( - &mut *pde, - PackageDataEntry::Installed { - installed, - manifest: manifest.clone(), - static_files, - }, - ); - pde.save(&mut tx).await?; - let receipts = InstallS9Receipts::new(&mut tx).await?; - // UpdateDependencyReceipts - let mut dep_errs = model - .expect(&mut tx) - .await? - .installed() - .expect(&mut tx) - .await? - .status() - .dependency_errors() - .get_mut(&mut tx) - .await?; - *dep_errs = DependencyErrors::init( - ctx, - &mut tx, - &manifest, - ¤t_dependencies, - &receipts.config.try_heal_receipts, - ) - .await?; - dep_errs.save(&mut tx).await?; + let mut next = PackageDataEntryInstalled { + installed, + manifest: manifest.clone(), + static_files, + }; - if let PackageDataEntry::Updating { + let mut auto_start = false; + let mut configured = false; + + if let PackageDataEntry::Updating(PackageDataEntryUpdating { installed: prev, .. - } = prev + }) = &prev { let prev_is_configured = prev.status.configured; let prev_migration = prev .manifest .migrations .to( - ctx, + &ctx, version, pkg_id, &prev.manifest.version, @@ -1314,7 +1127,7 @@ pub async fn install_s9pk( .migrations .from( &manifest.containers, - ctx, + &ctx, &prev.manifest.version, pkg_id, version, @@ -1328,123 +1141,95 @@ pub async fn install_s9pk( migration.or(prev_migration) }; - remove_from_current_dependents_lists( - &mut tx, - pkg_id, - &prev.current_dependencies, - &receipts.config.current_dependents, - ) - .await?; // remove previous - - let configured = if let Some(f) = viable_migration { - f.await?.configured && prev_is_configured - } else { - false - }; - if configured && manifest.config.is_some() { - let breakages = BTreeMap::new(); - let overrides = Default::default(); - - let configure_context = ConfigureContext { - breakages, - timeout: None, - config: None, - dry_run: false, - overrides, - }; - crate::config::configure(&ctx, pkg_id, configure_context).await?; - } else { - add_dependent_to_current_dependents_lists( - &mut tx, - pkg_id, - ¤t_dependencies, - &receipts.config.current_dependents, - ) - .await?; // add new + if let Some(f) = viable_migration { + configured = f.await?.configured && prev_is_configured; } if configured || manifest.config.is_none() { - let mut main_status = crate::db::DatabaseModel::new() - .package_data() - .idx_model(pkg_id) - .expect(&mut tx) - .await? - .installed() - .expect(&mut tx) - .await? - .status() - .main() - .get_mut(&mut tx) - .await?; - *main_status = prev.status.main; - main_status.save(&mut tx).await?; + auto_start = prev.status.main.running(); } - update_dependency_errors_of_dependents( - ctx, - &mut tx, - pkg_id, - &CurrentDependents({ - let mut current_dependents = current_dependents.0.clone(); - current_dependents.append(&mut prev.current_dependents.0.clone()); - current_dependents - }), - &receipts.config.update_dependency_receipts, - ) - .await?; if &prev.manifest.version != version { - cleanup(ctx, &prev.manifest.id, &prev.manifest.version).await?; + cleanup(&ctx, &prev.manifest.id, &prev.manifest.version).await?; } - } else if let PackageDataEntry::Restoring { .. } = prev { - manifest + } else if let PackageDataEntry::Restoring(PackageDataEntryRestoring { .. }) = prev { + next.installed.marketplace_url = manifest .backup - .restore( - ctx, - &mut tx, - pkg_id, - version, - &manifest.interfaces, - &manifest.volumes, - ) - .await?; - add_dependent_to_current_dependents_lists( - &mut tx, - pkg_id, - ¤t_dependencies, - &receipts.config.current_dependents, - ) - .await?; - update_dependency_errors_of_dependents( - ctx, - &mut tx, - pkg_id, - ¤t_dependents, - &receipts.config.update_dependency_receipts, - ) - .await?; - } else { - add_dependent_to_current_dependents_lists( - &mut tx, - pkg_id, - ¤t_dependencies, - &receipts.config.current_dependents, - ) - .await?; - update_dependency_errors_of_dependents( - ctx, - &mut tx, - pkg_id, - ¤t_dependents, - &receipts.config.update_dependency_receipts, - ) - .await?; - } - - if let Some(installed) = pde.installed() { - reconfigure_dependents_with_live_pointers(ctx, &mut tx, &receipts.config, installed) + .restore(&ctx, pkg_id, version, &manifest.volumes) .await?; } sql_tx.commit().await?; - tx.commit().await?; + + let to_configure = ctx + .db + .mutate(|db| { + for (package, icon) in dependents_static_dependency_info { + db.as_package_data_mut() + .as_idx_mut(&package) + .or_not_found(&package)? + .as_installed_mut() + .or_not_found(&package)? + .as_dependency_info_mut() + .insert( + &pkg_id, + &StaticDependencyInfo { + icon, + title: manifest.title.clone(), + }, + )?; + } + db.as_package_data_mut() + .insert(&pkg_id, &PackageDataEntry::Installed(next))?; + if let PackageDataEntry::Updating(PackageDataEntryUpdating { + installed: prev, .. + }) = &prev + { + remove_from_current_dependents_lists(db, pkg_id, &prev.current_dependencies)?; + } + add_dependent_to_current_dependents_lists(db, pkg_id, ¤t_dependencies)?; + + set_dependents_with_live_pointers_to_needs_config(db, pkg_id) + }) + .await?; + + if configured && manifest.config.is_some() { + let breakages = BTreeMap::new(); + let overrides = Default::default(); + + let configure_context = ConfigureContext { + breakages, + timeout: None, + config: None, + dry_run: false, + overrides, + }; + manager.configure(configure_context).await?; + } + + for to_configure in to_configure.into_iter().filter(|(dep, _)| dep != pkg_id) { + if let Err(e) = async { + ctx.managers + .get(&to_configure) + .await + .or_not_found(format!("manager for {}", to_configure.0))? + .configure(ConfigureContext { + breakages: BTreeMap::new(), + timeout: None, + config: None, + overrides: BTreeMap::new(), + dry_run: false, + }) + .await + } + .await + { + tracing::error!("error configuring dependent: {e}"); + tracing::debug!("{e:?}") + } + } + + if auto_start { + manager.start().await; + } tracing::info!("Install {}@{}: Complete", pkg_id, version); @@ -1468,57 +1253,36 @@ pub fn load_images<'a, P: AsRef + 'a + Send + Sync>( let path = entry.path(); let ext = path.extension().and_then(|ext| ext.to_str()); if ext == Some("tar") || ext == Some("s9pk") { - let mut load = Command::new("docker") - .arg("load") - .stdin(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn()?; - let load_in = load.stdin.take().ok_or_else(|| { - Error::new( - eyre!("Could not write to stdin of docker load"), - crate::ErrorKind::Docker, - ) - })?; - match ext { - Some("tar") => { - copy_and_shutdown(&mut File::open(&path).await?, load_in) - .await? - } - Some("s9pk") => match async { - let mut reader = S9pkReader::open(&path, true).await?; - copy_and_shutdown(&mut reader.docker_images().await?, load_in) - .await?; - Ok::<_, Error>(()) - } - .await - { - Ok(()) => (), - Err(e) => { - tracing::error!( - "Error loading docker images from s9pk: {e}" - ); - tracing::debug!("{e:?}"); - return Ok(()); + if let Err(e) = async { + match ext { + Some("tar") => { + Command::new(CONTAINER_TOOL) + .arg("load") + .input(Some(&mut File::open(&path).await?)) + .invoke(ErrorKind::Docker) + .await } - }, - _ => unreachable!(), - }; - - let res = load.wait_with_output().await?; - if !res.status.success() { - Err(Error::new( - eyre!( - "{}", - String::from_utf8(res.stderr).unwrap_or_else(|e| format!( - "Could not parse stderr: {}", - e - )) - ), - crate::ErrorKind::Docker, - )) - } else { - Ok(()) + Some("s9pk") => { + Command::new(CONTAINER_TOOL) + .arg("load") + .input(Some( + &mut S9pkReader::open(&path, true) + .await? + .docker_images() + .await?, + )) + .invoke(ErrorKind::Docker) + .await + } + _ => unreachable!(), + } } + .await + { + tracing::error!("Error loading docker images from s9pk: {e}"); + tracing::debug!("{e:?}"); + } + Ok(()) } else { Ok(()) } diff --git a/backend/src/install/package-icon.png b/backend/src/install/package-icon.png new file mode 100644 index 000000000..265558cfd Binary files /dev/null and b/backend/src/install/package-icon.png differ diff --git a/backend/src/install/progress.rs b/backend/src/install/progress.rs index 80bee0675..61e58e0e6 100644 --- a/backend/src/install/progress.rs +++ b/backend/src/install/progress.rs @@ -6,14 +6,16 @@ use std::sync::Arc; use std::task::{Context, Poll}; use std::time::Duration; -use patch_db::{DbHandle, HasModel, OptionModel, PatchDb}; +use models::{OptionExt, PackageId}; use serde::{Deserialize, Serialize}; use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite}; -use crate::Error; +use crate::db::model::Database; +use crate::prelude::*; #[derive(Debug, Deserialize, Serialize, HasModel, Default)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct InstallProgress { pub size: Option, pub downloaded: AtomicU64, @@ -24,8 +26,8 @@ pub struct InstallProgress { pub unpack_complete: AtomicBool, } impl InstallProgress { - pub fn new(size: Option) -> Arc { - Arc::new(InstallProgress { + pub fn new(size: Option) -> Self { + InstallProgress { size, downloaded: AtomicU64::new(0), download_complete: AtomicBool::new(false), @@ -33,26 +35,25 @@ impl InstallProgress { validation_complete: AtomicBool::new(false), unpacked: AtomicU64::new(0), unpack_complete: AtomicBool::new(false), - }) + } } pub fn download_complete(&self) { self.download_complete.store(true, Ordering::SeqCst) } - pub async fn track_download( - self: Arc, - model: OptionModel, - mut db: Db, - ) -> Result<(), Error> { + pub async fn track_download(self: Arc, db: PatchDb, id: PackageId) -> Result<(), Error> { + let update = |d: &mut Model| { + d.as_package_data_mut() + .as_idx_mut(&id) + .or_not_found(&id)? + .as_install_progress_mut() + .or_not_found("install-progress")? + .ser(&self) + }; while !self.download_complete.load(Ordering::SeqCst) { - let mut tx = db.begin().await?; - model.put(&mut tx, &self).await?; - tx.save().await?; - tokio::time::sleep(Duration::from_secs(1)).await; + db.mutate(&update).await?; + tokio::time::sleep(Duration::from_millis(300)).await; } - let mut tx = db.begin().await?; - model.put(&mut tx, &self).await?; - tx.save().await?; - Ok(()) + db.mutate(&update).await } pub async fn track_download_during< F: FnOnce() -> Fut, @@ -60,33 +61,35 @@ impl InstallProgress { T, >( self: &Arc, - model: OptionModel, - db: &PatchDb, + db: PatchDb, + id: &PackageId, f: F, ) -> Result { - let local_db = db.handle(); - let tracker = tokio::spawn(self.clone().track_download(model.clone(), local_db)); + let tracker = tokio::spawn(self.clone().track_download(db.clone(), id.clone())); let res = f().await; self.download_complete.store(true, Ordering::SeqCst); tracker.await.unwrap()?; res } - pub async fn track_read( + pub async fn track_read( self: Arc, - model: OptionModel, - mut db: Db, + db: PatchDb, + id: PackageId, complete: Arc, ) -> Result<(), Error> { + let update = |d: &mut Model| { + d.as_package_data_mut() + .as_idx_mut(&id) + .or_not_found(&id)? + .as_install_progress_mut() + .or_not_found("install-progress")? + .ser(&self) + }; while !complete.load(Ordering::SeqCst) { - let mut tx = db.begin().await?; - model.put(&mut tx, &self).await?; - tx.save().await?; - tokio::time::sleep(Duration::from_secs(1)).await; + db.mutate(&update).await?; + tokio::time::sleep(Duration::from_millis(300)).await; } - let mut tx = db.begin().await?; - model.put(&mut tx, &self).await?; - tx.save().await?; - Ok(()) + db.mutate(&update).await } pub async fn track_read_during< F: FnOnce() -> Fut, @@ -94,15 +97,14 @@ impl InstallProgress { T, >( self: &Arc, - model: OptionModel, - db: &PatchDb, + db: PatchDb, + id: &PackageId, f: F, ) -> Result { - let local_db = db.handle(); let complete = Arc::new(AtomicBool::new(false)); let tracker = tokio::spawn(self.clone().track_read( - model.clone(), - local_db, + db.clone(), + id.clone(), complete.clone(), )); let res = f().await; diff --git a/backend/src/install/update.rs b/backend/src/install/update.rs index bafbf04ec..694051213 100644 --- a/backend/src/install/update.rs +++ b/backend/src/install/update.rs @@ -1,105 +1,18 @@ use std::collections::BTreeMap; -use patch_db::{DbHandle, LockReceipt, LockTargetId, LockType, Verifier}; use rpc_toolkit::command; use tracing::instrument; use crate::config::not_found; use crate::context::RpcContext; use crate::db::model::CurrentDependents; -use crate::dependencies::{ - break_transitive, BreakTransitiveReceipts, BreakageRes, DependencyError, -}; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; use crate::util::serde::display_serializable; use crate::util::Version; use crate::Error; -pub struct UpdateReceipts { - break_receipts: BreakTransitiveReceipts, - current_dependents: LockReceipt, - dependency: LockReceipt, -} - -impl UpdateReceipts { - pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks); - Ok(setup(&db.lock_all(locks).await?)?) - } - - pub fn setup(locks: &mut Vec) -> impl FnOnce(&Verifier) -> Result { - let break_receipts = BreakTransitiveReceipts::setup(locks); - let current_dependents = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.current_dependents()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let dependency = crate::db::DatabaseModel::new() - .package_data() - .star() - .installed() - .map(|x| x.manifest().dependencies().star()) - .make_locker(LockType::Write) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - break_receipts: break_receipts(skeleton_key)?, - current_dependents: current_dependents.verify(skeleton_key)?, - dependency: dependency.verify(skeleton_key)?, - }) - } - } -} - #[command(subcommands(dry))] pub async fn update() -> Result<(), Error> { Ok(()) } - -#[instrument(skip_all)] -#[command(display(display_serializable))] -pub async fn dry( - #[context] ctx: RpcContext, - #[arg] id: PackageId, - #[arg] version: Version, -) -> Result { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - let mut breakages = BTreeMap::new(); - let receipts = UpdateReceipts::new(&mut tx).await?; - - for dependent in receipts - .current_dependents - .get(&mut tx, &id) - .await? - .ok_or_else(|| not_found!(id))? - .0 - .keys() - .into_iter() - .filter(|dependent| &&id != dependent) - { - if let Some(dep_info) = receipts.dependency.get(&mut tx, (&dependent, &id)).await? { - let version_req = dep_info.version; - if !version.satisfies(&version_req) { - break_transitive( - &mut tx, - &dependent, - &id, - DependencyError::IncorrectVersion { - expected: version_req, - received: version.clone(), - }, - &mut breakages, - &receipts.break_receipts, - ) - .await?; - } - } - } - tx.abort().await?; - Ok(BreakageRes(breakages)) -} diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 4e4b1619a..141ef1780 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -5,12 +5,21 @@ pub const DEFAULT_MARKETPLACE: &str = "https://registry.start9.com"; pub const BUFFER_SIZE: usize = 1024; pub const HOST_IP: [u8; 4] = [172, 18, 0, 1]; pub const TARGET: &str = current_platform::CURRENT_PLATFORM; -pub const OS_ARCH: &str = env!("OS_ARCH"); lazy_static::lazy_static! { pub static ref ARCH: &'static str = { let (arch, _) = TARGET.split_once("-").unwrap(); arch }; + pub static ref PLATFORM: String = { + if let Ok(platform) = std::fs::read_to_string("/usr/lib/startos/PLATFORM.txt") { + platform + } else { + ARCH.to_string() + } + }; + pub static ref SOURCE_DATE: SystemTime = { + std::fs::metadata(std::env::current_exe().unwrap()).unwrap().modified().unwrap() + }; } pub mod account; @@ -28,20 +37,22 @@ pub mod developer; pub mod diagnostic; pub mod disk; pub mod error; +pub mod firmware; pub mod hostname; pub mod init; pub mod inspect; pub mod install; pub mod logs; pub mod manager; -pub mod marketplace; pub mod middleware; pub mod migration; pub mod net; pub mod notifications; pub mod os_install; +pub mod prelude; pub mod procedure; pub mod properties; +pub mod registry; pub mod s9pk; pub mod setup; pub mod shutdown; @@ -54,6 +65,8 @@ pub mod util; pub mod version; pub mod volume; +use std::time::SystemTime; + pub use config::Config; pub use error::{Error, ErrorKind, ResultExt}; use rpc_toolkit::command; @@ -78,7 +91,7 @@ pub fn echo(#[arg] message: String) -> Result { disk::disk, notifications::notification, backup::backup, - marketplace::marketplace, + registry::marketplace::marketplace, ))] pub fn main_api() -> Result<(), RpcError> { Ok(()) @@ -105,7 +118,6 @@ pub fn server() -> Result<(), RpcError> { install::sideload, install::uninstall, install::list, - install::update::update, config::config, control::start, control::stop, @@ -124,7 +136,8 @@ pub fn package() -> Result<(), RpcError> { s9pk::pack, developer::verify, developer::init, - inspect::inspect + inspect::inspect, + registry::admin::publish, ))] pub fn portable_api() -> Result<(), RpcError> { Ok(()) diff --git a/backend/src/logs.rs b/backend/src/logs.rs index 30d73f4d7..691ae09b9 100644 --- a/backend/src/logs.rs +++ b/backend/src/logs.rs @@ -136,7 +136,13 @@ pub struct LogEntry { } impl std::fmt::Display for LogEntry { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{} {}", self.timestamp, self.message) + write!( + f, + "{} {}", + self.timestamp + .to_rfc3339_opts(chrono::SecondsFormat::Millis, true), + self.message + ) } } @@ -145,7 +151,7 @@ pub struct JournalctlEntry { #[serde(rename = "__REALTIME_TIMESTAMP")] pub timestamp: String, #[serde(rename = "MESSAGE")] - #[serde(deserialize_with = "deserialize_string_or_utf8_array")] + #[serde(deserialize_with = "deserialize_log_message")] pub message: String, #[serde(rename = "__CURSOR")] pub cursor: String, @@ -164,7 +170,7 @@ impl JournalctlEntry { } } -fn deserialize_string_or_utf8_array<'de, D: serde::de::Deserializer<'de>>( +fn deserialize_log_message<'de, D: serde::de::Deserializer<'de>>( deserializer: D, ) -> std::result::Result { struct Visitor; @@ -177,13 +183,7 @@ fn deserialize_string_or_utf8_array<'de, D: serde::de::Deserializer<'de>>( where E: serde::de::Error, { - Ok(v.to_owned()) - } - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, - { - Ok(v) + Ok(v.trim().to_owned()) } fn visit_unit(self) -> Result where @@ -198,22 +198,32 @@ fn deserialize_string_or_utf8_array<'de, D: serde::de::Deserializer<'de>>( String::from_utf8( std::iter::repeat_with(|| seq.next_element::().transpose()) .take_while(|a| a.is_some()) - .filter_map(|a| a) + .flatten() .collect::, _>>()?, ) + .map(|s| s.trim().to_owned()) .map_err(serde::de::Error::custom) } } deserializer.deserialize_any(Visitor) } +/// Defining how we are going to filter on a journalctl cli log. +/// Kernal: (-k --dmesg Show kernel message log from the current boot) +/// Unit: ( -u --unit=UNIT Show logs from the specified unit +/// --user-unit=UNIT Show logs from the specified user unit)) +/// System: Unit is startd, but we also filter on the comm +/// Container: Filtering containers, like podman/docker is done by filtering on the CONTAINER_NAME #[derive(Debug)] pub enum LogSource { Kernel, - Service(&'static str), + Unit(&'static str), + System, Container(PackageId), } +pub const SYSTEM_UNIT: &str = "startd"; + #[command( custom_cli(cli_logs(async, context(CliContext))), subcommands(self(logs_nofollow(async)), logs_follow), @@ -323,21 +333,15 @@ pub async fn cli_logs_generic_follow( .into()) } }; - base_url.set_scheme(ws_scheme).or_else(|_| { - Err(Error::new( - eyre!("Cannot set URL scheme"), - crate::ErrorKind::ParseUrl, - )) - })?; + base_url + .set_scheme(ws_scheme) + .map_err(|_| Error::new(eyre!("Cannot set URL scheme"), crate::ErrorKind::ParseUrl))?; let (mut stream, _) = // base_url is "http://127.0.0.1/", with a trailing slash, so we don't put a leading slash in this path: tokio_tungstenite::connect_async(format!("{}ws/rpc/{}", base_url, res.guid)).await?; while let Some(log) = stream.try_next().await? { - match log { - Message::Text(log) => { - println!("{}", serde_json::from_str::(&log)?); - } - _ => (), + if let Message::Text(log) = log { + println!("{}", serde_json::from_str::(&log)?); } } @@ -361,11 +365,22 @@ pub async fn journalctl( LogSource::Kernel => { cmd.arg("-k"); } - LogSource::Service(id) => { + LogSource::Unit(id) => { cmd.arg("-u"); cmd.arg(id); } + LogSource::System => { + cmd.arg("-u"); + cmd.arg(SYSTEM_UNIT); + cmd.arg(format!("_COMM={}", SYSTEM_UNIT)); + } LogSource::Container(id) => { + #[cfg(not(feature = "docker"))] + cmd.arg(format!( + "SYSLOG_IDENTIFIER={}", + DockerProcedure::container_name(&id, None) + )); + #[cfg(feature = "docker")] cmd.arg(format!( "CONTAINER_NAME={}", DockerProcedure::container_name(&id, None) @@ -373,7 +388,7 @@ pub async fn journalctl( } }; - let cursor_formatted = format!("--after-cursor={}", cursor.clone().unwrap_or("")); + let cursor_formatted = format!("--after-cursor={}", cursor.unwrap_or("")); if cursor.is_some() { cmd.arg(&cursor_formatted); if before { diff --git a/backend/src/manager/health.rs b/backend/src/manager/health.rs index 1ec89c26c..30f18051a 100644 --- a/backend/src/manager/health.rs +++ b/backend/src/manager/health.rs @@ -1,111 +1,27 @@ -use std::collections::BTreeMap; - -use itertools::Itertools; -use patch_db::{DbHandle, LockReceipt, LockType}; +use models::OptionExt; use tracing::instrument; use crate::context::RpcContext; -use crate::db::model::CurrentDependents; -use crate::dependencies::{break_transitive, heal_transitive, DependencyError}; -use crate::s9pk::manifest::{Manifest, PackageId}; -use crate::status::health_check::{HealthCheckId, HealthCheckResult}; +use crate::prelude::*; +use crate::s9pk::manifest::PackageId; use crate::status::MainStatus; use crate::Error; -struct HealthCheckPreInformationReceipt { - status_model: LockReceipt, - manifest: LockReceipt, -} -impl HealthCheckPreInformationReceipt { - pub async fn new(db: &'_ mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, id); - setup(&db.lock_all(locks).await?) - } - - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let status_model = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.status().main()) - .make_locker(LockType::Read) - .add_to_keys(locks); - let manifest = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.manifest()) - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - status_model: status_model.verify(skeleton_key)?, - manifest: manifest.verify(skeleton_key)?, - }) - } - } -} - -struct HealthCheckStatusReceipt { - status: LockReceipt, - current_dependents: LockReceipt, -} -impl HealthCheckStatusReceipt { - pub async fn new(db: &'_ mut impl DbHandle, id: &PackageId) -> Result { - let mut locks = Vec::new(); - - let setup = Self::setup(&mut locks, id); - setup(&db.lock_all(locks).await?) - } - - pub fn setup( - locks: &mut Vec, - id: &PackageId, - ) -> impl FnOnce(&patch_db::Verifier) -> Result { - let status = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.status().main()) - .make_locker(LockType::Write) - .add_to_keys(locks); - let current_dependents = crate::db::DatabaseModel::new() - .package_data() - .idx_model(id) - .and_then(|x| x.installed()) - .map(|x| x.current_dependents()) - .make_locker(LockType::Read) - .add_to_keys(locks); - move |skeleton_key| { - Ok(Self { - status: status.verify(skeleton_key)?, - current_dependents: current_dependents.verify(skeleton_key)?, - }) - } - } -} - +/// So, this is used for a service to run a health check cycle, go out and run the health checks, and store those in the db #[instrument(skip_all)] -pub async fn check( - ctx: &RpcContext, - db: &mut Db, - id: &PackageId, -) -> Result<(), Error> { - let mut tx = db.begin().await?; +pub async fn check(ctx: &RpcContext, id: &PackageId) -> Result<(), Error> { let (manifest, started) = { - let mut checkpoint = tx.begin().await?; - let receipts = HealthCheckPreInformationReceipt::new(&mut checkpoint, id).await?; + let peeked = ctx.db.peek().await; + let pde = peeked + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .expect_as_installed()?; - let manifest = receipts.manifest.get(&mut checkpoint).await?; + let manifest = pde.as_installed().as_manifest().de()?; - let started = receipts.status_model.get(&mut checkpoint).await?.started(); + let started = pde.as_installed().as_status().as_main().de()?.started(); - checkpoint.save().await?; (manifest, started) }; @@ -113,69 +29,28 @@ pub async fn check( tracing::debug!("Checking health of {}", id); manifest .health_checks - .check_all( - ctx, - &manifest.containers, - started, - id, - &manifest.version, - &manifest.volumes, - ) + .check_all(ctx, started, id, &manifest.version, &manifest.volumes) .await? } else { return Ok(()); }; - let current_dependents = { - let mut checkpoint = tx.begin().await?; - let receipts = HealthCheckStatusReceipt::new(&mut checkpoint, id).await?; + ctx.db + .mutate(|v| { + let pde = v + .as_package_data_mut() + .as_idx_mut(id) + .or_not_found(id)? + .expect_as_installed_mut()?; + let status = pde.as_installed_mut().as_status_mut().as_main_mut(); - let status = receipts.status.get(&mut checkpoint).await?; - - if let MainStatus::Running { health: _, started } = status { - receipts - .status - .set( - &mut checkpoint, - MainStatus::Running { - health: health_results.clone(), - started, - }, - ) - .await?; - } - let current_dependents = receipts.current_dependents.get(&mut checkpoint).await?; - - checkpoint.save().await?; - current_dependents - }; - - let receipts = crate::dependencies::BreakTransitiveReceipts::new(&mut tx).await?; - - for (dependent, info) in (current_dependents).0.iter() { - let failures: BTreeMap = health_results - .iter() - .filter(|(_, hc_res)| !matches!(hc_res, HealthCheckResult::Success { .. })) - .filter(|(hc_id, _)| info.health_checks.contains(hc_id)) - .map(|(k, v)| (k.clone(), v.clone())) - .collect(); - - if !failures.is_empty() { - break_transitive( - &mut tx, - &dependent, - id, - DependencyError::HealthChecksFailed { failures }, - &mut BTreeMap::new(), - &receipts, - ) - .await?; - } else { - heal_transitive(ctx, &mut tx, &dependent, id, &receipts.dependency_receipt).await?; - } - } - - tx.save().await?; - - Ok(()) + if let MainStatus::Running { health: _, started } = status.de()? { + status.ser(&MainStatus::Running { + health: health_results.clone(), + started, + })?; + } + Ok(()) + }) + .await } diff --git a/backend/src/manager/js_api.rs b/backend/src/manager/js_api.rs index 8f26f2d50..d8e194cfd 100644 --- a/backend/src/manager/js_api.rs +++ b/backend/src/manager/js_api.rs @@ -12,6 +12,8 @@ use sqlx::Acquire; use crate::{ config::hook::ConfigHook, manager::{start_stop::StartStop, Manager}, + net::keys::Key, + net::vhost::AlpnInfo, }; use super::try_get_running_ip; @@ -95,7 +97,13 @@ impl OsApi for Manager { let mut tx = secrets.begin().await?; let addr = svc - .add_lan(&mut tx, id.clone(), external_port, internal_port, false) + .add_lan( + &mut tx, + id.clone(), + external_port, + internal_port, + Err(AlpnInfo::Specified(vec![])), + ) .await .map_err(|e| eyre!("Could not add to local: {e:?}"))?; diff --git a/backend/src/manager/manager_container.rs b/backend/src/manager/manager_container.rs index e9f01ad00..32e11c2e5 100644 --- a/backend/src/manager/manager_container.rs +++ b/backend/src/manager/manager_container.rs @@ -1,22 +1,42 @@ use std::sync::Arc; use std::time::Duration; -use futures::FutureExt; -use patch_db::PatchDbHandle; +use models::OptionExt; use tokio::sync::watch; use tokio::sync::watch::Sender; use tracing::instrument; use super::start_stop::StartStop; use super::{manager_seed, run_main, ManagerPersistentContainer, RunMainResult}; +use crate::prelude::*; use crate::procedure::NoOutput; use crate::s9pk::manifest::Manifest; use crate::status::MainStatus; -use crate::util::{GeneralBoxedGuard, NonDetachingJoinHandle}; +use crate::util::NonDetachingJoinHandle; use crate::Error; -pub type ManageContainerOverride = Arc>>; +pub type ManageContainerOverride = Arc>>; +pub type Override = MainStatus; + +pub struct OverrideGuard { + override_main_status: Option, +} +impl OverrideGuard { + pub fn drop(self) {} +} +impl Drop for OverrideGuard { + fn drop(&mut self) { + if let Some(override_main_status) = self.override_main_status.take() { + override_main_status.send_modify(|x| { + *x = None; + }); + } + } +} + +/// This is the thing describing the state machine actor for a service +/// state and current running/ desired states. pub struct ManageContainer { pub(super) current_state: Arc>, pub(super) desired_state: Arc>, @@ -30,10 +50,12 @@ impl ManageContainer { seed: Arc, persistent_container: ManagerPersistentContainer, ) -> Result { - let mut db = seed.ctx.db.handle(); let current_state = Arc::new(watch::channel(StartStop::Stop).0); let desired_state = Arc::new( - watch::channel::(get_status(&mut db, &seed.manifest).await.into()).0, + watch::channel::( + get_status(seed.ctx.db.peek().await, &seed.manifest).into(), + ) + .0, ); let override_main_status: ManageContainerOverride = Arc::new(watch::channel(None).0); let service = tokio::spawn(create_service_manager( @@ -59,20 +81,40 @@ impl ManageContainer { }) } - pub fn set_override(&self, override_status: Option) -> GeneralBoxedGuard { + /// Set override is used during something like a restart of a service. We want to show certain statuses be different + /// from the actual status of the service. + pub fn set_override(&self, override_status: Override) -> Result { + let status = Some(override_status); + if self.override_main_status.borrow().is_some() { + return Err(Error::new( + eyre!("Already have an override"), + ErrorKind::InvalidRequest, + )); + } self.override_main_status - .send_modify(|x| *x = override_status); - let override_main_status = self.override_main_status.clone(); - let guard = GeneralBoxedGuard::new(move || { - override_main_status.send_modify(|x| *x = None); - }); - guard + .send_modify(|x| *x = status.clone()); + Ok(OverrideGuard { + override_main_status: Some(self.override_main_status.clone()), + }) } + /// Set the override, but don't have a guard to revert it. Used only on the mananger to do a shutdown. + pub(super) async fn lock_state_forever( + &self, + seed: &manager_seed::ManagerSeed, + ) -> Result<(), Error> { + let current_state = get_status(seed.ctx.db.peek().await, &seed.manifest); + self.override_main_status + .send_modify(|x| *x = Some(current_state)); + Ok(()) + } + + /// We want to set the state of the service, like to start or stop pub fn to_desired(&self, new_state: StartStop) { self.desired_state.send_modify(|x| *x = new_state); } + /// This is a tool to say wait for the service to be in a certain state. pub async fn wait_for_desired(&self, new_state: StartStop) { let mut current_state = self.current_state(); self.to_desired(new_state); @@ -81,10 +123,12 @@ impl ManageContainer { } } + /// Getter pub fn current_state(&self) -> watch::Receiver { self.current_state.subscribe() } + /// Getter pub fn desired_state(&self) -> watch::Receiver { self.desired_state.subscribe() } @@ -144,41 +188,34 @@ async fn create_service_manager( async fn save_state( desired_state: Arc>, current_state: Arc>, - override_main_status: Arc>>, + override_main_status: ManageContainerOverride, seed: Arc, ) { let mut desired_state_receiver = desired_state.subscribe(); let mut current_state_receiver = current_state.subscribe(); let mut override_main_status_receiver = override_main_status.subscribe(); loop { - let current: StartStop = current_state_receiver.borrow().clone(); - let desired: StartStop = desired_state_receiver.borrow().clone(); + let current: StartStop = *current_state_receiver.borrow(); + let desired: StartStop = *desired_state_receiver.borrow(); let override_status = override_main_status_receiver.borrow().clone(); - let mut db = seed.ctx.db.handle(); - let res = match (override_status, current, desired) { - (Some(status), _, _) => set_status(&mut db, &seed.manifest, &status).await, - (None, StartStop::Start, StartStop::Start) => { - set_status( - &mut db, - &seed.manifest, - &MainStatus::Running { - started: chrono::Utc::now(), - health: Default::default(), - }, - ) - .await - } - (None, StartStop::Start, StartStop::Stop) => { - set_status(&mut db, &seed.manifest, &MainStatus::Stopping).await - } - (None, StartStop::Stop, StartStop::Start) => { - set_status(&mut db, &seed.manifest, &MainStatus::Starting).await - } - (None, StartStop::Stop, StartStop::Stop) => { - set_status(&mut db, &seed.manifest, &MainStatus::Stopped).await - } + let status = match (override_status.clone(), current, desired) { + (Some(status), _, _) => status, + (_, StartStop::Start, StartStop::Start) => MainStatus::Running { + started: chrono::Utc::now(), + health: Default::default(), + }, + (_, StartStop::Start, StartStop::Stop) => MainStatus::Stopping, + (_, StartStop::Stop, StartStop::Start) => MainStatus::Starting, + (_, StartStop::Stop, StartStop::Stop) => MainStatus::Stopped, }; - if let Err(err) = res { + + let manifest = &seed.manifest; + if let Err(err) = seed + .ctx + .db + .mutate(|db| set_status(db, manifest, &status)) + .await + { tracing::error!("Did not set status for {}", seed.container_name); tracing::debug!("{:?}", err); } @@ -223,40 +260,6 @@ async fn run_main_log_result(result: RunMainResult, seed: Arc (), // restart Ok(Err(e)) => { - #[cfg(feature = "unstable")] - { - use crate::notifications::NotificationLevel; - let mut db = seed.ctx.db.handle(); - let started = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&seed.manifest.id) - .and_then(|pde| pde.installed()) - .map::<_, MainStatus>(|i| i.status().main()) - .get(&mut db) - .await; - match started.as_deref() { - Ok(Some(MainStatus::Running { .. })) => { - let res = seed.ctx.notification_manager - .notify( - &mut db, - Some(seed.manifest.id.clone()), - NotificationLevel::Warning, - String::from("Service Crashed"), - format!("The service {} has crashed with the following exit code: {}\nDetails: {}", seed.manifest.id.clone(), e.0, e.1), - (), - Some(3600) // 1 hour - ) - .await; - if let Err(e) = res { - tracing::error!("Failed to issue notification: {}", e); - tracing::debug!("{:?}", e); - } - } - _ => { - tracing::error!("service just started. not issuing crash notification") - } - } - } tracing::error!( "The service {} has crashed with the following exit code: {}", seed.manifest.id.clone(), @@ -272,56 +275,26 @@ async fn run_main_log_result(result: RunMainResult, seed: Arc MainStatus { - async move { - Ok::<_, Error>( - crate::db::DatabaseModel::new() - .package_data() - .idx_model(&manifest.id) - .expect(db) - .await? - .installed() - .expect(db) - .await? - .status() - .main() - .get(db) - .await? - .clone(), - ) - } - .map(|x| x.unwrap_or_else(|e| MainStatus::Stopped)) - .await +pub(super) fn get_status(db: Peeked, manifest: &Manifest) -> MainStatus { + db.as_package_data() + .as_idx(&manifest.id) + .and_then(|x| x.as_installed()) + .filter(|x| x.as_manifest().as_version().de().ok() == Some(manifest.version.clone())) + .and_then(|x| x.as_status().as_main().de().ok()) + .unwrap_or(MainStatus::Stopped) } #[instrument(skip(db, manifest))] -async fn set_status( - db: &mut PatchDbHandle, - manifest: &Manifest, - main_status: &MainStatus, -) -> Result<(), Error> { - if crate::db::DatabaseModel::new() - .package_data() - .idx_model(&manifest.id) - .expect(db) - .await? - .installed() - .exists(db) - .await? - { - crate::db::DatabaseModel::new() - .package_data() - .idx_model(&manifest.id) - .expect(db) - .await? - .installed() - .expect(db) - .await? - .status() - .main() - .put(db, main_status) - .await?; - } - Ok(()) +fn set_status(db: &mut Peeked, manifest: &Manifest, main_status: &MainStatus) -> Result<(), Error> { + let Some(installed) = db + .as_package_data_mut() + .as_idx_mut(&manifest.id) + .or_not_found(&manifest.id)? + .as_installed_mut() + else { + return Ok(()); + }; + installed.as_status_mut().as_main_mut().ser(main_status) } diff --git a/backend/src/manager/manager_map.rs b/backend/src/manager/manager_map.rs index 4e21004ac..07f128ccd 100644 --- a/backend/src/manager/manager_map.rs +++ b/backend/src/manager/manager_map.rs @@ -2,46 +2,31 @@ use std::collections::BTreeMap; use std::sync::Arc; use color_eyre::eyre::eyre; -use patch_db::DbHandle; -use sqlx::{Executor, Postgres}; use tokio::sync::RwLock; use tracing::instrument; use super::Manager; use crate::context::RpcContext; +use crate::prelude::*; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::util::Version; use crate::Error; +/// This is the structure to contain all the service managers #[derive(Default)] pub struct ManagerMap(RwLock>>); impl ManagerMap { #[instrument(skip_all)] - pub async fn init( - &self, - ctx: &RpcContext, - db: &mut Db, - secrets: &mut Ex, - ) -> Result<(), Error> - where - for<'a> &'a mut Ex: Executor<'a, Database = Postgres>, - { + pub async fn init(&self, ctx: RpcContext, peeked: Peeked) -> Result<(), Error> { let mut res = BTreeMap::new(); - for package in crate::db::DatabaseModel::new() - .package_data() - .keys(db) - .await? - { - let man: Manifest = if let Some(manifest) = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&package) - .and_then(|pkg| pkg.installed()) - .map(|m| m.manifest()) - .get(db) - .await? - .to_owned() + for package in peeked.as_package_data().keys()? { + let man: Manifest = if let Some(manifest) = peeked + .as_package_data() + .as_idx(&package) + .and_then(|x| x.as_installed()) + .map(|x| x.as_manifest().de()) { - manifest + manifest? } else { continue; }; @@ -55,17 +40,20 @@ impl ManagerMap { Ok(()) } + /// Used during the install process #[instrument(skip_all)] - pub async fn add(&self, ctx: RpcContext, manifest: Manifest) -> Result<(), Error> { + pub async fn add(&self, ctx: RpcContext, manifest: Manifest) -> Result, Error> { let mut lock = self.0.write().await; let id = (manifest.id.clone(), manifest.version.clone()); if let Some(man) = lock.remove(&id) { man.exit().await; } - lock.insert(id, Arc::new(Manager::new(ctx, manifest).await?)); - Ok(()) + let manager = Arc::new(Manager::new(ctx.clone(), manifest).await?); + lock.insert(id, manager.clone()); + Ok(manager) } + /// This is ran during the cleanup, so when we are uninstalling the service #[instrument(skip_all)] pub async fn remove(&self, id: &(PackageId, Version)) { if let Some(man) = self.0.write().await.remove(id) { @@ -73,13 +61,14 @@ impl ManagerMap { } } + /// Used during a shutdown #[instrument(skip_all)] pub async fn empty(&self) -> Result<(), Error> { let res = futures::future::join_all(std::mem::take(&mut *self.0.write().await).into_iter().map( |((id, version), man)| async move { tracing::debug!("Manager for {}@{} shutting down", id, version); - man.exit().await; + man.shutdown().await?; tracing::debug!("Manager for {}@{} is shutdown", id, version); if let Err(e) = Arc::try_unwrap(man) { tracing::trace!( diff --git a/backend/src/manager/manager_seed.rs b/backend/src/manager/manager_seed.rs index b92f96491..f90e7739f 100644 --- a/backend/src/manager/manager_seed.rs +++ b/backend/src/manager/manager_seed.rs @@ -1,9 +1,13 @@ -use bollard::container::StopContainerOptions; +use models::ErrorKind; use crate::context::RpcContext; +use crate::procedure::docker::DockerProcedure; +use crate::procedure::PackageProcedure; use crate::s9pk::manifest::Manifest; +use crate::util::docker::stop_container; use crate::Error; +/// This is helper structure for a service, the seed of the data that is needed for the manager_container pub struct ManagerSeed { pub ctx: RpcContext, pub manifest: Manifest, @@ -12,35 +16,20 @@ pub struct ManagerSeed { impl ManagerSeed { pub async fn stop_container(&self) -> Result<(), Error> { - match self - .ctx - .docker - .stop_container( - &self.container_name, - Some(StopContainerOptions { - t: self - .manifest - .containers - .as_ref() - .and_then(|c| c.main.sigterm_timeout) - .map(|d| d.as_secs()) - .unwrap_or(30) as i64, - }), - ) - .await + match stop_container( + &self.container_name, + match &self.manifest.main { + PackageProcedure::Docker(DockerProcedure { + sigterm_timeout: Some(sigterm_timeout), + .. + }) => Some(**sigterm_timeout), + _ => None, + }, + None, + ) + .await { - Err(bollard::errors::Error::DockerResponseServerError { - status_code: 404, // NOT FOUND - .. - }) - | Err(bollard::errors::Error::DockerResponseServerError { - status_code: 409, // CONFLICT - .. - }) - | Err(bollard::errors::Error::DockerResponseServerError { - status_code: 304, // NOT MODIFIED - .. - }) => (), // Already stopped + Err(e) if e.kind == ErrorKind::NotFound => (), // Already stopped a => a?, } Ok(()) diff --git a/backend/src/manager/mod.rs b/backend/src/manager/mod.rs index f08fc6d67..f8f9ff16d 100644 --- a/backend/src/manager/mod.rs +++ b/backend/src/manager/mod.rs @@ -4,23 +4,19 @@ use std::sync::Arc; use std::task::Poll; use std::time::Duration; -use color_eyre::{eyre::eyre, Report}; +use color_eyre::eyre::eyre; use embassy_container_init::ProcessGroupId; use futures::future::BoxFuture; use futures::{Future, FutureExt, TryFutureExt}; use helpers::UnixRpcClient; -use models::{ErrorKind, PackageId}; +use models::{ErrorKind, OptionExt, PackageId}; use nix::sys::signal::Signal; -use patch_db::DbHandle; use persistent_container::PersistentContainer; use rand::SeedableRng; use sqlx::Connection; use start_stop::StartStop; -use tokio::sync::oneshot; -use tokio::sync::{ - watch::{self, Sender}, - Mutex, -}; +use tokio::sync::watch::{self, Sender}; +use tokio::sync::{oneshot, Mutex}; use tracing::instrument; use transition_state::TransitionState; @@ -28,28 +24,28 @@ use crate::backup::target::PackageBackupInfo; use crate::backup::PackageBackupReport; use crate::config::action::ConfigRes; use crate::config::spec::ValueSpecPointer; -use crate::config::{not_found, ConfigReceipts, ConfigureContext}; +use crate::config::ConfigureContext; use crate::context::RpcContext; use crate::db::model::{CurrentDependencies, CurrentDependencyInfo}; use crate::dependencies::{ - add_dependent_to_current_dependents_lists, break_transitive, heal_all_dependents_transitive, - DependencyError, DependencyErrors, TaggedDependencyError, + add_dependent_to_current_dependents_lists, compute_dependency_config_errs, }; use crate::disk::mount::backup::BackupMountGuard; use crate::disk::mount::guard::TmpMountGuard; use crate::install::cleanup::remove_from_current_dependents_lists; use crate::net::net_controller::NetService; use crate::net::vhost::AlpnInfo; +use crate::prelude::*; use crate::procedure::docker::{DockerContainer, DockerProcedure, LongRunning}; use crate::procedure::{NoOutput, ProcedureName}; use crate::s9pk::manifest::Manifest; use crate::status::MainStatus; +use crate::util::docker::{get_container_ip, kill_container}; use crate::util::NonDetachingJoinHandle; use crate::volume::Volume; use crate::Error; pub mod health; -mod js_api; mod manager_container; mod manager_map; pub mod manager_seed; @@ -109,12 +105,13 @@ impl Gid { } } +/// This is the controller of the services. Here is where we can control a service with a start, stop, restart, etc. #[derive(Clone)] pub struct Manager { seed: Arc, manage_container: Arc, - transition: Arc>>, + transition: Arc>, persistent_container: ManagerPersistentContainer, pub gid: Arc, @@ -143,106 +140,111 @@ impl Manager { }) } - pub fn start(&self) { - self._transition_abort(); - self.manage_container.to_desired(StartStop::Start); - } - pub fn stop(&self) { - self._transition_abort(); - self.manage_container.to_desired(StartStop::Stop); - } - pub async fn restart(&self) { + /// awaiting this does not wait for the start to complete + pub async fn start(&self) { if self._is_transition_restart() { return; } - self._transition_replace(self._transition_restart()); + self._transition_abort().await; + self.manage_container.to_desired(StartStop::Start); } + + /// awaiting this does not wait for the stop to complete + pub async fn stop(&self) { + self._transition_abort().await; + self.manage_container.to_desired(StartStop::Stop); + } + /// awaiting this does not wait for the restart to complete + pub async fn restart(&self) { + if self._is_transition_restart() + && *self.manage_container.desired_state().borrow() == StartStop::Stop + { + return; + } + if self.manage_container.desired_state().borrow().is_start() { + self._transition_replace(self._transition_restart()).await; + } + } + /// awaiting this does not wait for the restart to complete pub async fn configure( &self, configure_context: ConfigureContext, - ) -> Result, Error> { - if self._is_transition_configure() { - return Ok(configure_context.breakages); + ) -> Result, Error> { + if self._is_transition_restart() { + self._transition_abort().await; + } else if self._is_transition_backup() { + return Err(Error::new( + eyre!("Can't configure because service is backing up"), + ErrorKind::InvalidRequest, + )); } let context = self.seed.ctx.clone(); let id = self.seed.manifest.id.clone(); - let (transition_state, done) = configure(context, id, configure_context).remote_handle(); - self._transition_replace({ - let manage_container = self.manage_container.clone(); + let breakages = configure(context, id, configure_context).await?; - TransitionState::Configuring( - tokio::spawn(async move { - let desired_state = manage_container.desired_state(); - let state_reverter = DesiredStateReverter::new(manage_container.clone()); - let mut current_state = manage_container.current_state(); - manage_container.to_desired(StartStop::Stop); - while current_state.borrow().is_start() { - current_state.changed().await.unwrap(); - } + self.restart().await; - transition_state.await; - - state_reverter.revert().await; - }) - .into(), - ) - }); - done.await + Ok(breakages) } + + /// awaiting this does not wait for the backup to complete pub async fn backup(&self, backup_guard: BackupGuard) -> BackupReturn { if self._is_transition_backup() { return BackupReturn::AlreadyRunning(PackageBackupReport { - error: Some("Can't do backup because service is in a backing up state".to_owned()), + error: Some("Can't do backup because service is already backing up".to_owned()), }); } let (transition_state, done) = self._transition_backup(backup_guard); - self._transition_replace(transition_state); + self._transition_replace(transition_state).await; done.await } pub async fn exit(&self) { - self.stop(); - let mut current_status = self.manage_container.current_state(); - - while current_status.borrow().is_start() { - current_status.changed().await.unwrap(); - } + self._transition_abort().await; + self.manage_container + .wait_for_desired(StartStop::Stop) + .await; } + /// A special exit that is overridden the start state, should only be called in the shutdown, where we remove other containers + async fn shutdown(&self) -> Result<(), Error> { + self.manage_container.lock_state_forever(&self.seed).await?; + + self.exit().await; + Ok(()) + } + + /// Used when we want to shutdown the service pub async fn signal(&self, signal: Signal) -> Result<(), Error> { - let rpc_client = self.rpc_client(); - let seed = self.seed.clone(); let gid = self.gid.clone(); send_signal(self, gid, signal).await } + /// Used as a getter, but also used in procedure pub fn rpc_client(&self) -> Option> { (*self.persistent_container) .as_ref() .map(|x| x.rpc_client()) } - fn _transition_abort(&self) { - if let Some(transition) = self - .transition - .send_replace(Default::default()) - .join_handle() - { - transition.abort(); - } - } - fn _transition_replace(&self, transition_state: TransitionState) { + async fn _transition_abort(&self) { self.transition - .send_replace(Arc::new(transition_state)) - .abort(); + .send_replace(Default::default()) + .abort() + .await; + } + async fn _transition_replace(&self, transition_state: TransitionState) { + self.transition.send_replace(transition_state).abort().await; } - pub(super) fn perform_restart(&self) -> impl Future + 'static { + pub(super) fn perform_restart(&self) -> impl Future> + 'static { let manage_container = self.manage_container.clone(); async move { - let _ = manage_container.set_override(Some(MainStatus::Restarting)); + let restart_override = manage_container.set_override(MainStatus::Restarting)?; manage_container.wait_for_desired(StartStop::Stop).await; manage_container.wait_for_desired(StartStop::Start).await; + restart_override.drop(); + Ok(()) } } fn _transition_restart(&self) -> TransitionState { @@ -250,7 +252,9 @@ impl Manager { let restart = self.perform_restart(); TransitionState::Restarting( tokio::spawn(async move { - restart.await; + if let Err(err) = restart.await { + tracing::error!("Error restarting service: {}", err); + } transition.send_replace(Default::default()); }) .into(), @@ -259,36 +263,42 @@ impl Manager { fn perform_backup( &self, backup_guard: BackupGuard, - ) -> impl Future, Error>> + 'static { + ) -> impl Future, Error>> { let manage_container = self.manage_container.clone(); let seed = self.seed.clone(); async move { + let peek = seed.ctx.db.peek().await; let state_reverter = DesiredStateReverter::new(manage_container.clone()); - let mut tx = seed.ctx.db.handle(); - let _ = manage_container - .set_override(Some(get_status(&mut tx, &seed.manifest).await.backing_up())); + let override_guard = + manage_container.set_override(get_status(peek, &seed.manifest).backing_up())?; manage_container.wait_for_desired(StartStop::Stop).await; let backup_guard = backup_guard.lock().await; let guard = backup_guard.mount_package_backup(&seed.manifest.id).await?; - let res = seed - .manifest - .backup - .create( - &seed.ctx, - &mut tx, - &seed.manifest.id, - &seed.manifest.title, - &seed.manifest.version, - &seed.manifest.interfaces, - &seed.manifest.volumes, - ) - .await; + let return_value = seed.manifest.backup.create(seed.clone()).await; guard.unmount().await?; drop(backup_guard); - let return_value = res; + let manifest_id = seed.manifest.id.clone(); + seed.ctx + .db + .mutate(|db| { + if let Some(progress) = db + .as_server_info_mut() + .as_status_info_mut() + .as_backup_progress_mut() + .transpose_mut() + .and_then(|p| p.as_idx_mut(&manifest_id)) + { + progress.as_complete_mut().ser(&true)?; + } + Ok(()) + }) + .await?; + state_reverter.revert().await; + + override_guard.drop(); Ok::<_, Error>(return_value) } } @@ -297,11 +307,13 @@ impl Manager { backup_guard: BackupGuard, ) -> (TransitionState, BoxFuture) { let (send, done) = oneshot::channel(); + + let transition_state = self.transition.clone(); ( TransitionState::BackingUp( tokio::spawn( self.perform_backup(backup_guard) - .then(finnish_up_backup_task(self.transition.clone(), send)), + .then(finish_up_backup_task(transition_state, send)), ) .into(), ), @@ -312,295 +324,242 @@ impl Manager { } fn _is_transition_restart(&self) -> bool { let transition = self.transition.borrow(); - matches!(**transition, TransitionState::Restarting(_)) + matches!(*transition, TransitionState::Restarting(_)) } fn _is_transition_backup(&self) -> bool { let transition = self.transition.borrow(); - matches!(**transition, TransitionState::BackingUp(_)) - } - fn _is_transition_configure(&self) -> bool { - let transition = self.transition.borrow(); - matches!(**transition, TransitionState::Configuring(_)) + matches!(*transition, TransitionState::BackingUp(_)) } } #[instrument(skip_all)] -fn configure( +async fn configure( ctx: RpcContext, id: PackageId, mut configure_context: ConfigureContext, -) -> BoxFuture<'static, Result, Error>> { - async move { - let mut db = ctx.db.handle(); - let mut tx = db.begin().await?; - let db = &mut tx; +) -> Result, Error> { + let db = ctx.db.peek().await; + let id = &id; + let ctx = &ctx; + let overrides = &mut configure_context.overrides; + // fetch data from db + let manifest = db + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .as_manifest() + .de()?; - let receipts = ConfigReceipts::new(db).await?; - let id = &id; - let ctx = &ctx; - let overrides = &mut configure_context.overrides; - // fetch data from db - let action = receipts - .config_actions - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; - let dependencies = receipts - .dependencies - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; - let volumes = receipts - .volumes - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; - let version = receipts - .version - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; + // get current config and current spec + let ConfigRes { + config: old_config, + spec, + } = manifest + .config + .as_ref() + .or_not_found("Manifest config")? + .get(ctx, id, &manifest.version, &manifest.volumes) + .await?; - // get current config and current spec - let ConfigRes { - config: old_config, - spec, - } = action.get(ctx, id, &version, &volumes).await?; + // determine new config to use + let mut config = if let Some(config) = configure_context.config.or_else(|| old_config.clone()) { + config + } else { + spec.gen( + &mut rand::rngs::StdRng::from_entropy(), + &configure_context.timeout, + )? + }; - // determine new config to use - let mut config = - if let Some(config) = configure_context.config.or_else(|| old_config.clone()) { - config - } else { - spec.gen( - &mut rand::rngs::StdRng::from_entropy(), - &configure_context.timeout, - )? - }; + spec.validate(&manifest)?; + spec.matches(&config)?; // check that new config matches spec - let manifest = receipts - .manifest - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; + // TODO Commit or not? + spec.update(ctx, &manifest, overrides, &mut config).await?; // dereference pointers in the new config - spec.validate(&manifest)?; - spec.matches(&config)?; // check that new config matches spec - spec.update( - ctx, - db, - &manifest, - overrides, - &mut config, - &receipts.config_receipts, - ) - .await?; // dereference pointers in the new config + let manifest = db + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .as_installed() + .or_not_found(id)? + .as_manifest() + .de()?; - // create backreferences to pointers - let mut sys = receipts - .system_pointers - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; - sys.truncate(0); - let mut current_dependencies: CurrentDependencies = CurrentDependencies( - dependencies - .0 - .iter() - .filter_map(|(id, info)| { - if info.requirement.required() { - Some((id.clone(), CurrentDependencyInfo::default())) - } else { - None - } - }) - .collect(), - ); - for ptr in spec.pointers(&config)? { - match ptr { - ValueSpecPointer::Package(pkg_ptr) => { - if let Some(current_dependency) = - current_dependencies.0.get_mut(pkg_ptr.package_id()) - { - current_dependency.pointers.push(pkg_ptr); - } else { - current_dependencies.0.insert( - pkg_ptr.package_id().to_owned(), - CurrentDependencyInfo { - pointers: vec![pkg_ptr], - health_checks: BTreeSet::new(), - }, - ); - } - } - ValueSpecPointer::System(s) => sys.push(s), - } - } - receipts.system_pointers.set(db, sys, id).await?; - - let signal = if !configure_context.dry_run { - // run config action - let res = action - .set(ctx, id, &version, &dependencies, &volumes, &config) - .await?; - - ctx.call_config_hooks(id.clone(), &serde_json::Value::Object(config.clone())) - .await; - - // track dependencies with no pointers - for (package_id, health_checks) in res.depends_on.into_iter() { - if let Some(current_dependency) = current_dependencies.0.get_mut(&package_id) { - current_dependency.health_checks.extend(health_checks); + let dependencies = &manifest.dependencies; + let mut current_dependencies: CurrentDependencies = CurrentDependencies( + dependencies + .0 + .iter() + .filter_map(|(id, info)| { + if info.requirement.required() { + Some((id.clone(), CurrentDependencyInfo::default())) } else { + None + } + }) + .collect(), + ); + for ptr in spec.pointers(&config)? { + match ptr { + ValueSpecPointer::Package(pkg_ptr) => { + if let Some(info) = current_dependencies.0.get_mut(pkg_ptr.package_id()) { + info.pointers.insert(pkg_ptr); + } else { + let id = pkg_ptr.package_id().to_owned(); + let mut pointers = BTreeSet::new(); + pointers.insert(pkg_ptr); current_dependencies.0.insert( - package_id, + id, CurrentDependencyInfo { - pointers: Vec::new(), - health_checks, + pointers, + health_checks: BTreeSet::new(), }, ); } } + ValueSpecPointer::System(_) => (), + } + } - // track dependency health checks - current_dependencies = current_dependencies.map(|x| { - x.into_iter() - .filter(|(dep_id, _)| { - if dep_id != id && !manifest.dependencies.0.contains_key(dep_id) { - tracing::warn!("Illegal dependency specified: {}", dep_id); - false - } else { - true - } - }) - .collect() - }); - res.signal - } else { - None - }; - - // update dependencies - let prev_current_dependencies = receipts - .current_dependencies - .get(db, id) - .await? - .unwrap_or_default(); - remove_from_current_dependents_lists( - db, - id, - &prev_current_dependencies, - &receipts.current_dependents, - ) - .await?; // remove previous - add_dependent_to_current_dependents_lists( - db, - id, - ¤t_dependencies, - &receipts.current_dependents, - ) - .await?; // add new - current_dependencies.0.remove(id); - receipts - .current_dependencies - .set(db, current_dependencies.clone(), id) + let action = manifest.config.as_ref().or_not_found(id)?; + let version = &manifest.version; + let volumes = &manifest.volumes; + if !configure_context.dry_run { + // run config action + let res = action + .set(ctx, id, version, &dependencies, volumes, &config) .await?; - let errs = receipts - .dependency_errors - .get(db, &id) - .await? - .ok_or_else(|| not_found!(&*id))?; - tracing::warn!("Dependency Errors: {:?}", errs); - let errs = DependencyErrors::init( - ctx, - db, - &manifest, - ¤t_dependencies, - &receipts.dependency_receipt.try_heal, - ) - .await?; - receipts.dependency_errors.set(db, errs, id).await?; + // track dependencies with no pointers + for (package_id, health_checks) in res.depends_on.into_iter() { + if let Some(current_dependency) = current_dependencies.0.get_mut(&package_id) { + current_dependency.health_checks.extend(health_checks); + } else { + current_dependencies.0.insert( + package_id, + CurrentDependencyInfo { + pointers: BTreeSet::new(), + health_checks, + }, + ); + } + } - // cache current config for dependents - configure_context - .overrides - .insert(id.clone(), config.clone()); + // track dependency health checks + current_dependencies = current_dependencies.map(|x| { + x.into_iter() + .filter(|(dep_id, _)| { + if dep_id != id && !manifest.dependencies.0.contains_key(dep_id) { + tracing::warn!("Illegal dependency specified: {}", dep_id); + false + } else { + true + } + }) + .collect() + }); + } - // handle dependents - let dependents = receipts - .current_dependents - .get(db, id) - .await? - .ok_or_else(|| not_found!(&*id))?; - for (dependent, _dep_info) in dependents.0.iter().filter(|(dep_id, _)| dep_id != &id) { - let dependent_container = receipts.docker_containers.get(db, dependent).await?; - let dependent_container = &dependent_container; - // check if config passes dependent check - if let Some(cfg) = receipts - .manifest_dependencies_config - .get(db, (dependent, id)) + let dependency_config_errs = + compute_dependency_config_errs(&ctx, &db, &manifest, ¤t_dependencies, overrides) + .await?; + + // cache current config for dependents + configure_context + .overrides + .insert(id.clone(), config.clone()); + + // handle dependents + + let dependents = db + .as_package_data() + .as_idx(id) + .or_not_found(id)? + .as_installed() + .or_not_found(id)? + .as_current_dependents() + .de()?; + for (dependent, _dep_info) in dependents.0.iter().filter(|(dep_id, _)| dep_id != &id) { + // check if config passes dependent check + if let Some(cfg) = db + .as_package_data() + .as_idx(dependent) + .or_not_found(dependent)? + .as_installed() + .or_not_found(dependent)? + .as_manifest() + .as_dependencies() + .as_idx(id) + .or_not_found(id)? + .as_config() + .de()? + { + let manifest = db + .as_package_data() + .as_idx(dependent) + .or_not_found(dependent)? + .as_installed() + .or_not_found(dependent)? + .as_manifest() + .de()?; + if let Err(error) = cfg + .check( + ctx, + dependent, + &manifest.version, + &manifest.volumes, + id, + &config, + ) .await? { - let manifest = receipts - .manifest - .get(db, dependent) - .await? - .ok_or_else(|| not_found!(&*id))?; - if let Err(error) = cfg - .check( - ctx, - dependent_container, - dependent, - &manifest.version, - &manifest.volumes, - id, - &config, - ) - .await? - { - let dep_err = DependencyError::ConfigUnsatisfied { error }; - break_transitive( - db, - dependent, - id, - dep_err, - &mut configure_context.breakages, - &receipts.break_transitive_receipts, - ) - .await?; - } - - heal_all_dependents_transitive(ctx, db, id, &receipts.dependency_receipt).await?; + configure_context.breakages.insert(dependent.clone(), error); } } - - if let Some(signal) = signal { - match ctx.managers.get(&(id.clone(), version.clone())).await { - None => { - // in theory this should never happen, which indicates this function should be moved behind the - // Manager interface - return Err(Error::new( - eyre!("Manager Not Found for package being configured"), - crate::ErrorKind::Incoherent, - )); - } - Some(m) => { - async move { m.signal(signal).await }.await?; - } - } - } - receipts.configured.set(db, true, &id).await?; - - if configure_context.dry_run { - tx.abort().await?; - } else { - tx.commit().await?; - } - - Ok(configure_context.breakages) } - .boxed() + + if !configure_context.dry_run { + return ctx + .db + .mutate(move |db| { + remove_from_current_dependents_lists(db, id, ¤t_dependencies)?; + add_dependent_to_current_dependents_lists(db, id, ¤t_dependencies)?; + current_dependencies.0.remove(id); + for (dep, errs) in db + .as_package_data_mut() + .as_entries_mut()? + .into_iter() + .filter_map(|(id, pde)| { + pde.as_installed_mut() + .map(|i| (id, i.as_status_mut().as_dependency_config_errors_mut())) + }) + { + errs.remove(id)?; + if let Some(err) = configure_context.breakages.get(&dep) { + errs.insert(id, err)?; + } + } + let installed = db + .as_package_data_mut() + .as_idx_mut(id) + .or_not_found(id)? + .as_installed_mut() + .or_not_found(id)?; + installed + .as_current_dependencies_mut() + .ser(¤t_dependencies)?; + let status = installed.as_status_mut(); + status.as_configured_mut().ser(&true)?; + status + .as_dependency_config_errors_mut() + .ser(&dependency_config_errs)?; + Ok(configure_context.breakages) + }) + .await; // add new + } + + Ok(configure_context.breakages) } struct DesiredStateReverter { @@ -640,8 +599,8 @@ impl Drop for DesiredStateReverter { type BackupDoneSender = oneshot::Sender>; -fn finnish_up_backup_task( - transition: Arc>>, +fn finish_up_backup_task( + transition: Arc>, send: BackupDoneSender, ) -> impl FnOnce(Result, Error>) -> BoxFuture<'static, ()> { move |result| { @@ -764,27 +723,11 @@ enum GetRunningIp { async fn get_long_running_ip(seed: &ManagerSeed, runtime: &mut LongRunning) -> GetRunningIp { loop { - match container_inspect(seed).await { - Ok(res) => { - match res - .network_settings - .and_then(|ns| ns.networks) - .and_then(|mut n| n.remove("start9")) - .and_then(|es| es.ip_address) - .filter(|ip| !ip.is_empty()) - .map(|ip| ip.parse()) - .transpose() - { - Ok(Some(ip_addr)) => return GetRunningIp::Ip(ip_addr), - Ok(None) => (), - Err(e) => return GetRunningIp::Error(e.into()), - } - } - Err(bollard::errors::Error::DockerResponseServerError { - status_code: 404, // NOT FOUND - .. - }) => (), - Err(e) => return GetRunningIp::Error(e.into()), + match get_container_ip(&seed.container_name).await { + Ok(Some(ip_addr)) => return GetRunningIp::Ip(ip_addr), + Ok(None) => (), + Err(e) if e.kind == ErrorKind::NotFound => (), + Err(e) => return GetRunningIp::Error(e), } if let Poll::Ready(res) = futures::poll!(&mut runtime.running_output) { match res { @@ -800,16 +743,6 @@ async fn get_long_running_ip(seed: &ManagerSeed, runtime: &mut LongRunning) -> G } } -#[instrument(skip(seed))] -async fn container_inspect( - seed: &ManagerSeed, -) -> Result { - seed.ctx - .docker - .inspect_container(&seed.container_name, None) - .await -} - #[instrument(skip(seed))] async fn add_network_for_main( seed: &ManagerSeed, @@ -826,7 +759,7 @@ async fn add_network_for_main( for (id, interface) in &seed.manifest.interfaces.0 { for (external, internal) in interface.lan_config.iter().flatten() { svc.add_lan( - &mut tx, + tx.as_mut(), id.clone(), external.0, internal.internal, @@ -835,13 +768,14 @@ async fn add_network_for_main( .await?; } for (external, internal) in interface.tor_config.iter().flat_map(|t| &t.port_mapping) { - svc.add_tor(&mut tx, id.clone(), external.0, internal.0) + svc.add_tor(tx.as_mut(), id.clone(), external.0, internal.0) .await?; } } for volume in seed.manifest.volumes.values() { if let Volume::Certificate { interface_id } = volume { - svc.export_cert(&mut tx, interface_id, ip.into()).await?; + svc.export_cert(tx.as_mut(), interface_id, ip.into()) + .await?; } } tx.commit().await?; @@ -856,8 +790,7 @@ async fn remove_network_for_main(svc: NetService) -> Result<(), Error> { async fn main_health_check_daemon(seed: Arc) { tokio::time::sleep(Duration::from_secs(HEALTH_CHECK_GRACE_PERIOD_SECONDS)).await; loop { - let mut db = seed.ctx.db.handle(); - if let Err(e) = health::check(&seed.ctx, &mut db, &seed.manifest.id).await { + if let Err(e) = health::check(&seed.ctx, &seed.manifest.id).await { tracing::error!( "Failed to run health check for {}: {}", &seed.manifest.id, @@ -871,42 +804,14 @@ async fn main_health_check_daemon(seed: Arc) { type RuntimeOfCommand = NonDetachingJoinHandle, Error>>; -async fn try_get_running_ip(seed: &ManagerSeed) -> Result, Report> { - Ok(container_inspect(seed) - .await - .map(|x| x.network_settings)? - .and_then(|ns| ns.networks) - .and_then(|mut n| n.remove("start9")) - .and_then(|es| es.ip_address) - .filter(|ip| !ip.is_empty()) - .map(|ip| ip.parse()) - .transpose()?) -} - #[instrument(skip(seed, runtime))] async fn get_running_ip(seed: &ManagerSeed, mut runtime: &mut RuntimeOfCommand) -> GetRunningIp { loop { - match container_inspect(seed).await { - Ok(res) => { - match res - .network_settings - .and_then(|ns| ns.networks) - .and_then(|mut n| n.remove("start9")) - .and_then(|es| es.ip_address) - .filter(|ip| !ip.is_empty()) - .map(|ip| ip.parse()) - .transpose() - { - Ok(Some(ip_addr)) => return GetRunningIp::Ip(ip_addr), - Ok(None) => (), - Err(e) => return GetRunningIp::Error(e.into()), - } - } - Err(bollard::errors::Error::DockerResponseServerError { - status_code: 404, // NOT FOUND - .. - }) => (), - Err(e) => return GetRunningIp::Error(e.into()), + match get_container_ip(&seed.container_name).await { + Ok(Some(ip_addr)) => return GetRunningIp::Ip(ip_addr), + Ok(None) => (), + Err(e) if e.kind == ErrorKind::NotFound => (), + Err(e) => return GetRunningIp::Error(e), } if let Poll::Ready(res) = futures::poll!(&mut runtime) { match res { @@ -960,7 +865,7 @@ async fn send_signal(manager: &Manager, gid: Arc, signal: Signal) -> Result None, // TODO next_gid, Some(rpc_client), - Arc::new(manager.clone()), + todo!(), ) .await? { @@ -969,28 +874,10 @@ async fn send_signal(manager: &Manager, gid: Arc, signal: Signal) -> Result } } else { // send signal to container - manager - .seed - .ctx - .docker - .kill_container( - &manager.seed.container_name, - Some(bollard::container::KillContainerOptions { - signal: signal.to_string(), - }), - ) + kill_container(&manager.seed.container_name, Some(signal)) .await .or_else(|e| { - if matches!( - e, - bollard::errors::Error::DockerResponseServerError { - status_code: 409, // CONFLICT - .. - } | bollard::errors::Error::DockerResponseServerError { - status_code: 404, // NOT FOUND - .. - } - ) { + if e.kind == ErrorKind::NotFound { Ok(()) } else { Err(e) diff --git a/backend/src/manager/persistent_container.rs b/backend/src/manager/persistent_container.rs index 84aa78b12..d9868a622 100644 --- a/backend/src/manager/persistent_container.rs +++ b/backend/src/manager/persistent_container.rs @@ -16,6 +16,8 @@ use crate::procedure::docker::DockerContainer; use crate::util::NonDetachingJoinHandle; use crate::Error; +/// Persistant container are the old containers that need to run all the time +/// The goal is that all services will be persistent containers, waiting to run the main system. pub struct PersistentContainer { _running_docker: NonDetachingJoinHandle<()>, pub rpc_client: Receiver>, diff --git a/backend/src/manager/start_stop.rs b/backend/src/manager/start_stop.rs index 60e8d9ec1..3842abe57 100644 --- a/backend/src/manager/start_stop.rs +++ b/backend/src/manager/start_stop.rs @@ -10,9 +10,6 @@ impl StartStop { pub(crate) fn is_start(&self) -> bool { matches!(self, StartStop::Start) } - pub(crate) fn is_stop(&self) -> bool { - matches!(self, StartStop::Stop) - } } impl From for StartStop { fn from(value: MainStatus) -> Self { @@ -21,9 +18,15 @@ impl From for StartStop { MainStatus::Restarting => StartStop::Start, MainStatus::Stopping => StartStop::Stop, MainStatus::Starting => StartStop::Start, - MainStatus::Running { started, health } => StartStop::Start, - MainStatus::BackingUp { started, health } if started.is_some() => StartStop::Start, - MainStatus::BackingUp { started, health } => StartStop::Stop, + MainStatus::Running { + started: _, + health: _, + } => StartStop::Start, + MainStatus::BackingUp { started, health: _ } if started.is_some() => StartStop::Start, + MainStatus::BackingUp { + started: _, + health: _, + } => StartStop::Stop, } } } diff --git a/backend/src/manager/transition_state.rs b/backend/src/manager/transition_state.rs index bea191538..122c0f703 100644 --- a/backend/src/manager/transition_state.rs +++ b/backend/src/manager/transition_state.rs @@ -1,23 +1,30 @@ use helpers::NonDetachingJoinHandle; -pub(crate) enum TransitionState { +/// Used only in the manager/mod and is used to keep track of the state of the manager during the +/// transitional states +pub(super) enum TransitionState { BackingUp(NonDetachingJoinHandle<()>), Restarting(NonDetachingJoinHandle<()>), - Configuring(NonDetachingJoinHandle<()>), None, } impl TransitionState { - pub(crate) fn join_handle(&self) -> Option<&NonDetachingJoinHandle<()>> { + pub(super) fn take(&mut self) -> Self { + std::mem::take(self) + } + pub(super) fn into_join_handle(self) -> Option> { Some(match self { TransitionState::BackingUp(a) => a, TransitionState::Restarting(a) => a, - TransitionState::Configuring(a) => a, TransitionState::None => return None, }) } - pub(crate) fn abort(&self) { - self.join_handle().map(|transition| transition.abort()); + pub(super) async fn abort(&mut self) { + if let Some(s) = self.take().into_join_handle() { + if s.wait_for_abort().await.is_ok() { + tracing::trace!("transition completed before abort"); + } + } } } diff --git a/backend/src/middleware/auth.rs b/backend/src/middleware/auth.rs index ecc07ffd6..611923ad6 100644 --- a/backend/src/middleware/auth.rs +++ b/backend/src/middleware/auth.rs @@ -47,7 +47,7 @@ impl HasLoggedOutSessions { "UPDATE session SET logged_out = CURRENT_TIMESTAMP WHERE id = $1", session ) - .execute(&mut sqlx_conn) + .execute(sqlx_conn.as_mut()) .await?; for socket in open_authed_websockets.remove(&session).unwrap_or_default() { let _ = socket.send(()); @@ -94,7 +94,7 @@ impl HasValidSession { pub async fn from_session(session: &HashSessionToken, ctx: &RpcContext) -> Result { let session_hash = session.hashed(); let session = sqlx::query!("UPDATE session SET last_active = CURRENT_TIMESTAMP WHERE id = $1 AND logged_out IS NULL OR logged_out > CURRENT_TIMESTAMP", session_hash) - .execute(&mut ctx.secret_store.acquire().await?) + .execute(ctx.secret_store.acquire().await?.as_mut()) .await?; if session.rows_affected() == 0 { return Err(Error::new( diff --git a/backend/src/middleware/cors.rs b/backend/src/middleware/cors.rs index 132a2385f..5f33bc08d 100644 --- a/backend/src/middleware/cors.rs +++ b/backend/src/middleware/cors.rs @@ -1,4 +1,6 @@ use futures::FutureExt; +use http::HeaderValue; +use hyper::header::HeaderMap; use rpc_toolkit::hyper::http::Error as HttpError; use rpc_toolkit::hyper::{Body, Method, Request, Response}; use rpc_toolkit::rpc_server_helpers::{ @@ -6,24 +8,35 @@ use rpc_toolkit::rpc_server_helpers::{ }; use rpc_toolkit::Metadata; +fn get_cors_headers(req: &Request) -> HeaderMap { + let mut res = HeaderMap::new(); + if let Some(origin) = req.headers().get("Origin") { + res.insert("Access-Control-Allow-Origin", origin.clone()); + } + if let Some(method) = req.headers().get("Access-Control-Request-Method") { + res.insert("Access-Control-Allow-Methods", method.clone()); + } + if let Some(headers) = req.headers().get("Access-Control-Request-Headers") { + res.insert("Access-Control-Allow-Headers", headers.clone()); + } + res.insert( + "Access-Control-Allow-Credentials", + HeaderValue::from_static("true"), + ); + res +} + pub async fn cors( req: &mut Request, _metadata: M, ) -> Result>, HttpError> { + let headers = get_cors_headers(req); if req.method() == Method::OPTIONS { - Ok(Err(Response::builder() - .header( - "Access-Control-Allow-Origin", - if let Some(origin) = req.headers().get("origin").and_then(|s| s.to_str().ok()) { - origin - } else { - "*" - }, - ) - .header("Access-Control-Allow-Methods", "*") - .header("Access-Control-Allow-Headers", "*") - .header("Access-Control-Allow-Credentials", "true") - .body(Body::empty())?)) + Ok(Err({ + let mut res = Response::new(Body::empty()); + res.headers_mut().extend(headers.into_iter()); + res + })) } else { Ok(Ok(Box::new(|_, _| { async move { @@ -31,8 +44,7 @@ pub async fn cors( async move { let res: DynMiddlewareStage4 = Box::new(|res| { async move { - res.headers_mut() - .insert("Access-Control-Allow-Origin", "*".parse()?); + res.headers_mut().extend(headers.into_iter()); Ok::<_, HttpError>(()) } .boxed() diff --git a/backend/src/middleware/db.rs b/backend/src/middleware/db.rs index eeeeb299a..c3ceadda6 100644 --- a/backend/src/middleware/db.rs +++ b/backend/src/middleware/db.rs @@ -1,4 +1,3 @@ -use color_eyre::eyre::eyre; use futures::future::BoxFuture; use futures::FutureExt; use http::HeaderValue; @@ -11,7 +10,6 @@ use rpc_toolkit::yajrc::RpcMethod; use rpc_toolkit::Metadata; use crate::context::RpcContext; -use crate::{Error, ResultExt}; pub fn db(ctx: RpcContext) -> DynMiddleware { Box::new( @@ -20,51 +18,21 @@ pub fn db(ctx: RpcContext) -> DynMiddleware { -> BoxFuture>, HttpError>> { let ctx = ctx.clone(); async move { - let m2: DynMiddlewareStage2 = Box::new(move |req, rpc_req| { + let m2: DynMiddlewareStage2 = Box::new(move |_req, rpc_req| { async move { - let seq = req.headers.remove("x-patch-sequence"); let sync_db = metadata .get(rpc_req.method.as_str(), "sync_db") .unwrap_or(false); let m3: DynMiddlewareStage3 = Box::new(move |res, _| { async move { - if sync_db && seq.is_some() { - match async { - let seq = seq - .ok_or_else(|| { - Error::new( - eyre!("Missing X-Patch-Sequence"), - crate::ErrorKind::InvalidRequest, - ) - })? - .to_str() - .with_kind(crate::ErrorKind::InvalidRequest)? - .parse()?; - let res = ctx.db.sync(seq).await?; - let json = match res { - Ok(revs) => serde_json::to_vec(&revs), - Err(dump) => serde_json::to_vec(&[dump]), - } - .with_kind(crate::ErrorKind::Serialization)?; - Ok::<_, Error>(base64::encode_config( - &json, - base64::URL_SAFE, - )) - } - .await - { - Ok(a) => res - .headers - .append("X-Patch-Updates", HeaderValue::from_str(&a)?), - Err(e) => res.headers.append( - "X-Patch-Error", - HeaderValue::from_str(&base64::encode_config( - &e.to_string(), - base64::URL_SAFE, - ))?, - ), - }; + if sync_db { + res.headers.append( + "X-Patch-Sequence", + HeaderValue::from_str( + &ctx.db.sequence().await.to_string(), + )?, + ); } Ok(Ok(noop4())) } diff --git a/backend/src/middleware/encrypt.rs b/backend/src/middleware/encrypt.rs index 6eb8ed967..94167b7e2 100644 --- a/backend/src/middleware/encrypt.rs +++ b/backend/src/middleware/encrypt.rs @@ -13,7 +13,8 @@ pub fn pbkdf2(password: impl AsRef<[u8]>, salt: impl AsRef<[u8]>) -> CipherKey, pub to: IndexMap, @@ -27,14 +29,14 @@ impl Migrations { #[instrument(skip_all)] pub fn validate( &self, - container: &Option, + _container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, ) -> Result<(), Error> { for (version, migration) in &self.from { migration - .validate(container, eos_version, volumes, image_ids, true) + .validate(eos_version, volumes, image_ids, true) .with_ctx(|_| { ( crate::ErrorKind::ValidateS9pk, @@ -44,7 +46,7 @@ impl Migrations { } for (version, migration) in &self.to { migration - .validate(container, eos_version, volumes, image_ids, true) + .validate(eos_version, volumes, image_ids, true) .with_ctx(|_| { ( crate::ErrorKind::ValidateS9pk, @@ -58,7 +60,7 @@ impl Migrations { #[instrument(skip_all)] pub fn from<'a>( &'a self, - container: &'a Option, + _container: &'a Option, ctx: &'a RpcContext, version: &'a Version, pkg_id: &'a PackageId, @@ -133,6 +135,7 @@ impl Migrations { #[derive(Clone, Debug, Default, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct MigrationRes { pub configured: bool, } diff --git a/backend/src/net/dhcp.rs b/backend/src/net/dhcp.rs index ccf2b109f..cbe7ff19d 100644 --- a/backend/src/net/dhcp.rs +++ b/backend/src/net/dhcp.rs @@ -8,6 +8,7 @@ use tokio::sync::RwLock; use crate::context::RpcContext; use crate::db::model::IpInfo; use crate::net::utils::{iface_is_physical, list_interfaces}; +use crate::prelude::*; use crate::util::display_none; use crate::Error; @@ -58,12 +59,14 @@ pub async fn dhcp() -> Result<(), Error> { pub async fn update(#[context] ctx: RpcContext, #[arg] interface: String) -> Result<(), Error> { if iface_is_physical(&interface).await { let ip_info = IpInfo::for_interface(&interface).await?; - crate::db::DatabaseModel::new() - .server_info() - .ip_info() - .idx_model(&interface) - .put(&mut ctx.db.handle(), &ip_info) + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_ip_info_mut() + .insert(&interface, &ip_info) + }) .await?; + let mut cached = CACHED_IPS.write().await; if cached.is_empty() { *cached = _ips().await?; diff --git a/backend/src/net/dns.rs b/backend/src/net/dns.rs index a8910f698..7b2784a50 100644 --- a/backend/src/net/dns.rs +++ b/backend/src/net/dns.rs @@ -13,8 +13,8 @@ use tokio::process::Command; use tokio::sync::RwLock; use tracing::instrument; use trust_dns_server::authority::MessageResponseBuilder; -use trust_dns_server::client::op::{Header, ResponseCode}; -use trust_dns_server::client::rr::{Name, Record, RecordType}; +use trust_dns_server::proto::op::{Header, ResponseCode}; +use trust_dns_server::proto::rr::{Name, Record, RecordType}; use trust_dns_server::server::{Request, RequestHandler, ResponseHandler, ResponseInfo}; use trust_dns_server::ServerFuture; @@ -50,17 +50,15 @@ impl Resolver { } else { None } + } else if let Some(ip) = self.services.read().await.get(&None) { + Some( + ip.iter() + .filter(|(_, rc)| rc.strong_count() > 0) + .map(|(ip, _)| *ip) + .collect(), + ) } else { - if let Some(ip) = self.services.read().await.get(&None) { - Some( - ip.iter() - .filter(|(_, rc)| rc.strong_count() > 0) - .map(|(ip, _)| *ip) - .collect(), - ) - } else { - None - } + None } } _ => None, @@ -88,7 +86,7 @@ impl RequestHandler for Resolver { Record::from_rdata( request.request_info().query.name().to_owned().into(), 0, - trust_dns_server::client::rr::RData::A(ip), + trust_dns_server::proto::rr::RData::A(ip.into()), ) }) .collect::>(), diff --git a/backend/src/net/interface.rs b/backend/src/net/interface.rs index c7929ab65..a055bb277 100644 --- a/backend/src/net/interface.rs +++ b/backend/src/net/interface.rs @@ -4,10 +4,10 @@ use indexmap::IndexSet; pub use models::InterfaceId; use serde::{Deserialize, Deserializer, Serialize}; use sqlx::{Executor, Postgres}; -use torut::onion::TorSecretKeyV3; use tracing::instrument; use crate::db::model::{InterfaceAddressMap, InterfaceAddresses}; +use crate::net::keys::Key; use crate::s9pk::manifest::PackageId; use crate::util::serde::Port; use crate::{Error, ResultExt}; @@ -44,33 +44,13 @@ impl Interfaces { lan_address: None, }; if iface.tor_config.is_some() || iface.lan_config.is_some() { - let key = TorSecretKeyV3::generate(); - let key_vec = key.as_bytes().to_vec(); - sqlx::query!( - "INSERT INTO tor (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO NOTHING", - **package_id, - **id, - key_vec, - ) - .execute(&mut *secrets) - .await?; - let key_row = sqlx::query!( - "SELECT key FROM tor WHERE package = $1 AND interface = $2", - **package_id, - **id, - ) - .fetch_one(&mut *secrets) - .await?; - let mut key = [0_u8; 64]; - key.clone_from_slice(&key_row.key); - let key = TorSecretKeyV3::from(key); - let onion = key.public().get_onion_address(); + let key = + Key::for_interface(secrets, Some((package_id.clone(), id.clone()))).await?; if iface.tor_config.is_some() { - addrs.tor_address = Some(onion.to_string()); + addrs.tor_address = Some(key.tor_address().to_string()); } if iface.lan_config.is_some() { - addrs.lan_address = - Some(format!("{}.local", onion.get_address_without_dot_onion())); + addrs.lan_address = Some(key.local_address()); } } interface_addresses.0.insert(id.clone(), addrs); diff --git a/backend/src/net/keys.rs b/backend/src/net/keys.rs index 70c041f0b..6f5f13f82 100644 --- a/backend/src/net/keys.rs +++ b/backend/src/net/keys.rs @@ -1,5 +1,4 @@ use color_eyre::eyre::eyre; -use ed25519_dalek::{ExpandedSecretKey, SecretKey}; use models::{Id, InterfaceId, PackageId}; use openssl::pkey::{PKey, Private}; use openssl::sha::Sha256; @@ -12,37 +11,46 @@ use tracing::instrument; use zeroize::Zeroize; use crate::net::ssl::CertPair; -use crate::Error; +use crate::prelude::*; +use crate::util::crypto::ed25519_expand_key; // TODO: delete once we may change tor addresses #[instrument(skip(secrets))] async fn compat( secrets: impl PgExecutor<'_>, interface: &Option<(PackageId, InterfaceId)>, -) -> Result, Error> { +) -> Result, Error> { if let Some((package, interface)) = interface { if let Some(r) = sqlx::query!( "SELECT key FROM tor WHERE package = $1 AND interface = $2", - **package, - **interface + package, + interface ) .fetch_optional(secrets) .await? { - Ok(Some(ExpandedSecretKey::from_bytes(&r.key)?)) + Ok(Some(<[u8; 64]>::try_from(r.key).map_err(|e| { + Error::new( + eyre!("expected vec of len 64, got len {}", e.len()), + ErrorKind::ParseDbField, + ) + })?)) } else { Ok(None) } + } else if let Some(key) = sqlx::query!("SELECT tor_key FROM account WHERE id = 0") + .fetch_one(secrets) + .await? + .tor_key + { + Ok(Some(<[u8; 64]>::try_from(key).map_err(|e| { + Error::new( + eyre!("expected vec of len 64, got len {}", e.len()), + ErrorKind::ParseDbField, + ) + })?)) } else { - if let Some(key) = sqlx::query!("SELECT tor_key FROM account WHERE id = 0") - .fetch_one(secrets) - .await? - .tor_key - { - Ok(Some(ExpandedSecretKey::from_bytes(&key)?)) - } else { - Ok(None) - } + Ok(None) } } @@ -66,10 +74,7 @@ impl Key { .unwrap_or_else(|| "embassy".to_owned()) } pub fn tor_key(&self) -> TorSecretKeyV3 { - ed25519_dalek::ExpandedSecretKey::from_bytes(&self.tor_key) - .unwrap() - .to_bytes() - .into() + self.tor_key.into() } pub fn tor_address(&self) -> OnionAddressV3 { self.tor_key().public().get_onion_address() @@ -89,7 +94,7 @@ impl Key { pub fn openssl_key_nistp256(&self) -> PKey { let mut buf = self.base; loop { - if let Ok(k) = p256::SecretKey::from_be_bytes(&buf) { + if let Ok(k) = p256::SecretKey::from_slice(&buf) { return PKey::private_key_from_pkcs8(&*k.to_pkcs8_der().unwrap().as_bytes()) .unwrap(); } @@ -113,11 +118,7 @@ impl Key { } } pub fn from_bytes(interface: Option<(PackageId, InterfaceId)>, bytes: [u8; 32]) -> Self { - Self::from_pair( - interface, - bytes, - ExpandedSecretKey::from(&SecretKey::from_bytes(&bytes).unwrap()).to_bytes(), - ) + Self::from_pair(interface, bytes, ed25519_expand_key(&bytes)) } pub fn new(interface: Option<(PackageId, InterfaceId)>) -> Self { Self::from_bytes(interface, rand::random()) @@ -152,7 +153,7 @@ impl Key { WHERE network_keys.package = $1 "#, - **package + package ) .fetch_all(secrets) .await? @@ -197,8 +198,8 @@ impl Key { let k = tentative.as_slice(); let actual = sqlx::query!( "INSERT INTO network_keys (package, interface, key) VALUES ($1, $2, $3) ON CONFLICT (package, interface) DO UPDATE SET package = EXCLUDED.package RETURNING key", - **pkg, - **iface, + pkg, + iface, k, ) .fetch_one(&mut *secrets) @@ -227,7 +228,7 @@ impl Key { }; let mut res = Self::from_bytes(interface, actual); if let Some(tor_key) = compat(secrets, &res.interface).await? { - res.tor_key = tor_key.to_bytes(); + res.tor_key = tor_key; } Ok(res) } diff --git a/backend/src/net/mod.rs b/backend/src/net/mod.rs index d0508943d..afba879f0 100644 --- a/backend/src/net/mod.rs +++ b/backend/src/net/mod.rs @@ -11,7 +11,6 @@ pub mod dns; pub mod forward; pub mod interface; pub mod keys; -#[cfg(feature = "avahi")] pub mod mdns; pub mod net_controller; pub mod ssl; @@ -24,7 +23,7 @@ pub mod wifi; pub const PACKAGE_CERT_PATH: &str = "/var/lib/embassy/ssl"; -#[command(subcommands(tor::tor, dhcp::dhcp))] +#[command(subcommands(tor::tor, dhcp::dhcp, ssl::ssl))] pub fn net() -> Result<(), Error> { Ok(()) } diff --git a/backend/src/net/net_controller.rs b/backend/src/net/net_controller.rs index 32ceaeace..39df25ee9 100644 --- a/backend/src/net/net_controller.rs +++ b/backend/src/net/net_controller.rs @@ -4,16 +4,16 @@ use std::sync::{Arc, Weak}; use color_eyre::eyre::eyre; use models::InterfaceId; -use patch_db::{DbHandle, LockType, PatchDb}; +use patch_db::PatchDb; use sqlx::PgExecutor; use tracing::instrument; +use crate::db::prelude::PatchDbExt; use crate::error::ErrorCollection; use crate::hostname::Hostname; use crate::net::dns::DnsController; use crate::net::forward::LpfController; use crate::net::keys::Key; -#[cfg(feature = "avahi")] use crate::net::mdns::MdnsController; use crate::net::ssl::{export_cert, export_key, SslManager}; use crate::net::tor::TorController; @@ -24,7 +24,6 @@ use crate::{Error, HOST_IP}; pub struct NetController { pub(super) tor: TorController, - #[cfg(feature = "avahi")] pub(super) mdns: MdnsController, pub(super) vhost: VHostController, pub(super) dns: DnsController, @@ -46,7 +45,6 @@ impl NetController { let ssl = Arc::new(ssl); let mut res = Self { tor: TorController::new(tor_control, tor_socks), - #[cfg(feature = "avahi")] mdns: MdnsController::init().await?, vhost: VHostController::new(ssl.clone()), dns: DnsController::init(dns_bind).await?, @@ -161,6 +159,7 @@ impl NetController { let dns = self.dns.add(Some(package.clone()), ip).await?; Ok(NetService { + shutdown: false, id: package, ip, dns, @@ -206,14 +205,12 @@ impl NetController { ) .await?, ); - #[cfg(feature = "avahi")] rcs.push(self.mdns.add(key.base_address()).await?); Ok(rcs) } async fn remove_lan(&self, key: &Key, external: u16, rcs: Vec>) -> Result<(), Error> { drop(rcs); - #[cfg(feature = "avahi")] self.mdns.gc(key.base_address()).await?; self.vhost.gc(Some(key.local_address()), external).await } @@ -229,6 +226,7 @@ impl NetController { } pub struct NetService { + shutdown: bool, id: PackageId, ip: Ipv4Addr, dns: Arc<()>, @@ -310,7 +308,7 @@ impl NetService { .await?, ); self.lan.insert(lan_idx, lan); - Ok(addr) + Ok(()) } pub async fn remove_lan(&mut self, id: InterfaceId, external: u16) -> Result<(), Error> { let ctrl = self.net_controller()?; @@ -321,18 +319,19 @@ impl NetService { } pub async fn add_lpf(&mut self, db: &PatchDb, internal: u16) -> Result { let ctrl = self.net_controller()?; - let mut db = db.handle(); - let lpf_model = crate::db::DatabaseModel::new().lan_port_forwards(); - lpf_model.lock(&mut db, LockType::Write).await?; // TODO: replace all this with an RMW - let mut lpf = lpf_model.get_mut(&mut db).await?; - let external = lpf.alloc(self.id.clone(), internal).ok_or_else(|| { - Error::new( - eyre!("No ephemeral ports available"), - crate::ErrorKind::Network, - ) - })?; - lpf.save(&mut db).await?; - drop(db); + let external = db + .mutate(|db| { + let mut lpf = db.as_lan_port_forwards().de()?; + let external = lpf.alloc(self.id.clone(), internal).ok_or_else(|| { + Error::new( + eyre!("No ephemeral ports available"), + crate::ErrorKind::Network, + ) + })?; + db.as_lan_port_forwards_mut().ser(&lpf)?; + Ok(external) + }) + .await?; let rc = ctrl.add_lpf(external, (self.ip, internal).into()).await?; let (_, mut lpfs) = self.lpf.remove(&internal).unwrap_or_default(); lpfs.push(rc); @@ -375,6 +374,7 @@ impl NetService { Ok(()) } pub async fn remove_all(mut self) -> Result<(), Error> { + self.shutdown = true; let mut errors = ErrorCollection::new(); if let Some(ctrl) = Weak::upgrade(&self.controller) { for ((_, external), (key, rcs)) in std::mem::take(&mut self.lan) { @@ -388,9 +388,9 @@ impl NetService { } std::mem::take(&mut self.dns); errors.handle(ctrl.dns.gc(Some(self.id.clone()), self.ip).await); - self.ip = Ipv4Addr::new(0, 0, 0, 0); errors.into_result() } else { + tracing::warn!("NetService dropped after NetController is shutdown"); Err(Error::new( eyre!("NetController is shutdown"), crate::ErrorKind::Network, @@ -401,11 +401,12 @@ impl NetService { impl Drop for NetService { fn drop(&mut self) { - if self.ip != Ipv4Addr::new(0, 0, 0, 0) { + if !self.shutdown { tracing::debug!("Dropping NetService for {}", self.id); let svc = std::mem::replace( self, NetService { + shutdown: true, id: Default::default(), ip: Ipv4Addr::new(0, 0, 0, 0), dns: Default::default(), diff --git a/backend/src/net/ssl.rs b/backend/src/net/ssl.rs index af785d476..1f9397add 100644 --- a/backend/src/net/ssl.rs +++ b/backend/src/net/ssl.rs @@ -5,6 +5,7 @@ use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; use futures::FutureExt; +use libc::time_t; use openssl::asn1::{Asn1Integer, Asn1Time}; use openssl::bn::{BigNum, MsbOption}; use openssl::ec::{EcGroup, EcKey}; @@ -13,18 +14,27 @@ use openssl::nid::Nid; use openssl::pkey::{PKey, Private}; use openssl::x509::{X509Builder, X509Extension, X509NameBuilder, X509}; use openssl::*; +use rpc_toolkit::command; use tokio::sync::{Mutex, RwLock}; use tracing::instrument; use crate::account::AccountInfo; +use crate::context::RpcContext; use crate::hostname::Hostname; +use crate::init::check_time_is_synchronized; use crate::net::dhcp::ips; use crate::net::keys::{Key, KeyInfo}; -use crate::s9pk::manifest::PackageId; -use crate::{Error, ErrorKind, ResultExt}; +use crate::{Error, ErrorKind, ResultExt, SOURCE_DATE}; static CERTIFICATE_VERSION: i32 = 2; // X509 version 3 is actually encoded as '2' in the cert because fuck you. +fn unix_time(time: SystemTime) -> time_t { + time.duration_since(UNIX_EPOCH) + .map(|d| d.as_secs() as time_t) + .or_else(|_| UNIX_EPOCH.elapsed().map(|d| -(d.as_secs() as time_t))) + .unwrap_or_default() +} + #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct CertPair { pub ed25519: X509, @@ -54,9 +64,13 @@ impl CertPair { }), ); if cert - .not_after() - .compare(Asn1Time::days_from_now(30)?.as_ref())? - == Ordering::Greater + .not_before() + .compare(Asn1Time::days_from_now(0)?.as_ref())? + == Ordering::Less + && cert + .not_after() + .compare(Asn1Time::days_from_now(30)?.as_ref())? + == Ordering::Greater && ips.is_superset(&ip) { return Ok(cert.clone()); @@ -79,6 +93,14 @@ impl CertPair { } } +pub async fn root_ca_start_time() -> Result { + Ok(if check_time_is_synchronized().await? { + SystemTime::now() + } else { + *SOURCE_DATE + }) +} + #[derive(Debug)] pub struct SslManager { hostname: Hostname, @@ -88,9 +110,13 @@ pub struct SslManager { cert_cache: RwLock>, } impl SslManager { - pub fn new(account: &AccountInfo) -> Result { + pub fn new(account: &AccountInfo, start_time: SystemTime) -> Result { let int_key = generate_key()?; - let int_cert = make_int_cert((&account.root_ca_key, &account.root_ca_cert), &int_key)?; + let int_cert = make_int_cert( + (&account.root_ca_key, &account.root_ca_cert), + &int_key, + start_time, + )?; Ok(Self { hostname: account.hostname.clone(), root_cert: account.root_ca_cert.clone(), @@ -159,14 +185,20 @@ pub fn generate_key() -> Result, Error> { } #[instrument(skip_all)] -pub fn make_root_cert(root_key: &PKey, hostname: &Hostname) -> Result { +pub fn make_root_cert( + root_key: &PKey, + hostname: &Hostname, + start_time: SystemTime, +) -> Result { let mut builder = X509Builder::new()?; builder.set_version(CERTIFICATE_VERSION)?; - let embargo = Asn1Time::days_from_now(0)?; + let unix_start_time = unix_time(start_time); + + let embargo = Asn1Time::from_unix(unix_start_time - 86400)?; builder.set_not_before(&embargo)?; - let expiration = Asn1Time::days_from_now(3650)?; + let expiration = Asn1Time::from_unix(unix_start_time + (10 * 364 * 86400))?; builder.set_not_after(&expiration)?; builder.set_serial_number(&*rand_serial()?)?; @@ -213,14 +245,17 @@ pub fn make_root_cert(root_key: &PKey, hostname: &Hostname) -> Result, &X509), applicant: &PKey, + start_time: SystemTime, ) -> Result { let mut builder = X509Builder::new()?; builder.set_version(CERTIFICATE_VERSION)?; - let embargo = Asn1Time::days_from_now(0)?; + let unix_start_time = unix_time(start_time); + + let embargo = Asn1Time::from_unix(unix_start_time - 86400)?; builder.set_not_before(&embargo)?; - let expiration = Asn1Time::days_from_now(3650)?; + let expiration = Asn1Time::from_unix(unix_start_time + (10 * 364 * 86400))?; builder.set_not_after(&expiration)?; builder.set_serial_number(&*rand_serial()?)?; @@ -343,17 +378,10 @@ pub fn make_leaf_cert( let mut builder = X509Builder::new()?; builder.set_version(CERTIFICATE_VERSION)?; - let embargo = Asn1Time::from_unix( - SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|d| d.as_secs() as i64) - .or_else(|_| UNIX_EPOCH.elapsed().map(|d| -(d.as_secs() as i64))) - .unwrap_or_default() - - 86400, - )?; + let embargo = Asn1Time::from_unix(unix_time(SystemTime::now()) - 86400)?; builder.set_not_before(&embargo)?; - // Google Apple and Mozilla reject certificate horizons longer than 397 days + // Google Apple and Mozilla reject certificate horizons longer than 398 days // https://techbeacon.com/security/google-apple-mozilla-enforce-1-year-max-security-certifications let expiration = Asn1Time::days_from_now(397)?; builder.set_not_after(&expiration)?; @@ -415,3 +443,16 @@ pub fn make_leaf_cert( let cert = builder.build(); Ok(cert) } + +#[command(subcommands(size))] +pub async fn ssl() -> Result<(), Error> { + Ok(()) +} + +#[command] +pub async fn size(#[context] ctx: RpcContext) -> Result { + Ok(format!( + "Cert Catch size: {}", + ctx.net_controller.ssl.cert_cache.read().await.len() + )) +} diff --git a/backend/src/net/static_server.rs b/backend/src/net/static_server.rs index d191d7724..a8fe3749e 100644 --- a/backend/src/net/static_server.rs +++ b/backend/src/net/static_server.rs @@ -1,5 +1,5 @@ -use std::borrow::Cow; use std::fs::Metadata; +use std::future::Future; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::UNIX_EPOCH; @@ -10,7 +10,6 @@ use digest::Digest; use futures::FutureExt; use http::header::ACCEPT_ENCODING; use http::request::Parts as RequestParts; -use http::response::Builder; use hyper::{Body, Method, Request, Response, StatusCode}; use include_dir::{include_dir, Dir}; use new_mime_guess::MimeGuess; @@ -264,6 +263,21 @@ async fn alt_ui(req: Request, ui_mode: UiMode) -> Result, E } } +async fn if_authorized< + F: FnOnce() -> Fut, + Fut: Future, Error>> + Send + Sync, +>( + ctx: &RpcContext, + parts: &RequestParts, + f: F, +) -> Result, Error> { + if let Err(e) = HasValidSession::from_request_parts(parts, ctx).await { + un_authorized(e, parts.uri.path()) + } else { + f().await + } +} + async fn main_embassy_ui(req: Request, ctx: RpcContext) -> Result, Error> { let (request_parts, _body) = req.into_parts(); match ( @@ -276,69 +290,56 @@ async fn main_embassy_ui(req: Request, ctx: RpcContext) -> Result { - match HasValidSession::from_request_parts(&request_parts, &ctx).await { - Ok(_) => { - let sub_path = Path::new(path); - if let Ok(rest) = sub_path.strip_prefix("package-data") { - FileData::from_path( - &request_parts, - &ctx.datadir.join(PKG_PUBLIC_DIR).join(rest), - ) - .await? - .into_response(&request_parts) - .await - } else if let Ok(rest) = sub_path.strip_prefix("eos") { - match rest.to_str() { - Some("local.crt") => cert_send(&ctx.account.read().await.root_ca_cert), - None => Ok(bad_request()), - _ => Ok(not_found()), - } - } else { - Ok(not_found()) - } + if_authorized(&ctx, &request_parts, || async { + let sub_path = Path::new(path); + if let Ok(rest) = sub_path.strip_prefix("package-data") { + FileData::from_path( + &request_parts, + &ctx.datadir.join(PKG_PUBLIC_DIR).join(rest), + ) + .await? + .into_response(&request_parts) + .await + } else { + Ok(not_found()) } - Err(e) => un_authorized(e, &format!("public/{path}")), - } + }) + .await } (&Method::GET, Some(("proxy", target))) => { - match HasValidSession::from_request_parts(&request_parts, &ctx).await { - Ok(_) => { - let target = urlencoding::decode(target)?; - let res = ctx - .client - .get(target.as_ref()) - .headers( - request_parts - .headers - .iter() - .filter(|(h, _)| { - !PROXY_STRIP_HEADERS - .iter() - .any(|bad| h.as_str().eq_ignore_ascii_case(bad)) - }) - .map(|(h, v)| (h.clone(), v.clone())) - .collect(), - ) - .send() - .await - .with_kind(crate::ErrorKind::Network)?; - let mut hres = Response::builder().status(res.status()); - for (h, v) in res.headers().clone() { - if let Some(h) = h { - hres = hres.header(h, v); - } + if_authorized(&ctx, &request_parts, || async { + let target = urlencoding::decode(target)?; + let res = ctx + .client + .get(target.as_ref()) + .headers( + request_parts + .headers + .iter() + .filter(|(h, _)| { + !PROXY_STRIP_HEADERS + .iter() + .any(|bad| h.as_str().eq_ignore_ascii_case(bad)) + }) + .map(|(h, v)| (h.clone(), v.clone())) + .collect(), + ) + .send() + .await + .with_kind(crate::ErrorKind::Network)?; + let mut hres = Response::builder().status(res.status()); + for (h, v) in res.headers().clone() { + if let Some(h) = h { + hres = hres.header(h, v); } - hres.body(Body::wrap_stream(res.bytes_stream())) - .with_kind(crate::ErrorKind::Network) } - Err(e) => un_authorized(e, &format!("proxy/{target}")), - } + hres.body(Body::wrap_stream(res.bytes_stream())) + .with_kind(crate::ErrorKind::Network) + }) + .await } (&Method::GET, Some(("eos", "local.crt"))) => { - match HasValidSession::from_request_parts(&request_parts, &ctx).await { - Ok(_) => cert_send(&ctx.account.read().await.root_ca_cert), - Err(e) => un_authorized(e, "eos/local.crt"), - } + cert_send(&ctx.account.read().await.root_ca_cert) } (&Method::GET, _) => { let uri_path = UiMode::Main.path( diff --git a/backend/src/net/tor.rs b/backend/src/net/tor.rs index dcccbfe54..9926d3c6c 100644 --- a/backend/src/net/tor.rs +++ b/backend/src/net/tor.rs @@ -139,7 +139,7 @@ pub async fn logs_nofollow( _ctx: (), (limit, cursor, before, _): (Option, Option, bool, bool), ) -> Result { - fetch_logs(LogSource::Service(SYSTEMD_UNIT), limit, cursor, before).await + fetch_logs(LogSource::Unit(SYSTEMD_UNIT), limit, cursor, before).await } #[command(rpc_only, rename = "follow", display(display_none))] @@ -147,7 +147,7 @@ pub async fn logs_follow( #[context] ctx: RpcContext, #[parent_data] (limit, _, _, _): (Option, Option, bool, bool), ) -> Result { - follow_logs(ctx, LogSource::Service(SYSTEMD_UNIT), limit).await + follow_logs(ctx, LogSource::Unit(SYSTEMD_UNIT), limit).await } fn event_handler(_event: AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>> { @@ -305,7 +305,7 @@ async fn torctl( .invoke(ErrorKind::Tor) .await?; - let logs = journalctl(LogSource::Service(SYSTEMD_UNIT), 0, None, false, true).await?; + let logs = journalctl(LogSource::Unit(SYSTEMD_UNIT), 0, None, false, true).await?; let mut tcp_stream = None; for _ in 0..60 { @@ -617,7 +617,7 @@ async fn torctl( let mut last_success = Instant::now(); loop { tokio::time::sleep(Duration::from_secs(30)).await; - if let Err(e) = tokio::time::timeout( + if tokio::time::timeout( Duration::from_secs(30), tokio_socks::tcp::Socks5Stream::connect( tor_socks, @@ -627,6 +627,7 @@ async fn torctl( .await .map_err(|e| e.to_string()) .and_then(|e| e.map_err(|e| e.to_string())) + .is_err() { if last_success.elapsed() > *health_timeout { let err = Error::new(eyre!("Tor health check failed for longer than current timeout ({health_timeout:?})"), crate::ErrorKind::Tor); diff --git a/backend/src/net/utils.rs b/backend/src/net/utils.rs index 80bfa7ca0..e496bd1f7 100644 --- a/backend/src/net/utils.rs +++ b/backend/src/net/utils.rs @@ -152,7 +152,7 @@ impl hyper::server::accept::Accept for TcpListeners { type Error = std::io::Error; fn poll_accept( - mut self: std::pin::Pin<&mut Self>, + self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> std::task::Poll>> { for listener in self.listeners.iter() { diff --git a/backend/src/net/vhost.rs b/backend/src/net/vhost.rs index e8e754baf..bfbba0572 100644 --- a/backend/src/net/vhost.rs +++ b/backend/src/net/vhost.rs @@ -16,12 +16,13 @@ use tokio::sync::{Mutex, RwLock}; use tokio_rustls::rustls::server::Acceptor; use tokio_rustls::rustls::{RootCertStore, ServerConfig}; use tokio_rustls::{LazyConfigAcceptor, TlsConnector}; +use tracing::instrument; use crate::net::keys::Key; use crate::net::ssl::SslManager; use crate::net::utils::SingleAccept; +use crate::prelude::*; use crate::util::io::{BackTrackingReader, TimeoutStream}; -use crate::Error; // not allowed: <=1024, >=32768, 5355, 5432, 9050, 6010, 9051, 5353 @@ -36,6 +37,7 @@ impl VHostController { servers: Mutex::new(BTreeMap::new()), } } + #[instrument(skip_all)] pub async fn add( &self, key: Key, @@ -63,6 +65,7 @@ impl VHostController { writable.insert(external, server); Ok(rc?) } + #[instrument(skip_all)] pub async fn gc(&self, hostname: Option, external: u16) -> Result<(), Error> { let mut writable = self.servers.lock().await; if let Some(server) = writable.remove(&external) { @@ -93,6 +96,7 @@ struct VHostServer { _thread: NonDetachingJoinHandle<()>, } impl VHostServer { + #[instrument(skip_all)] async fn new(port: u16, ssl: Arc) -> Result { // check if port allowed let listener = TcpListener::bind(SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), port)) @@ -268,7 +272,14 @@ impl VHostServer { .await .with_kind(crate::ErrorKind::OpenSsl)?; let mut tls_stream = - mid.into_stream(Arc::new(cfg)).await?; + match mid.into_stream(Arc::new(cfg)).await { + Ok(a) => a, + Err(e) => { + tracing::trace!( "VHostController: failed to accept TLS connection on port {port}: {e}"); + tracing::trace!("{e:?}"); + return Ok(()) + } + }; tls_stream.get_mut().0.stop_buffering(); tokio::io::copy_bidirectional( &mut tls_stream, @@ -283,7 +294,14 @@ impl VHostServer { cfg.alpn_protocols.push(proto.into()); } let mut tls_stream = - mid.into_stream(Arc::new(cfg)).await?; + match mid.into_stream(Arc::new(cfg)).await { + Ok(a) => a, + Err(e) => { + tracing::trace!( "VHostController: failed to accept TLS connection on port {port}: {e}"); + tracing::trace!("{e:?}"); + return Ok(()) + } + }; tls_stream.get_mut().0.stop_buffering(); tokio::io::copy_bidirectional( &mut tls_stream, @@ -294,7 +312,14 @@ impl VHostServer { Err(AlpnInfo::Specified(alpn)) => { cfg.alpn_protocols = alpn; let mut tls_stream = - mid.into_stream(Arc::new(cfg)).await?; + match mid.into_stream(Arc::new(cfg)).await { + Ok(a) => a, + Err(e) => { + tracing::trace!( "VHostController: failed to accept TLS connection on port {port}: {e}"); + tracing::trace!("{e:?}"); + return Ok(()) + } + }; tls_stream.get_mut().0.stop_buffering(); tokio::io::copy_bidirectional( &mut tls_stream, @@ -304,10 +329,12 @@ impl VHostServer { } } .map_or_else( - |e| match e.kind() { - std::io::ErrorKind::UnexpectedEof => Ok(()), + |e| { + use std::io::ErrorKind as E; + match e.kind() { + E::UnexpectedEof | E::BrokenPipe | E::ConnectionAborted | E::ConnectionReset | E::ConnectionRefused | E::TimedOut | E::Interrupted | E::NotConnected => Ok(()), _ => Err(e), - }, + }}, |_| Ok(()), )?; } else { @@ -323,8 +350,10 @@ impl VHostServer { }); } Err(e) => { - tracing::error!("Error in VHostController on port {port}: {e}"); - tracing::debug!("{e:?}"); + tracing::trace!( + "VHostController: failed to accept connection on port {port}: {e}" + ); + tracing::trace!("{e:?}"); } } } diff --git a/backend/src/net/wifi.rs b/backend/src/net/wifi.rs index 5ed233856..8429f9205 100644 --- a/backend/src/net/wifi.rs +++ b/backend/src/net/wifi.rs @@ -6,7 +6,6 @@ use std::time::Duration; use clap::ArgMatches; use isocountry::CountryCode; use lazy_static::lazy_static; -use patch_db::DbHandle; use regex::Regex; use rpc_toolkit::command; use tokio::process::Command; @@ -14,6 +13,7 @@ use tokio::sync::RwLock; use tracing::instrument; use crate::context::RpcContext; +use crate::prelude::*; use crate::util::serde::{display_serializable, IoFormat}; use crate::util::{display_none, Invoke}; use crate::{Error, ErrorKind}; @@ -52,8 +52,6 @@ pub async fn add( #[context] ctx: RpcContext, #[arg] ssid: String, #[arg] password: String, - #[arg] priority: isize, - #[arg] connect: bool, ) -> Result<(), Error> { let wifi_manager = wifi_manager(&ctx)?; if !ssid.is_ascii() { @@ -69,26 +67,22 @@ pub async fn add( )); } async fn add_procedure( - db: impl DbHandle, + db: PatchDb, wifi_manager: WifiManager, ssid: &Ssid, password: &Psk, - priority: isize, ) -> Result<(), Error> { tracing::info!("Adding new WiFi network: '{}'", ssid.0); let mut wpa_supplicant = wifi_manager.write().await; - wpa_supplicant - .add_network(db, ssid, password, priority) - .await?; + wpa_supplicant.add_network(db, ssid, password).await?; drop(wpa_supplicant); Ok(()) } if let Err(err) = add_procedure( - &mut ctx.db.handle(), + ctx.db.clone(), wifi_manager.clone(), &Ssid(ssid.clone()), &Psk(password.clone()), - priority, ) .await { @@ -113,7 +107,7 @@ pub async fn connect(#[context] ctx: RpcContext, #[arg] ssid: String) -> Result< )); } async fn connect_procedure( - mut db: impl DbHandle, + db: PatchDb, wifi_manager: WifiManager, ssid: &Ssid, ) -> Result<(), Error> { @@ -121,7 +115,7 @@ pub async fn connect(#[context] ctx: RpcContext, #[arg] ssid: String) -> Result< let current = wpa_supplicant.get_current_network().await?; drop(wpa_supplicant); let mut wpa_supplicant = wifi_manager.write().await; - let connected = wpa_supplicant.select_network(&mut db, ssid).await?; + let connected = wpa_supplicant.select_network(db.clone(), ssid).await?; if connected { tracing::info!("Successfully connected to WiFi: '{}'", ssid.0); } else { @@ -131,19 +125,15 @@ pub async fn connect(#[context] ctx: RpcContext, #[arg] ssid: String) -> Result< tracing::info!("No WiFi to revert to!"); } Some(current) => { - wpa_supplicant.select_network(&mut db, ¤t).await?; + wpa_supplicant.select_network(db, ¤t).await?; } } } Ok(()) } - if let Err(err) = connect_procedure( - &mut ctx.db.handle(), - wifi_manager.clone(), - &Ssid(ssid.clone()), - ) - .await + if let Err(err) = + connect_procedure(ctx.db.clone(), wifi_manager.clone(), &Ssid(ssid.clone())).await { tracing::error!("Failed to connect to WiFi network '{}': {}", &ssid, err); return Err(Error::new( @@ -176,9 +166,7 @@ pub async fn delete(#[context] ctx: RpcContext, #[arg] ssid: String) -> Result<( return Err(Error::new(color_eyre::eyre::eyre!("Forbidden: Deleting this network would make your server unreachable. Either connect to ethernet or connect to a different WiFi network to remedy this."), ErrorKind::Wifi)); } - wpa_supplicant - .remove_network(&mut ctx.db.handle(), &ssid) - .await?; + wpa_supplicant.remove_network(ctx.db.clone(), &ssid).await?; Ok(()) } #[derive(serde::Serialize, serde::Deserialize)] @@ -186,7 +174,7 @@ pub async fn delete(#[context] ctx: RpcContext, #[arg] ssid: String) -> Result<( pub struct WiFiInfo { ssids: HashMap, connected: Option, - country: CountryCode, + country: Option, ethernet: bool, available_wifi: Vec, } @@ -228,7 +216,7 @@ fn display_wifi_info(info: WiFiInfo, matches: &ArgMatches) { .as_ref() .and_then(|x| info.ssids.get(x)) .map_or("[N/A]".to_owned(), |ss| format!("{}", ss.0)), - &info.country.alpha2(), + info.country.as_ref().map(|c| c.alpha2()).unwrap_or("00"), &format!("{}", info.ethernet) ]); table_global.print_tty(false).unwrap(); @@ -397,7 +385,7 @@ pub async fn set_country( } wpa_supplicant.remove_all_connections().await?; - wpa_supplicant.save_config(&mut ctx.db.handle()).await?; + wpa_supplicant.save_config(ctx.db.clone()).await?; Ok(()) } @@ -529,7 +517,7 @@ impl WpaCli { Ok(()) } - pub async fn get_country_low(&self) -> Result { + pub async fn get_country_low(&self) -> Result, Error> { let r = Command::new("iw") .arg("reg") .arg("get") @@ -551,12 +539,16 @@ impl WpaCli { ErrorKind::Wifi, ) })?[1]; - Ok(CountryCode::for_alpha2(country).map_err(|_| { - Error::new( - color_eyre::eyre::eyre!("Invalid Country Code: {}", country), - ErrorKind::Wifi, - ) - })?) + if country == "00" { + Ok(None) + } else { + Ok(Some(CountryCode::for_alpha2(country).map_err(|_| { + Error::new( + color_eyre::eyre::eyre!("Invalid Country Code: {}", country), + ErrorKind::Wifi, + ) + })?)) + } } pub async fn remove_network_low(&mut self, id: NetworkId) -> Result<(), Error> { let _ = Command::new("nmcli") @@ -645,13 +637,14 @@ impl WpaCli { Ok(()) } - pub async fn save_config(&mut self, mut db: impl DbHandle) -> Result<(), Error> { - crate::db::DatabaseModel::new() - .server_info() - .last_wifi_region() - .put(&mut db, &Some(self.get_country_low().await?)) - .await?; - Ok(()) + pub async fn save_config(&mut self, db: PatchDb) -> Result<(), Error> { + let new_country = self.get_country_low().await?; + db.mutate(|d| { + d.as_server_info_mut() + .as_last_wifi_region_mut() + .ser(&new_country) + }) + .await } async fn check_active_network(&self, ssid: &Ssid) -> Result, Error> { Ok(self @@ -682,7 +675,7 @@ impl WpaCli { .collect()) } #[instrument(skip_all)] - pub async fn select_network(&mut self, db: impl DbHandle, ssid: &Ssid) -> Result { + pub async fn select_network(&mut self, db: PatchDb, ssid: &Ssid) -> Result { let m_id = self.check_active_network(ssid).await?; match m_id { None => Err(Error::new( @@ -734,7 +727,7 @@ impl WpaCli { } } #[instrument(skip_all)] - pub async fn remove_network(&mut self, db: impl DbHandle, ssid: &Ssid) -> Result { + pub async fn remove_network(&mut self, db: PatchDb, ssid: &Ssid) -> Result { let found_networks = self.find_networks(ssid).await?; if found_networks.is_empty() { return Ok(true); @@ -748,23 +741,16 @@ impl WpaCli { #[instrument(skip_all)] pub async fn set_add_network( &mut self, - db: impl DbHandle, + db: PatchDb, ssid: &Ssid, psk: &Psk, - priority: isize, ) -> Result<(), Error> { self.set_add_network_low(ssid, psk).await?; self.save_config(db).await?; Ok(()) } #[instrument(skip_all)] - pub async fn add_network( - &mut self, - db: impl DbHandle, - ssid: &Ssid, - psk: &Psk, - priority: isize, - ) -> Result<(), Error> { + pub async fn add_network(&mut self, db: PatchDb, ssid: &Ssid, psk: &Psk) -> Result<(), Error> { self.add_network_low(ssid, psk).await?; self.save_config(db).await?; Ok(()) diff --git a/backend/src/notifications.rs b/backend/src/notifications.rs index 962927e90..73351471c 100644 --- a/backend/src/notifications.rs +++ b/backend/src/notifications.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use chrono::{DateTime, Utc}; use color_eyre::eyre::eyre; -use patch_db::{DbHandle, LockType}; use rpc_toolkit::command; use sqlx::PgPool; use tokio::sync::Mutex; @@ -12,6 +11,7 @@ use tracing::instrument; use crate::backup::BackupReport; use crate::context::RpcContext; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; use crate::util::display_none; use crate::util::serde::display_serializable; @@ -30,13 +30,8 @@ pub async fn list( #[arg] limit: Option, ) -> Result, Error> { let limit = limit.unwrap_or(40); - let mut handle = ctx.db.handle(); match before { None => { - let model = crate::db::DatabaseModel::new() - .server_info() - .unread_notification_count(); - model.lock(&mut handle, LockType::Write).await?; let records = sqlx::query!( "SELECT id, package_id, created_at, code, level, title, message, data FROM notifications ORDER BY id DESC LIMIT $1", limit as i64 @@ -70,8 +65,14 @@ pub async fn list( }) }) .collect::, Error>>()?; - // set notification count to zero - model.put(&mut handle, &0).await?; + + ctx.db + .mutate(|d| { + d.as_server_info_mut() + .as_unread_notification_count_mut() + .ser(&0) + }) + .await?; Ok(notifs) } Some(before) => { @@ -139,15 +140,7 @@ pub async fn create( #[arg] message: String, ) -> Result<(), Error> { ctx.notification_manager - .notify( - &mut ctx.db.handle(), - package, - level, - title, - message, - (), - None, - ) + .notify(ctx.db.clone(), package, level, title, message, (), None) .await } @@ -232,10 +225,10 @@ impl NotificationManager { cache: Mutex::new(HashMap::new()), } } - #[instrument(skip_all)] - pub async fn notify( + #[instrument(skip(db, subtype, self))] + pub async fn notify( &self, - db: &mut Db, + db: PatchDb, package_id: Option, level: NotificationLevel, title: String, @@ -243,17 +236,14 @@ impl NotificationManager { subtype: T, debounce_interval: Option, ) -> Result<(), Error> { + let peek = db.peek().await; if !self .should_notify(&package_id, &level, &title, debounce_interval) .await { return Ok(()); } - let mut count = crate::db::DatabaseModel::new() - .server_info() - .unread_notification_count() - .get_mut(db) - .await?; + let mut count = peek.as_server_info().as_unread_notification_count().de()?; let sql_package_id = package_id.as_ref().map(|p| &**p); let sql_code = T::CODE; let sql_level = format!("{}", level); @@ -268,9 +258,13 @@ impl NotificationManager { message, sql_data ).execute(&self.sqlite).await?; - *count += 1; - count.save(db).await?; - Ok(()) + count += 1; + db.mutate(|db| { + db.as_server_info_mut() + .as_unread_notification_count_mut() + .ser(&count) + }) + .await } async fn should_notify( &self, diff --git a/backend/src/os_install/mod.rs b/backend/src/os_install/mod.rs index 19f320f06..9e21e9f23 100644 --- a/backend/src/os_install/mod.rs +++ b/backend/src/os_install/mod.rs @@ -272,7 +272,7 @@ pub async fn execute( .invoke(crate::ErrorKind::OpenSsh) .await?; - let dev = MountGuard::mount( + let embassy_fs = MountGuard::mount( &Bind::new(rootfs.as_ref()), current.join("media/embassy/embassyfs"), MountType::ReadOnly, @@ -315,19 +315,18 @@ pub async fn execute( .arg("update-grub2") .invoke(crate::ErrorKind::Grub) .await?; - dev.unmount(false).await?; if let Some(efivarfs) = efivarfs { efivarfs.unmount(false).await?; } sys.unmount(false).await?; proc.unmount(false).await?; + embassy_fs.unmount(false).await?; if let Some(efi) = efi { efi.unmount(false).await?; } boot.unmount(false).await?; rootfs.unmount().await?; - Ok(()) } diff --git a/backend/src/prelude.rs b/backend/src/prelude.rs new file mode 100644 index 000000000..ab5de1d38 --- /dev/null +++ b/backend/src/prelude.rs @@ -0,0 +1,6 @@ +pub use color_eyre::eyre::eyre; +pub use models::OptionExt; + +pub use crate::db::prelude::*; +pub use crate::ensure_code; +pub use crate::error::{Error, ErrorCollection, ErrorKind, ResultExt}; diff --git a/backend/src/procedure/docker.rs b/backend/src/procedure/docker.rs index 59fe84399..57207d5c9 100644 --- a/backend/src/procedure/docker.rs +++ b/backend/src/procedure/docker.rs @@ -6,15 +6,11 @@ use std::os::unix::prelude::FileTypeExt; use std::path::{Path, PathBuf}; use std::time::Duration; -use async_stream::stream; -use bollard::container::RemoveContainerOptions; -use chrono::format::Item; use color_eyre::eyre::eyre; -use color_eyre::Report; use futures::future::{BoxFuture, Either as EitherFuture}; use futures::{FutureExt, TryStreamExt}; use helpers::{NonDetachingJoinHandle, UnixRpcClient}; -use models::{Id, ImageId}; +use models::{Id, ImageId, SYSTEM_PACKAGE_ID}; use nix::sys::signal; use nix::unistd::Pid; use serde::de::DeserializeOwned; @@ -26,7 +22,9 @@ use tracing::instrument; use super::ProcedureName; use crate::context::RpcContext; -use crate::s9pk::manifest::{PackageId, SYSTEM_PACKAGE_ID}; +use crate::prelude::*; +use crate::s9pk::manifest::PackageId; +use crate::util::docker::{remove_container, CONTAINER_TOOL}; use crate::util::serde::{Duration as SerdeDuration, IoFormat}; use crate::util::Version; use crate::volume::{VolumeId, Volumes}; @@ -45,8 +43,9 @@ lazy_static::lazy_static! { }; } -#[derive(Clone, Debug, Deserialize, Serialize, patch_db::HasModel)] +#[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct DockerContainers { pub main: DockerContainer, // #[serde(default)] @@ -58,6 +57,7 @@ pub struct DockerContainers { /// part of this struct by choice. Used for the times that we are creating our own entry points #[derive(Clone, Debug, Deserialize, Serialize, patch_db::HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct DockerContainer { pub image: ImageId, #[serde(default)] @@ -199,7 +199,7 @@ impl DockerProcedure { image_ids: &BTreeSet, expected_io: bool, ) -> Result<(), color_eyre::eyre::Report> { - for (volume, _) in &self.mounts { + for volume in self.mounts.keys() { if !volumes.contains_key(volume) && !matches!(&volume, &VolumeId::Backup) { color_eyre::eyre::bail!("unknown volume: {}", volume); } @@ -229,8 +229,8 @@ impl DockerProcedure { timeout: Option, ) -> Result, Error> { let name = name.docker_name(); - let name: Option<&str> = name.as_ref().map(|x| &**x); - let mut cmd = tokio::process::Command::new("docker"); + let name: Option<&str> = name.as_deref(); + let mut cmd = tokio::process::Command::new(CONTAINER_TOOL); let container_name = Self::container_name(pkg_id, name); cmd.arg("run") .arg("--rm") @@ -241,25 +241,7 @@ impl DockerProcedure { .arg(format!("--hostname={}", &container_name)) .arg("--no-healthcheck") .kill_on_drop(true); - match ctx - .docker - .remove_container( - &container_name, - Some(RemoveContainerOptions { - v: false, - force: true, - link: false, - }), - ) - .await - { - Ok(()) - | Err(bollard::errors::Error::DockerResponseServerError { - status_code: 404, // NOT FOUND - .. - }) => Ok(()), - Err(e) => Err(e), - }?; + remove_container(&container_name, true).await?; cmd.args(self.docker_args(ctx, pkg_id, pkg_version, volumes).await?); let input_buf = if let (Some(input), Some(format)) = (&input, &self.io_format) { cmd.stdin(std::process::Stdio::piped()); @@ -402,19 +384,17 @@ impl DockerProcedure { &self, _ctx: &RpcContext, pkg_id: &PackageId, - pkg_version: &Version, - name: ProcedureName, - volumes: &Volumes, + _pkg_version: &Version, + _name: ProcedureName, + _volumes: &Volumes, input: Option, timeout: Option, ) -> Result, Error> { - let name = name.docker_name(); - let name: Option<&str> = name.as_deref(); - let mut cmd = tokio::process::Command::new("docker"); + let mut cmd = tokio::process::Command::new(CONTAINER_TOOL); cmd.arg("exec"); - cmd.args(self.docker_args_inject(pkg_id).await?); + cmd.args(self.docker_args_inject(pkg_id)); let input_buf = if let (Some(input), Some(format)) = (&input, &self.io_format) { cmd.stdin(std::process::Stdio::piped()); Some(format.to_vec(input)?) @@ -561,7 +541,7 @@ impl DockerProcedure { input: Option, timeout: Option, ) -> Result, Error> { - let mut cmd = tokio::process::Command::new("docker"); + let mut cmd = tokio::process::Command::new(CONTAINER_TOOL); cmd.arg("run").arg("--rm").arg("--network=none"); cmd.args( self.docker_args(ctx, pkg_id, pkg_version, &volumes.to_readonly()) @@ -642,7 +622,18 @@ impl DockerProcedure { } })); - let exit_status = handle.wait().await.with_kind(crate::ErrorKind::Docker)?; + let handle = if let Some(dur) = timeout { + async move { + tokio::time::timeout(dur, handle.wait()) + .await + .with_kind(crate::ErrorKind::Docker)? + .with_kind(crate::ErrorKind::Docker) + } + .boxed() + } else { + async { handle.wait().await.with_kind(crate::ErrorKind::Docker) }.boxed() + }; + let exit_status = handle.await?; Ok( if exit_status.success() || exit_status.code() == Some(143) { Ok(serde_json::from_value( @@ -726,7 +717,7 @@ impl DockerProcedure { if fty.is_block_device() || fty.is_char_device() { res.push(entry.path()); } else if fty.is_dir() { - get_devices(&*entry.path(), res).await?; + get_devices(&entry.path(), res).await?; } } Ok(()) @@ -745,7 +736,7 @@ impl DockerProcedure { res.push(OsStr::new("--entrypoint").into()); res.push(OsStr::new(&self.entrypoint).into()); if self.system { - res.push(OsString::from(self.image.for_package(&*SYSTEM_PACKAGE_ID, None)).into()); + res.push(OsString::from(self.image.for_package(&SYSTEM_PACKAGE_ID, None)).into()); } else { res.push(OsString::from(self.image.for_package(pkg_id, Some(pkg_version))).into()); } @@ -763,7 +754,7 @@ impl DockerProcedure { + self.args.len(), // [ARG...] ) } - async fn docker_args_inject(&self, pkg_id: &PackageId) -> Result>, Error> { + fn docker_args_inject(&self, pkg_id: &PackageId) -> Vec> { let mut res = self.new_docker_args(); if let Some(shm_size_mb) = self.shm_size_mb { res.push(OsStr::new("--shm-size").into()); @@ -776,7 +767,7 @@ impl DockerProcedure { res.extend(self.args.iter().map(|s| OsStr::new(s).into())); - Ok(res) + res } } @@ -820,20 +811,20 @@ impl LongRunning { socket_path: &Path, ) -> Result { const INIT_EXEC: &str = "/start9/bin/embassy_container_init"; - const BIND_LOCATION: &str = "/usr/lib/embassy/container/"; + const BIND_LOCATION: &str = "/usr/lib/startos/container/"; tracing::trace!("setup_long_running_docker_cmd"); - LongRunning::cleanup_previous_container(ctx, container_name).await?; + remove_container(container_name, true).await?; let image_architecture = { - let mut cmd = tokio::process::Command::new("docker"); + let mut cmd = tokio::process::Command::new(CONTAINER_TOOL); cmd.arg("image") .arg("inspect") .arg("--format") .arg("'{{.Architecture}}'"); if docker.system { - cmd.arg(docker.image.for_package(&*SYSTEM_PACKAGE_ID, None)); + cmd.arg(docker.image.for_package(&SYSTEM_PACKAGE_ID, None)); } else { cmd.arg(docker.image.for_package(pkg_id, Some(pkg_version))); } @@ -841,7 +832,7 @@ impl LongRunning { arch.replace('\'', "").trim().to_string() }; - let mut cmd = tokio::process::Command::new("docker"); + let mut cmd = tokio::process::Command::new(CONTAINER_TOOL); cmd.arg("run") .arg("--network=start9") .arg(format!("--add-host=embassy:{}", Ipv4Addr::from(HOST_IP))) @@ -855,7 +846,7 @@ impl LongRunning { input = socket_path.display() )) .arg("--name") - .arg(&container_name) + .arg(container_name) .arg(format!("--hostname={}", &container_name)) .arg("--entrypoint") .arg(format!("{INIT_EXEC}.{image_architecture}")) @@ -885,7 +876,7 @@ impl LongRunning { } cmd.arg("--log-driver=journald"); if docker.system { - cmd.arg(docker.image.for_package(&*SYSTEM_PACKAGE_ID, None)); + cmd.arg(docker.image.for_package(&SYSTEM_PACKAGE_ID, None)); } else { cmd.arg(docker.image.for_package(pkg_id, Some(pkg_version))); } @@ -894,53 +885,17 @@ impl LongRunning { cmd.stdin(std::process::Stdio::piped()); Ok(cmd) } - - async fn cleanup_previous_container( - ctx: &RpcContext, - container_name: &str, - ) -> Result<(), Error> { - match ctx - .docker - .remove_container( - container_name, - Some(RemoveContainerOptions { - v: false, - force: true, - link: false, - }), - ) - .await - { - Ok(()) - | Err(bollard::errors::Error::DockerResponseServerError { - status_code: 404, // NOT FOUND - .. - }) => Ok(()), - Err(e) => Err(e)?, - } - } } async fn buf_reader_to_lines( reader: impl AsyncBufRead + Unpin, limit: impl Into>, ) -> Result, Error> { - let lines = stream! { - let mut lines = reader.lines(); - while let Some(line) = lines.next_line().await? { - yield Ok::<_, Report>(line); - } - }; - let output: RingVec = lines - .try_fold( - RingVec::new(limit.into().unwrap_or(1000)), - |mut acc, line| async move { - acc.push(line); - Ok(acc) - }, - ) - .await - .with_kind(crate::ErrorKind::Unknown)?; - let output: Vec = output.value.into_iter().collect(); + let mut lines = reader.lines(); + let mut answer = RingVec::new(limit.into().unwrap_or(1000)); + while let Some(line) = lines.next_line().await? { + answer.push(line); + } + let output: Vec = answer.value.into_iter().collect(); Ok(output) } @@ -1005,4 +960,11 @@ mod tests { assert_eq!(CAPACITY_IN, ring.value.capacity()); assert_eq!(CAPACITY_IN, ring.value.len()); } + + #[test] + fn tests_buf_reader_to_lines() { + let mut reader = BufReader::new("hello\nworld\n".as_bytes()); + let lines = futures::executor::block_on(buf_reader_to_lines(&mut reader, None)).unwrap(); + assert_eq!(lines, vec!["hello", "world"]); + } } diff --git a/backend/src/procedure/js_scripts.rs b/backend/src/procedure/js_scripts.rs index 4c49e7f74..d7e5ae97f 100644 --- a/backend/src/procedure/js_scripts.rs +++ b/backend/src/procedure/js_scripts.rs @@ -2,23 +2,22 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::Duration; -use color_eyre::eyre::eyre; -use color_eyre::Report; -use embassy_container_init::{ProcessGroupId, SignalGroup, SignalGroupParams}; -use helpers::{Address, AddressSchemaLocal, AddressSchemaOnion, Callback, OsApi, UnixRpcClient}; +use embassy_container_init::ProcessGroupId; +use helpers::UnixRpcClient; pub use js_engine::JsError; use js_engine::{JsExecutionEnvironment, PathForVolumeId}; -use models::{ErrorKind, InterfaceId, VolumeId}; +use models::VolumeId; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; +use tokio::process::Command; use tracing::instrument; use super::ProcedureName; -use crate::context::RpcContext; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; -use crate::util::{GeneralGuard, Version}; +use crate::util::serde::IoFormat; +use crate::util::{Invoke, Version}; use crate::volume::Volumes; -use crate::Error; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "kebab-case")] @@ -46,56 +45,15 @@ impl PathForVolumeId for Volumes { } } -struct SandboxOsApi { - _ctx: RpcContext, -} -#[async_trait::async_trait] -impl OsApi for SandboxOsApi { - #[allow(unused_variables)] - async fn get_service_config( - &self, - id: PackageId, - path: &str, - callback: Option, - ) -> Result, Report> { - Err(eyre!("Operation not permitted")) - } - #[allow(unused_variables)] - async fn bind_local( - &self, - internal_port: u16, - address_schema: AddressSchemaLocal, - ) -> Result { - Err(eyre!("Operation not permitted")) - } - #[allow(unused_variables)] - async fn bind_onion( - &self, - internal_port: u16, - address_schema: AddressSchemaOnion, - ) -> Result { - Err(eyre!("Operation not permitted")) - } - #[allow(unused_variables)] - async fn unbind_local(&self, id: InterfaceId, external: u16) -> Result<(), Report> { - Err(eyre!("Operation not permitted")) - } - #[allow(unused_variables)] - async fn unbind_onion(&self, id: InterfaceId, external: u16) -> Result<(), Report> { - Err(eyre!("Operation not permitted")) - } - fn set_started(&self) -> Result<(), Report> { - Err(eyre!("Operation not permitted")) - } - async fn restart(&self) -> Result<(), Report> { - Err(eyre!("Operation not permitted")) - } - async fn start(&self) -> Result<(), Report> { - Err(eyre!("Operation not permitted")) - } - async fn stop(&self) -> Result<(), Report> { - Err(eyre!("Operation not permitted")) - } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ExecuteArgs { + pub procedure: JsProcedure, + pub directory: PathBuf, + pub pkg_id: PackageId, + pub pkg_version: Version, + pub name: ProcedureName, + pub volumes: Volumes, + pub input: Option, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] @@ -120,56 +78,32 @@ impl JsProcedure { volumes: &Volumes, input: Option, timeout: Option, - gid: ProcessGroupId, - rpc_client: Option>, - os: Arc, + _gid: ProcessGroupId, + _rpc_client: Option>, ) -> Result, Error> { - let cleaner_client = rpc_client.clone(); - let cleaner = GeneralGuard::new(move || { - tokio::spawn(async move { - if let Some(client) = cleaner_client { - client - .request(SignalGroup, SignalGroupParams { gid, signal: 9 }) - .await - .map_err(|e| { - Error::new(eyre!("{}: {:?}", e.message, e.data), ErrorKind::Docker) - }) - } else { - Ok(()) - } - }) - }); - let res = async move { - let running_action = JsExecutionEnvironment::load_from_package( - os, - directory, - pkg_id, - pkg_version, - Box::new(volumes.clone()), - gid, - rpc_client, - ) - .await? - .run_action(name, input, self.args.clone()); - let output: Option = match timeout { - Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action) - .await - .map_err(|_| (JsError::Timeout, "Timed out. Retrying soon...".to_owned()))??, - None => running_action.await?, - }; - let output: O = unwrap_known_error(output)?; - Ok(output) - } - .await - .map_err(|(error, message)| (error.as_code_num(), message)); - cleaner.drop().await.unwrap()?; - Ok(res) + Command::new("start-deno") + .arg("execute") + .input(Some(&mut std::io::Cursor::new(IoFormat::Json.to_vec( + &ExecuteArgs { + procedure: self.clone(), + directory: directory.clone(), + pkg_id: pkg_id.clone(), + pkg_version: pkg_version.clone(), + name, + volumes: volumes.clone(), + input: input.and_then(|x| serde_json::to_value(x).ok()), + }, + )?))) + .timeout(timeout) + .invoke(ErrorKind::Javascript) + .await + .and_then(|res| IoFormat::Json.from_slice(&res)) } #[instrument(skip_all)] pub async fn sandboxed( &self, - ctx: &RpcContext, + directory: &PathBuf, pkg_id: &PackageId, pkg_version: &Version, volumes: &Volumes, @@ -177,25 +111,75 @@ impl JsProcedure { timeout: Option, name: ProcedureName, ) -> Result, Error> { - Ok(async move { + Command::new("start-deno") + .arg("sandbox") + .input(Some(&mut std::io::Cursor::new(IoFormat::Json.to_vec( + &ExecuteArgs { + procedure: self.clone(), + directory: directory.clone(), + pkg_id: pkg_id.clone(), + pkg_version: pkg_version.clone(), + name, + volumes: volumes.clone(), + input: input.and_then(|x| serde_json::to_value(x).ok()), + }, + )?))) + .timeout(timeout) + .invoke(ErrorKind::Javascript) + .await + .and_then(|res| IoFormat::Json.from_slice(&res)) + } + + #[instrument(skip_all)] + pub async fn execute_impl( + &self, + directory: &PathBuf, + pkg_id: &PackageId, + pkg_version: &Version, + name: ProcedureName, + volumes: &Volumes, + input: Option, + ) -> Result, Error> { + let res = async move { let running_action = JsExecutionEnvironment::load_from_package( - Arc::new(SandboxOsApi { _ctx: ctx.clone() }), - &ctx.datadir, + directory, + pkg_id, + pkg_version, + Box::new(volumes.clone()), + ) + .await? + .run_action(name, input, self.args.clone()); + let output: Option = running_action.await?; + let output: O = unwrap_known_error(output)?; + Ok(output) + } + .await + .map_err(|(error, message)| (error.as_code_num(), message)); + + Ok(res) + } + + #[instrument(skip_all)] + pub async fn sandboxed_impl( + &self, + directory: &PathBuf, + pkg_id: &PackageId, + pkg_version: &Version, + volumes: &Volumes, + input: Option, + name: ProcedureName, + ) -> Result, Error> { + Ok(async move { + let running_action = JsExecutionEnvironment::load_from_package( + directory, pkg_id, pkg_version, Box::new(volumes.clone()), - ProcessGroupId(0), - None, ) .await? .read_only_effects() .run_action(name, input, self.args.clone()); - let output: Option = match timeout { - Some(timeout_duration) => tokio::time::timeout(timeout_duration, running_action) - .await - .map_err(|_| (JsError::Timeout, "Timed out. Retrying soon...".to_owned()))??, - None => running_action.await?, - }; + let output: Option = running_action.await?; let output: O = unwrap_known_error(output)?; Ok(output) } @@ -873,134 +857,40 @@ mod tests { } })) .unwrap(); - let input: Option = None; - let timeout = Some(Duration::from_secs(10)); - js_action - .execute::( - &path, - &package_id, - &package_version, - name, - &volumes, - input, - timeout, - ProcessGroupId(0), - None, - Arc::new(OsApiMock::default()), - ) - .await - .unwrap() - .unwrap(); - } - #[tokio::test] - async fn test_callback() { - let api = Arc::new(OsApiMock::default()); - let action_api = api.clone(); - let spawned = tokio::spawn(async move { - let mut watching = api.config_callbacks.subscribe(); - loop { - if watching.borrow().is_empty() { - watching.changed().await.unwrap(); - continue; - } - api.config_callbacks.send_modify(|x| { - x[0].call(vec![json!("This is something across the wire!")]) - .map_err(|e| format!("Failed call")) - .unwrap(); - }); - break; - } - }); - let js_action = JsProcedure { args: vec![] }; - let path: PathBuf = "test/js_action_execute/" - .parse::() - .unwrap() - .canonicalize() - .unwrap(); - let package_id = "test-package".parse().unwrap(); - let package_version: Version = "0.3.0.3".parse().unwrap(); - let name = ProcedureName::Action("test-callback".parse().unwrap()); - let volumes: Volumes = serde_json::from_value(json!({ - "main": { - "type": "data" - }, - "compat": { - "type": "assets" - }, - "filebrowser" :{ - "package-id": "filebrowser", - "path": "data", - "readonly": true, - "type": "pointer", - "volume-id": "main", - } - })) + let package_id = "test-package".parse().unwrap(); + let package_version: Version = "0.3.0.3".parse().unwrap(); + let name = ProcedureName::Action("test-disk-usage".parse().unwrap()); + let volumes: Volumes = serde_json::from_value(serde_json::json!({ + "main": { + "type": "data" + }, + "compat": { + "type": "assets" + }, + "filebrowser" :{ + "package-id": "filebrowser", + "path": "data", + "readonly": true, + "type": "pointer", + "volume-id": "main", + } + })) + .unwrap(); + let input: Option = None; + let timeout = Some(Duration::from_secs(10)); + js_action + .execute::( + &path, + &package_id, + &package_version, + name, + &volumes, + input, + timeout, + ProcessGroupId(0), + None, + ) + .await + .unwrap() .unwrap(); - let input: Option = None; - let timeout = Some(Duration::from_secs(10)); - js_action - .execute::( - &path, - &package_id, - &package_version, - name, - &volumes, - input, - timeout, - ProcessGroupId(0), - None, - action_api, - ) - .await - .unwrap() - .unwrap(); - spawned.await.unwrap(); - } - - #[tokio::test] - async fn js_disk_usage() { - let js_action = JsProcedure { args: vec![] }; - let path: PathBuf = "test/js_action_execute/" - .parse::() - .unwrap() - .canonicalize() - .unwrap(); - let package_id = "test-package".parse().unwrap(); - let package_version: Version = "0.3.0.3".parse().unwrap(); - let name = ProcedureName::Action("test-disk-usage".parse().unwrap()); - let volumes: Volumes = serde_json::from_value(serde_json::json!({ - "main": { - "type": "data" - }, - "compat": { - "type": "assets" - }, - "filebrowser" :{ - "package-id": "filebrowser", - "path": "data", - "readonly": true, - "type": "pointer", - "volume-id": "main", - } - })) - .unwrap(); - let input: Option = None; - let timeout = Some(Duration::from_secs(10)); - dbg!(js_action - .execute::( - &path, - &package_id, - &package_version, - name, - &volumes, - input, - timeout, - ProcessGroupId(0), - None, - Arc::new(OsApiMock::default()), - ) - .await - .unwrap() - .unwrap()); - } } diff --git a/backend/src/procedure/mod.rs b/backend/src/procedure/mod.rs index 72d56ffa1..5af047e71 100644 --- a/backend/src/procedure/mod.rs +++ b/backend/src/procedure/mod.rs @@ -8,8 +8,9 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use tracing::instrument; -use self::docker::{DockerContainers, DockerProcedure}; +use self::docker::DockerProcedure; use crate::context::RpcContext; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; use crate::util::Version; use crate::volume::Volumes; @@ -20,11 +21,10 @@ pub mod docker; pub mod js_scripts; pub use models::ProcedureName; -// TODO: create RPC endpoint that looks up the appropriate action and calls `execute` - #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] #[serde(tag = "type")] +#[model = "Model"] pub enum PackageProcedure { Docker(DockerProcedure), @@ -43,7 +43,6 @@ impl PackageProcedure { #[instrument(skip_all)] pub fn validate( &self, - container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, @@ -121,7 +120,6 @@ impl PackageProcedure { #[instrument(skip_all)] pub async fn sandboxed( &self, - container: &Option, ctx: &RpcContext, pkg_id: &PackageId, pkg_version: &Version, @@ -140,7 +138,15 @@ impl PackageProcedure { #[cfg(feature = "js_engine")] PackageProcedure::Script(procedure) => { procedure - .sandboxed(ctx, pkg_id, pkg_version, volumes, input, timeout, name) + .sandboxed( + &ctx.datadir, + pkg_id, + pkg_version, + volumes, + input, + timeout, + name, + ) .await } } @@ -158,13 +164,21 @@ impl std::fmt::Display for PackageProcedure { } } +// TODO: make this not allocate #[derive(Debug)] pub struct NoOutput; impl<'de> Deserialize<'de> for NoOutput { - fn deserialize(_: D) -> Result + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { + let _ = Value::deserialize(deserializer); Ok(NoOutput) } } + +#[test] +fn test_deser_no_output() { + serde_json::from_str::("").unwrap(); + serde_json::from_str::>("{\"Ok\": null}").unwrap(); +} diff --git a/backend/src/properties.rs b/backend/src/properties.rs index 22e57aa2d..851033b71 100644 --- a/backend/src/properties.rs +++ b/backend/src/properties.rs @@ -5,8 +5,9 @@ use serde_json::Value; use tracing::instrument; use crate::context::RpcContext; +use crate::prelude::*; use crate::procedure::ProcedureName; -use crate::s9pk::manifest::{Manifest, PackageId}; +use crate::s9pk::manifest::PackageId; use crate::{Error, ErrorKind}; pub fn display_properties(response: Value, _: &ArgMatches) { @@ -20,17 +21,15 @@ pub async fn properties(#[context] ctx: RpcContext, #[arg] id: PackageId) -> Res #[instrument(skip_all)] pub async fn fetch_properties(ctx: RpcContext, id: PackageId) -> Result { - let mut db = ctx.db.handle(); + let peek = ctx.db.peek().await; - let manifest: Manifest = crate::db::DatabaseModel::new() - .package_data() - .idx_model(&id) - .and_then(|p| p.installed()) - .map(|m| m.manifest()) - .get(&mut db) - .await? - .to_owned() - .ok_or_else(|| Error::new(eyre!("{} is not installed", id), ErrorKind::NotFound))?; + let manifest = peek + .as_package_data() + .as_idx(&id) + .ok_or_else(|| Error::new(eyre!("{} is not installed", id), ErrorKind::NotFound))? + .expect_as_installed()? + .as_manifest() + .de()?; if let Some(props) = manifest.properties { props .execute::<(), Value>( diff --git a/backend/src/registry/admin.rs b/backend/src/registry/admin.rs new file mode 100644 index 000000000..44b83d161 --- /dev/null +++ b/backend/src/registry/admin.rs @@ -0,0 +1,211 @@ +use std::path::PathBuf; +use std::time::Duration; + +use color_eyre::eyre::eyre; +use console::style; +use futures::StreamExt; +use indicatif::{ProgressBar, ProgressStyle}; +use reqwest::{header, Body, Client, Url}; +use rpc_toolkit::command; + +use crate::s9pk::reader::S9pkReader; +use crate::util::display_none; +use crate::{Error, ErrorKind}; + +async fn registry_user_pass(location: &str) -> Result<(Url, String, String), Error> { + let mut url = Url::parse(location)?; + let user = url.username().to_string(); + let pass = url.password().map(str::to_string); + if user.is_empty() || url.path() != "/" { + return Err(Error::new( + eyre!("{location:?} is not like \"https://user@registry.example.com/\""), + ErrorKind::ParseUrl, + )); + } + let _ = url.set_username(""); + let _ = url.set_password(None); + + let pass = match pass { + Some(p) => p, + None => { + let pass_prompt = format!("{} Password for {user}: ", style("?").yellow()); + tokio::task::spawn_blocking(move || rpassword::prompt_password(pass_prompt)) + .await + .unwrap()? + } + }; + Ok((url, user.to_string(), pass.to_string())) +} + +#[derive(serde::Serialize, Debug)] +struct Package { + id: String, + version: String, + arches: Option>, +} + +async fn do_index( + httpc: &Client, + mut url: Url, + user: &str, + pass: &str, + pkg: &Package, +) -> Result<(), Error> { + url.set_path("/admin/v0/index"); + let req = httpc + .post(url) + .header(header::ACCEPT, "text/plain") + .basic_auth(user, Some(pass)) + .json(pkg) + .build()?; + let res = httpc.execute(req).await?; + if !res.status().is_success() { + let info = res.text().await?; + return Err(Error::new(eyre!("{}", info), ErrorKind::Registry)); + } + Ok(()) +} + +async fn do_upload( + httpc: &Client, + mut url: Url, + user: &str, + pass: &str, + body: Body, +) -> Result<(), Error> { + url.set_path("/admin/v0/upload"); + let req = httpc + .post(url) + .header(header::ACCEPT, "text/plain") + .basic_auth(user, Some(pass)) + .body(body) + .build()?; + let res = httpc.execute(req).await?; + if !res.status().is_success() { + let info = res.text().await?; + return Err(Error::new(eyre!("{}", info), ErrorKind::Registry)); + } + Ok(()) +} + +#[command(cli_only, display(display_none))] +pub async fn publish( + #[arg] location: String, + #[arg] path: PathBuf, + #[arg(rename = "no-verify", long = "no-verify")] no_verify: bool, + #[arg(rename = "no-upload", long = "no-upload")] no_upload: bool, + #[arg(rename = "no-index", long = "no-index")] no_index: bool, +) -> Result<(), Error> { + // Prepare for progress bars. + let bytes_bar_style = + ProgressStyle::with_template("{percent}% {wide_bar} [{bytes}/{total_bytes}] [{eta}]") + .unwrap(); + let plain_line_style = + ProgressStyle::with_template("{prefix:.bold.dim} {wide_msg}...").unwrap(); + let spinner_line_style = + ProgressStyle::with_template("{prefix:.bold.dim} {spinner} {wide_msg}...").unwrap(); + + // Read the file to get manifest information and check validity.. + // Open file right away so it can not change out from under us. + let file = tokio::fs::File::open(&path).await?; + + let manifest = if no_verify { + let pb = ProgressBar::new(1) + .with_style(spinner_line_style.clone()) + .with_prefix("[1/3]") + .with_message("Querying s9pk"); + pb.enable_steady_tick(Duration::from_millis(200)); + let mut s9pk = S9pkReader::open(&path, false).await?; + let m = s9pk.manifest().await?.clone(); + pb.set_style(plain_line_style.clone()); + pb.abandon(); + m + } else { + let pb = ProgressBar::new(1) + .with_style(spinner_line_style.clone()) + .with_prefix("[1/3]") + .with_message("Verifying s9pk"); + pb.enable_steady_tick(Duration::from_millis(200)); + let mut s9pk = S9pkReader::open(&path, true).await?; + s9pk.validate().await?; + let m = s9pk.manifest().await?.clone(); + pb.set_style(plain_line_style.clone()); + pb.abandon(); + m + }; + let pkg = Package { + id: manifest.id.to_string(), + version: manifest.version.to_string(), + arches: manifest.hardware_requirements.arch.clone(), + }; + println!("{} id = {}", style(">").green(), pkg.id); + println!("{} version = {}", style(">").green(), pkg.version); + if let Some(arches) = &pkg.arches { + println!("{} arches = {:?}", style(">").green(), arches); + } else { + println!( + "{} No architecture listed in hardware_requirements", + style(">").red() + ); + } + + // Process the url and get the user's password. + let (registry, user, pass) = registry_user_pass(&location).await?; + + // Now prepare a stream of the file which will show a progress bar as it is consumed. + let file_size = file.metadata().await?.len(); + let file_stream = tokio_util::io::ReaderStream::new(file); + ProgressBar::new(0) + .with_style(plain_line_style.clone()) + .with_prefix("[2/3]") + .with_message("Uploading s9pk") + .abandon(); + let pb = ProgressBar::new(file_size).with_style(bytes_bar_style.clone()); + let stream_pb = pb.clone(); + let file_stream = file_stream.inspect(move |bytes| { + if let Ok(bytes) = bytes { + stream_pb.inc(bytes.len() as u64); + } + }); + + let httpc = Client::builder().build().unwrap(); + // And upload! + if no_upload { + println!("{} Skipping upload", style(">").yellow()); + } else { + do_upload( + &httpc, + registry.clone(), + &user, + &pass, + Body::wrap_stream(file_stream), + ) + .await?; + } + pb.finish_and_clear(); + + // Also index, so it will show up in the registry. + let pb = ProgressBar::new(0) + .with_style(spinner_line_style.clone()) + .with_prefix("[3/3]") + .with_message("Indexing registry"); + pb.enable_steady_tick(Duration::from_millis(200)); + if no_index { + println!("{} Skipping index", style(">").yellow()); + } else { + do_index(&httpc, registry.clone(), &user, &pass, &pkg).await?; + } + pb.set_style(plain_line_style.clone()); + pb.abandon(); + + // All done + if !no_index { + println!( + "{} Package {} is now published to {}", + style(">").green(), + pkg.id, + registry + ); + } + Ok(()) +} diff --git a/backend/src/marketplace.rs b/backend/src/registry/marketplace.rs similarity index 89% rename from backend/src/marketplace.rs rename to backend/src/registry/marketplace.rs index 40b81d1cb..979733198 100644 --- a/backend/src/marketplace.rs +++ b/backend/src/registry/marketplace.rs @@ -1,3 +1,4 @@ +use base64::Engine; use color_eyre::eyre::eyre; use reqwest::{StatusCode, Url}; use rpc_toolkit::command; @@ -12,7 +13,7 @@ pub fn marketplace() -> Result<(), Error> { Ok(()) } -pub fn with_query_params(ctx: &RpcContext, mut url: Url) -> Url { +pub fn with_query_params(ctx: RpcContext, mut url: Url) -> Url { url.query_pairs_mut() .append_pair( "os.version", @@ -22,7 +23,7 @@ pub fn with_query_params(ctx: &RpcContext, mut url: Url) -> Url { "os.compat", &crate::version::Current::new().compat().to_string(), ) - .append_pair("os.arch", crate::OS_ARCH) + .append_pair("os.arch", &*crate::PLATFORM) .append_pair("hardware.arch", &*crate::ARCH) .append_pair("hardware.ram", &ctx.hardware.ram.to_string()); @@ -38,7 +39,7 @@ pub fn with_query_params(ctx: &RpcContext, mut url: Url) -> Url { pub async fn get(#[context] ctx: RpcContext, #[arg] url: Url) -> Result { let mut response = ctx .client - .get(with_query_params(&ctx, url)) + .get(with_query_params(ctx.clone(), url)) .send() .await .with_kind(crate::ErrorKind::Network)?; @@ -65,12 +66,11 @@ pub async fn get(#[context] ctx: RpcContext, #[arg] url: Url) -> Result Ok(Value::String(format!( "data:{};base64,{}", ctype, - base64::encode_config( + base64::engine::general_purpose::URL_SAFE.encode( &response .bytes() .await - .with_kind(crate::ErrorKind::Registry)?, - base64::URL_SAFE + .with_kind(crate::ErrorKind::Registry)? ) ))), _ => Err(Error::new( diff --git a/backend/src/registry/mod.rs b/backend/src/registry/mod.rs new file mode 100644 index 000000000..27f541f1d --- /dev/null +++ b/backend/src/registry/mod.rs @@ -0,0 +1,2 @@ +pub mod admin; +pub mod marketplace; diff --git a/backend/src/s9pk/builder.rs b/backend/src/s9pk/builder.rs index 24869564f..199742439 100644 --- a/backend/src/s9pk/builder.rs +++ b/backend/src/s9pk/builder.rs @@ -1,4 +1,4 @@ -use sha2_old::{Digest, Sha512}; +use sha2::{Digest, Sha512}; use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom}; use tracing::instrument; use typed_builder::TypedBuilder; @@ -43,7 +43,7 @@ impl< { /// BLOCKING #[instrument(skip_all)] - pub async fn pack(mut self, key: &ed25519_dalek::Keypair) -> Result<(), Error> { + pub async fn pack(mut self, key: &ed25519_dalek::SigningKey) -> Result<(), Error> { let header_pos = self.writer.stream_position().await?; if header_pos != 0 { tracing::warn!("Appending to non-empty file."); @@ -132,7 +132,7 @@ impl< // header let (hash, _) = writer.finish(); self.writer.seek(SeekFrom::Start(header_pos)).await?; - header.pubkey = key.public.clone(); + header.pubkey = key.into(); header.signature = key.sign_prehashed(hash, Some(SIG_CONTEXT))?; header .serialize(&mut self.writer) diff --git a/backend/src/s9pk/header.rs b/backend/src/s9pk/header.rs index 9e8bfae7e..4f77ad855 100644 --- a/backend/src/s9pk/header.rs +++ b/backend/src/s9pk/header.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use color_eyre::eyre::eyre; -use ed25519_dalek::{PublicKey, Signature}; +use ed25519_dalek::{Signature, VerifyingKey}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt}; use crate::Error; @@ -11,15 +11,15 @@ pub const VERSION: u8 = 1; #[derive(Debug)] pub struct Header { - pub pubkey: PublicKey, + pub pubkey: VerifyingKey, pub signature: Signature, pub table_of_contents: TableOfContents, } impl Header { pub fn placeholder() -> Self { Header { - pubkey: PublicKey::default(), - signature: Signature::from_bytes(&[0; 64]).expect("Invalid ed25519 signature"), + pubkey: VerifyingKey::default(), + signature: Signature::from_bytes(&[0; 64]), table_of_contents: Default::default(), } } @@ -28,7 +28,7 @@ impl Header { writer.write_all(&MAGIC).await?; writer.write_all(&[VERSION]).await?; writer.write_all(self.pubkey.as_bytes()).await?; - writer.write_all(self.signature.as_ref()).await?; + writer.write_all(&self.signature.to_bytes()).await?; self.table_of_contents.serialize(writer).await?; Ok(()) } @@ -51,11 +51,11 @@ impl Header { } let mut pubkey_bytes = [0; 32]; reader.read_exact(&mut pubkey_bytes).await?; - let pubkey = PublicKey::from_bytes(&pubkey_bytes) + let pubkey = VerifyingKey::from_bytes(&pubkey_bytes) .map_err(|e| Error::new(e, crate::ErrorKind::ParseS9pk))?; let mut sig_bytes = [0; 64]; reader.read_exact(&mut sig_bytes).await?; - let signature = Signature::from_bytes(&sig_bytes).expect("Invalid ed25519 signature"); + let signature = Signature::from_bytes(&sig_bytes); let table_of_contents = TableOfContents::deserialize(reader).await?; Ok(Header { diff --git a/backend/src/s9pk/manifest.rs b/backend/src/s9pk/manifest.rs index 52b499375..3eee540ed 100644 --- a/backend/src/s9pk/manifest.rs +++ b/backend/src/s9pk/manifest.rs @@ -2,8 +2,7 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use color_eyre::eyre::eyre; -pub use models::{PackageId, SYSTEM_PACKAGE_ID}; -use patch_db::HasModel; +pub use models::PackageId; use serde::{Deserialize, Serialize}; use url::Url; @@ -14,6 +13,7 @@ use crate::config::action::ConfigActions; use crate::dependencies::Dependencies; use crate::migration::Migrations; use crate::net::interface::Interfaces; +use crate::prelude::*; use crate::procedure::docker::DockerContainers; use crate::procedure::PackageProcedure; use crate::status::health_check::HealthChecks; @@ -29,6 +29,7 @@ fn current_version() -> Version { #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct Manifest { #[serde(default = "current_version")] pub eos_version: Version, @@ -36,7 +37,6 @@ pub struct Manifest { #[serde(default)] pub git_hash: Option, pub title: String, - #[model] pub version: Version, pub description: Description, #[serde(default)] @@ -52,31 +52,23 @@ pub struct Manifest { pub donation_url: Option, #[serde(default)] pub alerts: Alerts, - #[model] pub main: PackageProcedure, pub health_checks: HealthChecks, - #[model] pub config: Option, - #[model] pub properties: Option, - #[model] pub volumes: Volumes, // #[serde(default)] pub interfaces: Interfaces, // #[serde(default)] - #[model] pub backup: BackupActions, #[serde(default)] - #[model] pub migrations: Migrations, #[serde(default)] pub actions: Actions, // #[serde(default)] // pub permissions: Permissions, #[serde(default)] - #[model] pub dependencies: Dependencies, - #[model] pub containers: Option, #[serde(default)] @@ -120,7 +112,7 @@ pub struct HardwareRequirements { #[serde(default)] device: BTreeMap, ram: Option, - arch: Option>, + pub arch: Option>, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] diff --git a/backend/src/s9pk/mod.rs b/backend/src/s9pk/mod.rs index a5fff7e11..e1bf4caba 100644 --- a/backend/src/s9pk/mod.rs +++ b/backend/src/s9pk/mod.rs @@ -28,7 +28,7 @@ pub mod header; pub mod manifest; pub mod reader; -pub const SIG_CONTEXT: &'static [u8] = b"s9pk"; +pub const SIG_CONTEXT: &[u8] = b"s9pk"; #[command(cli_only, display(display_none))] #[instrument(skip_all)] diff --git a/backend/src/s9pk/reader.rs b/backend/src/s9pk/reader.rs index 7e069f436..e901b1a14 100644 --- a/backend/src/s9pk/reader.rs +++ b/backend/src/s9pk/reader.rs @@ -7,11 +7,11 @@ use std::str::FromStr; use std::task::{Context, Poll}; use color_eyre::eyre::eyre; -use digest_old::Output; -use ed25519_dalek::PublicKey; +use digest::Output; +use ed25519_dalek::VerifyingKey; use futures::TryStreamExt; use models::ImageId; -use sha2_old::{Digest, Sha512}; +use sha2::{Digest, Sha512}; use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, ReadBuf}; use tracing::instrument; @@ -147,7 +147,7 @@ impl FromStr for ImageTag { pub struct S9pkReader { hash: Option>, hash_string: Option, - developer_key: PublicKey, + developer_key: VerifyingKey, toc: TableOfContents, pos: u64, rdr: R, @@ -185,18 +185,14 @@ impl S9pkReader { .map(|i| i.validate(&man.id, &man.version).map(|_| i.image_id)) .collect::, _>>()?; man.description.validate()?; - man.actions - .0 - .iter() - .map(|(_, action)| { - action.validate( - containers, - &man.eos_version, - &man.volumes, - &validated_image_ids, - ) - }) - .collect::>()?; + man.actions.0.iter().try_for_each(|(_, action)| { + action.validate( + containers, + &man.eos_version, + &man.volumes, + &validated_image_ids, + ) + })?; man.backup.validate( containers, &man.eos_version, @@ -211,21 +207,11 @@ impl S9pkReader { &validated_image_ids, )?; } - man.health_checks.validate( - containers, - &man.eos_version, - &man.volumes, - &validated_image_ids, - )?; + man.health_checks + .validate(&man.eos_version, &man.volumes, &validated_image_ids)?; man.interfaces.validate()?; man.main - .validate( - containers, - &man.eos_version, - &man.volumes, - &validated_image_ids, - false, - ) + .validate(&man.eos_version, &man.volumes, &validated_image_ids, false) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Main"))?; man.migrations.validate( containers, @@ -263,13 +249,7 @@ impl S9pkReader { } if let Some(props) = &man.properties { props - .validate( - containers, - &man.eos_version, - &man.volumes, - &validated_image_ids, - true, - ) + .validate(&man.eos_version, &man.volumes, &validated_image_ids, true) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, "Properties"))?; } man.volumes.validate(&man.interfaces)?; @@ -353,7 +333,7 @@ impl S9pkReader { self.hash_string.as_ref().map(|s| s.as_str()) } - pub fn developer_key(&self) -> &PublicKey { + pub fn developer_key(&self) -> &VerifyingKey { &self.developer_key } @@ -377,7 +357,7 @@ impl S9pkReader { }) } - pub async fn manifest_raw<'a>(&'a mut self) -> Result, Error> { + pub async fn manifest_raw(&mut self) -> Result, Error> { self.read_handle(self.toc.manifest).await } @@ -387,27 +367,27 @@ impl S9pkReader { .with_ctx(|_| (crate::ErrorKind::ParseS9pk, "Deserializing Manifest (CBOR)")) } - pub async fn license<'a>(&'a mut self) -> Result, Error> { - Ok(self.read_handle(self.toc.license).await?) + pub async fn license(&mut self) -> Result, Error> { + self.read_handle(self.toc.license).await } - pub async fn instructions<'a>(&'a mut self) -> Result, Error> { - Ok(self.read_handle(self.toc.instructions).await?) + pub async fn instructions(&mut self) -> Result, Error> { + self.read_handle(self.toc.instructions).await } - pub async fn icon<'a>(&'a mut self) -> Result, Error> { - Ok(self.read_handle(self.toc.icon).await?) + pub async fn icon(&mut self) -> Result, Error> { + self.read_handle(self.toc.icon).await } - pub async fn docker_images<'a>(&'a mut self) -> Result>, Error> { + pub async fn docker_images(&mut self) -> Result>, Error> { DockerReader::new(self.read_handle(self.toc.docker_images).await?).await } - pub async fn assets<'a>(&'a mut self) -> Result, Error> { - Ok(self.read_handle(self.toc.assets).await?) + pub async fn assets(&mut self) -> Result, Error> { + self.read_handle(self.toc.assets).await } - pub async fn scripts<'a>(&'a mut self) -> Result>, Error> { + pub async fn scripts(&mut self) -> Result>, Error> { Ok(match self.toc.scripts { None => None, Some(a) => Some(self.read_handle(a).await?), diff --git a/backend/src/s9pk/specv2.md b/backend/src/s9pk/specv2.md new file mode 100644 index 000000000..9bf993463 --- /dev/null +++ b/backend/src/s9pk/specv2.md @@ -0,0 +1,28 @@ +## Header + +### Magic + +2B: `0x3b3b` + +### Version + +varint: `0x02` + +### Pubkey + +32B: ed25519 pubkey + +### TOC + +- number of sections (varint) +- FOREACH section + - sig (32B: ed25519 signature of BLAKE-3 of rest of section) + - name (varstring) + - TYPE (varint) + - TYPE=FILE (`0x01`) + - mime (varstring) + - pos (32B: u64 BE) + - len (32B: u64 BE) + - hash (32B: BLAKE-3 of file contents) + - TYPE=TOC (`0x02`) + - recursively defined diff --git a/backend/src/setup.rs b/backend/src/setup.rs index ea825cf63..64c324095 100644 --- a/backend/src/setup.rs +++ b/backend/src/setup.rs @@ -3,10 +3,8 @@ use std::sync::Arc; use std::time::Duration; use color_eyre::eyre::eyre; -use futures::StreamExt; use josekit::jwk::Jwk; use openssl::x509::X509; -use patch_db::DbHandle; use rpc_toolkit::command; use rpc_toolkit::yajrc::RpcError; use serde::{Deserialize, Serialize}; @@ -33,6 +31,8 @@ use crate::disk::REPAIR_DISK_PATH; use crate::hostname::Hostname; use crate::init::{init, InitResult}; use crate::middleware::encrypt::EncryptedWire; +use crate::net::ssl::root_ca_start_time; +use crate::prelude::*; use crate::util::io::{dir_copy, dir_size, Counter}; use crate::{Error, ErrorKind, ResultExt}; @@ -58,23 +58,21 @@ async fn setup_init( let InitResult { secret_store, db } = init(&RpcContextConfig::load(ctx.config_path.clone()).await?).await?; let mut secrets_handle = secret_store.acquire().await?; - let mut db_handle = db.handle(); let mut secrets_tx = secrets_handle.begin().await?; - let mut db_tx = db_handle.begin().await?; - let mut account = AccountInfo::load(&mut secrets_tx).await?; + let mut account = AccountInfo::load(secrets_tx.as_mut()).await?; if let Some(password) = password { account.set_password(&password)?; - account.save(&mut secrets_tx).await?; - crate::db::DatabaseModel::new() - .server_info() - .password_hash() - .put(&mut db_tx, &account.password) - .await?; + account.save(secrets_tx.as_mut()).await?; + db.mutate(|m| { + m.as_server_info_mut() + .as_password_hash_mut() + .ser(&account.password) + }) + .await?; } - db_tx.commit().await?; secrets_tx.commit().await?; Ok(( @@ -266,39 +264,47 @@ pub async fn execute( complete: false, })); drop(status); - tokio::task::spawn(async move { - match execute_inner( - ctx.clone(), - embassy_logicalname, - embassy_password, - recovery_source, - recovery_password, - ) - .await - { - Ok((guid, hostname, tor_addr, root_ca)) => { - tracing::info!("Setup Complete!"); - *ctx.setup_result.write().await = Some(( - guid, - SetupResult { - tor_address: format!("https://{}", tor_addr), - lan_address: hostname.lan_address(), - root_ca: String::from_utf8( - root_ca.to_pem().expect("failed to serialize root ca"), - ) - .expect("invalid pem string"), - }, - )); - *ctx.setup_status.write().await = Some(Ok(SetupStatus { - bytes_transferred: 0, - total_bytes: None, - complete: true, - })); - } - Err(e) => { - tracing::error!("Error Setting Up Server: {}", e); - tracing::debug!("{:?}", e); - *ctx.setup_status.write().await = Some(Err(e.into())); + tokio::task::spawn({ + async move { + let ctx = ctx.clone(); + let recovery_source = recovery_source; + + let embassy_password = embassy_password; + let recovery_source = recovery_source; + let recovery_password = recovery_password; + match execute_inner( + ctx.clone(), + embassy_logicalname, + embassy_password, + recovery_source, + recovery_password, + ) + .await + { + Ok((guid, hostname, tor_addr, root_ca)) => { + tracing::info!("Setup Complete!"); + *ctx.setup_result.write().await = Some(( + guid, + SetupResult { + tor_address: format!("https://{}", tor_addr), + lan_address: hostname.lan_address(), + root_ca: String::from_utf8( + root_ca.to_pem().expect("failed to serialize root ca"), + ) + .expect("invalid pem string"), + }, + )); + *ctx.setup_status.write().await = Some(Ok(SetupStatus { + bytes_transferred: 0, + total_bytes: None, + complete: true, + })); + } + Err(e) => { + tracing::error!("Error Setting Up Server: {}", e); + tracing::debug!("{:?}", e); + *ctx.setup_status.write().await = Some(Err(e.into())); + } } } }); @@ -373,7 +379,7 @@ async fn fresh_setup( ctx: &SetupContext, embassy_password: &str, ) -> Result<(Hostname, OnionAddressV3, X509), Error> { - let account = AccountInfo::new(embassy_password)?; + let account = AccountInfo::new(embassy_password, root_ca_start_time().await?)?; let sqlite_pool = ctx.secret_store().await?; account.save(&sqlite_pool).await?; sqlite_pool.close().await; @@ -397,7 +403,7 @@ async fn recover( ) -> Result<(Arc, Hostname, OnionAddressV3, X509), Error> { let recovery_source = TmpMountGuard::mount(&recovery_source, ReadWrite).await?; recover_full_embassy( - ctx.clone(), + ctx, guid.clone(), embassy_password, recovery_source, diff --git a/backend/src/shutdown.rs b/backend/src/shutdown.rs index 47dc3c432..7a34d1e94 100644 --- a/backend/src/shutdown.rs +++ b/backend/src/shutdown.rs @@ -6,14 +6,15 @@ use rpc_toolkit::command; use crate::context::RpcContext; use crate::disk::main::export; use crate::init::{STANDBY_MODE_PATH, SYSTEM_REBUILD_PATH}; +use crate::prelude::*; use crate::sound::SHUTDOWN; +use crate::util::docker::CONTAINER_TOOL; use crate::util::{display_none, Invoke}; -use crate::{Error, ErrorKind, OS_ARCH}; +use crate::PLATFORM; #[derive(Debug, Clone)] pub struct Shutdown { - pub datadir: PathBuf, - pub disk_guid: Option>, + pub export_args: Option<(Arc, PathBuf)>, pub restart: bool, } impl Shutdown { @@ -43,22 +44,24 @@ impl Shutdown { tracing::error!("Error Stopping Journald: {}", e); tracing::debug!("{:?}", e); } - if let Err(e) = Command::new("systemctl") - .arg("stop") - .arg("docker") - .invoke(crate::ErrorKind::Docker) - .await - { - tracing::error!("Error Stopping Docker: {}", e); - tracing::debug!("{:?}", e); + if CONTAINER_TOOL == "docker" { + if let Err(e) = Command::new("systemctl") + .arg("stop") + .arg("docker") + .invoke(crate::ErrorKind::Docker) + .await + { + tracing::error!("Error Stopping Docker: {}", e); + tracing::debug!("{:?}", e); + } } - if let Some(guid) = &self.disk_guid { - if let Err(e) = export(guid, &self.datadir).await { + if let Some((guid, datadir)) = &self.export_args { + if let Err(e) = export(guid, datadir).await { tracing::error!("Error Exporting Volume Group: {}", e); tracing::debug!("{:?}", e); } } - if OS_ARCH != "raspberrypi" || self.restart { + if &*PLATFORM != "raspberrypi" || self.restart { if let Err(e) = SHUTDOWN.play().await { tracing::error!("Error Playing Shutdown Song: {}", e); tracing::debug!("{:?}", e); @@ -66,34 +69,39 @@ impl Shutdown { } }); drop(rt); - if OS_ARCH == "raspberrypi" { + if &*PLATFORM == "raspberrypi" { if !self.restart { std::fs::write(STANDBY_MODE_PATH, "").unwrap(); Command::new("sync").spawn().unwrap().wait().unwrap(); } Command::new("reboot").spawn().unwrap().wait().unwrap(); + } else if self.restart { + Command::new("reboot").spawn().unwrap().wait().unwrap(); } else { - if self.restart { - Command::new("reboot").spawn().unwrap().wait().unwrap(); - } else { - Command::new("shutdown") - .arg("-h") - .arg("now") - .spawn() - .unwrap() - .wait() - .unwrap(); - } + Command::new("shutdown") + .arg("-h") + .arg("now") + .spawn() + .unwrap() + .wait() + .unwrap(); } } } #[command(display(display_none))] pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> { + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_shutting_down_mut() + .ser(&true) + }) + .await?; ctx.shutdown .send(Some(Shutdown { - datadir: ctx.datadir.clone(), - disk_guid: Some(ctx.disk_guid.clone()), + export_args: Some((ctx.disk_guid.clone(), ctx.datadir.clone())), restart: false, })) .map_err(|_| ()) @@ -103,10 +111,17 @@ pub async fn shutdown(#[context] ctx: RpcContext) -> Result<(), Error> { #[command(display(display_none))] pub async fn restart(#[context] ctx: RpcContext) -> Result<(), Error> { + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_restarting_mut() + .ser(&true) + }) + .await?; ctx.shutdown .send(Some(Shutdown { - datadir: ctx.datadir.clone(), - disk_guid: Some(ctx.disk_guid.clone()), + export_args: Some((ctx.disk_guid.clone(), ctx.datadir.clone())), restart: true, })) .map_err(|_| ()) diff --git a/backend/src/sound.rs b/backend/src/sound.rs index ca010c7c3..8dc78357c 100644 --- a/backend/src/sound.rs +++ b/backend/src/sound.rs @@ -15,7 +15,7 @@ lazy_static::lazy_static! { static ref C_0: f64 = *A_4 / SEMITONE_K.powf(9f64) / 2f64.powf(4f64); } -pub const SOUND_LOCK_FILE: &'static str = "/etc/embassy/sound.lock"; +pub const SOUND_LOCK_FILE: &str = "/etc/embassy/sound.lock"; struct SoundInterface { guard: Option, diff --git a/backend/src/ssh.rs b/backend/src/ssh.rs index 091f2ccbe..697e05727 100644 --- a/backend/src/ssh.rs +++ b/backend/src/ssh.rs @@ -4,7 +4,7 @@ use chrono::Utc; use clap::ArgMatches; use color_eyre::eyre::eyre; use rpc_toolkit::command; -use sqlx::{Executor, Pool, Postgres}; +use sqlx::{Pool, Postgres}; use tracing::instrument; use crate::context::RpcContext; diff --git a/backend/src/status/health_check.rs b/backend/src/status/health_check.rs index e7b412e8a..1b3e8f6b5 100644 --- a/backend/src/status/health_check.rs +++ b/backend/src/status/health_check.rs @@ -7,7 +7,6 @@ use serde::{Deserialize, Serialize}; use tracing::instrument; use crate::context::RpcContext; -use crate::procedure::docker::DockerContainers; use crate::procedure::{NoOutput, PackageProcedure, ProcedureName}; use crate::s9pk::manifest::PackageId; use crate::util::serde::Duration; @@ -21,15 +20,14 @@ impl HealthChecks { #[instrument(skip_all)] pub fn validate( &self, - container: &Option, eos_version: &Version, volumes: &Volumes, image_ids: &BTreeSet, ) -> Result<(), Error> { - for (_, check) in &self.0 { + for check in self.0.values() { check .implementation - .validate(container, eos_version, &volumes, image_ids, false) + .validate(eos_version, volumes, image_ids, false) .with_ctx(|_| { ( crate::ErrorKind::ValidateS9pk, @@ -42,7 +40,6 @@ impl HealthChecks { pub async fn check_all( &self, ctx: &RpcContext, - container: &Option, started: DateTime, pkg_id: &PackageId, pkg_version: &Version, @@ -52,7 +49,7 @@ impl HealthChecks { Ok::<_, Error>(( id.clone(), check - .check(ctx, container, id, started, pkg_id, pkg_version, volumes) + .check(ctx, id, started, pkg_id, pkg_version, volumes) .await?, )) })) @@ -75,7 +72,6 @@ impl HealthCheck { pub async fn check( &self, ctx: &RpcContext, - container: &Option, id: &HealthCheckId, started: DateTime, pkg_id: &PackageId, @@ -107,7 +103,7 @@ impl HealthCheck { } } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] #[serde(tag = "result")] pub enum HealthCheckResult { diff --git a/backend/src/status/mod.rs b/backend/src/status/mod.rs index 073ea4e88..2a5a9391f 100644 --- a/backend/src/status/mod.rs +++ b/backend/src/status/mod.rs @@ -1,25 +1,34 @@ use std::collections::BTreeMap; use chrono::{DateTime, Utc}; -use patch_db::{HasModel, Model}; +use models::PackageId; use serde::{Deserialize, Serialize}; use self::health_check::HealthCheckId; -use crate::dependencies::DependencyErrors; +use crate::prelude::*; use crate::status::health_check::HealthCheckResult; pub mod health_check; #[derive(Clone, Debug, Deserialize, Serialize, HasModel)] #[serde(rename_all = "kebab-case")] +#[model = "Model"] pub struct Status { pub configured: bool, - #[model] pub main: MainStatus, - #[model] - pub dependency_errors: DependencyErrors, + #[serde(default)] + pub dependency_config_errors: DependencyConfigErrors, } -#[derive(Debug, Clone, Deserialize, Serialize, HasModel)] +#[derive(Clone, Debug, Deserialize, Serialize, HasModel, Default)] +#[serde(rename_all = "kebab-case")] +#[model = "Model"] +pub struct DependencyConfigErrors(pub BTreeMap); +impl Map for DependencyConfigErrors { + type Key = PackageId; + type Value = String; +} + +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] #[serde(tag = "status")] #[serde(rename_all = "kebab-case")] pub enum MainStatus { @@ -71,7 +80,6 @@ impl MainStatus { MainStatus::Starting { .. } => None, } } - pub fn backing_up(&self) -> Self { let (started, health) = match self { MainStatus::Starting { .. } => (Some(Utc::now()), Default::default()), @@ -84,8 +92,3 @@ impl MainStatus { MainStatus::BackingUp { started, health } } } -impl MainStatusModel { - pub fn started(self) -> Model>> { - self.0.child("started") - } -} diff --git a/backend/src/system.rs b/backend/src/system.rs index 9e8e0e049..989cdc4aa 100644 --- a/backend/src/system.rs +++ b/backend/src/system.rs @@ -1,6 +1,7 @@ use std::fmt; use chrono::Utc; +use clap::ArgMatches; use color_eyre::eyre::eyre; use futures::FutureExt; use rpc_toolkit::command; @@ -17,13 +18,12 @@ use crate::logs::{ cli_logs_generic_follow, cli_logs_generic_nofollow, fetch_logs, follow_logs, LogFollowResponse, LogResponse, LogSource, }; +use crate::prelude::*; use crate::shutdown::Shutdown; use crate::util::serde::{display_serializable, IoFormat}; use crate::util::{display_none, Invoke}; use crate::{Error, ErrorKind, ResultExt}; -pub const SYSTEMD_UNIT: &'static str = "startd"; - #[command(subcommands(zram))] pub async fn experimental() -> Result<(), Error> { Ok(()) @@ -59,16 +59,12 @@ pub async fn enable_zram() -> Result<(), Error> { #[command(display(display_none))] pub async fn zram(#[context] ctx: RpcContext, #[arg] enable: bool) -> Result<(), Error> { - let mut db = ctx.db.handle(); - let mut zram = crate::db::DatabaseModel::new() - .server_info() - .zram() - .get_mut(&mut db) - .await?; - if enable == *zram { + let db = ctx.db.peek().await; + + let zram = db.as_server_info().as_zram().de()?; + if enable == zram { return Ok(()); } - *zram = enable; if enable { enable_zram().await?; } else { @@ -80,13 +76,74 @@ pub async fn zram(#[context] ctx: RpcContext, #[arg] enable: bool) -> Result<(), .await .with_kind(ErrorKind::Zram)?; } - zram.save(&mut db).await?; + ctx.db + .mutate(|v| { + v.as_server_info_mut().as_zram_mut().ser(&enable)?; + Ok(()) + }) + .await?; Ok(()) } -#[command] -pub async fn time() -> Result { - Ok(Utc::now().to_rfc3339()) +#[derive(Serialize, Deserialize)] +pub struct TimeInfo { + now: String, + uptime: u64, +} + +fn display_time(arg: TimeInfo, matches: &ArgMatches) { + use std::fmt::Write; + + use prettytable::*; + + if matches.is_present("format") { + return display_serializable(arg, matches); + } + + let days = arg.uptime / (24 * 60 * 60); + let days_s = arg.uptime % (24 * 60 * 60); + let hours = days_s / (60 * 60); + let hours_s = arg.uptime % (60 * 60); + let minutes = hours_s / 60; + let seconds = arg.uptime % 60; + let mut uptime_string = String::new(); + if days > 0 { + write!(&mut uptime_string, "{days} days").unwrap(); + } + if hours > 0 { + if !uptime_string.is_empty() { + uptime_string += ", "; + } + write!(&mut uptime_string, "{hours} hours").unwrap(); + } + if minutes > 0 { + if !uptime_string.is_empty() { + uptime_string += ", "; + } + write!(&mut uptime_string, "{minutes} minutes").unwrap(); + } + if !uptime_string.is_empty() { + uptime_string += ", "; + } + write!(&mut uptime_string, "{seconds} seconds").unwrap(); + + let mut table = Table::new(); + table.add_row(row![bc -> "NOW", &arg.now]); + table.add_row(row![bc -> "UPTIME", &uptime_string]); + table.print_tty(false).unwrap(); +} + +#[command(display(display_time))] +pub async fn time( + #[context] ctx: RpcContext, + #[allow(unused_variables)] + #[arg(long = "format")] + format: Option, +) -> Result { + Ok(TimeInfo { + now: Utc::now().to_rfc3339(), + uptime: ctx.start_time.elapsed().as_secs(), + }) } #[command( @@ -128,7 +185,7 @@ pub async fn logs_nofollow( _ctx: (), (limit, cursor, before, _): (Option, Option, bool, bool), ) -> Result { - fetch_logs(LogSource::Service(SYSTEMD_UNIT), limit, cursor, before).await + fetch_logs(LogSource::System, limit, cursor, before).await } #[command(rpc_only, rename = "follow", display(display_none))] @@ -136,7 +193,7 @@ pub async fn logs_follow( #[context] ctx: RpcContext, #[parent_data] (limit, _, _, _): (Option, Option, bool, bool), ) -> Result { - follow_logs(ctx, LogSource::Service(SYSTEMD_UNIT), limit).await + follow_logs(ctx, LogSource::System, limit).await } #[command( @@ -303,60 +360,44 @@ impl<'de> Deserialize<'de> for GigaBytes { } #[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "kebab-case")] pub struct MetricsGeneral { - #[serde(rename = "Temperature")] - temperature: Option, + pub temperature: Option, } #[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "kebab-case")] pub struct MetricsMemory { - #[serde(rename = "Percentage Used")] pub percentage_used: Percentage, - #[serde(rename = "Total")] pub total: MebiBytes, - #[serde(rename = "Available")] pub available: MebiBytes, - #[serde(rename = "Used")] pub used: MebiBytes, - #[serde(rename = "Swap Total")] - pub swap_total: MebiBytes, - #[serde(rename = "Swap Free")] - pub swap_free: MebiBytes, - #[serde(rename = "Swap Used")] - pub swap_used: MebiBytes, + pub zram_total: MebiBytes, + pub zram_available: MebiBytes, + pub zram_used: MebiBytes, } #[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "kebab-case")] pub struct MetricsCpu { - #[serde(rename = "User Space")] - user_space: Percentage, - #[serde(rename = "Kernel Space")] - kernel_space: Percentage, - #[serde(rename = "I/O Wait")] - wait: Percentage, - #[serde(rename = "Idle")] + percentage_used: Percentage, idle: Percentage, - #[serde(rename = "Usage")] - usage: Percentage, + user_space: Percentage, + kernel_space: Percentage, + wait: Percentage, } #[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "kebab-case")] pub struct MetricsDisk { - #[serde(rename = "Size")] - size: GigaBytes, - #[serde(rename = "Used")] + percentage_used: Percentage, used: GigaBytes, - #[serde(rename = "Available")] available: GigaBytes, - #[serde(rename = "Percentage Used")] - used_percentage: Percentage, + capacity: GigaBytes, } #[derive(Deserialize, Serialize, Clone, Debug)] +#[serde(rename_all = "kebab-case")] pub struct Metrics { - #[serde(rename = "General")] general: MetricsGeneral, - #[serde(rename = "Memory")] memory: MetricsMemory, - #[serde(rename = "CPU")] cpu: MetricsCpu, - #[serde(rename = "Disk")] disk: MetricsDisk, } @@ -588,7 +629,8 @@ async fn get_temp() -> Result { .flat_map(|(_, v)| v.as_object()) .flatten() .filter_map(|(k, v)| { - if k.ends_with("_input") { + // we have seen so far that `temp1` is always a composite reading of some sort, so we should just use that for each chip + if k.trim() == "temp1_input" { v.as_f64() } else { None @@ -681,7 +723,7 @@ async fn get_cpu_info(last: &mut ProcStat) -> Result { kernel_space: Percentage((new.system() - last.system()) as f64 * 100.0 / total_diff as f64), idle: Percentage((new.idle - last.idle) as f64 * 100.0 / total_diff as f64), wait: Percentage((new.iowait - last.iowait) as f64 * 100.0 / total_diff as f64), - usage: Percentage((new.used() - last.used()) as f64 * 100.0 / total_diff as f64), + percentage_used: Percentage((new.used() - last.used()) as f64 * 100.0 / total_diff as f64), }; *last = new; Ok(res) @@ -694,8 +736,8 @@ pub struct MemInfo { buffers: Option, cached: Option, slab: Option, - swap_total: Option, - swap_free: Option, + zram_total: Option, + zram_free: Option, } #[instrument(skip_all)] pub async fn get_mem_info() -> Result { @@ -707,8 +749,8 @@ pub async fn get_mem_info() -> Result { buffers: None, cached: None, slab: None, - swap_total: None, - swap_free: None, + zram_total: None, + zram_free: None, }; fn get_num_kb(l: &str) -> Result { let e = Error::new( @@ -733,8 +775,8 @@ pub async fn get_mem_info() -> Result { _ if entry.starts_with("Buffers") => mem_info.buffers = Some(get_num_kb(entry)?), _ if entry.starts_with("Cached") => mem_info.cached = Some(get_num_kb(entry)?), _ if entry.starts_with("Slab") => mem_info.slab = Some(get_num_kb(entry)?), - _ if entry.starts_with("SwapTotal") => mem_info.swap_total = Some(get_num_kb(entry)?), - _ if entry.starts_with("SwapFree") => mem_info.swap_free = Some(get_num_kb(entry)?), + _ if entry.starts_with("SwapTotal") => mem_info.zram_total = Some(get_num_kb(entry)?), + _ if entry.starts_with("SwapFree") => mem_info.zram_free = Some(get_num_kb(entry)?), _ => (), } } @@ -750,24 +792,24 @@ pub async fn get_mem_info() -> Result { let buffers = ensure_present(mem_info.buffers, "Buffers")?; let cached = ensure_present(mem_info.cached, "Cached")?; let slab = ensure_present(mem_info.slab, "Slab")?; - let swap_total_k = ensure_present(mem_info.swap_total, "SwapTotal")?; - let swap_free_k = ensure_present(mem_info.swap_free, "SwapFree")?; + let zram_total_k = ensure_present(mem_info.zram_total, "SwapTotal")?; + let zram_free_k = ensure_present(mem_info.zram_free, "SwapFree")?; let total = MebiBytes(mem_total as f64 / 1024.0); let available = MebiBytes(mem_available as f64 / 1024.0); let used = MebiBytes((mem_total - mem_free - buffers - cached - slab) as f64 / 1024.0); - let swap_total = MebiBytes(swap_total_k as f64 / 1024.0); - let swap_free = MebiBytes(swap_free_k as f64 / 1024.0); - let swap_used = MebiBytes((swap_total_k - swap_free_k) as f64 / 1024.0); + let zram_total = MebiBytes(zram_total_k as f64 / 1024.0); + let zram_available = MebiBytes(zram_free_k as f64 / 1024.0); + let zram_used = MebiBytes((zram_total_k - zram_free_k) as f64 / 1024.0); let percentage_used = Percentage((total.0 - available.0) / total.0 * 100.0); Ok(MetricsMemory { percentage_used, total, available, used, - swap_total, - swap_free, - swap_used, + zram_total, + zram_available, + zram_used, }) } @@ -791,10 +833,10 @@ async fn get_disk_info() -> Result { let total_percentage = total_used as f64 / total_size as f64 * 100.0f64; Ok(MetricsDisk { - size: GigaBytes(total_size as f64 / 1_000_000_000.0), + capacity: GigaBytes(total_size as f64 / 1_000_000_000.0), used: GigaBytes(total_used as f64 / 1_000_000_000.0), available: GigaBytes(total_available as f64 / 1_000_000_000.0), - used_percentage: Percentage(total_percentage as f64), + percentage_used: Percentage(total_percentage as f64), }) } diff --git a/backend/src/update/mod.rs b/backend/src/update/mod.rs index 90ac2870c..4ce57a8d1 100644 --- a/backend/src/update/mod.rs +++ b/backend/src/update/mod.rs @@ -1,13 +1,11 @@ use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; use clap::ArgMatches; use color_eyre::eyre::{eyre, Result}; use emver::Version; use helpers::{Rsync, RsyncOptions}; use lazy_static::lazy_static; -use patch_db::{DbHandle, LockType, Revision}; use reqwest::Url; use rpc_toolkit::command; use tokio::process::Command; @@ -19,15 +17,15 @@ use crate::db::model::UpdateProgress; use crate::disk::mount::filesystem::bind::Bind; use crate::disk::mount::filesystem::ReadWrite; use crate::disk::mount::guard::MountGuard; -use crate::marketplace::with_query_params; use crate::notifications::NotificationLevel; +use crate::prelude::*; +use crate::registry::marketplace::with_query_params; use crate::sound::{ CIRCLE_OF_5THS_SHORT, UPDATE_FAILED_1, UPDATE_FAILED_2, UPDATE_FAILED_3, UPDATE_FAILED_4, }; use crate::update::latest_information::LatestInformation; use crate::util::Invoke; -use crate::version::{Current, VersionT}; -use crate::{Error, ErrorKind, ResultExt, OS_ARCH}; +use crate::{Error, ErrorKind, ResultExt, PLATFORM}; mod latest_information; @@ -77,15 +75,12 @@ fn display_update_result(status: UpdateResult, _: &ArgMatches) { } #[instrument(skip_all)] -async fn maybe_do_update( - ctx: RpcContext, - marketplace_url: Url, -) -> Result>, Error> { - let mut db = ctx.db.handle(); +async fn maybe_do_update(ctx: RpcContext, marketplace_url: Url) -> Result, Error> { + let peeked = ctx.db.peek().await; let latest_version: Version = ctx .client .get(with_query_params( - &ctx, + ctx.clone(), format!("{}/eos/v0/latest", marketplace_url,).parse()?, )) .send() @@ -95,31 +90,8 @@ async fn maybe_do_update( .await .with_kind(ErrorKind::Network)? .version; - crate::db::DatabaseModel::new() - .server_info() - .lock(&mut db, LockType::Write) - .await?; - let current_version = crate::db::DatabaseModel::new() - .server_info() - .version() - .get_mut(&mut db) - .await?; - if &latest_version < ¤t_version { - return Ok(None); - } - let mut tx = db.begin().await?; - let mut status = crate::db::DatabaseModel::new() - .server_info() - .status_info() - .get_mut(&mut tx) - .await?; - if status.update_progress.is_some() { - return Err(Error::new( - eyre!("Server is already updating!"), - crate::ErrorKind::InvalidRequest, - )); - } - if status.updated { + let current_version = peeked.as_server_info().as_version().de()?; + if latest_version < *current_version { return Ok(None); } @@ -127,41 +99,62 @@ async fn maybe_do_update( base: marketplace_url, version: latest_version, }; + let status = ctx + .db + .mutate(|db| { + let mut status = peeked.as_server_info().as_status_info().de()?; + if status.update_progress.is_some() { + return Err(Error::new( + eyre!("Server is already updating!"), + crate::ErrorKind::InvalidRequest, + )); + } - status.update_progress = Some(UpdateProgress { - size: None, - downloaded: 0, - }); - status.save(&mut tx).await?; - let rev = tx.commit().await?; + status.update_progress = Some(UpdateProgress { + size: None, + downloaded: 0, + }); + db.as_server_info_mut().as_status_info_mut().ser(&status)?; + Ok(status) + }) + .await?; + + if status.updated { + return Ok(None); + } tokio::spawn(async move { let res = do_update(ctx.clone(), eos_url).await; - let mut db = ctx.db.handle(); - let mut status = crate::db::DatabaseModel::new() - .server_info() - .status_info() - .get_mut(&mut db) - .await - .expect("could not access status"); - status.update_progress = None; + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_update_progress_mut() + .ser(&None) + }) + .await?; match res { Ok(()) => { - status.updated = true; - status.save(&mut db).await.expect("could not save status"); + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_updated_mut() + .ser(&true) + }) + .await?; CIRCLE_OF_5THS_SHORT .play() .await .expect("could not play sound"); } Err(e) => { - status.save(&mut db).await.expect("could not save status"); ctx.notification_manager .notify( - &mut db, + ctx.db.clone(), None, NotificationLevel::Error, - "embassyOS Update Failed".to_owned(), + "StartOS Update Failed".to_owned(), format!("Update was not successful because of {}", e), (), None, @@ -187,8 +180,9 @@ async fn maybe_do_update( .expect("could not play song: update failed 4"); } } + Ok::<(), Error>(()) }); - Ok(rev) + Ok(Some(())) } #[instrument(skip_all)] @@ -200,17 +194,16 @@ async fn do_update(ctx: RpcContext, eos_url: EosUrl) -> Result<(), Error> { ) .await?; while let Some(progress) = rsync.progress.next().await { - crate::db::DatabaseModel::new() - .server_info() - .status_info() - .update_progress() - .put( - &mut ctx.db.handle(), - &UpdateProgress { - size: Some(100), - downloaded: (100.0 * progress) as u64, - }, - ) + ctx.db + .mutate(|db| { + db.as_server_info_mut() + .as_status_info_mut() + .as_update_progress_mut() + .ser(&Some(UpdateProgress { + size: Some(100), + downloaded: (100.0 * progress) as u64, + })) + }) .await?; } rsync.wait().await?; @@ -238,7 +231,7 @@ impl EosUrl { .host_str() .ok_or_else(|| Error::new(eyre!("Could not get host of base"), ErrorKind::ParseUrl))?; let version: &Version = &self.version; - Ok(format!("{host}::{version}/{OS_ARCH}/") + Ok(format!("{host}::{version}/{}/", &*PLATFORM) .parse() .map_err(|_| Error::new(eyre!("Could not parse path"), ErrorKind::ParseUrl))?) } @@ -304,7 +297,7 @@ async fn sync_boot() -> Result<(), Error> { .await? .wait() .await?; - if OS_ARCH != "raspberrypi" { + if &*PLATFORM != "raspberrypi" { let dev_mnt = MountGuard::mount(&Bind::new("/dev"), "/media/embassy/next/dev", ReadWrite).await?; let sys_mnt = diff --git a/backend/src/util/config.rs b/backend/src/util/config.rs index ddc6f87c8..f719f563f 100644 --- a/backend/src/util/config.rs +++ b/backend/src/util/config.rs @@ -1,11 +1,12 @@ use std::fs::File; use std::path::{Path, PathBuf}; +use patch_db::Value; use serde::Deserialize; -use serde_json::Value; +use crate::prelude::*; use crate::util::serde::IoFormat; -use crate::{Config, Error, ResultExt}; +use crate::{Config, Error}; pub const DEVICE_CONFIG_PATH: &str = "/media/embassy/config/config.yaml"; pub const CONFIG_PATH: &str = "/etc/embassy/config.yaml"; @@ -37,7 +38,7 @@ pub fn load_config_from_paths<'a, T: for<'de> Deserialize<'de>>( config = merge_configs(config, new); } } - serde_json::from_value(Value::Object(config)).with_kind(crate::ErrorKind::Deserialization) + from_value(Value::Object(config)) } pub fn merge_configs(mut first: Config, second: Config) -> Config { diff --git a/backend/src/util/cpupower.rs b/backend/src/util/cpupower.rs new file mode 100644 index 000000000..a48502754 --- /dev/null +++ b/backend/src/util/cpupower.rs @@ -0,0 +1,125 @@ +use std::borrow::Cow; +use std::collections::BTreeSet; + +use imbl::OrdMap; +use tokio::process::Command; + +use crate::prelude::*; +use crate::util::Invoke; + +pub const GOVERNOR_PERFORMANCE: Governor = Governor(Cow::Borrowed("performance")); + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Governor(Cow<'static, str>); +impl std::fmt::Display for Governor { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} +impl std::ops::Deref for Governor { + type Target = str; + fn deref(&self) -> &Self::Target { + &*self.0 + } +} +impl std::borrow::Borrow for Governor { + fn borrow(&self) -> &str { + &**self + } +} + +pub async fn get_available_governors() -> Result, Error> { + let raw = String::from_utf8( + Command::new("cpupower") + .arg("frequency-info") + .arg("-g") + .invoke(ErrorKind::CpuSettings) + .await?, + )?; + let mut for_cpu: OrdMap> = OrdMap::new(); + let mut current_cpu = None; + for line in raw.lines() { + if line.starts_with("analyzing") { + current_cpu = Some( + sscanf::sscanf!(line, "analyzing CPU {u32}:") + .map_err(|e| eyre!("{e}")) + .with_kind(ErrorKind::ParseSysInfo)?, + ); + } else if let Some(rest) = line + .trim() + .strip_prefix("available cpufreq governors:") + .map(|s| s.trim()) + { + if rest != "Not Available" { + for_cpu + .entry(current_cpu.ok_or_else(|| { + Error::new( + eyre!("governors listed before cpu"), + ErrorKind::ParseSysInfo, + ) + })?) + .or_default() + .extend( + rest.split_ascii_whitespace() + .map(|g| Governor(Cow::Owned(g.to_owned()))), + ); + } + } + } + Ok(for_cpu + .into_iter() + .fold(None, |acc: Option>, (_, x)| { + if let Some(acc) = acc { + Some(acc.intersection(&x).cloned().collect()) + } else { + Some(x) + } + }) + .unwrap_or_default()) // include only governors available for ALL cpus +} + +pub async fn current_governor() -> Result, Error> { + let Some(raw) = Command::new("cpupower") + .arg("frequency-info") + .arg("-p") + .invoke(ErrorKind::CpuSettings) + .await + .and_then(|s| Ok(Some(String::from_utf8(s)?))) + .or_else(|e| { + if e.source + .to_string() + .contains("Unable to determine current policy") + { + Ok(None) + } else { + Err(e) + } + })? + else { + return Ok(None); + }; + + for line in raw.lines() { + if let Some(governor) = line + .trim() + .strip_prefix("The governor \"") + .and_then(|s| s.strip_suffix("\" may decide which speed to use")) + { + return Ok(Some(Governor(Cow::Owned(governor.to_owned())))); + } + } + Err(Error::new( + eyre!("Failed to parse cpupower output:\n{raw}"), + ErrorKind::ParseSysInfo, + )) +} + +pub async fn set_governor(governor: &Governor) -> Result<(), Error> { + Command::new("cpupower") + .arg("frequency-set") + .arg("-g") + .arg(&*governor.0) + .invoke(ErrorKind::CpuSettings) + .await?; + Ok(()) +} diff --git a/backend/src/util/crypto.rs b/backend/src/util/crypto.rs new file mode 100644 index 000000000..5c1aed01e --- /dev/null +++ b/backend/src/util/crypto.rs @@ -0,0 +1,9 @@ +use ed25519_dalek::{SecretKey, EXPANDED_SECRET_KEY_LENGTH}; + +#[inline] +pub fn ed25519_expand_key(key: &SecretKey) -> [u8; EXPANDED_SECRET_KEY_LENGTH] { + ed25519_dalek_v1::ExpandedSecretKey::from( + &ed25519_dalek_v1::SecretKey::from_bytes(key).unwrap(), + ) + .to_bytes() +} diff --git a/backend/src/util/docker.rs b/backend/src/util/docker.rs new file mode 100644 index 000000000..fb6bc15f4 --- /dev/null +++ b/backend/src/util/docker.rs @@ -0,0 +1,239 @@ +use std::net::Ipv4Addr; +use std::time::Duration; + +use models::{Error, ErrorKind, PackageId, ResultExt, Version}; +use nix::sys::signal::Signal; +use tokio::process::Command; + +use crate::util::Invoke; + +#[cfg(feature = "docker")] +pub const CONTAINER_TOOL: &str = "docker"; +#[cfg(not(feature = "docker"))] +pub const CONTAINER_TOOL: &str = "podman"; + +#[cfg(feature = "docker")] +pub const CONTAINER_DATADIR: &str = "/var/lib/docker"; +#[cfg(not(feature = "docker"))] +pub const CONTAINER_DATADIR: &str = "/var/lib/containers"; + +pub struct DockerImageSha(String); + +// docker images start9/${package}/*:${version} -q --no-trunc +pub async fn images_for( + package: &PackageId, + version: &Version, +) -> Result, Error> { + Ok(String::from_utf8( + Command::new(CONTAINER_TOOL) + .arg("images") + .arg(format!("start9/{package}/*:{version}")) + .arg("--no-trunc") + .arg("-q") + .invoke(ErrorKind::Docker) + .await?, + )? + .lines() + .map(|l| DockerImageSha(l.trim().to_owned())) + .collect()) +} + +// docker rmi -f ${sha} +pub async fn remove_image(sha: &DockerImageSha) -> Result<(), Error> { + match Command::new(CONTAINER_TOOL) + .arg("rmi") + .arg("-f") + .arg(&sha.0) + .invoke(ErrorKind::Docker) + .await + .map(|_| ()) + { + Err(e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such image") => + { + Ok(()) + } + a => a, + }?; + Ok(()) +} + +// docker image prune -f +pub async fn prune_images() -> Result<(), Error> { + Command::new(CONTAINER_TOOL) + .arg("image") + .arg("prune") + .arg("-f") + .invoke(ErrorKind::Docker) + .await?; + Ok(()) +} + +// docker container inspect ${name} --format '{{.NetworkSettings.Networks.start9.IPAddress}}' +pub async fn get_container_ip(name: &str) -> Result, Error> { + match Command::new(CONTAINER_TOOL) + .arg("container") + .arg("inspect") + .arg(name) + .arg("--format") + .arg("{{.NetworkSettings.Networks.start9.IPAddress}}") + .invoke(ErrorKind::Docker) + .await + { + Err(e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such container") => + { + Ok(None) + } + Err(e) => Err(e), + Ok(a) => { + let out = std::str::from_utf8(&a)?.trim(); + if out.is_empty() { + Ok(None) + } else { + Ok(Some({ + out.parse() + .with_ctx(|_| (ErrorKind::ParseNetAddress, out.to_string()))? + })) + } + } + } +} + +// docker stop -t ${timeout} -s ${signal} ${name} +pub async fn stop_container( + name: &str, + timeout: Option, + signal: Option, +) -> Result<(), Error> { + let mut cmd = Command::new(CONTAINER_TOOL); + cmd.arg("stop"); + if let Some(dur) = timeout { + cmd.arg("-t").arg(dur.as_secs().to_string()); + } + if let Some(sig) = signal { + cmd.arg("-s").arg(sig.to_string()); + } + cmd.arg(name); + match cmd.invoke(ErrorKind::Docker).await { + Ok(_) => Ok(()), + Err(mut e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such container") => + { + e.kind = ErrorKind::NotFound; + Err(e) + } + Err(e) => Err(e), + } +} + +// docker kill -s ${signal} ${name} +pub async fn kill_container(name: &str, signal: Option) -> Result<(), Error> { + let mut cmd = Command::new(CONTAINER_TOOL); + cmd.arg("kill"); + if let Some(sig) = signal { + cmd.arg("-s").arg(sig.to_string()); + } + cmd.arg(name); + match cmd.invoke(ErrorKind::Docker).await { + Ok(_) => Ok(()), + Err(mut e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such container") => + { + e.kind = ErrorKind::NotFound; + Err(e) + } + Err(e) => Err(e), + } +} + +// docker pause ${name} +pub async fn pause_container(name: &str) -> Result<(), Error> { + let mut cmd = Command::new(CONTAINER_TOOL); + cmd.arg("pause"); + cmd.arg(name); + match cmd.invoke(ErrorKind::Docker).await { + Ok(_) => Ok(()), + Err(mut e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such container") => + { + e.kind = ErrorKind::NotFound; + Err(e) + } + Err(e) => Err(e), + } +} + +// docker unpause ${name} +pub async fn unpause_container(name: &str) -> Result<(), Error> { + let mut cmd = Command::new(CONTAINER_TOOL); + cmd.arg("unpause"); + cmd.arg(name); + match cmd.invoke(ErrorKind::Docker).await { + Ok(_) => Ok(()), + Err(mut e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such container") => + { + e.kind = ErrorKind::NotFound; + Err(e) + } + Err(e) => Err(e), + } +} + +// docker rm -f ${name} +pub async fn remove_container(name: &str, force: bool) -> Result<(), Error> { + let mut cmd = Command::new(CONTAINER_TOOL); + cmd.arg("rm"); + if force { + cmd.arg("-f"); + } + cmd.arg(name); + match cmd.invoke(ErrorKind::Docker).await { + Ok(_) => Ok(()), + Err(e) + if e.source + .to_string() + .to_ascii_lowercase() + .contains("no such container") => + { + Ok(()) + } + Err(e) => Err(e), + } +} + +// docker network create -d bridge --subnet ${subnet} --opt com.podman.network.bridge.name=${bridge_name} +pub async fn create_bridge_network( + name: &str, + subnet: &str, + bridge_name: &str, +) -> Result<(), Error> { + let mut cmd = Command::new(CONTAINER_TOOL); + cmd.arg("network").arg("create"); + cmd.arg("-d").arg("bridge"); + cmd.arg("--subnet").arg(subnet); + cmd.arg("--opt") + .arg(format!("com.docker.network.bridge.name={bridge_name}")); + cmd.arg(name); + cmd.invoke(ErrorKind::Docker).await?; + Ok(()) +} diff --git a/backend/src/util/http_reader.rs b/backend/src/util/http_reader.rs index a32dd113d..87e8c114e 100644 --- a/backend/src/util/http_reader.rs +++ b/backend/src/util/http_reader.rs @@ -376,5 +376,5 @@ async fn s9pk_test() { .unwrap(); let manifest = s9pk.manifest().await.unwrap(); - assert_eq!(&**manifest.id, "ghost"); + assert_eq!(&manifest.id.to_string(), "ghost"); } diff --git a/backend/src/util/io.rs b/backend/src/util/io.rs index ad831d14f..282a2db8e 100644 --- a/backend/src/util/io.rs +++ b/backend/src/util/io.rs @@ -143,7 +143,7 @@ where { let mut buffer = Vec::new(); reader.read_to_end(&mut buffer).await?; - serde_toml::from_slice(&buffer) + serde_toml::from_str(std::str::from_utf8(&buffer)?) .map_err(color_eyre::eyre::Error::from) .with_kind(crate::ErrorKind::Deserialization) } @@ -153,7 +153,9 @@ where T: serde::Serialize, W: AsyncWrite + Unpin, { - let mut buffer = serde_toml::to_vec(value).with_kind(crate::ErrorKind::Serialization)?; + let mut buffer = serde_toml::to_string(value) + .with_kind(crate::ErrorKind::Serialization)? + .into_bytes(); buffer.extend_from_slice(b"\n"); writer.write_all(&buffer).await?; Ok(()) @@ -522,7 +524,6 @@ pub fn dir_copy<'a, P0: AsRef + 'a + Send + Sync, P1: AsRef + 'a + S let src_path = e.path(); let dst_path = dst_path.join(e.file_name()); if m.is_file() { - let len = m.len(); let mut dst_file = tokio::fs::File::create(&dst_path).await.with_ctx(|_| { ( crate::ErrorKind::Filesystem, @@ -638,7 +639,7 @@ impl AsyncWrite for TimeoutStream { cx: &mut std::task::Context<'_>, buf: &[u8], ) -> std::task::Poll> { - let mut this = self.project(); + let this = self.project(); let res = this.stream.poll_write(cx, buf); if res.is_ready() { this.sleep.reset(Instant::now() + *this.timeout); @@ -649,7 +650,7 @@ impl AsyncWrite for TimeoutStream { self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { - let mut this = self.project(); + let this = self.project(); let res = this.stream.poll_flush(cx); if res.is_ready() { this.sleep.reset(Instant::now() + *this.timeout); @@ -660,7 +661,7 @@ impl AsyncWrite for TimeoutStream { self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> std::task::Poll> { - let mut this = self.project(); + let this = self.project(); let res = this.stream.poll_shutdown(cx); if res.is_ready() { this.sleep.reset(Instant::now() + *this.timeout); diff --git a/backend/src/util/logger.rs b/backend/src/util/logger.rs index 8208f7de6..c7ab41ba2 100644 --- a/backend/src/util/logger.rs +++ b/backend/src/util/logger.rs @@ -10,13 +10,28 @@ impl EmbassyLogger { use tracing_subscriber::prelude::*; use tracing_subscriber::{fmt, EnvFilter}; - let filter_layer = EnvFilter::from_default_env(); + let filter_layer = EnvFilter::builder() + .with_default_directive( + format!("{}=info", std::module_path!().split("::").next().unwrap()) + .parse() + .unwrap(), + ) + .from_env_lossy(); + #[cfg(feature = "unstable")] + let filter_layer = filter_layer + .add_directive("tokio=trace".parse().unwrap()) + .add_directive("runtime=trace".parse().unwrap()); let fmt_layer = fmt::layer().with_target(true); - tracing_subscriber::registry() + let sub = tracing_subscriber::registry() .with(filter_layer) .with(fmt_layer) - .with(ErrorLayer::default()) + .with(ErrorLayer::default()); + + #[cfg(feature = "unstable")] + let sub = sub.with(console_subscriber::spawn()); + + sub } pub fn init() -> Self { Self::base_subscriber().init(); diff --git a/backend/src/util/lshw.rs b/backend/src/util/lshw.rs index 4de4bf46e..dd260f644 100644 --- a/backend/src/util/lshw.rs +++ b/backend/src/util/lshw.rs @@ -44,6 +44,20 @@ pub async fn lshw() -> Result, Error> { for class in KNOWN_CLASSES { cmd.arg("-class").arg(*class); } - serde_json::from_slice(&cmd.invoke(crate::ErrorKind::Lshw).await?) - .with_kind(crate::ErrorKind::Deserialization) + Ok( + serde_json::from_slice::>( + &cmd.invoke(crate::ErrorKind::Lshw).await?, + ) + .with_kind(crate::ErrorKind::Deserialization)? + .into_iter() + .filter_map(|v| match serde_json::from_value(v) { + Ok(a) => Some(a), + Err(e) => { + tracing::error!("Failed to parse lshw output: {e}"); + tracing::debug!("{e:?}"); + None + } + }) + .collect(), + ) } diff --git a/backend/src/util/mod.rs b/backend/src/util/mod.rs index 0b70604b0..2683f23c8 100644 --- a/backend/src/util/mod.rs +++ b/backend/src/util/mod.rs @@ -6,6 +6,7 @@ use std::pin::Pin; use std::process::Stdio; use std::sync::Arc; use std::task::{Context, Poll}; +use std::time::Duration; use async_trait::async_trait; use clap::ArgMatches; @@ -16,7 +17,7 @@ pub use helpers::NonDetachingJoinHandle; use lazy_static::lazy_static; pub use models::Version; use pin_project::pin_project; -use sha2_old::Digest; +use sha2::Digest; use tokio::fs::File; use tokio::sync::{Mutex, OwnedMutexGuard, RwLock}; use tracing::instrument; @@ -24,13 +25,16 @@ use tracing::instrument; use crate::shutdown::Shutdown; use crate::{Error, ErrorKind, ResultExt as _}; pub mod config; +pub mod cpupower; +pub mod crypto; +pub mod docker; pub mod http_reader; pub mod io; pub mod logger; pub mod lshw; pub mod serde; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, ::serde::Deserialize, ::serde::Serialize)] pub enum Never {} impl Never {} impl Never { @@ -46,15 +50,116 @@ impl std::fmt::Display for Never { impl std::error::Error for Never {} #[async_trait::async_trait] -pub trait Invoke { +pub trait Invoke<'a> { + type Extended<'ext> + where + Self: 'ext, + 'ext: 'a; + fn timeout<'ext: 'a>(&'ext mut self, timeout: Option) -> Self::Extended<'ext>; + fn input<'ext: 'a, Input: tokio::io::AsyncRead + Unpin + Send>( + &'ext mut self, + input: Option<&'ext mut Input>, + ) -> Self::Extended<'ext>; async fn invoke(&mut self, error_kind: crate::ErrorKind) -> Result, Error>; } + +pub struct ExtendedCommand<'a> { + cmd: &'a mut tokio::process::Command, + timeout: Option, + input: Option<&'a mut (dyn tokio::io::AsyncRead + Unpin + Send)>, +} +impl<'a> std::ops::Deref for ExtendedCommand<'a> { + type Target = tokio::process::Command; + fn deref(&self) -> &Self::Target { + &*self.cmd + } +} +impl<'a> std::ops::DerefMut for ExtendedCommand<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.cmd + } +} + #[async_trait::async_trait] -impl Invoke for tokio::process::Command { +impl<'a> Invoke<'a> for tokio::process::Command { + type Extended<'ext> = ExtendedCommand<'ext> + where + Self: 'ext, + 'ext: 'a; + fn timeout<'ext: 'a>(&'ext mut self, timeout: Option) -> Self::Extended<'ext> { + ExtendedCommand { + cmd: self, + timeout, + input: None, + } + } + fn input<'ext: 'a, Input: tokio::io::AsyncRead + Unpin + Send>( + &'ext mut self, + input: Option<&'ext mut Input>, + ) -> Self::Extended<'ext> { + ExtendedCommand { + cmd: self, + timeout: None, + input: if let Some(input) = input { + Some(&mut *input) + } else { + None + }, + } + } async fn invoke(&mut self, error_kind: crate::ErrorKind) -> Result, Error> { - self.stdout(Stdio::piped()); - self.stderr(Stdio::piped()); - let res = self.output().await?; + ExtendedCommand { + cmd: self, + timeout: None, + input: None, + } + .invoke(error_kind) + .await + } +} + +#[async_trait::async_trait] +impl<'a> Invoke<'a> for ExtendedCommand<'a> { + type Extended<'ext> = &'ext mut ExtendedCommand<'ext> + where + Self: 'ext, + 'ext: 'a; + fn timeout<'ext: 'a>(&'ext mut self, timeout: Option) -> Self::Extended<'ext> { + self.timeout = timeout; + self + } + fn input<'ext: 'a, Input: tokio::io::AsyncRead + Unpin + Send>( + &'ext mut self, + input: Option<&'ext mut Input>, + ) -> Self::Extended<'ext> { + self.input = if let Some(input) = input { + Some(&mut *input) + } else { + None + }; + self + } + async fn invoke(&mut self, error_kind: crate::ErrorKind) -> Result, Error> { + self.cmd.kill_on_drop(true); + if self.input.is_some() { + self.cmd.stdin(Stdio::piped()); + } + self.cmd.stdout(Stdio::piped()); + self.cmd.stderr(Stdio::piped()); + let mut child = self.cmd.spawn()?; + if let (Some(mut stdin), Some(input)) = (child.stdin.take(), self.input.take()) { + use tokio::io::AsyncWriteExt; + tokio::io::copy(input, &mut stdin).await?; + stdin.flush().await?; + stdin.shutdown().await?; + drop(stdin); + } + let res = match self.timeout { + None => child.wait_with_output().await?, + Some(t) => tokio::time::timeout(t, child.wait_with_output()) + .await + .with_kind(ErrorKind::Timeout)??, + }; crate::ensure_code!( res.status.success(), error_kind, @@ -170,9 +275,7 @@ impl std::io::Write for FmtWriter { } } -pub fn display_none(_: T, _: &ArgMatches) { - () -} +pub fn display_none(_: T, _: &ArgMatches) {} pub struct Container(RwLock>); impl Container { @@ -183,7 +286,7 @@ impl Container { std::mem::replace(&mut *self.0.write().await, Some(value)) } pub async fn take(&self) -> Option { - std::mem::replace(&mut *self.0.write().await, None) + self.0.write().await.take() } pub async fn is_empty(&self) -> bool { self.0.read().await.is_none() @@ -220,7 +323,7 @@ impl tokio::io::AsyncWrite for HashWriter Poll> { let this = self.project(); - let written = tokio::io::AsyncWrite::poll_write(this.writer, cx, &buf); + let written = tokio::io::AsyncWrite::poll_write(this.writer, cx, buf); match written { // only update the hasher once Poll::Ready(res) => { @@ -256,6 +359,29 @@ where } } +pub struct GeneralBoxedGuard(Option>); +impl GeneralBoxedGuard { + pub fn new(f: impl FnOnce() + 'static + Send + Sync) -> Self { + GeneralBoxedGuard(Some(Box::new(f))) + } + + pub fn drop(mut self) { + self.0.take().unwrap()() + } + + pub fn drop_without_action(mut self) { + self.0 = None; + } +} + +impl Drop for GeneralBoxedGuard { + fn drop(&mut self) { + if let Some(destroy) = self.0.take() { + destroy(); + } + } +} + pub struct GeneralGuard T, T = ()>(Option); impl T, T> GeneralGuard { pub fn new(f: F) -> Self { @@ -279,29 +405,6 @@ impl T, T> Drop for GeneralGuard { } } -pub struct GeneralBoxedGuard(Option ()>>); -impl GeneralBoxedGuard { - pub fn new(f: impl FnOnce() -> () + 'static) -> Self { - GeneralBoxedGuard(Some(Box::new(f))) - } - - pub fn drop(mut self) -> () { - self.0.take().unwrap()() - } - - pub fn drop_without_action(mut self) { - self.0 = None; - } -} - -impl Drop for GeneralBoxedGuard { - fn drop(&mut self) { - if let Some(destroy) = self.0.take() { - destroy(); - } - } -} - pub struct FileLock(OwnedMutexGuard<()>, Option>); impl Drop for FileLock { fn drop(&mut self) { diff --git a/backend/src/util/serde.rs b/backend/src/util/serde.rs index 856923c09..4a6f7551b 100644 --- a/backend/src/util/serde.rs +++ b/backend/src/util/serde.rs @@ -97,20 +97,25 @@ pub fn serialize_display_opt( } pub mod ed25519_pubkey { - use ed25519_dalek::PublicKey; + use ed25519_dalek::VerifyingKey; use serde::de::{Error, Unexpected, Visitor}; use serde::{Deserializer, Serializer}; - pub fn serialize(pubkey: &PublicKey, serializer: S) -> Result { + pub fn serialize( + pubkey: &VerifyingKey, + serializer: S, + ) -> Result { serializer.serialize_str(&base32::encode( base32::Alphabet::RFC4648 { padding: true }, pubkey.as_bytes(), )) } - pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + pub fn deserialize<'de, D: Deserializer<'de>>( + deserializer: D, + ) -> Result { struct PubkeyVisitor; impl<'de> Visitor<'de> for PubkeyVisitor { - type Value = ed25519_dalek::PublicKey; + type Value = ed25519_dalek::VerifyingKey; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(formatter, "an RFC4648 encoded string") } @@ -118,10 +123,13 @@ pub mod ed25519_pubkey { where E: Error, { - PublicKey::from_bytes( - &base32::decode(base32::Alphabet::RFC4648 { padding: true }, v).ok_or( - Error::invalid_value(Unexpected::Str(v), &"an RFC4648 encoded string"), - )?, + VerifyingKey::from_bytes( + &<[u8; 32]>::try_from( + base32::decode(base32::Alphabet::RFC4648 { padding: true }, v).ok_or( + Error::invalid_value(Unexpected::Str(v), &"an RFC4648 encoded string"), + )?, + ) + .map_err(|e| Error::invalid_length(e.len(), &"32 bytes"))?, ) .map_err(Error::custom) } @@ -312,11 +320,12 @@ impl IoFormat { .with_kind(crate::ErrorKind::Serialization), IoFormat::Toml => writer .write_all( - &serde_toml::to_vec( + serde_toml::to_string( &serde_toml::Value::try_from(value) .with_kind(crate::ErrorKind::Serialization)?, ) - .with_kind(crate::ErrorKind::Serialization)?, + .with_kind(crate::ErrorKind::Serialization)? + .as_bytes(), ) .with_kind(crate::ErrorKind::Serialization), IoFormat::TomlPretty => writer @@ -346,10 +355,11 @@ impl IoFormat { .with_kind(crate::ErrorKind::Serialization)?; Ok(res) } - IoFormat::Toml => serde_toml::to_vec( + IoFormat::Toml => serde_toml::to_string( &serde_toml::Value::try_from(value).with_kind(crate::ErrorKind::Serialization)?, ) - .with_kind(crate::ErrorKind::Serialization), + .with_kind(crate::ErrorKind::Serialization) + .map(|s| s.into_bytes()), IoFormat::TomlPretty => serde_toml::to_string_pretty( &serde_toml::Value::try_from(value).with_kind(crate::ErrorKind::Serialization)?, ) @@ -408,7 +418,8 @@ impl IoFormat { serde_cbor::de::from_reader(slice).with_kind(crate::ErrorKind::Deserialization) } IoFormat::Toml | IoFormat::TomlPretty => { - serde_toml::from_slice(slice).with_kind(crate::ErrorKind::Deserialization) + serde_toml::from_str(std::str::from_utf8(slice)?) + .with_kind(crate::ErrorKind::Deserialization) } } } diff --git a/backend/src/version/mod.rs b/backend/src/version/mod.rs index 0bd16adba..3c14c934d 100644 --- a/backend/src/version/mod.rs +++ b/backend/src/version/mod.rs @@ -2,14 +2,13 @@ use std::cmp::Ordering; use async_trait::async_trait; use color_eyre::eyre::eyre; -use patch_db::DbHandle; use rpc_toolkit::command; use sqlx::PgPool; -use crate::init::InitReceipts; +use crate::prelude::*; use crate::Error; -mod v0_3_4_3; +mod v0_3_5; mod v0_4_0; pub type Current = v0_4_0::Version; @@ -17,8 +16,8 @@ pub type Current = v0_4_0::Version; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] #[serde(untagged)] enum Version { - LT0_3_4_3(LTWrapper), - V0_3_4_3(Wrapper), + LT0_3_5(LTWrapper), + V0_3_5(Wrapper), V0_4_0(Wrapper), Other(emver::Version), } @@ -35,8 +34,8 @@ impl Version { #[cfg(test)] fn as_sem_ver(&self) -> emver::Version { match self { - Version::LT0_3_4_3(LTWrapper(_, x)) => x.clone(), - Version::V0_3_4_3(Wrapper(x)) => x.semver(), + Version::LT0_3_5(LTWrapper(_, x)) => x.clone(), + Version::V0_3_5(Wrapper(x)) => x.semver(), Version::V0_4_0(Wrapper(x)) => x.semver(), Version::Other(x) => x.clone(), } @@ -52,55 +51,43 @@ where fn new() -> Self; fn semver(&self) -> emver::Version; fn compat(&self) -> &'static emver::VersionRange; - async fn up(&self, db: &mut Db, secrets: &PgPool) -> Result<(), Error>; - async fn down(&self, db: &mut Db, secrets: &PgPool) -> Result<(), Error>; - async fn commit( - &self, - db: &mut Db, - receipts: &InitReceipts, - ) -> Result<(), Error> { - receipts - .version_range - .set(db, self.compat().clone()) - .await?; - receipts - .server_version - .set(db, self.semver().into()) - .await?; - + async fn up(&self, db: &PatchDb, secrets: &PgPool) -> Result<(), Error>; + async fn down(&self, db: &PatchDb, secrets: &PgPool) -> Result<(), Error>; + async fn commit(&self, db: &PatchDb) -> Result<(), Error> { + let semver = self.semver().into(); + let compat = self.compat().clone(); + db.mutate(|d| { + d.as_server_info_mut().as_version_mut().ser(&semver)?; + d.as_server_info_mut() + .as_eos_version_compat_mut() + .ser(&compat)?; + Ok(()) + }) + .await?; Ok(()) } - async fn migrate_to( + async fn migrate_to( &self, version: &V, - db: &mut Db, + db: &PatchDb, secrets: &PgPool, - receipts: &InitReceipts, ) -> Result<(), Error> { match self.semver().cmp(&version.semver()) { - Ordering::Greater => { - self.rollback_to_unchecked(version, db, secrets, receipts) - .await - } - Ordering::Less => { - version - .migrate_from_unchecked(self, db, secrets, receipts) - .await - } + Ordering::Greater => self.rollback_to_unchecked(version, db, secrets).await, + Ordering::Less => version.migrate_from_unchecked(self, db, secrets).await, Ordering::Equal => Ok(()), } } - async fn migrate_from_unchecked( + async fn migrate_from_unchecked( &self, version: &V, - db: &mut Db, + db: &PatchDb, secrets: &PgPool, - receipts: &InitReceipts, ) -> Result<(), Error> { let previous = Self::Previous::new(); if version.semver() < previous.semver() { previous - .migrate_from_unchecked(version, db, secrets, receipts) + .migrate_from_unchecked(version, db, secrets) .await?; } else if version.semver() > previous.semver() { return Err(Error::new( @@ -113,24 +100,21 @@ where } tracing::info!("{} -> {}", previous.semver(), self.semver(),); self.up(db, secrets).await?; - self.commit(db, receipts).await?; + self.commit(db).await?; Ok(()) } - async fn rollback_to_unchecked( + async fn rollback_to_unchecked( &self, version: &V, - db: &mut Db, + db: &PatchDb, secrets: &PgPool, - receipts: &InitReceipts, ) -> Result<(), Error> { let previous = Self::Previous::new(); tracing::info!("{} -> {}", self.semver(), previous.semver(),); self.down(db, secrets).await?; - previous.commit(db, receipts).await?; + previous.commit(db).await?; if version.semver() < previous.semver() { - previous - .rollback_to_unchecked(version, db, secrets, receipts) - .await?; + previous.rollback_to_unchecked(version, db, secrets).await?; } else if version.semver() > previous.semver() { return Err(Error::new( eyre!( @@ -194,27 +178,18 @@ where } } -pub async fn init( - db: &mut Db, - secrets: &PgPool, - receipts: &crate::init::InitReceipts, -) -> Result<(), Error> { - let version = Version::from_util_version(receipts.server_version.get(db).await?); +pub async fn init(db: &PatchDb, secrets: &PgPool) -> Result<(), Error> { + let version = Version::from_util_version(db.peek().await.as_server_info().as_version().de()?); + match version { - Version::LT0_3_4_3(_) => { + Version::LT0_3_5(_) => { return Err(Error::new( - eyre!("Cannot migrate from pre-0.3.4. Please update to v0.3.4 first."), + eyre!("Cannot migrate from pre-0.3.5. Please update to v0.3.5 first."), crate::ErrorKind::MigrationFailed, )); } - Version::V0_3_4_3(v) => { - v.0.migrate_to(&Current::new(), db, secrets, receipts) - .await? - } - Version::V0_4_0(v) => { - v.0.migrate_to(&Current::new(), db, secrets, receipts) - .await? - } + Version::V0_3_5(v) => v.0.migrate_to(&Current::new(), db, secrets).await?, + Version::V0_4_0(v) => v.0.migrate_to(&Current::new(), db, secrets).await?, Version::Other(_) => { return Err(Error::new( eyre!("Cannot downgrade"), @@ -225,8 +200,7 @@ pub async fn init( Ok(()) } -pub const COMMIT_HASH: &str = - git_version::git_version!(args = ["--always", "--abbrev=40", "--dirty=-modified"]); +pub const COMMIT_HASH: &str = include_str!("../../../GIT_HASH.txt"); #[command(rename = "git-info", local, metadata(authenticated = false))] pub fn git_info() -> Result<&'static str, Error> { @@ -247,15 +221,15 @@ mod tests { fn versions() -> impl Strategy { prop_oneof![ - em_version().prop_map(|v| if v < v0_3_4_3::Version::new().semver() { - Version::LT0_3_4_3(LTWrapper(v0_3_4_3::Version::new(), v)) + em_version().prop_map(|v| if v < v0_3_5::Version::new().semver() { + Version::LT0_3_5(LTWrapper(v0_3_5::Version::new(), v)) } else { - Version::LT0_3_4_3(LTWrapper( - v0_3_4_3::Version::new(), + Version::LT0_3_5(LTWrapper( + v0_3_5::Version::new(), emver::Version::new(0, 3, 0, 0), )) }), - Just(Version::V0_3_4_3(Wrapper(v0_3_4_3::Version::new()))), + Just(Version::V0_3_5(Wrapper(v0_3_5::Version::new()))), Just(Version::V0_4_0(Wrapper(v0_4_0::Version::new()))), em_version().prop_map(Version::Other), ] diff --git a/backend/src/version/v0_3_4_4.rs b/backend/src/version/v0_3_4_4.rs deleted file mode 100644 index 1876ff700..000000000 --- a/backend/src/version/v0_3_4_4.rs +++ /dev/null @@ -1,41 +0,0 @@ -use async_trait::async_trait; -use emver::VersionRange; -use models::ResultExt; - -use super::v0_3_0::V0_3_0_COMPAT; -use super::*; - -const V0_3_4_4: emver::Version = emver::Version::new(0, 3, 4, 4); - -#[derive(Clone, Debug)] -pub struct Version; - -#[async_trait] -impl VersionT for Version { - type Previous = v0_3_4_3::Version; - fn new() -> Self { - Version - } - fn semver(&self) -> emver::Version { - V0_3_4_4 - } - fn compat(&self) -> &'static VersionRange { - &*V0_3_0_COMPAT - } - async fn up(&self, db: &mut Db, _secrets: &PgPool) -> Result<(), Error> { - let mut tor_addr = crate::db::DatabaseModel::new() - .server_info() - .tor_address() - .get_mut(db) - .await?; - tor_addr - .set_scheme("https") - .map_err(|_| eyre!("unable to update url scheme to https")) - .with_kind(crate::ErrorKind::ParseUrl)?; - tor_addr.save(db).await?; - Ok(()) - } - async fn down(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> { - Ok(()) - } -} diff --git a/backend/src/version/v0_3_4_3.rs b/backend/src/version/v0_3_5.rs similarity index 70% rename from backend/src/version/v0_3_4_3.rs rename to backend/src/version/v0_3_5.rs index 9a822c517..279897743 100644 --- a/backend/src/version/v0_3_4_3.rs +++ b/backend/src/version/v0_3_5.rs @@ -3,8 +3,9 @@ use emver::VersionRange; use lazy_static::lazy_static; use super::*; +use crate::prelude::*; -const V0_3_4_3: emver::Version = emver::Version::new(0, 3, 4, 3); +const V0_3_5: emver::Version = emver::Version::new(0, 3, 5, 0); lazy_static! { static ref V0_3_0_COMPAT: VersionRange = VersionRange::Conj( Box::new(VersionRange::Anchor( @@ -25,15 +26,15 @@ impl VersionT for Version { Version } fn semver(&self) -> emver::Version { - V0_3_4_3 + V0_3_5 } fn compat(&self) -> &'static VersionRange { - &*V0_3_0_COMPAT + &V0_3_0_COMPAT } - async fn up(&self, db: &mut Db, _secrets: &PgPool) -> Result<(), Error> { + async fn up(&self, _db: &PatchDb, _secrets: &PgPool) -> Result<(), Error> { Ok(()) } - async fn down(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> { + async fn down(&self, _db: &PatchDb, _secrets: &PgPool) -> Result<(), Error> { Ok(()) } } diff --git a/backend/src/version/v0_4_0.rs b/backend/src/version/v0_4_0.rs index a1e281ec5..bcf5b57a4 100644 --- a/backend/src/version/v0_4_0.rs +++ b/backend/src/version/v0_4_0.rs @@ -17,7 +17,7 @@ pub struct Version; #[async_trait] impl VersionT for Version { - type Previous = v0_3_4_3::Version; + type Previous = v0_3_5::Version; fn new() -> Self { Version } @@ -27,10 +27,10 @@ impl VersionT for Version { fn compat(&self) -> &'static VersionRange { &*V0_4_0_COMPAT } - async fn up(&self, db: &mut Db, secrets: &PgPool) -> Result<(), Error> { + async fn up(&self, _db: &PatchDb, _secrets: &PgPool) -> Result<(), Error> { Ok(()) } - async fn down(&self, db: &mut Db, secrets: &PgPool) -> Result<(), Error> { + async fn down(&self, _db: &PatchDb, _secrets: &PgPool) -> Result<(), Error> { Ok(()) } } diff --git a/backend/src/volume.rs b/backend/src/volume.rs index 594217980..1633b7d18 100644 --- a/backend/src/volume.rs +++ b/backend/src/volume.rs @@ -4,13 +4,13 @@ use std::path::{Path, PathBuf}; pub use helpers::script_dir; pub use models::VolumeId; -use patch_db::{HasModel, Map, MapModel}; use serde::{Deserialize, Serialize}; use tracing::instrument; use crate::context::RpcContext; use crate::net::interface::{InterfaceId, Interfaces}; use crate::net::PACKAGE_CERT_PATH; +use crate::prelude::*; use crate::s9pk::manifest::PackageId; use crate::util::Version; use crate::{Error, ResultExt}; @@ -27,6 +27,12 @@ impl Volumes { volume .validate(interfaces) .with_ctx(|_| (crate::ErrorKind::ValidateS9pk, format!("Volume {}", id)))?; + if let Volume::Backup { .. } = volume { + return Err(Error::new( + eyre!("Invalid volume type \"backup\""), + ErrorKind::ParseS9pk, + )); // Volume::Backup is for internal use and shouldn't be declared in manifest + } } Ok(()) } @@ -82,13 +88,6 @@ impl DerefMut for Volumes { impl Map for Volumes { type Key = VolumeId; type Value = Volume; - fn get(&self, key: &Self::Key) -> Option<&Self::Value> { - self.0.get(key) - } -} -pub type VolumesModel = MapModel; -impl HasModel for Volumes { - type Model = MapModel; } pub fn data_dir>(datadir: P, pkg_id: &PackageId, volume_id: &VolumeId) -> PathBuf { @@ -117,7 +116,7 @@ pub fn cert_dir(pkg_id: &PackageId, interface_id: &InterfaceId) -> PathBuf { Path::new(PACKAGE_CERT_PATH).join(pkg_id).join(interface_id) } -#[derive(Clone, Debug, Deserialize, Serialize, HasModel)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(tag = "type")] #[serde(rename_all = "kebab-case")] pub enum Volume { @@ -138,7 +137,6 @@ pub enum Volume { #[serde(rename_all = "kebab-case")] Certificate { interface_id: InterfaceId }, #[serde(rename_all = "kebab-case")] - #[serde(skip)] Backup { readonly: bool }, } impl Volume { diff --git a/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js b/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js index 752051b9a..dc3e0f717 100644 --- a/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js +++ b/backend/test/js_action_execute/package-data/scripts/test-package/0.3.0.3/embassy.js @@ -855,7 +855,7 @@ export const action = { }, /** * Created this test because of issue - * https://github.com/Start9Labs/embassy-os/issues/1737 + * https://github.com/Start9Labs/start-os/issues/1737 * which that we couldn't create a dir that was deeply nested, and the parents where * not created yet. Found this out during the migrations, where the parent would die. * @param {*} effects @@ -931,7 +931,7 @@ export const action = { }, /** * Created this test because of issue - * https://github.com/Start9Labs/embassy-os/issues/2121 + * https://github.com/Start9Labs/start-os/issues/2121 * That the empty in the create dies * @param {*} effects * @param {*} _input diff --git a/backend/update-sqlx-data.sh b/backend/update-sqlx-data.sh index 46dc26a0e..83ec111f0 100755 --- a/backend/update-sqlx-data.sh +++ b/backend/update-sqlx-data.sh @@ -15,7 +15,7 @@ docker run -d --rm --name=tmp_postgres -e POSTGRES_PASSWORD=password -v $TMP_DIR PG_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' tmp_postgres) DATABASE_URL=postgres://postgres:password@$PG_IP/postgres cargo sqlx migrate run - DATABASE_URL=postgres://postgres:password@$PG_IP/postgres cargo sqlx prepare -- --lib --profile=test + DATABASE_URL=postgres://postgres:password@$PG_IP/postgres PLATFORM=$(uname -m) cargo sqlx prepare -- --lib --profile=test ) docker stop tmp_postgres diff --git a/basename.sh b/basename.sh new file mode 100755 index 000000000..679faa5bc --- /dev/null +++ b/basename.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +cd "$(dirname "${BASH_SOURCE[0]}")" + +PLATFORM="$(if [ -f ./PLATFORM.txt ]; then cat ./PLATFORM.txt; else echo unknown; fi)" +VERSION="$(cat ./VERSION.txt)" +GIT_HASH="$(cat ./GIT_HASH.txt)" +if [[ "$GIT_HASH" =~ ^@ ]]; then + GIT_HASH=unknown +else + GIT_HASH="$(echo -n "$GIT_HASH" | head -c 7)" +fi +STARTOS_ENV="$(cat ./ENVIRONMENT.txt)" +VERSION_FULL="${VERSION}-${GIT_HASH}" +if [ -n "$STARTOS_ENV" ]; then + VERSION_FULL="$VERSION_FULL~${STARTOS_ENV}" +fi + +echo -n "startos-${VERSION_FULL}_${PLATFORM}" \ No newline at end of file diff --git a/build-cargo-dep.sh b/build-cargo-dep.sh index f4ad4c951..f3cb8e969 100755 --- a/build-cargo-dep.sh +++ b/build-cargo-dep.sh @@ -4,7 +4,7 @@ set -e shopt -s expand_aliases if [ "$0" != "./build-cargo-dep.sh" ]; then - >&2 echo "Must be run from embassy-os directory" + >&2 echo "Must be run from start-os directory" exit 1 fi diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 000000000..357c0e49f --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,2 @@ +lib/depends +lib/conflicts \ No newline at end of file diff --git a/build/lib/conflicts b/build/dpkg-deps/conflicts similarity index 51% rename from build/lib/conflicts rename to build/dpkg-deps/conflicts index 536950a42..12a2f73b2 100644 --- a/build/lib/conflicts +++ b/build/dpkg-deps/conflicts @@ -1,5 +1,5 @@ -openresolv dhcpcd5 firewalld nginx -nginx-common \ No newline at end of file +nginx-common +openresolv \ No newline at end of file diff --git a/build/lib/depends b/build/dpkg-deps/depends similarity index 89% rename from build/lib/depends rename to build/dpkg-deps/depends index 23d19660e..a712d4a52 100644 --- a/build/lib/depends +++ b/build/dpkg-deps/depends @@ -6,16 +6,14 @@ bmon btrfs-progs ca-certificates cifs-utils -containerd.io -curl cryptsetup -docker-ce -docker-ce-cli -docker-compose-plugin +curl +dmidecode dosfstools e2fsprogs ecryptfs-utils exfatprogs +flashrom grub-common htop httpdirfs @@ -23,6 +21,8 @@ iotop iw jq libavahi-client3 +libyajl2 +linux-cpupower lm-sensors lshw lvm2 @@ -34,6 +34,7 @@ network-manager nvme-cli nyx openssh-server +podman postgresql psmisc qemu-guest-agent diff --git a/build/dpkg-deps/docker.depends b/build/dpkg-deps/docker.depends new file mode 100644 index 000000000..dd78be8a1 --- /dev/null +++ b/build/dpkg-deps/docker.depends @@ -0,0 +1,5 @@ ++ containerd.io ++ docker-ce ++ docker-ce-cli ++ docker-compose-plugin +- podman \ No newline at end of file diff --git a/build/dpkg-deps/generate.sh b/build/dpkg-deps/generate.sh new file mode 100755 index 000000000..53a7b87e5 --- /dev/null +++ b/build/dpkg-deps/generate.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +cd "$(dirname "${BASH_SOURCE[0]}")" + +IFS="-" read -ra FEATURES <<< "$ENVIRONMENT" + +feature_file_checker=' +/^#/ { next } +/^\+ [a-z0-9]+$/ { next } +/^- [a-z0-9]+$/ { next } +{ exit 1 } +' + +for type in conflicts depends; do + pkgs=() + for feature in ${FEATURES[@]}; do + file="$feature.$type" + if [ -f $file ]; then + # TODO check for syntax errrors + cat $file | awk "$feature_file_checker" + for pkg in $(cat $file | awk '/^\+/ {print $2}'); do + pkgs+=($pkg) + done + fi + done + for pkg in $(cat $type); do + SKIP= + for feature in ${FEATURES[@]}; do + file="$feature.$type" + if [ -f $file ]; then + if grep "^- $pkg$" $file; then + SKIP=1 + fi + fi + done + if [ -z $SKIP ]; then + pkgs+=($pkg) + fi + done + (IFS=$'\n'; echo "${pkgs[*]}") | sort -u > ../lib/$type +done diff --git a/build/dpkg-deps/unstable.depends b/build/dpkg-deps/unstable.depends new file mode 100644 index 000000000..fe5dee256 --- /dev/null +++ b/build/dpkg-deps/unstable.depends @@ -0,0 +1,2 @@ ++ gdb ++ heaptrack \ No newline at end of file diff --git a/build/lib/docker-engine.slice b/build/lib/docker-engine.slice deleted file mode 100644 index fd8f93ba4..000000000 --- a/build/lib/docker-engine.slice +++ /dev/null @@ -1,8 +0,0 @@ -[Unit] -Description=Slice that limits docker resources -Before=slices.target - -[Slice] -MemoryAccounting=true -MemoryHigh=80% -MemoryMax=85% diff --git a/build/lib/firmware/librem_mini_v2/PureBoot-Release-28.1.rom.gz b/build/lib/firmware/librem_mini_v2/PureBoot-Release-28.1.rom.gz new file mode 100644 index 000000000..3e5376759 Binary files /dev/null and b/build/lib/firmware/librem_mini_v2/PureBoot-Release-28.1.rom.gz differ diff --git a/build/lib/motd b/build/lib/motd old mode 100644 new mode 100755 index 88ff55d6f..5e98aa887 --- a/build/lib/motd +++ b/build/lib/motd @@ -2,23 +2,33 @@ printf "\n" printf "Welcome to\n" cat << "ASCII" - ╭ ━ ━ ━ ╮ ╭ ╮ ╱ ╱ ╱ ╱ ╱ ╭ ╮ ╭ ━ ━ ━ ┳ ━ ━ ━ ╮ - ┃ ╭ ━ ╮ ┣ ╯ ╰ ╮ ╱ ╱ ╱ ╭ ╯ ╰ ┫ ╭ ━ ╮ ┃ ╭ ━ ╮ ┃ - ┃ ╰ ━ ━ ╋ ╮ ╭ ╋ ━ ━ ┳ ┻ ╮ ╭ ┫ ┃ ╱ ┃ ┃ ╰ ━ ━ ╮ - ╰ ━ ━ ╮ ┃ ┃ ┃ ┃ ╭ ╮ ┃ ╭ ┫ ┃ ┃ ┃ ╱ ┃ ┣ ━ ━ ╮ ┃ - ┃ ╰ ━ ╯ ┃ ┃ ╰ ┫ ╭ ╮ ┃ ┃ ┃ ╰ ┫ ╰ ━ ╯ ┃ ╰ ━ ╯ ┃ - ╰ ━ ━ ━ ╯ ╰ ━ ┻ ╯ ╰ ┻ ╯ ╰ ━ ┻ ━ ━ ━ ┻ ━ ━ ━ ╯ + + ███████ + █ █ █ + █ █ █ █ + █ █ █ █ + █ █ █ █ + █ █ █ █ + █ █ + ███████ + + _____ __ ___ __ __ + (_ | /\ |__) | / \(_ + __) | / \| \ | \__/__) ASCII +printf " v$(cat /usr/lib/startos/VERSION.txt)\n\n" printf " %s (%s %s)\n" "$(uname -o)" "$(uname -r)" "$(uname -m)" -printf " $(start-cli --version | sed 's/StartOS CLI /StartOS v/g') - $(start-cli git-info)" -if [ -n "$(cat /usr/lib/embassy/ENVIRONMENT.txt)" ]; then - printf " ~ $(cat /usr/lib/embassy/ENVIRONMENT.txt)\n" +printf " Git Hash: $(cat /usr/lib/startos/GIT_HASH.txt)" +if [ -n "$(cat /usr/lib/startos/ENVIRONMENT.txt)" ]; then + printf " ~ $(cat /usr/lib/startos/ENVIRONMENT.txt)\n" else printf "\n" fi printf "\n" -printf " * Documentation: https://start9.com\n" +printf " * Documentation: https://docs.start9.com\n" printf " * Management: https://%s.local\n" "$(hostname)" -printf " * Support: https://t.me/start9_labs\n" +printf " * Support: https://start9.com/contact\n" +printf " * Source Code: https://github.com/Start9Labs/start-os\n" +printf " * License: MIT\n" printf "\n" diff --git a/build/lib/scripts/chroot-and-upgrade b/build/lib/scripts/chroot-and-upgrade index f155176a8..f95e49924 100755 --- a/build/lib/scripts/chroot-and-upgrade +++ b/build/lib/scripts/chroot-and-upgrade @@ -5,9 +5,10 @@ if [ "$UID" -ne 0 ]; then exit 1 fi -echo 'Syncing...' - -rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next +if [ -z "$NO_SYNC" ]; then + echo 'Syncing...' + rsync -a --delete --force --info=progress2 /media/embassy/embassyfs/current/ /media/embassy/next +fi mkdir -p /media/embassy/next/run mkdir -p /media/embassy/next/dev @@ -20,7 +21,13 @@ mount --bind /sys /media/embassy/next/sys mount --bind /proc /media/embassy/next/proc mount --bind /boot /media/embassy/next/boot -chroot /media/embassy/next $@ +if [ -z "$*" ]; then + chroot /media/embassy/next + CHROOT_RES=$? +else + chroot /media/embassy/next "$SHELL" -c "$*" + CHROOT_RES=$? +fi umount /media/embassy/next/run umount /media/embassy/next/dev @@ -28,10 +35,12 @@ umount /media/embassy/next/sys umount /media/embassy/next/proc umount /media/embassy/next/boot -echo 'Upgrading...' +if [ "$CHROOT_RES" -eq 0 ]; then + echo 'Upgrading...' -touch /media/embassy/config/upgrade + touch /media/embassy/config/upgrade -sync + sync -reboot + reboot +fi \ No newline at end of file diff --git a/build/lib/scripts/enable-kiosk b/build/lib/scripts/enable-kiosk index 3e6d0992d..ad7cd4bf3 100755 --- a/build/lib/scripts/enable-kiosk +++ b/build/lib/scripts/enable-kiosk @@ -6,35 +6,79 @@ set -e /usr/bin/apt update /usr/bin/apt install --no-install-recommends -y xserver-xorg x11-xserver-utils xinit firefox-esr matchbox-window-manager libnss3-tools +#Change a default preference set by stock debian firefox-esr +sed -i 's|^pref("extensions.update.enabled", true);$|pref("extensions.update.enabled", false);|' /etc/firefox-esr/firefox-esr.js + +if ! id kiosk; then + # create kiosk user + useradd -s /bin/bash --create-home kiosk +fi + # create kiosk script -cat > /home/start9/kiosk.sh << 'EOF' +cat > /home/kiosk/kiosk.sh << 'EOF' #!/bin/sh PROFILE=$(mktemp -d) if [ -f /usr/local/share/ca-certificates/startos-root-ca.crt ]; then certutil -A -n "StartOS Local Root CA" -t "TCu,Cuw,Tuw" -i /usr/local/share/ca-certificates/startos-root-ca.crt -d $PROFILE fi cat >> $PROFILE/prefs.js << EOT -user_pref("network.proxy.autoconfig_url", "file:///usr/lib/embassy/proxy.pac"); -user_pref("network.proxy.socks_remote_dns", true); -user_pref("network.proxy.type", 2); -user_pref("dom.securecontext.allowlist_onions", true); -user_pref("dom.securecontext.whitelist_onions", true); -user_pref("signon.rememberSignons", false); -user_pref("extensions.activeThemeID", "firefox-compact-dark@mozilla.org"); -user_pref("browser.theme.content-theme", 0); -user_pref("browser.theme.toolbar-theme", 0); -user_pref("datareporting.policy.firstRunURL", ""); +user_pref("app.normandy.api_url", ""); +user_pref("app.normandy.enabled", false); +user_pref("app.shield.optoutstudies.enabled", false); +user_pref("app.update.enabled", false); +user_pref("browser.aboutHomeSnippets.updateUrl", ""); +user_pref("browser.bookmarks.addedImportButton", false); +user_pref("browser.casting.enabled", false); +user_pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false); +user_pref("browser.newtabpage.activity-stream.feeds.asrouterfeed", false); +user_pref("browser.newtabpage.activity-stream.feeds.topsites", false); +user_pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false); +user_pref("browser.onboarding.enabled", false); +user_pref("browser.ping-centre.telemetry", false); +user_pref("browser.pocket.enabled", false); +user_pref("browser.safebrowsing.blockedURIs.enabled", false); user_pref("browser.safebrowsing.malware.enabled", false); user_pref("browser.safebrowsing.phishing.enabled", false); +user_pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false); +user_pref("browser.safebrowsing.downloads.remote.block_uncommon", false); +user_pref("browser.safebrowsing.downloads.remote.enabled", false); +user_pref("browser.search.geoip.url", ""); +user_pref("browser.search.update", false); +user_pref("browser.search.suggest.enabled", false); +user_pref("browser.startup.homepage_override.mstone", "ignore"); +user_pref("browser.theme.content-theme", 0); +user_pref("browser.theme.toolbar-theme", 0); +user_pref("browser.urlbar.groupLabels.enabled", false); +user_pref("browser.urlbar.suggest.searches" false); +user_pref("datareporting.policy.firstRunURL", ""); user_pref("datareporting.healthreport.service.enabled", false); user_pref("datareporting.healthreport.uploadEnabled", false); user_pref("datareporting.policy.dataSubmissionEnabled", false); -user_pref("datareporting.policy.dataSubmissionEnabled", false); -user_pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false); -user_pref("browser.ping-centre.telemetry", false); -user_pref("browser.onboarding.enabled", false); +user_pref("dom.securecontext.allowlist_onions", true); +user_pref("dom.securecontext.whitelist_onions", true); +user_pref("experiments.enabled", false); +user_pref("experiments.activeExperiment", false); +user_pref("experiments.supported", false); +user_pref("extensions.activeThemeID", "firefox-compact-dark@mozilla.org"); +user_pref("extensions.blocklist.enabled", false); +user_pref("extensions.getAddons.cache.enabled", false); +user_pref("extensions.pocket.enabled", false); +user_pref("extensions.update.enabled", false); +user_pref("extensions.shield-recipe-client.enabled", false); +user_pref("extensions.shield-recipe-client.user_id", ""); +user_pref("extensions.shield-recipe-client.api_url", ""); +user_pref("media.gmp-gmpopenh264.enabled", false); +user_pref("messaging-system.rsexperimentloader.enabled", false); +user_pref("network.allow-experiments", false); +user_pref("network.captive-portal-service.enabled", false); +user_pref("network.connectivity-service.enabled", false); +user_pref("network.proxy.autoconfig_url", "file:///usr/lib/startos/proxy.pac"); +user_pref("network.proxy.socks_remote_dns", true); +user_pref("network.proxy.type", 2); +user_pref("signon.rememberSignons", false); user_pref("toolkit.telemetry.archive.enabled", false); user_pref("toolkit.telemetry.bhrPing.enabled", false); +user_pref("toolkit.telemetry.coverage.opt-out", true); user_pref("toolkit.telemetry.enabled", false); user_pref("toolkit.telemetry.firstShutdownPing.enabled", false); user_pref("toolkit.telemetry.newProfilePing.enabled", false); @@ -43,25 +87,15 @@ user_pref("toolkit.telemetry.shutdownPingSender.enabled", false); user_pref("toolkit.telemetry.unified", false); user_pref("toolkit.telemetry.updatePing.enabled", false); user_pref("toolkit.telemetry.cachedClientID", ""); -user_pref("experiments.enabled", false); -user_pref("experiments.activeExperiment", false); -user_pref("experiments.supported", false); -user_pref("network.allow-experiments", false); -user_pref("extensions.shield-recipe-client.enabled", false); -user_pref("extensions.shield-recipe-client.user_id", ""); -user_pref("extensions.shield-recipe-client.api_url", ""); -user_pref("app.normandy.enabled", false); -user_pref("app.normandy.api_url", ""); -user_pref("app.shield.optoutstudies.enabled", true); EOT while ! curl "http://localhost" > /dev/null; do sleep 1 done -while ! /usr/lib/embassy/scripts/check-monitor; do +while ! /usr/lib/startos/scripts/check-monitor; do sleep 15 done ( - while /usr/lib/embassy/scripts/check-monitor; do + while /usr/lib/startos/scripts/check-monitor; do sleep 15 done killall firefox-esr @@ -70,11 +104,11 @@ matchbox-window-manager -use_titlebar no & firefox-esr http://localhost --profile $PROFILE rm -rf $PROFILE EOF -chmod +x /home/start9/kiosk.sh +chmod +x /home/kiosk/kiosk.sh # use kiosk if tty (not pts) -if ! grep -q 'kiosk' /home/start9/.profile; then -cat >> /home/start9/.profile << 'EOF' +if ! grep -q 'kiosk' /home/kiosk/.profile; then +cat >> /home/kiosk/.profile << 'EOF' # Use kiosk for TTY if [[ "$(tty)" =~ ^/dev/tty ]]; then exec startx "$HOME/kiosk.sh" @@ -87,7 +121,7 @@ mkdir -p /etc/systemd/system/getty@tty1.service.d cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << 'EOF' [Service] ExecStart= -ExecStart=-/sbin/agetty --autologin start9 --noclear %I $TERM +ExecStart=-/sbin/agetty --autologin kiosk --noclear %I $TERM EOF ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service diff --git a/build/lib/scripts/fake-apt b/build/lib/scripts/fake-apt index 378320c53..8f23c213a 100755 --- a/build/lib/scripts/fake-apt +++ b/build/lib/scripts/fake-apt @@ -13,7 +13,7 @@ fi >&2 echo ' sudo rm /usr/local/bin/apt' >&2 echo >&2 echo 'Otherwise, what you probably want to do is run:' ->&2 echo ' sudo /usr/lib/embassy/scripts/chroot-and-upgrade' +>&2 echo ' sudo /usr/lib/startos/scripts/chroot-and-upgrade' >&2 echo 'You can run apt in this context to add packages to your system.' >&2 echo 'When you are done with your changes, type "exit" and the device will reboot into a system with the changes applied.' >&2 echo 'This is still NOT RECOMMENDED if you don'"'"'t know what you are doing, but at least isn'"'"'t guaranteed to break things.' diff --git a/build/lib/scripts/persist-apt-install b/build/lib/scripts/persist-apt-install index 3ed5c24b1..974833ca3 100755 --- a/build/lib/scripts/persist-apt-install +++ b/build/lib/scripts/persist-apt-install @@ -14,7 +14,7 @@ while [ -n "$1" ]; do done if [ ${#TO_INSTALL[@]} -ne 0 ]; then -/usr/lib/embassy/scripts/chroot-and-upgrade << EOF +/usr/lib/startos/scripts/chroot-and-upgrade << EOF apt-get update && apt-get install -y ${TO_INSTALL[@]} EOF fi \ No newline at end of file diff --git a/build/lib/scripts/tor-check.sh b/build/lib/scripts/tor-check.sh new file mode 100755 index 000000000..f434cf8a7 --- /dev/null +++ b/build/lib/scripts/tor-check.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +fail=$(printf " [\033[31m fail \033[0m]") +pass=$(printf " [\033[32m pass \033[0m]") + +onion_list=( + "Start9|http://privacy34kn4ez3y3nijweec6w4g54i3g54sdv7r5mr6soma3w4begyd.onion" + "Mempool|http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion" + "DuckDuckGo|https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion" + "Brave Search|https://search.brave4u7jddbv7cyviptqjc7jusxh72uik7zt6adtckl5f4nwy2v72qd.onion" +) + +# Check if ~/.startos/tor-check.list exists and read its contents if available +if [ -f ~/.startos/tor-check.list ]; then + while IFS= read -r line; do + # Check if the line starts with a # + if [[ ! "$line" =~ ^# ]]; then + onion_list+=("$line") + fi + done < ~/.startos/tor-check.list +fi + +echo "Testing connection to Onion Pages ..." + +for data in "${onion_list[@]}"; do + name="${data%%|*}" + url="${data#*|}" + if curl --socks5-hostname localhost:9050 "$url" > /dev/null 2>&1; then + echo " ${pass}: $name ($url) " + else + echo " ${fail}: $name ($url) " + fi +done + +echo +echo "Done." diff --git a/build/raspberrypi/make-image.sh b/build/raspberrypi/make-image.sh index 3a0bf5291..3b07cb3a8 100755 --- a/build/raspberrypi/make-image.sh +++ b/build/raspberrypi/make-image.sh @@ -15,6 +15,8 @@ ENVIRONMENT=$(cat ENVIRONMENT.txt) GIT_HASH=$(cat GIT_HASH.txt | head -c 7) DATE=$(date +%Y%m%d) +ROOT_PART_END=7217792 + VERSION_FULL="$VERSION-$GIT_HASH" if [ -n "$ENVIRONMENT" ]; then @@ -22,7 +24,7 @@ if [ -n "$ENVIRONMENT" ]; then fi TARGET_NAME=startos-${VERSION_FULL}-${DATE}_raspberrypi.img -TARGET_SIZE=$[(6817791+1)*512] +TARGET_SIZE=$[($ROOT_PART_END+1)*512] rm -f $TARGET_NAME truncate -s $TARGET_SIZE $TARGET_NAME @@ -43,7 +45,7 @@ truncate -s $TARGET_SIZE $TARGET_NAME echo p echo 2 echo 526336 - echo 6817791 + echo $ROOT_PART_END echo a echo 1 echo w @@ -58,12 +60,12 @@ sudo mount `partition_for ${OUTPUT_DEVICE} 2` $TMPDIR sudo mkdir $TMPDIR/boot sudo mount `partition_for ${OUTPUT_DEVICE} 1` $TMPDIR/boot sudo unsquashfs -f -d $TMPDIR startos.raspberrypi.squashfs -REAL_GIT_HASH=$(cat $TMPDIR/usr/lib/embassy/GIT_HASH.txt) -REAL_VERSION=$(cat $TMPDIR/usr/lib/embassy/VERSION.txt) -REAL_ENVIRONMENT=$(cat $TMPDIR/usr/lib/embassy/ENVIRONMENT.txt) -sudo sed -i 's| boot=embassy| init=/usr/lib/embassy/scripts/init_resize\.sh|' $TMPDIR/boot/cmdline.txt +REAL_GIT_HASH=$(cat $TMPDIR/usr/lib/startos/GIT_HASH.txt) +REAL_VERSION=$(cat $TMPDIR/usr/lib/startos/VERSION.txt) +REAL_ENVIRONMENT=$(cat $TMPDIR/usr/lib/startos/ENVIRONMENT.txt) +sudo sed -i 's| boot=embassy| init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/cmdline.txt sudo cp ./build/raspberrypi/fstab $TMPDIR/etc/ -sudo cp ./build/raspberrypi/init_resize.sh $TMPDIR/usr/lib/embassy/scripts/init_resize.sh +sudo cp ./build/raspberrypi/init_resize.sh $TMPDIR/usr/lib/startos/scripts/init_resize.sh sudo umount $TMPDIR/boot sudo umount $TMPDIR sudo losetup -d $OUTPUT_DEVICE diff --git a/build/registry/cleanDanglingImages b/build/registry/cleanDanglingImages new file mode 100644 index 000000000..481522903 --- /dev/null +++ b/build/registry/cleanDanglingImages @@ -0,0 +1,9 @@ +#!/bin/bash + +for image in $(find /root/resources/eos/ -type f -name '*.squashfs' -mmin +240 -exec realpath {} \;); do + if ! mount | grep "^$image" > /dev/null; then + >&2 echo "Removing dangling image: $image" + rm $image + fi +done +find /root/resources/eos -type d -empty -delete diff --git a/build/registry/downloadIndexActionResult b/build/registry/downloadIndexActionResult new file mode 100644 index 000000000..4bda4c6b8 --- /dev/null +++ b/build/registry/downloadIndexActionResult @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e + +RUN_ID=$1 + +if [ -z "$RUN_ID" ]; then + >&2 echo usage: $0 '' + exit 1 +fi + +TMP_DIR=/var/tmp/action-run-results/$RUN_ID + +rm -rf $TMP_DIR +mkdir -p $TMP_DIR + +cd $TMP_DIR + +for arch in x86_64 x86_64-nonfree aarch64 aarch64-nonfree raspberrypi; do + gh run download -R Start9Labs/start-os $RUN_ID -n $arch.squashfs +done + +VERSION= +HASH= +for file in $(ls *.squashfs); do + if [[ $file =~ ^startos-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?)-([a-f0-9]{7}(~[a-z-]+)?|unknown)_([a-z0-9_-]+).squashfs$ ]]; then + if [ -n "$VERSION" ] && [ "$VERSION" != "${BASH_REMATCH[1]}" ]; then + >&2 echo "VERSION MISMATCH: expected $VERSION got ${BASH_REMATCH[1]}" + exit 2 + fi + if [ -n "$HASH" ] && [ "$HASH" != "${BASH_REMATCH[3]}" ]; then + >&2 echo "HASH MISMATCH: expected $HASH got ${BASH_REMATCH[3]}" + exit 3 + fi + VERSION="${BASH_REMATCH[1]}" + HASH="${BASH_REMATCH[3]}" + fi +done + +mkdir -p /root/resources/eos/$VERSION +rm -rf /root/resources/eos/$VERSION/$HASH +mv $TMP_DIR /root/resources/eos/$VERSION/$HASH + +cd /root/resources/eos/$VERSION +setOsCommitHash $HASH \ No newline at end of file diff --git a/build/registry/resync.cgi b/build/registry/resync.cgi new file mode 100644 index 000000000..f8479824f --- /dev/null +++ b/build/registry/resync.cgi @@ -0,0 +1,22 @@ +#!/bin/bash + +declare -A params +while IFS='=' read -r -d '&' key value && [[ -n "$key" ]]; do + params["$key"]=$value +done <<<"${QUERY_STRING}&" + +index_key="${params['key']}" +if [ -z "$index_key" ] || [ "$index_key" != "$(cat /var/www/index_key.txt)" ]; then + echo "HTTP/1.1 401 UNAUTHORIZED" + echo "Content-Type: text/html" + echo + echo "UNAUTHORIZED" + exit +fi + +touch /tmp/resync + +echo "HTTP/1.1 200 OK" +echo "Content-Type: text/html" +echo +echo "OK: Upload successful" \ No newline at end of file diff --git a/build/registry/resyncRsyncRegistry b/build/registry/resyncRsyncRegistry index f3e803ff7..2f5aba510 100755 --- a/build/registry/resyncRsyncRegistry +++ b/build/registry/resyncRsyncRegistry @@ -6,12 +6,14 @@ # Then we are going to make sure that each of these files is then put on the rsyncd server # so the embassies can pull them down +date >> /var/log/resyncRsyncRegistry.runlog + cat > /etc/rsyncd.conf << RD uid = root gid = root use chroot = yes -max connections = 50 +max connections = 4 pid file = /var/run/rsyncd.pid exclude = lost+found/ timeout = 900 @@ -27,7 +29,7 @@ do filename=${dir##*/} version=$(echo $directory | sed -r 's/.*\///') version_dir="/srv/rsync/$version" - type=$(echo "$filename" | sed -r "s/^.*?\.(\w+)\.squashfs$/\1/") + type=$(echo "$filename" | sed -r "s/^.*?\.([a-z0-9_-]+)\.squashfs$/\1/") new_dir="$version_dir/$type" @@ -51,4 +53,4 @@ INSERTING done echo "Created rsyncd.conf file, restarting service" -systemctl restart rsync +systemctl restart rsync \ No newline at end of file diff --git a/build/registry/setOsCommitHash b/build/registry/setOsCommitHash new file mode 100644 index 000000000..8da761200 --- /dev/null +++ b/build/registry/setOsCommitHash @@ -0,0 +1,39 @@ +#!/bin/bash + +# Get the current directory +PWD=$(pwd) +HASH=$1 + +if [ -z "$HASH" ]; then + >&2 echo "usage: setOsCommitHash " + exit 1 +fi + +# Define the expected pattern for the directory +pattern="/root/resources/eos/" + +# Check if the current directory matches the pattern +if [[ $PWD =~ ^$pattern([0-9.]+)$ ]]; then + # Extract the version number from the directory path + version="${BASH_REMATCH[1]}" +else + >&2 echo "MUST BE IN OS VERSION DIRECTORY" + exit 1 +fi + +if ! [ -d "$HASH" ]; then + >&2 echo "$HASH: No such directory" + exit 1 +fi + +for file in $(ls $HASH/startos-$version-${HASH}_*.squashfs); do + if [[ $file =~ ^$HASH/startos-$version-${HASH}_([a-z0-9_-]+).squashfs$ ]]; then + arch="${BASH_REMATCH[1]}" + echo "Found arch $arch" + umount /srv/rsync/$version/$arch + rm eos.$arch.squashfs + ln -s $file eos.$arch.squashfs + fi +done + +resyncRsyncRegistry \ No newline at end of file diff --git a/build/registry/upload.cgi b/build/registry/upload.cgi new file mode 100644 index 000000000..b5dd79a82 --- /dev/null +++ b/build/registry/upload.cgi @@ -0,0 +1,48 @@ +#!/bin/bash + +declare -A params +while IFS='=' read -r -d '&' key value && [[ -n "$key" ]]; do + params["$key"]=$value +done <<<"${QUERY_STRING}&" + +index_key="${params['key']}" +if [ -z "$index_key" ] || [ "$index_key" != "$(cat /var/www/index_key.txt)" ]; then + echo "HTTP/1.1 401 UNAUTHORIZED" + echo "Content-Type: text/html" + echo + echo "UNAUTHORIZED" + exit +fi + +git_hash="${params['gitHash']}" +version="${params['version']}" +platform="${params['platform']}" +shasum="${params['shasum']}" +if [ -z "$git_hash" ] || [ -z "$version" ] || [ -z "$platform" ] || [ -z "$shasum" ]; then + echo "HTTP/1.1 400 BAD REQUEST" + echo "Content-Type: text/html" + echo + echo "BAD REQUEST: missing param" + exit +fi + +tmp_file=$(mktemp /var/tmp/tmp.XXXXXXXXXX.squashfs) +cat > $tmp_file + +if ! sha256sum $tmp_file | grep "$shasum"; then + rm $tmp_file + echo "HTTP/1.1 400 BAD REQUEST" + echo "Content-Type: text/html" + echo + echo "BAD REQUEST: shasum mismatch" +fi + +mkdir -p /var/www/resources/eos/${version}/${git_hash} +mv $tmp_file /var/www/resources/eos/${version}/${git_hash}/startos-${version}-${git_hash}_${platform}.squashfs +rm /var/www/resources/eos/${version}/eos.${platform}.squashfs +ln -rs /var/www/resources/eos/${version}/${git_hash}/startos-${version}-${git_hash}_${platform}.squashfs /var/www/resources/eos/${version}/eos.${platform}.squashfs + +echo "HTTP/1.1 200 OK" +echo "Content-Type: text/html" +echo +echo "OK: Upload successful" \ No newline at end of file diff --git a/check-git-hash.sh b/check-git-hash.sh index 8c286840d..874dcc8bf 100755 --- a/check-git-hash.sh +++ b/check-git-hash.sh @@ -1,6 +1,10 @@ #!/bin/bash -GIT_HASH="$(git describe --always --abbrev=40 --dirty=-modified)" +if [ "$GIT_BRANCH_AS_HASH" != 1 ]; then + GIT_HASH="$(git describe --always --abbrev=40 --dirty=-modified)" +else + GIT_HASH="@$(git rev-parse --abbrev-ref HEAD)" +fi if ! [ -f ./GIT_HASH.txt ] || [ "$(cat ./GIT_HASH.txt)" != "$GIT_HASH" ]; then echo -n "$GIT_HASH" > ./GIT_HASH.txt diff --git a/check-platform.sh b/check-platform.sh new file mode 100755 index 000000000..aebb0fc5f --- /dev/null +++ b/check-platform.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if ! [ -f ./PLATFORM.txt ] || [ "$(cat ./PLATFORM.txt)" != "$PLATFORM" ] && [ -n "$PLATFORM" ]; then + >&2 echo "Updating PLATFORM.txt to \"$PLATFORM\"" + echo -n "$PLATFORM" > ./PLATFORM.txt +fi + +echo -n ./PLATFORM.txt diff --git a/compress-uis.sh b/compress-uis.sh index 964ddeb57..1a7ea9124 100755 --- a/compress-uis.sh +++ b/compress-uis.sh @@ -4,19 +4,21 @@ set -e rm -rf frontend/dist/static -find frontend/dist/raw -type f -not -name '*.gz' -and -not -name '*.br' | xargs -n 1 -P 0 gzip -kf -find frontend/dist/raw -type f -not -name '*.gz' -and -not -name '*.br' | xargs -n 1 -P 0 brotli -kf +if ! [[ "$ENVIRONMENT" =~ (^|-)dev($|-) ]]; then + find frontend/dist/raw -type f -not -name '*.gz' -and -not -name '*.br' | xargs -n 1 -P 0 gzip -kf + find frontend/dist/raw -type f -not -name '*.gz' -and -not -name '*.br' | xargs -n 1 -P 0 brotli -kf -for file in $(find frontend/dist/raw -type f -not -name '*.gz' -and -not -name '*.br'); do - raw_size=$(du --bytes $file | awk '{print $1}') - gz_size=$(du --bytes $file.gz | awk '{print $1}') - br_size=$(du --bytes $file.br | awk '{print $1}') - if [ $((gz_size * 100 / raw_size)) -gt 70 ]; then - rm $file.gz - fi - if [ $((br_size * 100 / raw_size)) -gt 70 ]; then - rm $file.br - fi -done + for file in $(find frontend/dist/raw -type f -not -name '*.gz' -and -not -name '*.br'); do + raw_size=$(du $file | awk '{print $1 * 512}') + gz_size=$(du $file.gz | awk '{print $1 * 512}') + br_size=$(du $file.br | awk '{print $1 * 512}') + if [ $((gz_size * 100 / raw_size)) -gt 70 ]; then + rm $file.gz + fi + if [ $((br_size * 100 / raw_size)) -gt 70 ]; then + rm $file.br + fi + done +fi cp -r frontend/dist/raw frontend/dist/static \ No newline at end of file diff --git a/build/lib/scripts/postinst b/debian/postinst similarity index 77% rename from build/lib/scripts/postinst rename to debian/postinst index 550110f2a..6a65a749d 100755 --- a/build/lib/scripts/postinst +++ b/debian/postinst @@ -8,10 +8,10 @@ fi if [ -f /usr/sbin/grub-probe ]; then mv /usr/sbin/grub-probe /usr/sbin/grub-probe-default - ln -s /usr/lib/embassy/scripts/grub-probe-eos /usr/sbin/grub-probe + ln -s /usr/lib/startos/scripts/grub-probe-eos /usr/sbin/grub-probe fi -cp /usr/lib/embassy/scripts/embassy-initramfs-module /etc/initramfs-tools/scripts/embassy +cp /usr/lib/startos/scripts/embassy-initramfs-module /etc/initramfs-tools/scripts/embassy if ! grep overlay /etc/initramfs-tools/modules > /dev/null; then echo overlay >> /etc/initramfs-tools/modules @@ -21,6 +21,7 @@ update-initramfs -u -k all if [ -f /etc/default/grub ]; then sed -i '/\(^\|#\)GRUB_CMDLINE_LINUX=/c\GRUB_CMDLINE_LINUX="boot=embassy"' /etc/default/grub + sed -i '/\(^\|#\)GRUB_DISTRIBUTOR=/c\GRUB_DISTRIBUTOR="StartOS v$(cat /usr/lib/startos/VERSION.txt)"' /etc/default/grub fi # change timezone @@ -46,6 +47,7 @@ dns=systemd-resolved [ifupdown] managed=true EOF +$SYSTEMCTL enable startd.service $SYSTEMCTL enable systemd-resolved.service $SYSTEMCTL enable systemd-networkd-wait-online.service $SYSTEMCTL enable ssh.service @@ -70,20 +72,20 @@ fi sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config sed -i 's/Restart=on-failure/Restart=always/g' /lib/systemd/system/tor@default.service -sed -i 's/ExecStart=\/usr\/bin\/dockerd/ExecStart=\/usr\/bin\/dockerd --exec-opt native.cgroupdriver=systemd/g' /lib/systemd/system/docker.service sed -i '/\(^\|#\)entries-per-entry-group-max=/c\entries-per-entry-group-max=128' /etc/avahi/avahi-daemon.conf sed -i '/\(^\|#\)Storage=/c\Storage=persistent' /etc/systemd/journald.conf sed -i '/\(^\|#\)Compress=/c\Compress=yes' /etc/systemd/journald.conf sed -i '/\(^\|#\)SystemMaxUse=/c\SystemMaxUse=1G' /etc/systemd/journald.conf sed -i '/\(^\|#\)ForwardToSyslog=/c\ForwardToSyslog=no' /etc/systemd/journald.conf -mkdir -p /etc/docker -ln -sf /usr/lib/embassy/docker-engine.slice /etc/systemd/system/docker-engine.slice -cat > /etc/docker/daemon.json << EOF -{ - "storage-driver": "overlay2", - "cgroup-parent": "docker-engine.slice" -} -EOF +sed -i '/^\s*#\?\s*issue_discards\s*=\s*/c\issue_discards = 1' /etc/lvm/lvm.conf + +if cat /usr/lib/startos/ENVIRONMENT.txt | grep '(^|-)docker(-|$)'; then + sed -i 's/ExecStart=\/usr\/bin\/dockerd/ExecStart=\/usr\/bin\/dockerd --exec-opt native.cgroupdriver=systemd/g' /lib/systemd/system/docker.service + mkdir -p /etc/docker + echo '{ "storage-driver": "overlay2" }' > /etc/docker/daemon.json +else + podman network create -d bridge --subnet 172.18.0.1/24 --opt com.docker.network.bridge.name=br-start9 start9 +fi mkdir -p /etc/nginx/ssl # fix to suppress docker warning, fixed in 21.xx release of docker cli: https://github.com/docker/cli/pull/2934 @@ -100,6 +102,7 @@ CookieAuthentication 1 EOF rm -rf /var/lib/tor/* +ln -sf /usr/lib/startos/scripts/tor-check.sh /usr/bin/tor-check echo "fs.inotify.max_user_watches=1048576" > /etc/sysctl.d/97-embassy.conf @@ -112,9 +115,9 @@ dpkg-reconfigure --frontend noninteractive locales groupadd embassy -ln -s /usr/lib/embassy/scripts/dhclient-exit-hook /etc/dhcp/dhclient-exit-hooks.d/embassy +ln -s /usr/lib/startos/scripts/dhclient-exit-hook /etc/dhcp/dhclient-exit-hooks.d/embassy rm -f /etc/motd -ln -sf /usr/lib/embassy/motd /etc/update-motd.d/00-embassy +ln -sf /usr/lib/startos/motd /etc/update-motd.d/00-embassy chmod -x /etc/update-motd.d/* chmod +x /etc/update-motd.d/00-embassy diff --git a/dpkg-build.sh b/dpkg-build.sh new file mode 100755 index 000000000..e8ffdb0ac --- /dev/null +++ b/dpkg-build.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -e + +cd "$(dirname "${BASH_SOURCE[0]}")" + +BASENAME=$(./basename.sh) +VERSION=$(cat ./VERSION.txt) +if [ "$PLATFORM" = "x86_64" ] || [ "$PLATFORM" = "x86_64-nonfree" ]; then + DEB_ARCH=amd64 +elif [ "$PLATFORM" = "aarch64" ] || [ "$PLATFORM" = "aarch64-nonfree" ] || [ "$PLATFORM" = "raspberrypi" ]; then + DEB_ARCH=arm64 +else + DEB_ARCH="$PLATFORM" +fi + +rm -rf dpkg-workdir/$BASENAME +mkdir -p dpkg-workdir/$BASENAME + +make install DESTDIR=dpkg-workdir/$BASENAME + +DEPENDS=$(cat dpkg-workdir/$BASENAME/usr/lib/startos/depends | tr $'\n' ',' | sed 's/,,\+/,/g' | sed 's/,$//') +CONFLICTS=$(cat dpkg-workdir/$BASENAME/usr/lib/startos/conflicts | tr $'\n' ',' | sed 's/,,\+/,/g' | sed 's/,$//') + +cp -r debian dpkg-workdir/$BASENAME/DEBIAN +cat > dpkg-workdir/$BASENAME/DEBIAN/control << EOF +Package: startos +Version: ${VERSION} +Section: unknown +Priority: required +Maintainer: Aiden McClelland +Homepage: https://start9.com +Architecture: ${DEB_ARCH} +Multi-Arch: foreign +Depends: ${DEPENDS} +Conflicts: ${CONFLICTS} +Description: StartOS Debian Package +EOF + +cd dpkg-workdir/$BASENAME +find . -type f -not -path "./DEBIAN/*" -exec md5sum {} \; | sort -k 2 | sed 's/\.\/\(.*\)/\1/' > DEBIAN/md5sums +cd ../.. + +cd dpkg-workdir +dpkg-deb --root-owner-group -b $BASENAME +mkdir -p ../results +mv $BASENAME.deb ../results/$BASENAME.deb +rm -rf $BASENAME \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md index 2382ccaec..a43471a5c 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -50,9 +50,8 @@ Valid values for "maskAs" are `tor` and `lan`. ```sh npm run start:ui -npm run start:install-wiz +npm run start:install npm run start:setup -npm run start:dui ``` ## Running locally with proxied backend diff --git a/frontend/angular.json b/frontend/angular.json index 5af567f09..95cb07ade 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -36,6 +36,11 @@ "input": "node_modules/monaco-editor", "output": "assets/monaco-editor/" }, + { + "glob": "**/*", + "input": "node_modules/@taiga-ui/icons/src", + "output": "assets/taiga-ui/icons" + }, "projects/ui/src/manifest.webmanifest", { "glob": "ngsw.json", diff --git a/frontend/config-sample.json b/frontend/config-sample.json index fc8593f18..37d5ea038 100644 --- a/frontend/config-sample.json +++ b/frontend/config-sample.json @@ -1,8 +1,6 @@ { "useMocks": true, "enableWidgets": false, - "packageArch": "aarch64", - "osArch": "raspberrypi", "ui": { "api": { "url": "rpc", @@ -14,6 +12,7 @@ }, "mocks": { "maskAs": "tor", + "maskAsHttps": true, "skipStartupAlerts": true } }, diff --git a/frontend/lint-staged.config.js b/frontend/lint-staged.config.js index 731cc9d5e..de03fa870 100644 --- a/frontend/lint-staged.config.js +++ b/frontend/lint-staged.config.js @@ -4,6 +4,6 @@ module.exports = { 'projects/ui/**/*.ts': () => 'npm run check:ui', 'projects/shared/**/*.ts': () => 'npm run check:shared', 'projects/marketplace/**/*.ts': () => 'npm run check:marketplace', - 'projects/install-wizard/**/*.ts': () => 'npm run check:install-wiz', + 'projects/install-wizard/**/*.ts': () => 'npm run check:install', 'projects/setup-wizard/**/*.ts': () => 'npm run check:setup', } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 95b5fba70..ba63f0ae3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "startos-ui", - "version": "0.3.4.4", + "version": "0.3.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "startos-ui", - "version": "0.3.4.4", + "version": "0.3.5", "dependencies": { "@angular/animations": "^16.1.4", "@angular/common": "^16.1.4", @@ -23,13 +23,13 @@ "@start9labs/argon2": "^0.1.0", "@start9labs/emver": "^0.1.5", "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc8.beta2", - "@taiga-ui/addon-charts": "3.52.0", - "@taiga-ui/cdk": "3.52.0", - "@taiga-ui/core": "3.52.0", - "@taiga-ui/experimental": "3.52.0", - "@taiga-ui/icons": "3.52.0", - "@taiga-ui/kit": "3.52.0", - "@taiga-ui/styles": "3.52.0", + "@taiga-ui/addon-charts": "3.53.0", + "@taiga-ui/cdk": "3.53.0", + "@taiga-ui/core": "3.53.0", + "@taiga-ui/experimental": "3.53.0", + "@taiga-ui/icons": "3.53.0", + "@taiga-ui/kit": "3.53.0", + "@taiga-ui/styles": "3.53.0", "@tinkoff/ng-dompurify": "4.0.0", "ansi-to-html": "^0.7.2", "base64-js": "^1.5.1", @@ -63,7 +63,6 @@ "@angular/compiler-cli": "^16.1.4", "@angular/language-service": "^16.1.4", "@ionic/cli": "^6.19.0", - "@types/cron": "^2.0.0", "@types/dompurify": "^2.3.3", "@types/estree": "^0.0.51", "@types/js-yaml": "^4.0.5", @@ -121,12 +120,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1602.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.7.tgz", - "integrity": "sha512-r6+z4jRE+e9VNeTmJCGz5VI5azRagOqE4SIDqaywz75eHOJ9UPSo9MHy8zFw1eLt1WcvCDqk+Pk9+krh2E+B8Q==", + "version": "0.1602.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.10.tgz", + "integrity": "sha512-FwemQXh3edqA/S6zPpsqKei5v7gt0R0WpjJoAJaz+FOpfDwij1fwnKr88XINY8xcefTcQaTDQxJZheJShA/hHw==", "devOptional": true, "dependencies": { - "@angular-devkit/core": "16.2.7", + "@angular-devkit/core": "16.2.10", "rxjs": "7.8.1" }, "engines": { @@ -136,15 +135,15 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.7.tgz", - "integrity": "sha512-OTH4qzXmWXifhvH0iXwPUhElWEU9SUcIZyWYbv2NR5ImAw/GE07vDuBljGRJeSEC9MpFbThwEFbHD8oRWiLUag==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.10.tgz", + "integrity": "sha512-msB/qjIsAOySDxdU5DpcX2sWGUEJOFIO03O9+HbtLwf3NDfe74mFfejxuKlHJXIJdgpM2Zc948M6+618QKpUYA==", "dev": true, "dependencies": { "@ampproject/remapping": "2.2.1", - "@angular-devkit/architect": "0.1602.7", - "@angular-devkit/build-webpack": "0.1602.7", - "@angular-devkit/core": "16.2.7", + "@angular-devkit/architect": "0.1602.10", + "@angular-devkit/build-webpack": "0.1602.10", + "@angular-devkit/core": "16.2.10", "@babel/core": "7.22.9", "@babel/generator": "7.22.9", "@babel/helper-annotate-as-pure": "7.22.5", @@ -156,7 +155,7 @@ "@babel/runtime": "7.22.6", "@babel/template": "7.22.5", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "16.2.7", + "@ngtools/webpack": "16.2.10", "@vitejs/plugin-basic-ssl": "1.0.1", "ansi-colors": "4.1.3", "autoprefixer": "10.4.14", @@ -258,9 +257,9 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@angular-devkit/build-angular/node_modules/ajv": { @@ -366,12 +365,12 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1602.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.7.tgz", - "integrity": "sha512-3+MV9ehn65XUUMSBBgfg5K2zZs2jhif75ypI+BBUfZDUWeKR5MeGJy0aDHZ+2H94kPkmSD3PrkOuitWdnDjTgA==", + "version": "0.1602.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.10.tgz", + "integrity": "sha512-H7HiFKbZl/xVxpr1RH05SGawTpA1417wvr2nFGRu2OiePd0lPr6pIhcq8F8gt7JcA8yZKKaqjn2gU+6um2MFLg==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1602.7", + "@angular-devkit/architect": "0.1602.10", "rxjs": "7.8.1" }, "engines": { @@ -385,9 +384,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.7.tgz", - "integrity": "sha512-XskObYrg7NRdEuHnSVZOM7OeinEL8HzugjmKnawAa+dAbFCCoGsVWjMliA/Q8sb1yfGkyL0WW7DZABZj7EGwWA==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.10.tgz", + "integrity": "sha512-eo7suLDjyu5bSlEr4TluYkFm4v2PVLSAPgnau8XHHlN5Yg4P/BZ00ve7LA7C9S1gzRSCrxQhK5ki4rnoFTo5zg==", "dependencies": { "ajv": "8.12.0", "ajv-formats": "2.1.1", @@ -411,11 +410,11 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.7.tgz", - "integrity": "sha512-zu3xHwA4w+kXHkyyjGl3i7uSU2/kKLPKuyyixw0WLcKUQCYd7TWmu8OC0qCDa42XkxP9gGL091dJFu56exgneA==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.10.tgz", + "integrity": "sha512-UCfPJKVNekb21bWRbzyx81tfHN3x8vU4ZMX/VA6xALg//QalMB7NOkkXBAssthnLastkyzkUtlvApTp2+R+EkQ==", "dependencies": { - "@angular-devkit/core": "16.2.7", + "@angular-devkit/core": "16.2.10", "jsonc-parser": "3.2.0", "magic-string": "0.30.1", "ora": "5.4.1", @@ -428,9 +427,9 @@ } }, "node_modules/@angular/animations": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.10.tgz", - "integrity": "sha512-UudunZoyFWWNpuWkwiBxC3cleLCVJGHIfMgypFwC35YjtiIlRJ0r4nVkc96Rq1xd4mT71Dbk1kQHc8urB8A7aw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.12.tgz", + "integrity": "sha512-MD0ElviEfAJY8qMOd6/jjSSvtqER2RDAi0lxe6EtUacC1DHCYkaPrKW4vLqY+tmZBg1yf+6n+uS77pXcHHcA3w==", "dependencies": { "tslib": "^2.3.0" }, @@ -438,19 +437,19 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "16.2.10" + "@angular/core": "16.2.12" } }, "node_modules/@angular/cli": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.7.tgz", - "integrity": "sha512-30yBAYzbrj/WM4tLiX4IU5byw0b5Y5LEzcpjYZglv/RXPrnevGlRXmgCulpt8wIdkd668N7kXEQ23nipuJDXMg==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.10.tgz", + "integrity": "sha512-zDqlD+rXFuYZP169c2v35HkMbkchVCft5sS+VpoCCgYTk2rwxpeYkjJ8DQZztZJZRXQ+EMpkv/TubswmDro2zA==", "devOptional": true, "dependencies": { - "@angular-devkit/architect": "0.1602.7", - "@angular-devkit/core": "16.2.7", - "@angular-devkit/schematics": "16.2.7", - "@schematics/angular": "16.2.7", + "@angular-devkit/architect": "0.1602.10", + "@angular-devkit/core": "16.2.10", + "@angular-devkit/schematics": "16.2.10", + "@schematics/angular": "16.2.10", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.3", "ini": "4.1.1", @@ -476,9 +475,9 @@ } }, "node_modules/@angular/common": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.10.tgz", - "integrity": "sha512-cLth66aboInNcWFjDBRmK30jC5KN10nKDDcv4U/r3TDTBpKOtnmTjNFFr7dmjfUmVhHFy/66piBMfpjZI93Rxg==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.12.tgz", + "integrity": "sha512-B+WY/cT2VgEaz9HfJitBmgdk4I333XG/ybC98CMC4Wz8E49T8yzivmmxXB3OD6qvjcOB6ftuicl6WBqLbZNg2w==", "dependencies": { "tslib": "^2.3.0" }, @@ -486,14 +485,14 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "16.2.10", + "@angular/core": "16.2.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.10.tgz", - "integrity": "sha512-ty6SfqkZlV2bLU/SSi3wmxrEFgPrK+WVslCNIr3FlTnCBdqpIbadHN2QB3A1d9XaNc7c4Tq5DQKh34cwMwNbuw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.12.tgz", + "integrity": "sha512-6SMXUgSVekGM7R6l1Z9rCtUGtlg58GFmgbpMCsGf+VXxP468Njw8rjT2YZkf5aEPxEuRpSHhDYjqz7n14cwCXQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -501,7 +500,7 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "16.2.10" + "@angular/core": "16.2.12" }, "peerDependenciesMeta": { "@angular/core": { @@ -510,9 +509,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.10.tgz", - "integrity": "sha512-swgmtm4R23vQV9nJTXdDEFpOyIw3kz80mdT9qo3VId/2rqenOK253JsFypoqEj/fKzjV9gwXtTbmrMlhVyuyxw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.12.tgz", + "integrity": "sha512-pWSrr152562ujh6lsFZR8NfNc5Ljj+zSTQO44DsuB0tZjwEpnRcjJEgzuhGXr+CoiBf+jTSPZKemtSktDk5aaA==", "dev": true, "dependencies": { "@babel/core": "7.23.2", @@ -533,7 +532,7 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/compiler": "16.2.10", + "@angular/compiler": "16.2.12", "typescript": ">=4.9.3 <5.2" } }, @@ -583,12 +582,12 @@ } }, "node_modules/@angular/compiler-cli/node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -612,9 +611,9 @@ } }, "node_modules/@angular/core": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.10.tgz", - "integrity": "sha512-0XTsPjNflFhOl2CfNEdGeDOklG2t+m/D3g10Y7hg9dBjC1dURUEqTmM4d6J7JNbBURrP+/iP7uLsn3WRSipGUw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.12.tgz", + "integrity": "sha512-GLLlDeke/NjroaLYOks0uyzFVo6HyLl7VOm0K1QpLXnYvW63W9Ql/T3yguRZa7tRkOAeFZ3jw+1wnBD4O8MoUA==", "dependencies": { "tslib": "^2.3.0" }, @@ -627,9 +626,9 @@ } }, "node_modules/@angular/forms": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.10.tgz", - "integrity": "sha512-TZliEtSWIL1UzY8kjed4QcMawWS8gk/H60KVgzCh83NGE0wd1OGv20Z5OR7O8j07dxB9vaxY7CQz/8eCz5KaNQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.12.tgz", + "integrity": "sha512-1Eao89hlBgLR3v8tU91vccn21BBKL06WWxl7zLpQmG6Hun+2jrThgOE4Pf3os4fkkbH4Apj0tWL2fNIWe/blbw==", "dependencies": { "tslib": "^2.3.0" }, @@ -637,25 +636,25 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "16.2.10", - "@angular/core": "16.2.10", - "@angular/platform-browser": "16.2.10", + "@angular/common": "16.2.12", + "@angular/core": "16.2.12", + "@angular/platform-browser": "16.2.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-16.2.10.tgz", - "integrity": "sha512-r3KNXizhZDtj5/L68xnrtgHp5iSYf4NPyWHovoyAWClabsZ64cK38fOzMNCT/otrwqJWlz9ELnW/b/pxR+M9sw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-16.2.12.tgz", + "integrity": "sha512-sZwB+ZEjChx9EYcqPaS4OnhC/q5RcedZjIdM9mCxuU/MtseURRYRI/8Hnm1RHo9qyc5PmsQpg7p9Vp/5hXLUjw==", "dev": true, "engines": { "node": "^16.14.0 || >=18.10.0" } }, "node_modules/@angular/platform-browser": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.10.tgz", - "integrity": "sha512-TOZiK7ji550F8G39Ri255NnK1+2Xlr74RiElJdQct4TzfN0lqNf2KRDFFNwDohkP/78FUzcP4qBxs+Nf8M7OuQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.12.tgz", + "integrity": "sha512-NnH7ju1iirmVEsUq432DTm0nZBGQsBrU40M3ZeVHMQ2subnGiyUs3QyzDz8+VWLL/T5xTxWLt9BkDn65vgzlIQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -663,9 +662,9 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/animations": "16.2.10", - "@angular/common": "16.2.10", - "@angular/core": "16.2.10" + "@angular/animations": "16.2.12", + "@angular/common": "16.2.12", + "@angular/core": "16.2.12" }, "peerDependenciesMeta": { "@angular/animations": { @@ -674,9 +673,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.10.tgz", - "integrity": "sha512-YVmhAjOmsp2SWRonv6Mr/qXuKroCiew9asd1IlAZ//wqcml9ZrNAcX3WlDa8ZqdmOplQb0LuvvirfNB/6Is/jg==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.12.tgz", + "integrity": "sha512-ya54jerNgreCVAR278wZavwjrUWImMr2F8yM5n9HBvsMBbFaAQ83anwbOEiHEF2BlR+gJiEBLfpuPRMw20pHqw==", "dependencies": { "tslib": "^2.3.0" }, @@ -684,19 +683,19 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "16.2.10", - "@angular/compiler": "16.2.10", - "@angular/core": "16.2.10", - "@angular/platform-browser": "16.2.10" + "@angular/common": "16.2.12", + "@angular/compiler": "16.2.12", + "@angular/core": "16.2.12", + "@angular/platform-browser": "16.2.12" } }, "node_modules/@angular/pwa": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@angular/pwa/-/pwa-16.2.7.tgz", - "integrity": "sha512-7Tv3XIGmxRNmDyVOMKziUhsRSMuECLcKPJW9tl6cdIfcBCvjqEkZCGyQ4p2wBwYKhzcufHTF5hnLuOW8oQ0oCQ==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@angular/pwa/-/pwa-16.2.10.tgz", + "integrity": "sha512-qZFXdm8oTnH58A3ONXJ63G3rkgvBu+wSRhE/q4luickTLHrDp9P1YbvBdplJduhFHIh7tg6oFNd7ps0NuFklYg==", "dependencies": { - "@angular-devkit/schematics": "16.2.7", - "@schematics/angular": "16.2.7", + "@angular-devkit/schematics": "16.2.10", + "@schematics/angular": "16.2.10", "parse5-html-rewriting-stream": "7.0.0" }, "engines": { @@ -714,9 +713,9 @@ } }, "node_modules/@angular/router": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.10.tgz", - "integrity": "sha512-ndiq2NkGZ8hTsyL/KK8qsiR3UA0NjOFIn1jtGXOKtHryXZ6vSTtkhtkE4h4+G6/QNTL1IKtocFhOQt/xsc7DUA==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.12.tgz", + "integrity": "sha512-aU6QnYSza005V9P3W6PpkieL56O0IHps96DjqI1RS8yOJUl3THmokqYN4Fm5+HXy4f390FN9i6ftadYQDKeWmA==", "dependencies": { "tslib": "^2.3.0" }, @@ -724,16 +723,16 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "16.2.10", - "@angular/core": "16.2.10", - "@angular/platform-browser": "16.2.10", + "@angular/common": "16.2.12", + "@angular/core": "16.2.12", + "@angular/platform-browser": "16.2.12", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "16.2.10", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-16.2.10.tgz", - "integrity": "sha512-CBcmvLLYwkJUyRehxYrC/SOR5+rWAt6hKBHCNJHapLfVYddAC7xZNfjDp35e0rm0eOfCLlEUmtmi9DOqBHFM2A==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-16.2.12.tgz", + "integrity": "sha512-o0z0s4c76NmRASa+mUHn/q6vUKQNa06mGmLBDKm84vRQ1sQ2TJv+R1p8K9WkiM5mGy6tjQCDOgaz13TcxMFWOQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -744,8 +743,8 @@ "node": "^16.14.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "16.2.10", - "@angular/core": "16.2.10" + "@angular/common": "16.2.12", + "@angular/core": "16.2.12" } }, "node_modules/@assemblyscript/loader": { @@ -768,9 +767,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", + "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1026,9 +1025,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -1233,9 +1232,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", + "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1245,9 +1244,9 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", - "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1260,14 +1259,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", - "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.15" + "@babel/plugin-transform-optional-chaining": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1388,9 +1387,9 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1403,9 +1402,9 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", - "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1560,9 +1559,9 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1575,9 +1574,9 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.2.tgz", - "integrity": "sha512-BBYVGxbDVHfoeXbOwcagAkOQAm9NxoTdMGfTqghu1GrvadSaw6iW3Je6IcL5PNOw8VwjxqBECXy50/iCQSY/lQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.3.tgz", + "integrity": "sha512-59GsVNavGxAXCDDbakWSMJhajASb4kBCqDjqJsv+p5nKdbz7istmZ3HrX3L2LuiI80+zsOADCvooqQH3qGCucQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -1610,9 +1609,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1625,9 +1624,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", - "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.3.tgz", + "integrity": "sha512-QPZxHrThbQia7UdvfpaRRlq/J9ciz1J4go0k+lPBXbgaNeY7IQrBj/9ceWjvMMI07/ZBzHl/F0R/2K0qH7jCVw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1640,12 +1639,12 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", - "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1656,12 +1655,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", - "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.3.tgz", + "integrity": "sha512-PENDVxdr7ZxKPyi5Ffc0LjXdnJyrJxyqF5T5YjlVg4a0VFfQHW0r8iAtRiDXkfHlu1wwcvdtnndGYIeJLSuRMQ==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -1673,18 +1672,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", - "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.3.tgz", + "integrity": "sha512-FGEQmugvAEu2QtgtU0uTASXevfLMFfBeVCIIdcQhn/uBQsMTjBajdnAtanQlOcuihWh10PZ7+HWvc7NtBwP74w==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -1696,13 +1695,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" + "@babel/template": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -1711,10 +1710,24 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-computed-properties/node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", - "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1727,12 +1740,12 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", - "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1743,9 +1756,9 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", - "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1758,9 +1771,9 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", - "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.3.tgz", + "integrity": "sha512-vTG+cTGxPFou12Rj7ll+eD5yWeNl5/8xvQvF08y5Gv3v4mZQoyFf8/n9zg4q5vvCWt5jmgymfzMAldO7orBn7A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1774,12 +1787,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", - "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", "dev": true, "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1790,9 +1803,9 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", - "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.3.tgz", + "integrity": "sha512-yCLhW34wpJWRdTxxWtFZASJisihrfyMOTOQexhVzA78jlU+dH7Dw+zQgcPepQ5F3C6bAIiblZZ+qBggJdHiBAg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1806,9 +1819,9 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", - "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.3.tgz", + "integrity": "sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1821,13 +1834,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", "dev": true, "dependencies": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1838,9 +1851,9 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", - "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.3.tgz", + "integrity": "sha512-H9Ej2OiISIZowZHaBwF0tsJOih1PftXJtE8EWqlEIwpc7LMTGq0rPOrywKLQ4nefzx8/HMR0D3JGXoMHYvhi0A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1854,9 +1867,9 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1869,9 +1882,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", - "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.3.tgz", + "integrity": "sha512-+pD5ZbxofyOygEp+zZAfujY2ShNCXRpDRIPOiBmTO693hhyOEteZgl876Xs9SAHPQpcV0vz8LvA/T+w8AzyX8A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -1885,9 +1898,9 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1900,12 +1913,12 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz", - "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1916,12 +1929,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", - "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -1933,13 +1946,13 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz", - "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz", + "integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.0", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20" }, @@ -1951,12 +1964,12 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", - "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1983,9 +1996,9 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", - "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1998,9 +2011,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", - "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.3.tgz", + "integrity": "sha512-xzg24Lnld4DYIdysyf07zJ1P+iIfJpxtVFOzX4g+bsJ3Ng5Le7rXx9KwqKzuyaUeRnt+I1EICwQITqc0E2PmpA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2014,9 +2027,9 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", - "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.3.tgz", + "integrity": "sha512-s9GO7fIBi/BLsZ0v3Rftr6Oe4t0ctJ8h4CCXfPoEJwmvAPMyNrfkOOJzm6b9PX9YXcCJWWQd/sBF/N26eBiMVw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2030,16 +2043,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", - "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.3.tgz", + "integrity": "sha512-VxHt0ANkDmu8TANdE9Kc0rndo/ccsmfe2Cx2y5sI4hu3AukHQ5wAu4cM7j3ba8B9548ijVyclBU+nuDQftZsog==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", + "@babel/compat-data": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.22.15" + "@babel/plugin-transform-parameters": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -2049,13 +2062,13 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" + "@babel/helper-replace-supers": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -2065,9 +2078,9 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", - "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.3.tgz", + "integrity": "sha512-LxYSb0iLjUamfm7f1D7GpiS4j0UAC8AOiehnsGAP8BEsIX8EOi3qV6bbctw8M7ZvLtcoZfZX5Z7rN9PlWk0m5A==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2081,9 +2094,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz", - "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.3.tgz", + "integrity": "sha512-zvL8vIfIUgMccIAK1lxjvNv572JHFJIKb4MWBz5OGdBQA0fB0Xluix5rmOby48exiJc987neOmP/m9Fnpkz3Tg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2098,9 +2111,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", - "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2113,12 +2126,12 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", - "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2129,13 +2142,13 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", - "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.3.tgz", + "integrity": "sha512-a5m2oLNFyje2e/rGKjVfAELTVI5mbA0FeZpBnkOWWV7eSmKQ+T/XW0Vf+29ScLzSxX+rnsarvU0oie/4m6hkxA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -2147,9 +2160,9 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2162,9 +2175,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", - "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2178,9 +2191,9 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", - "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2222,9 +2235,9 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2237,9 +2250,9 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", @@ -2253,9 +2266,9 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", - "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2268,9 +2281,9 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2283,9 +2296,9 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", - "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2298,9 +2311,9 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", - "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -2313,12 +2326,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", - "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2329,12 +2342,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", - "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2345,12 +2358,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", - "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -2512,19 +2525,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", + "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/generator": "^7.23.3", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", + "@babel/parser": "^7.23.3", + "@babel/types": "^7.23.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2533,12 +2546,12 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", + "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -2548,9 +2561,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", + "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", @@ -2944,6 +2957,12 @@ "node": ">=12" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "devOptional": true + }, "node_modules/@iarna/toml": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", @@ -3710,9 +3729,9 @@ } }, "node_modules/@ng-web-apis/common": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-3.0.5.tgz", - "integrity": "sha512-rCaOxTKNQ0w0SFeH1Zdw+D8s2igE1QKRdVKDgAeZ7i4utQlSJWHP3de4k4lVEFM1cRiJh3Oq6QX2IOuLrgxEdw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-3.0.6.tgz", + "integrity": "sha512-ral+lzGpFS3aOCFB5DcHOI4lZhhp8GH4BnjSbngH2Xk8J0FKYdxRzvcPQVy7hS+TPUu0tW9uFVp6cC7odu3iyQ==", "dependencies": { "tslib": "^2.2.0" }, @@ -3723,9 +3742,9 @@ } }, "node_modules/@ng-web-apis/intersection-observer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@ng-web-apis/intersection-observer/-/intersection-observer-3.1.5.tgz", - "integrity": "sha512-+79rkKa7Ce1h6qcnDxvNITIjMjnVSaHZ1TlR5y57cOWhh2kyX5bBwgBx+lTa702o27oO3HOYrS3YnJidDiiPsQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@ng-web-apis/intersection-observer/-/intersection-observer-3.1.6.tgz", + "integrity": "sha512-Pzk0ycnYpq+EUf60kz+/A7nvCmhYzThc4ArwONwZzJqRF5xOS97CVWObs8hesorXxQdqlsrDNiu+JWuGxEvpzQ==", "dependencies": { "tslib": "^2.2.0" }, @@ -3735,9 +3754,9 @@ } }, "node_modules/@ng-web-apis/mutation-observer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@ng-web-apis/mutation-observer/-/mutation-observer-3.0.5.tgz", - "integrity": "sha512-pr8cxdNa+6VwZDAt7SWKrsuxr1yaTvbct9KG0dONl7zFLQf6n6yvpwgNTOz/PZQyReQxn8W7eHKPo4Q0aAwy/g==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@ng-web-apis/mutation-observer/-/mutation-observer-3.0.6.tgz", + "integrity": "sha512-UW1qoUi2whH0uWkVz5qpdYCLs1u2T0E0QoCMQKZfLEkBpsWRTkT0PTCa9WWX/BhehaSPg23nZZm8BEixd6PI9w==", "dependencies": { "tslib": "^2.2.0" }, @@ -3747,9 +3766,9 @@ } }, "node_modules/@ng-web-apis/resize-observer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@ng-web-apis/resize-observer/-/resize-observer-3.0.5.tgz", - "integrity": "sha512-nmOpNL7c+RAxsnsmF2TvSuyWGQMqCTJ7MYVzSrDdNDFVqkEX5yQGu0UC+JM/8sEBcePjqju6OkJDWOLGF7uhOQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@ng-web-apis/resize-observer/-/resize-observer-3.0.6.tgz", + "integrity": "sha512-QdGYdEdC0AzFonLfNOnyYyeCwnvK9jlskoeefvJN3Yyvds3ivBrrTjpeDOdiLsQpCPBp9/673imgq7355vkQow==", "dependencies": { "tslib": "^2.2.0" }, @@ -3759,9 +3778,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.7.tgz", - "integrity": "sha512-QnVoYpMNMuV387VgmP/c/ylD9qUIZpN02LMg3rQqz7NDej0jboBZaxqLJ+7jQaCoEIFVGIgL/RR/X1kponxJZg==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.10.tgz", + "integrity": "sha512-XAVn59zP3ztuKDtw92Xc9+64RK4u4c9g8y5GgtjIWeOwgNXl8bYhAo3uTZzrSrOu96DFZGjsmghFab/7/C2pDg==", "dev": true, "engines": { "node": "^16.14.0 || >=18.10.0", @@ -3880,6 +3899,20 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "devOptional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/@npmcli/node-gyp": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", @@ -4031,18 +4064,18 @@ } }, "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@schematics/angular": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.7.tgz", - "integrity": "sha512-sL+7vmwYPdo29rp99XYlm8gibqcjjOL5LKEleVQlv63SRES3HLMt7DeYivUfizcMENu/1hDtX41ig4Mu1SpNzg==", + "version": "16.2.10", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.10.tgz", + "integrity": "sha512-PXmoswvN7qknTsXDmEvhZ9UG+awwWnQ/1Jd/eqqQx08iAaAT81OsXj1bN7eSs6tEGBKGjPb6q2xzuiECAdymzg==", "dependencies": { - "@angular-devkit/core": "16.2.7", - "@angular-devkit/schematics": "16.2.7", + "@angular-devkit/core": "16.2.10", + "@angular-devkit/schematics": "16.2.10", "jsonc-parser": "3.2.0" }, "engines": { @@ -4086,6 +4119,113 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@sigstore/sign/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "devOptional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@sigstore/sign/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "devOptional": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "devOptional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sigstore/sign/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "devOptional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "devOptional": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, "node_modules/@sigstore/tuf": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", @@ -4133,9 +4273,9 @@ } }, "node_modules/@taiga-ui/addon-charts": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.52.0.tgz", - "integrity": "sha512-qu2p6Uo5qMTdh1hfnEB4xLHF0vsOw2YhDcq1bcqNWmI6Su2K090P2lsd9mCNyNHWAIrejjcCqBKRwJDopVm0hw==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-3.53.0.tgz", + "integrity": "sha512-hmZVovX7Pg9lwz33lzITVRCWDB1SzA68KFxxrVAgkRIw05il9pv7XUuCE9hv/Yb7F7w7LEZoz0+TohB09FW/EQ==", "dependencies": { "tslib": ">=2.0.0" }, @@ -4143,15 +4283,15 @@ "@angular/common": ">=12.0.0", "@angular/core": ">=12.0.0", "@ng-web-apis/common": ">=3.0.0", - "@taiga-ui/cdk": ">=3.52.0", - "@taiga-ui/core": ">=3.52.0", + "@taiga-ui/cdk": ">=3.53.0", + "@taiga-ui/core": ">=3.53.0", "@tinkoff/ng-polymorpheus": ">=4.0.0" } }, "node_modules/@taiga-ui/addon-commerce": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/addon-commerce/-/addon-commerce-3.52.0.tgz", - "integrity": "sha512-4oRmYhTsaN34L37MpwLder8eF3/WgsP/36qQWxsyhKCRN+H/ltpw7Yp16JO0Tg+nkj0ErtGOzZ4vZMl4+xJnAA==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/addon-commerce/-/addon-commerce-3.53.0.tgz", + "integrity": "sha512-iRzMEZKJg90FyP15eHvy12aD3YG0fmzP2ejBrm1L7GmJksaibsM8B2Foo7nA8PPsHsoRWBDJCVTfnLcc9ulDDg==", "peer": true, "dependencies": { "tslib": ">=2.0.0" @@ -4164,24 +4304,22 @@ "@maskito/core": ">=1.3.0", "@maskito/kit": ">=1.3.0", "@ng-web-apis/common": ">=3.0.0", - "@taiga-ui/cdk": ">=3.52.0", - "@taiga-ui/core": ">=3.52.0", - "@taiga-ui/i18n": ">=3.52.0", - "@taiga-ui/kit": ">=3.52.0", + "@taiga-ui/cdk": ">=3.53.0", + "@taiga-ui/core": ">=3.53.0", + "@taiga-ui/i18n": ">=3.53.0", + "@taiga-ui/kit": ">=3.53.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } }, "node_modules/@taiga-ui/cdk": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.52.0.tgz", - "integrity": "sha512-fZ9HGUu1rpJXf9yq8SH0K5qLugErtaoCQErGd0Waa6zEV9jb0bm4XoCwSAUKTAUutJ1iQCzj34F5oDoDTG2ydA==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-3.53.0.tgz", + "integrity": "sha512-/+knIWNVxywdxxq3MwYGMSGBcc+bJ0PLc9Qnn2KyhxhQylWx9OD1O3gO64BE+pdmcCaLH0bye5j52wy+4bpowg==", "dependencies": { - "@angular-devkit/schematics": "12.2.18", - "@ng-web-apis/common": "3.0.5", - "@ng-web-apis/mutation-observer": "3.0.5", - "@ng-web-apis/resize-observer": "3.0.5", - "@schematics/angular": "12.2.18", + "@ng-web-apis/common": "3.0.6", + "@ng-web-apis/mutation-observer": "3.0.6", + "@ng-web-apis/resize-observer": "3.0.6", "@tinkoff/ng-event-plugins": "3.1.0", "@tinkoff/ng-polymorpheus": "4.2.0", "tslib": "2.6.2" @@ -4198,144 +4336,12 @@ "rxjs": ">=6.0.0" } }, - "node_modules/@taiga-ui/cdk/node_modules/@angular-devkit/core": { - "version": "12.2.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.18.tgz", - "integrity": "sha512-GDLHGe9HEY5SRS+NrKr14C8aHsRCiBFkBFSSbeohgLgcgSXzZHFoU84nDWrl3KZNP8oqcUSv5lHu6dLcf2fnww==", - "dependencies": { - "ajv": "8.6.2", - "ajv-formats": "2.1.0", - "fast-json-stable-stringify": "2.1.0", - "magic-string": "0.25.7", - "rxjs": "6.6.7", - "source-map": "0.7.3" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/@angular-devkit/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@taiga-ui/cdk/node_modules/@angular-devkit/schematics": { - "version": "12.2.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.18.tgz", - "integrity": "sha512-bZ9NS5PgoVfetRC6WeQBHCY5FqPZ9y2TKHUo12sOB2YSL3tgWgh1oXyP8PtX34gasqsLjNULxEQsAQYEsiX/qQ==", - "dependencies": { - "@angular-devkit/core": "12.2.18", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/@angular-devkit/schematics/node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/@angular-devkit/schematics/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/@taiga-ui/cdk/node_modules/@schematics/angular": { - "version": "12.2.18", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.18.tgz", - "integrity": "sha512-niRS9Ly9y8uI0YmTSbo8KpdqCCiZ/ATMZWeS2id5M8JZvfXbngwiqJvojdSol0SWU+n1W4iA+lJBdt4gSKlD5w==", - "dependencies": { - "@angular-devkit/core": "12.2.18", - "@angular-devkit/schematics": "12.2.18", - "jsonc-parser": "3.0.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/ajv": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", - "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/ajv-formats": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", - "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/@taiga-ui/cdk/node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" - }, - "node_modules/@taiga-ui/cdk/node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/@taiga-ui/cdk/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" - } - }, "node_modules/@taiga-ui/core": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.52.0.tgz", - "integrity": "sha512-KstWj5idjABd4qj7kvv7qRRRCogGKlT90LaAHZ/ha6sR8/nLDXtLcLJkLrWSSI6LFQXXTLtj/SDeMxdMvkCTSw==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-3.53.0.tgz", + "integrity": "sha512-3YgkJbnXeZ4FzDdoRl9XOD0r+1RpMwjXSku/fbAt78X8+uRCWMJl9dVJzhTwhcD5HmwmNOjANAr2DtqAikfcOg==", "dependencies": { - "@taiga-ui/i18n": "^3.52.0", + "@taiga-ui/i18n": "^3.53.0", "tslib": ">=2.0.0" }, "peerDependencies": { @@ -4347,35 +4353,35 @@ "@angular/router": ">=12.0.0", "@ng-web-apis/common": ">=3.0.0", "@ng-web-apis/mutation-observer": ">=3.0.0", - "@taiga-ui/cdk": ">=3.52.0", - "@taiga-ui/i18n": ">=3.52.0", + "@taiga-ui/cdk": ">=3.53.0", + "@taiga-ui/i18n": ">=3.53.0", "@tinkoff/ng-event-plugins": ">=3.1.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } }, "node_modules/@taiga-ui/experimental": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/experimental/-/experimental-3.52.0.tgz", - "integrity": "sha512-oql9ctZ0eXeQ6f4n525sL4xI2N5r9+qu4sEvuJaS9Qv008hyxKdgdqLRB4CmG4qIphfukHm2Q1cU+lsDM7+ENg==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/experimental/-/experimental-3.53.0.tgz", + "integrity": "sha512-oAeID9MGt5AwMDNFJWixbBf00ZnclZmBRjRX+wAIr9KqlNUGzKU0BuyW/WaS+HwMMZlUzoE+P0lS1w+YJ6aaIg==", "dependencies": { "tslib": ">=2.0.0" }, "peerDependencies": { "@angular/common": ">=12.0.0", "@angular/core": ">=12.0.0", - "@taiga-ui/addon-commerce": ">=3.52.0", - "@taiga-ui/cdk": ">=3.52.0", - "@taiga-ui/core": ">=3.52.0", - "@taiga-ui/kit": ">=3.52.0", + "@taiga-ui/addon-commerce": ">=3.53.0", + "@taiga-ui/cdk": ">=3.53.0", + "@taiga-ui/core": ">=3.53.0", + "@taiga-ui/kit": ">=3.53.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } }, "node_modules/@taiga-ui/i18n": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.52.0.tgz", - "integrity": "sha512-182Yf1QQXEjKSqEScuH01DZMBIyCa2/yOe6qtvmlAHjl67DRjaajtd0N7ehrNl8C9TyN4HsAbcGRtyMP0/0xgQ==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-3.53.0.tgz", + "integrity": "sha512-/SfafSmWOejCyLab9OViMa/EZy4zC7bHFHxsVOnLwtowu1d8KiQFce6IyMZUryX07LZSrZwA1qNvhZNyfifGaw==", "dependencies": { "tslib": ">=2.0.0" }, @@ -4386,25 +4392,25 @@ } }, "node_modules/@taiga-ui/icons": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.52.0.tgz", - "integrity": "sha512-0DjCqzCgk5FGh64NCf1tNgbXVR8TEVn9kUyhdaoEVd3K38eVyKtx/6DWjB0oV5+a1ZG1uq+oP6ixNurC4C6x8g==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-3.53.0.tgz", + "integrity": "sha512-rQhLE4Z27r/OUmZHp3R9KXnz3TDQbzPTqoLuwNKAjrJuZ0NqnCJ74hm50RaiWAs5cO5tLZPjt0QSEi+NnM9qNg==", "dependencies": { "tslib": ">=2.0.0" }, "peerDependencies": { - "@taiga-ui/cdk": ">=3.52.0" + "@taiga-ui/cdk": ">=3.53.0" } }, "node_modules/@taiga-ui/kit": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.52.0.tgz", - "integrity": "sha512-T5DR6Np7RiMGX+xMmeGisCc33Js5X2nztObW5VfprU3C7eCp15Z7rw3J3+NdJtf90IJ4EijcbEP8HPxE2sJIVQ==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-3.53.0.tgz", + "integrity": "sha512-ZKWRc5aBDPZ+9L+tlWVi9kNV1PEraCmjn4QSykxtz+gyZZU19sTwwpjitFujAVFeH7fI48W+pW64pn4s7GtFAg==", "dependencies": { "@maskito/angular": "1.8.1", "@maskito/core": "1.8.1", "@maskito/kit": "1.8.1", - "@ng-web-apis/intersection-observer": "3.1.5", + "@ng-web-apis/intersection-observer": "3.1.6", "text-mask-core": "5.1.2", "tslib": ">=2.0.0" }, @@ -4416,19 +4422,19 @@ "@ng-web-apis/common": ">=3.0.0", "@ng-web-apis/mutation-observer": ">=3.0.0", "@ng-web-apis/resize-observer": ">=3.0.0", - "@taiga-ui/cdk": ">=3.52.0", - "@taiga-ui/core": ">=3.52.0", - "@taiga-ui/i18n": ">=3.52.0", + "@taiga-ui/cdk": ">=3.53.0", + "@taiga-ui/core": ">=3.53.0", + "@taiga-ui/i18n": ">=3.53.0", "@tinkoff/ng-polymorpheus": ">=4.0.0", "rxjs": ">=6.0.0" } }, "node_modules/@taiga-ui/styles": { - "version": "3.52.0", - "resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-3.52.0.tgz", - "integrity": "sha512-VabK+8cV2DErI8cENyy2u/xjX2U0bg8J0fL/A9PrCu8LS9VZGXuH7m7AbMbo05ADpmkqDYDt9N0eBzik3+pVxw==", + "version": "3.53.0", + "resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-3.53.0.tgz", + "integrity": "sha512-KGyWsrq9aGMM7yV5clIsM31/Wz3j+5egO3wP+yWWUGlr6NI+RYlNsl5tJKya5rNG9AA0Pmrv2q+yU3UAcgsyFg==", "peerDependencies": { - "@taiga-ui/cdk": ">=3.52.0", + "@taiga-ui/cdk": ">=3.53.0", "tslib": ">=2.0.0" } }, @@ -4492,15 +4498,6 @@ "path-browserify": "^1.0.1" } }, - "node_modules/@ts-morph/common/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "optional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/@ts-morph/common/node_modules/minimatch": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", @@ -4577,34 +4574,10 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@tufjs/models/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "devOptional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "devOptional": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@types/body-parser": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", - "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, "dependencies": { "@types/connect": "*", @@ -4612,43 +4585,33 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", - "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { - "version": "3.4.37", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", - "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", - "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.3.tgz", + "integrity": "sha512-6mfQ6iNvhSKCZJoY6sIG3m0pKkdUcweVNOLuBBKvoWGzl2yRxOJcYOTRyLKt3nxXvBLJWa6QkW//tgbIwJehmA==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" } }, - "node_modules/@types/cron": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.4.0.tgz", - "integrity": "sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==", - "deprecated": "This is a stub types definition. cron provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "cron": "*" - } - }, "node_modules/@types/dompurify": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.4.0.tgz", @@ -4658,9 +4621,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", - "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", + "version": "8.44.7", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz", + "integrity": "sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -4668,9 +4631,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", - "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -4684,9 +4647,9 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", - "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -4696,9 +4659,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.39", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", - "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", "dev": true, "dependencies": { "@types/node": "*", @@ -4708,45 +4671,45 @@ } }, "node_modules/@types/fs-extra": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.4.tgz", - "integrity": "sha512-OMcQKnlrkrOI0TaZ/MgVDA8LYFl7CykzFsjMj9l5x3un2nFxCY20ZFlnqrM0lcqlbs0Yro2HbnZlmopyRaoJ5w==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.5.tgz", + "integrity": "sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/http-errors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", - "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, "node_modules/@types/http-proxy": { - "version": "1.17.13", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", - "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/js-yaml": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.8.tgz", - "integrity": "sha512-m6jnPk1VhlYRiLFm3f8X9Uep761f+CK8mHyS65LutH2OhmBF0BeMEjHgg05usH8PLZMWWc/BUR9RPmkvpWnyRA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/luxon": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.3.tgz", - "integrity": "sha512-/BJF3NT0pRMuxrenr42emRUF67sXwcZCd+S1ksG/Fcf9O7C3kKCY4uJSbKBE4KDUIYr3WMsvfmWD8hRjXExBJQ==" + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.4.tgz", + "integrity": "sha512-H9OXxv4EzJwE75aTPKpiGXJq+y4LFxjpsdgKwSmr503P5DkWc3AG7VAFYrFNVvqemT5DfgZJV9itYhqBHSGujA==" }, "node_modules/@types/marked": { "version": "4.3.2", @@ -4755,9 +4718,9 @@ "dev": true }, "node_modules/@types/mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", - "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, "node_modules/@types/minimatch": { @@ -4767,51 +4730,63 @@ "optional": true }, "node_modules/@types/mustache": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.2.4.tgz", - "integrity": "sha512-5DK8oX+pyEJm8Arm57Ut2R4KCeDuNQhLAuU04IgaKB7nYsFYzhpWqSoFnp7kCtVG7wXKftnaEJIyUFTVvSkkzw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.2.5.tgz", + "integrity": "sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA==", "dev": true }, "node_modules/@types/node": { - "version": "18.18.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz", - "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==", - "dev": true + "version": "18.18.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", + "integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.9.tgz", + "integrity": "sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/node-jose": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@types/node-jose/-/node-jose-1.1.12.tgz", - "integrity": "sha512-HtSXbirRMuONr/KSNtBgh631xCt/t3lPz0geQ4pe/FA+yu06TUrJrXEU5y8nJFHNy8KhiZrq6OVlqXD1AtT/dQ==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@types/node-jose/-/node-jose-1.1.13.tgz", + "integrity": "sha512-QjMd4yhwy1EvSToQn0YI3cD29YhyfxFwj7NecuymjLys2/P0FwxWnkgBlFxCai6Y3aBCe7rbwmqwJJawxlgcXw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/parse-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", - "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "dev": true }, "node_modules/@types/pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4HCoGwR3221nOc7G0Z/6KgTNGgaaFGkbGrtUJsB+zlKX2LBVjFHHIUkieMBgHHXgBH5Gq6dZHJKdBYdtlhBQvw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/qs": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", - "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", - "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, "node_modules/@types/resolve": { @@ -4827,9 +4802,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", - "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -4837,18 +4812,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", - "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", - "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -4863,18 +4838,18 @@ "dev": true }, "node_modules/@types/sockjs": { - "version": "0.3.35", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", - "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/trusted-types": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.5.tgz", - "integrity": "sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.6.tgz", + "integrity": "sha512-HYtNooPvUY9WAVRBr4u+4Qa9fYD1ze2IUlAD3HoA6oehn1taGwBx3Oa52U4mTslTS+GAExKpaFu39Y5xUEwfjg==" }, "node_modules/@types/uuid": { "version": "8.3.4", @@ -4883,9 +4858,9 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", - "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz", + "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==", "dev": true, "dependencies": { "@types/node": "*" @@ -5186,9 +5161,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -5616,13 +5591,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz", - "integrity": "sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA==", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz", + "integrity": "sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==", "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.4.3", - "core-js-compat": "^3.32.2" + "core-js-compat": "^3.33.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -5818,13 +5793,12 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "devOptional": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -6000,9 +5974,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001553", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz", - "integrity": "sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==", + "version": "1.0.30001561", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz", + "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==", "dev": true, "funding": [ { @@ -6566,9 +6540,9 @@ } }, "node_modules/core-js": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.1.tgz", - "integrity": "sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==", + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.2.tgz", + "integrity": "sha512-XeBzWI6QL3nJQiHmdzbAOiMYqjrb7hwU7A39Qhvd/POSa/t9E1AeZyEZx3fNvp/vtM8zXwhoL0FsiS0hD0pruQ==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -6576,9 +6550,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.1.tgz", - "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz", + "integrity": "sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==", "dev": true, "dependencies": { "browserslist": "^4.22.1" @@ -6745,9 +6719,9 @@ } }, "node_modules/cronstrue": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-2.32.0.tgz", - "integrity": "sha512-dmNflOCNJL6lZEj0dp2YhGIPY83VTjFue6d9feFhnNtrER6mAjBrUvSgK95j3IB/xNGpLjaZDIDG6ACKTZr9Yw==", + "version": "2.41.0", + "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-2.41.0.tgz", + "integrity": "sha512-3ZS3eMJaxMRBGmDauKCKbyIRgVcph6uSpkhSbbZvvJWkelHiSTzGJbBqmu8io7Hspd2F45bQKnC1kzoNvtku2g==", "bin": { "cronstrue": "bin/cli.js" } @@ -7374,9 +7348,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.563", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", - "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", + "version": "1.4.580", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz", + "integrity": "sha512-T5q3pjQon853xxxHUq3ZP68ZpvJHuSMY2+BZaW3QzjS4HvNuvsMmZ/+lU+nCrftre1jFZ+OSlExynXWBihnXzw==", "dev": true }, "node_modules/elementtree": { @@ -7873,7 +7847,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -8391,30 +8366,6 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "devOptional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "devOptional": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -9093,30 +9044,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "devOptional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "devOptional": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -9179,6 +9106,12 @@ "node": ">=8" } }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "devOptional": true + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -9554,9 +9487,9 @@ } }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" @@ -9644,9 +9577,9 @@ } }, "node_modules/jiti": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", - "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -10618,29 +10551,43 @@ "dev": true }, "node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "devOptional": true, "dependencies": { "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" + "ssri": "^9.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "devOptional": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { @@ -10653,35 +10600,63 @@ } }, "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "devOptional": true, "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", - "minipass": "^7.0.3", + "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", "p-map": "^4.0.0", - "ssri": "^10.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "unique-filename": "^2.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/make-fetch-happen/node_modules/cacache/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 8" + } + }, + "node_modules/make-fetch-happen/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "devOptional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { @@ -10707,15 +10682,72 @@ "node": ">=12" } }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/make-fetch-happen/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { "node": ">=8" } }, + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "devOptional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "devOptional": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "devOptional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -10872,15 +10904,18 @@ "dev": true }, "node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "devOptional": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -10932,22 +10967,40 @@ "devOptional": true }, "node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "devOptional": true, "dependencies": { - "minipass": "^7.0.3", + "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", @@ -11161,6 +11214,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/multimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/multimatch/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mustache": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", @@ -11176,9 +11251,9 @@ "devOptional": true }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -11283,15 +11358,6 @@ "tslib": "2.5.3" } }, - "node_modules/ng-morph/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "optional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/ng-morph/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -11304,21 +11370,6 @@ "node": ">=10" } }, - "node_modules/ng-morph/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "optional": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ng-morph/node_modules/semver": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", @@ -11935,16 +11986,16 @@ } }, "node_modules/node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", "devOptional": true, "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^7.1.4", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", + "make-fetch-happen": "^10.0.3", "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", @@ -11971,6 +12022,16 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/node-gyp/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -12247,6 +12308,96 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-registry-fetch/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "devOptional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm-registry-fetch/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "devOptional": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "devOptional": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm-registry-fetch/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "devOptional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "devOptional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "devOptional": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/npm-registry-fetch/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -12256,6 +12407,32 @@ "node": ">=8" } }, + "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass-fetch/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "devOptional": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -13311,6 +13488,16 @@ "postcss": "^8.0.0" } }, + "node_modules/postcss-url/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/postcss-url/node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -13338,6 +13525,18 @@ "node": ">=4.0.0" } }, + "node_modules/postcss-url/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/postcss-url/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -13516,9 +13715,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -14108,6 +14307,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -14337,11 +14546,12 @@ "dev": true }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -14664,6 +14874,113 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/sigstore/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "devOptional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sigstore/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "devOptional": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "devOptional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sigstore/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "devOptional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "devOptional": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sigstore/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, "node_modules/sirv": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", @@ -14858,12 +15175,6 @@ "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -15393,6 +15704,16 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/test-exclude/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -15603,9 +15924,9 @@ } }, "node_modules/ts-node/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -15656,6 +15977,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/tslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/tslint/node_modules/builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -15775,6 +16106,113 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/tuf-js/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "devOptional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tuf-js/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "devOptional": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "devOptional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tuf-js/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "devOptional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "devOptional": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tuf-js/node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -15840,6 +16278,12 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -15905,9 +16349,9 @@ } }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -16111,9 +16555,9 @@ } }, "node_modules/vm2/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -16260,9 +16704,9 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -16464,9 +16908,9 @@ } }, "node_modules/webpack/node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true, "peer": true }, @@ -16938,9 +17382,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "engines": { "node": ">= 14" } diff --git a/frontend/package.json b/frontend/package.json index 1a0980626..8c8f1fc8b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,29 +1,29 @@ { "name": "startos-ui", - "version": "0.3.4.4", + "version": "0.3.5", "author": "Start9 Labs, Inc", "homepage": "https://start9.com/", "scripts": { "ng": "ng", - "check": "npm run check:shared && npm run check:marketplace && npm run check:ui && npm run check:install-wiz && npm run check:setup && npm run check:dui", + "check": "npm run check:shared && npm run check:marketplace && npm run check:ui && npm run check:install && npm run check:setup", "check:shared": "tsc --project projects/shared/tsconfig.json --noEmit --skipLibCheck", "check:marketplace": "tsc --project projects/marketplace/tsconfig.json --noEmit --skipLibCheck", - "check:install-wiz": "tsc --project projects/install-wizard/tsconfig.json --noEmit --skipLibCheck", + "check:install": "tsc --project projects/install-wizard/tsconfig.json --noEmit --skipLibCheck", "check:setup": "tsc --project projects/setup-wizard/tsconfig.json --noEmit --skipLibCheck", "check:ui": "tsc --project projects/ui/tsconfig.json --noEmit --skipLibCheck", "build:deps": "rm -rf .angular/cache && cd ../patch-db/client && npm ci && npm run build", - "build:install-wiz": "ng run install-wizard:build", + "build:install": "ng run install-wizard:build", "build:setup": "ng run setup-wizard:build", "build:ui": "ng run ui:build", "build:ui:dev": "ng run ui:build:development", "build:ui:stats": "ng run ui:build --stats-json", - "build:all": "npm run build:deps && npm run build:dui && npm run build:setup && npm run build:ui && npm run build:install-wiz", + "build:all": "npm run build:deps && npm run build:setup && npm run build:ui && npm run build:install", "build:shared": "ng build shared", "build:marketplace": "npm run build:shared && ng build marketplace", "analyze:ui": "webpack-bundle-analyzer dist/raw/ui/stats.json", "publish:shared": "npm run build:shared && npm publish ./dist/shared --access public", "publish:marketplace": "npm run build:marketplace && npm publish ./dist/marketplace --access public", - "start:install-wiz": "npm run-script build-config && ionic serve --project install-wizard --host 0.0.0.0", + "start:install": "npm run-script build-config && ionic serve --project install-wizard --host 0.0.0.0", "start:setup": "npm run-script build-config && ionic serve --project setup-wizard --host 0.0.0.0", "start:ui": "npm run-script build-config && ionic serve --project ui --ip --host 0.0.0.0", "start:ui:proxy": "npm run-script build-config && ionic serve --project ui --ip --host 0.0.0.0 -- --proxy-config proxy.conf.json", @@ -44,13 +44,14 @@ "@materia-ui/ngx-monaco-editor": "^6.0.0", "@start9labs/argon2": "^0.1.0", "@start9labs/emver": "^0.1.5", - "@taiga-ui/addon-charts": "3.52.0", - "@taiga-ui/cdk": "3.52.0", - "@taiga-ui/core": "3.52.0", - "@taiga-ui/experimental": "3.52.0", - "@taiga-ui/icons": "3.52.0", - "@taiga-ui/kit": "3.52.0", - "@taiga-ui/styles": "3.52.0", + "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc8.beta2", + "@taiga-ui/addon-charts": "3.53.0", + "@taiga-ui/cdk": "3.53.0", + "@taiga-ui/core": "3.53.0", + "@taiga-ui/experimental": "3.53.0", + "@taiga-ui/icons": "3.53.0", + "@taiga-ui/kit": "3.53.0", + "@taiga-ui/styles": "3.53.0", "@tinkoff/ng-dompurify": "4.0.0", "ansi-to-html": "^0.7.2", "base64-js": "^1.5.1", @@ -72,7 +73,6 @@ "patch-db-client": "file: ../../../patch-db/client", "pbkdf2": "^3.1.2", "rxjs": "^7.5.6", - "@start9labs/start-sdk": "0.4.0-rev0.lib0.rc8.beta2", "swiper": "^8.2.4", "ts-matches": "^5.2.1", "tslib": "^2.3.0", @@ -85,7 +85,6 @@ "@angular/compiler-cli": "^16.1.4", "@angular/language-service": "^16.1.4", "@ionic/cli": "^6.19.0", - "@types/cron": "^2.0.0", "@types/dompurify": "^2.3.3", "@types/estree": "^0.0.51", "@types/js-yaml": "^4.0.5", diff --git a/frontend/projects/install-wizard/src/app/pages/home/home.page.html b/frontend/projects/install-wizard/src/app/pages/home/home.page.html index d1ebe43b5..5bdaee493 100644 --- a/frontend/projects/install-wizard/src/app/pages/home/home.page.html +++ b/frontend/projects/install-wizard/src/app/pages/home/home.page.html @@ -2,8 +2,8 @@ -

- +
+
diff --git a/frontend/projects/setup-wizard/src/app/pages/home/home.page.html b/frontend/projects/setup-wizard/src/app/pages/home/home.page.html index 3c803bb34..ab517cbcb 100644 --- a/frontend/projects/setup-wizard/src/app/pages/home/home.page.html +++ b/frontend/projects/setup-wizard/src/app/pages/home/home.page.html @@ -4,13 +4,13 @@
- + Download your server's Root CA and
Note: This address will only work from a Tor-enabled browser. -
+

Setup Complete!

-
- -
-
-

Continue to login

- -
-
-
-
+ @@ -34,8 +32,8 @@ -
-
+
+
- - Download permanent address info - + Download address info

start.local was for setup purposes only. It will no longer work.

-
-
-

Download

- -
+
+

Download

+
-
-
-

Login to StartOS

- + + Trust your Root CA +

+ In the new tab, follow instructions to trust your + server's Root CA and log in. +

+
+ +
+
+

Open

+ +
-
+
diff --git a/frontend/projects/setup-wizard/src/app/pages/success/success.page.scss b/frontend/projects/setup-wizard/src/app/pages/success/success.page.scss index cec258241..910849788 100644 --- a/frontend/projects/setup-wizard/src/app/pages/success/success.page.scss +++ b/frontend/projects/setup-wizard/src/app/pages/success/success.page.scss @@ -18,19 +18,24 @@ ion-content { ion-grid { max-width: 760px; - height: 100%; } -.grid-center-wrapper { - height: 100%; - width: 100%; +.inline-container { display: flex; justify-content: center; align-items: center; } +.card-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1rem; +} + ion-card { - padding: 3rem; + padding: 2.4rem; h1 { color: var(--ion-color-success); @@ -44,14 +49,14 @@ ion-card { margin-bottom: 2rem; } + // download info card ion-card { - max-width: 91%; - min-width: 91%; + min-height: 260px; + width: 80%; background: #615F5F; color: var(--ion-text-color); box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); border-radius: 44px; - margin: auto; text-align: left; cursor: pointer; position: relative; @@ -70,14 +75,6 @@ ion-card { font-size: 1.3rem; } - ion-card-content { - padding-bottom: 4rem; - - p { - padding: 1rem 0; - } - } - ion-footer { position: absolute; bottom: 10px; @@ -100,19 +97,24 @@ ion-card { } } - .container { - display: flex; - justify-content: center; - align-items: center; - } - - #exit { - background: var(--color-accent); - height: 100%; - - .container p { - font-size: 1.4rem !important; - font-weight: bold; + .login-button { + --background: var(--color-accent); + --padding-bottom: 2.5rem; + --padding-top: 2.5rem; + --padding-start: 2.5rem; + --padding-end: 2.5rem; + --border-radius: 44px; + font-size: 1.4rem !important; + font-weight: bold; + text-transform: none; + letter-spacing: normal; + transition: all 350ms ease; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + + &:hover { + transition-property: transform; + transform: scale(1.05); + transition-delay: 40ms; } ion-icon { @@ -120,40 +122,62 @@ ion-card { } } - #launch { - background: var(--alt-blue); - height: 100%; - - .container p { - font-size: 1.4rem !important; - font-weight: bold; - } - - ion-icon { - font-size: 1.7rem; - } + .launch-button { + --background: var(--alt-blue); } - #information:after { + #information:after, #launch:after { content: ''; position: absolute; left: 0; - top: 80%; + top: 79%; width: 100%; height: 100%; background: var(--color-accent); } + + #launch:after { + background: var(--alt-blue); + } + } -.card-container { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 2rem; +.mb-12 { + margin-bottom: 3rem; } -.emphasis-warn { - font-weight: 600; - color: var(--ion-color-warning); +.pb-2 { + padding-bottom: 0.5rem; +} + +.pt-1 { + padding-top: 0.25rem; +} + + +.action-text { + font-variant-caps: all-small-caps; + padding-right: 0.5rem; + font-size: 1.5rem !important; + letter-spacing: 0.03rem; + padding-bottom: 0.1rem; +} + +@media (max-width: 700px) { + .setup { + flex-direction: column; + } + + ion-card { + ion-card { + width: 100%; + padding-bottom: unset; + } + #information:after { + top: 84%; + } + #launch:after { + top: 85%; + } + } } \ No newline at end of file diff --git a/frontend/projects/setup-wizard/src/app/pages/success/success.page.ts b/frontend/projects/setup-wizard/src/app/pages/success/success.page.ts index ed83131fa..7dc4b9add 100644 --- a/frontend/projects/setup-wizard/src/app/pages/success/success.page.ts +++ b/frontend/projects/setup-wizard/src/app/pages/success/success.page.ts @@ -46,18 +46,7 @@ export class SuccessPage { async ngAfterViewInit() { this.ngZone.runOutsideAngular(() => this.initMatrix()) - try { - const ret = await this.api.complete() - if (!this.isKiosk) { - this.torAddress = ret['tor-address'] - this.lanAddress = ret['lan-address'].replace(/^https:/, 'http:') - this.cert = ret['root-ca'] - - await this.api.exit() - } - } catch (e: any) { - await this.errorService.handleError(e) - } + setTimeout(() => this.complete(), 1000) } download() { @@ -84,6 +73,21 @@ export class SuccessPage { this.api.exit() } + private async complete() { + try { + const ret = await this.api.complete() + if (!this.isKiosk) { + this.torAddress = ret['tor-address'].replace(/^https:/, 'http:') + this.lanAddress = ret['lan-address'].replace(/^https:/, 'http:') + this.cert = ret['root-ca'] + + await this.api.exit() + } + } catch (e: any) { + this.errorService.handleError(e) + } + } + private initMatrix() { this.ctx = this.canvas.nativeElement.getContext('2d')! this.canvas.nativeElement.width = window.innerWidth diff --git a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts index 96730955e..375cd2135 100644 --- a/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts +++ b/frontend/projects/setup-wizard/src/app/services/api/mock-api.service.ts @@ -44,14 +44,14 @@ export class MockApiService extends ApiService { await pauseFor(1000) return [ { - logicalname: 'abcd', - vendor: 'Samsung', - model: 'T5', + logicalname: '/dev/nvme0n1p3', + vendor: 'Unknown Vendor', + model: 'Samsung SSD - 970 EVO Plus 2TB', partitions: [ { logicalname: 'pabcd', label: null, - capacity: 73264762332, + capacity: 1979120929996, used: null, 'embassy-os': { version: '0.2.17', @@ -63,13 +63,13 @@ export class MockApiService extends ApiService { guid: null, }, ], - capacity: 123456789123, + capacity: 1979120929996, guid: 'uuid-uuid-uuid-uuid', }, { logicalname: 'dcba', - vendor: 'Crucial', - model: 'MX500', + vendor: 'CT1000MX', + model: '500SSD1', partitions: [ { logicalname: 'pbcba', @@ -86,13 +86,13 @@ export class MockApiService extends ApiService { guid: null, }, ], - capacity: 124456789123, + capacity: 1000190509056, guid: null, }, { - logicalname: 'wxyz', - vendor: 'SanDisk', - model: 'Specialness', + logicalname: '/dev/sda', + vendor: 'ASMT', + model: '2115', partitions: [ { logicalname: 'pbcba', @@ -109,7 +109,7 @@ export class MockApiService extends ApiService { guid: 'guid-guid-guid-guid', }, ], - capacity: 123459789123, + capacity: 1000190509056, guid: null, }, ] diff --git a/frontend/projects/setup-wizard/src/styles.scss b/frontend/projects/setup-wizard/src/styles.scss index df201b214..b9f09b845 100644 --- a/frontend/projects/setup-wizard/src/styles.scss +++ b/frontend/projects/setup-wizard/src/styles.scss @@ -218,7 +218,7 @@ ion-toast { * { display: inline-block; vertical-align: middle; - padding: 0.3rem; + padding-left: 0px 0.3rem; } } diff --git a/frontend/projects/shared/assets/img/icon.png b/frontend/projects/shared/assets/img/icon.png index 8b373c5a0..c87903911 100644 Binary files a/frontend/projects/shared/assets/img/icon.png and b/frontend/projects/shared/assets/img/icon.png differ diff --git a/frontend/projects/shared/assets/img/icon_pwa.png b/frontend/projects/shared/assets/img/icon_pwa.png deleted file mode 100644 index c87903911..000000000 Binary files a/frontend/projects/shared/assets/img/icon_pwa.png and /dev/null differ diff --git a/frontend/projects/shared/assets/img/icon_transparent.png b/frontend/projects/shared/assets/img/icon_transparent.png deleted file mode 100644 index f0aafd15d..000000000 Binary files a/frontend/projects/shared/assets/img/icon_transparent.png and /dev/null differ diff --git a/frontend/projects/shared/assets/img/logo.png b/frontend/projects/shared/assets/img/logo.png deleted file mode 100644 index 029c5c616..000000000 Binary files a/frontend/projects/shared/assets/img/logo.png and /dev/null differ diff --git a/frontend/projects/shared/assets/img/logo_dark.png b/frontend/projects/shared/assets/img/logo_dark.png deleted file mode 100644 index 318f0b5ed..000000000 Binary files a/frontend/projects/shared/assets/img/logo_dark.png and /dev/null differ diff --git a/frontend/projects/ui/src/app/app/enter/enter.directive.ts b/frontend/projects/shared/src/directives/enter/enter.directive.ts similarity index 92% rename from frontend/projects/ui/src/app/app/enter/enter.directive.ts rename to frontend/projects/shared/src/directives/enter/enter.directive.ts index 2a93ad93b..8d3d6a399 100644 --- a/frontend/projects/ui/src/app/app/enter/enter.directive.ts +++ b/frontend/projects/shared/src/directives/enter/enter.directive.ts @@ -1,6 +1,6 @@ import { Directive, HostListener, Inject } from '@angular/core' import { DOCUMENT } from '@angular/common' -import { debounce } from '@start9labs/shared' +import { debounce } from '../../util/misc.util' @Directive({ selector: '[appEnter]', diff --git a/frontend/projects/ui/src/app/app/enter/enter.module.ts b/frontend/projects/shared/src/directives/enter/enter.module.ts similarity index 100% rename from frontend/projects/ui/src/app/app/enter/enter.module.ts rename to frontend/projects/shared/src/directives/enter/enter.module.ts diff --git a/frontend/projects/shared/src/public-api.ts b/frontend/projects/shared/src/public-api.ts index aaa32896b..31846b93e 100644 --- a/frontend/projects/shared/src/public-api.ts +++ b/frontend/projects/shared/src/public-api.ts @@ -21,6 +21,8 @@ export * from './components/ticker/ticker.module' export * from './directives/drag-scroller.directive' export * from './directives/responsive-col.directive' export * from './directives/safe-links.directive' +export * from './directives/enter/enter.directive' +export * from './directives/enter/enter.module' export * from './mocks/get-setup-status' diff --git a/frontend/projects/shared/src/services/http.service.ts b/frontend/projects/shared/src/services/http.service.ts index e294d4ef6..d79f07f85 100644 --- a/frontend/projects/shared/src/services/http.service.ts +++ b/frontend/projects/shared/src/services/http.service.ts @@ -38,12 +38,13 @@ export class HttpService { async rpcRequest( opts: RPCOptions, + fullUrl?: string, ): Promise>> { const { method, headers, params, timeout } = opts return this.httpRequest>({ method: Method.POST, - url: this.relativeUrl, + url: fullUrl || this.relativeUrl, headers, body: { method, params }, timeout, diff --git a/frontend/projects/shared/src/types/workspace-config.ts b/frontend/projects/shared/src/types/workspace-config.ts index 6a7669b98..745031170 100644 --- a/frontend/projects/shared/src/types/workspace-config.ts +++ b/frontend/projects/shared/src/types/workspace-config.ts @@ -1,6 +1,4 @@ export type WorkspaceConfig = { - packageArch: 'aarch64' | 'x86_64' - osArch: 'aarch64' | 'x86_64' | 'raspberrypi' gitHash: string useMocks: boolean enableWidgets: boolean @@ -13,6 +11,7 @@ export type WorkspaceConfig = { marketplace: MarketplaceConfig mocks: { maskAs: 'tor' | 'local' | 'localhost' | 'ipv4' | 'ipv6' | 'clearnet' + maskAsHttps: boolean skipStartupAlerts: boolean } } diff --git a/frontend/projects/ui/src/app/app.component.html b/frontend/projects/ui/src/app/app.component.html index f92600d2e..ceac3e214 100644 --- a/frontend/projects/ui/src/app/app.component.html +++ b/frontend/projects/ui/src/app/app.component.html @@ -27,10 +27,7 @@ type="overlay" side="end" class="right-menu container" - [class.container_offline]=" - (authService.isVerified$ | async) && - !(connection.connected$ | async) - " + [class.container_offline]="offline$ | async" [class.right-menu_hidden]="!drawer.open" [style.--side-width.px]="drawer.width" > @@ -48,10 +45,7 @@ [responsiveColViewport]="viewport" id="main-content" class="container" - [class.container_offline]=" - (authService.isVerified$ | async) && - !(connection.connected$ | async) - " + [class.container_offline]="offline$ | async" > hasNavigation(this.router.url))), ]).pipe(map(([isVerified, hasNavigation]) => isVerified && hasNavigation)) + readonly offline$ = combineLatest([ + this.authService.isVerified$, + this.connection.connected$, + this.patch + .watch$('server-info', 'status-info') + .pipe(startWith({ restarting: false, 'shutting-down': false })), + ]).pipe( + map( + ([verified, connected, status]) => + verified && + (!connected || status.restarting || status['shutting-down']), + ), + ) + constructor( private readonly router: Router, private readonly titleService: Title, diff --git a/frontend/projects/ui/src/app/app.module.ts b/frontend/projects/ui/src/app/app.module.ts index e3636426a..64787ff00 100644 --- a/frontend/projects/ui/src/app/app.module.ts +++ b/frontend/projects/ui/src/app/app.module.ts @@ -11,12 +11,13 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations' import { IonicModule } from '@ionic/angular' import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor' import { - MarkdownModule, DarkThemeModule, SharedPipesModule, LightThemeModule, LoadingModule, ResponsiveColViewportDirective, + EnterModule, + MarkdownModule, } from '@start9labs/shared' import { AppComponent } from './app.component' @@ -26,7 +27,6 @@ import { QRComponentModule } from './common/qr/qr.module' import { PreloaderModule } from './app/preloader/preloader.module' import { FooterModule } from './app/footer/footer.module' import { MenuModule } from './app/menu/menu.module' -import { EnterModule } from './app/enter/enter.module' import { APP_PROVIDERS } from './app.providers' import { PatchDbModule } from './services/patch-db/patch-db.module' import { ToastContainerModule } from './common/toast-container/toast-container.module' diff --git a/frontend/projects/ui/src/app/app/connection-bar/connection-bar.component.ts b/frontend/projects/ui/src/app/app/connection-bar/connection-bar.component.ts index dc5388b04..9c4b07b7f 100644 --- a/frontend/projects/ui/src/app/app/connection-bar/connection-bar.component.ts +++ b/frontend/projects/ui/src/app/app/connection-bar/connection-bar.component.ts @@ -1,6 +1,8 @@ import { ChangeDetectionStrategy, Component } from '@angular/core' +import { PatchDB } from 'patch-db-client' import { combineLatest, map, Observable, startWith } from 'rxjs' import { ConnectionService } from 'src/app/services/connection.service' +import { DataModel } from 'src/app/services/patch-db/data-model' @Component({ selector: 'connection-bar', @@ -19,8 +21,11 @@ export class ConnectionBarComponent { }> = combineLatest([ this.connectionService.networkConnected$, this.websocket$.pipe(startWith(false)), + this.patch + .watch$('server-info', 'status-info') + .pipe(startWith({ restarting: false, 'shutting-down': false })), ]).pipe( - map(([network, websocket]) => { + map(([network, websocket, status]) => { if (!network) return { message: 'No Internet', @@ -35,6 +40,20 @@ export class ConnectionBarComponent { icon: 'cloud-offline-outline', dots: true, } + if (status['shutting-down']) + return { + message: 'Shutting Down', + color: 'dark', + icon: 'power', + dots: true, + } + if (status.restarting) + return { + message: 'Restarting', + color: 'dark', + icon: 'power', + dots: true, + } return { message: 'Connected', @@ -45,5 +64,8 @@ export class ConnectionBarComponent { }), ) - constructor(private readonly connectionService: ConnectionService) {} + constructor( + private readonly connectionService: ConnectionService, + private readonly patch: PatchDB, + ) {} } diff --git a/frontend/projects/ui/src/app/app/menu/menu.component.html b/frontend/projects/ui/src/app/app/menu/menu.component.html index a6305090d..58892db0d 100644 --- a/frontend/projects/ui/src/app/app/menu/menu.component.html +++ b/frontend/projects/ui/src/app/app/menu/menu.component.html @@ -1,10 +1,5 @@ -
@@ -27,11 +22,17 @@ {{ page.title }} + !synced)), + ) + constructor( private readonly patch: PatchDB, private readonly eosService: EOSService, @@ -118,5 +126,6 @@ export class MenuComponent { private readonly splitPane: SplitPaneTracker, private readonly emver: Emver, private readonly connectionService: ConnectionService, + private readonly config: ConfigService, ) {} } diff --git a/frontend/projects/ui/src/app/app/preloader/preloader.component.html b/frontend/projects/ui/src/app/app/preloader/preloader.component.html index 5c1c4f388..b26815f2c 100644 --- a/frontend/projects/ui/src/app/app/preloader/preloader.component.html +++ b/frontend/projects/ui/src/app/app/preloader/preloader.component.html @@ -60,10 +60,7 @@ - - - diff --git a/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.html b/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.html new file mode 100644 index 000000000..a76cdab34 --- /dev/null +++ b/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.html @@ -0,0 +1,106 @@ +
+ + + +

Trust Your Root CA

+

+ Download and trust your server's Root Certificate Authority to establish + a secure (HTTPS) connection. You will need to repeat this on every + device you use to connect to your server. +

+
    +
  1. + Bookmark this page + - Save this page so you can access it later. You can also find the + address in the + StartOS-info.html + file downloaded at the end of initial setup. +
  2. +
  3. + Download your server's Root CA + - Your server uses its Root CA to generate SSL/TLS certificates for + itself and installed services. These certificates are then used to + encrypt network traffic with your client devices. +
    + + Download + + +
  4. +
  5. + Trust your server's Root CA + - Follow instructions for your OS. By trusting your server's Root CA, + your device can verify the authenticity of encrypted communications + with your server. +
    + + View Instructions + + +
  6. +
  7. + Test + - Refresh the page. If refreshing the page does not work, you may need + to quit and re-open your browser, then revisit this page. +
    + + Refresh + + +
  8. +
+ + Skip + + + (not recommended) +
+
+ + + + +

Root CA Trusted!

+

+ You have successfully trusted your server's Root CA and may now log in + securely. +

+ + Go to login + + +
+
+
+ + diff --git a/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.scss b/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.scss new file mode 100644 index 000000000..48b198525 --- /dev/null +++ b/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.scss @@ -0,0 +1,83 @@ +#trusted { + max-width: 40%; +} + +#untrusted { + max-width: 50%; +} + +.center-container { + padding: 1rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 100vh; +} + +ion-card { + color: var(--ion-color-dark); + background: #414141; + box-shadow: 0 4px 4px rgba(17, 17, 17, 0.144); + border-radius: 35px; + padding: 1.5rem; + width: 100%; + + h1 { + font-weight: bold; + font-size: 1.5rem; + padding-bottom: 1.5rem; + } + + p { + font-size: 21px; + line-height: 25px; + margin-bottom: 30px; + margin-top: 0; + } +} + +.text-center { + text-align: center; +} + +ol { + font-size: 17px; + line-height: 25px; + text-align: left; + + li { + padding-bottom: 24px; + } + + ion-button { + margin-top: 10px; + } +} + +.refresh { + --background: var(--ion-color-success-shade); +} + +.wiz-icon { + font-size: 64px; +} + +.skip_detail { + display: block; + font-size: 0.8rem; + margin-top: -13px; + padding-bottom: 0.5rem; +} + +@media (max-width: 700px) { + #trusted, #untrusted { + max-width: 100%; + } +} + +@media (min-width: 701px) and (max-width: 1200px) { + #trusted, #untrusted { + max-width: 75%; + } +} \ No newline at end of file diff --git a/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.ts b/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.ts new file mode 100644 index 000000000..fde1c968f --- /dev/null +++ b/frontend/projects/ui/src/app/apps/login/ca-wizard/ca-wizard.component.ts @@ -0,0 +1,49 @@ +import { Component, Inject } from '@angular/core' +import { ApiService } from 'src/app/services/api/embassy-api.service' +import { ConfigService } from 'src/app/services/config.service' +import { RELATIVE_URL } from '@start9labs/shared' +import { DOCUMENT } from '@angular/common' +import { WINDOW } from '@ng-web-apis/common' + +@Component({ + selector: 'ca-wizard', + templateUrl: './ca-wizard.component.html', + styleUrls: ['./ca-wizard.component.scss'], +}) +export class CAWizardComponent { + caTrusted = false + + constructor( + private readonly api: ApiService, + public readonly config: ConfigService, + @Inject(RELATIVE_URL) private readonly relativeUrl: string, + @Inject(DOCUMENT) public readonly document: Document, + @Inject(WINDOW) private readonly windowRef: Window, + ) {} + + async ngOnInit() { + await this.testHttps().catch(e => + console.warn('Failed Https connection attempt'), + ) + } + + download() { + this.document.getElementById('install-cert')?.click() + } + + refresh() { + this.document.location.reload() + } + + launchHttps() { + const host = this.config.getHost() + this.windowRef.open(`https://${host}`, '_self') + } + + private async testHttps() { + const url = `https://${this.document.location.host}${this.relativeUrl}` + await this.api.echo({ message: 'ping' }, url).then(() => { + this.caTrusted = true + }) + } +} diff --git a/frontend/projects/ui/src/app/apps/login/login.module.ts b/frontend/projects/ui/src/app/apps/login/login.module.ts index 93558f8ec..753bfe94e 100644 --- a/frontend/projects/ui/src/app/apps/login/login.module.ts +++ b/frontend/projects/ui/src/app/apps/login/login.module.ts @@ -3,8 +3,10 @@ import { RouterModule, Routes } from '@angular/router' import { CommonModule } from '@angular/common' import { FormsModule } from '@angular/forms' import { IonicModule } from '@ionic/angular' -import { SharedPipesModule } from '@start9labs/shared' import { LoginPage } from './login.page' +import { CAWizardComponent } from './ca-wizard/ca-wizard.component' +import { SharedPipesModule } from '@start9labs/shared' +import { TuiHintModule, TuiTooltipModule } from '@taiga-ui/core' const routes: Routes = [ { @@ -20,7 +22,9 @@ const routes: Routes = [ IonicModule, SharedPipesModule, RouterModule.forChild(routes), + TuiTooltipModule, + TuiHintModule, ], - declarations: [LoginPage], + declarations: [LoginPage, CAWizardComponent], }) export class LoginPageModule {} diff --git a/frontend/projects/ui/src/app/apps/login/login.page.html b/frontend/projects/ui/src/app/apps/login/login.page.html index 8719b360a..99f6abbe8 100644 --- a/frontend/projects/ui/src/app/apps/login/login.page.html +++ b/frontend/projects/ui/src/app/apps/login/login.page.html @@ -1,20 +1,54 @@ - - - - + + + + - - - StartOS Login - + + + - -
- - + + + + + StartOS Icon + + Login to StartOS + + + + @@ -25,7 +59,12 @@ [(ngModel)]="password" (ionChange)="error = ''" > - + - - -
-

- {{ error }} -

-
-
-
-
-
+

+ {{ error }} +

+ + + + + + + +
diff --git a/frontend/projects/ui/src/app/apps/login/login.page.scss b/frontend/projects/ui/src/app/apps/login/login.page.scss index ead93410c..690d97591 100644 --- a/frontend/projects/ui/src/app/apps/login/login.page.scss +++ b/frontend/projects/ui/src/app/apps/login/login.page.scss @@ -1,15 +1,5 @@ .content { - --background: #222428; -} - -.card { - background: #414141; -} - -.title { - margin: 24px 0 16px; - color: #e0e0e0; - text-transform: uppercase; + --background: #333333; } .grid { @@ -18,74 +8,69 @@ } .row { - height: 90%; + height: 100%; align-items: center; text-align: center; } -.logo { - max-width: 240px; - padding-bottom: 16px; -} +.banner { + position: absolute; + padding: 20px; + width: 100%; + display: inline-block; -.error { - display: block; - text-align: left; - padding-top: 4px; -} - -ion-button { - --border-radius: 0 4px 4px 0; -} - -ion-item { - --border-style: solid; - --border-color: var(--ion-color-light); - --border-radius: 4px 0 0 4px; - box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), - 0 1px 5px 0 rgba(0, 0, 0, 0.12); - - ion-button { - --border-radius: 4px; + ion-item { + max-width: 800px; + margin: auto; } } ion-card { - background: var(--ion-color-step-200); - box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); - border-radius: 44px; + background: #414141; + box-shadow: 0 4px 4px rgba(17, 17, 17, 0.144); + border-radius: 35px; min-height: 16rem; + contain: unset; + overflow: unset; + position: relative; +} + +ion-item { + --background: transparent; + --border-radius: 0px; +} + +.title { + padding-top: 55px; + color: #e0e0e0; + font-size: 1.3rem; +} + +.header { + &-icon { + width: 100px; + position: absolute; + left: 50%; + margin-left: -50px; + top: -17%; + z-index: 100; + } } .login-button { - margin-inline-start: 0; - margin-inline-end: 0; - height: 49px; - font-size: larger; - font-weight: bold; -} - -.form { - margin-bottom: 12px; - - * { - display: inline-block; - vertical-align: middle; - } + height: 45px; + width: 120px; + --border-radius: 50px; + margin: 0 auto; + margin-top: 27px; + margin-bottom: 10px; } .item-interactive { --highlight-background: #5260ff !important; } - -@media (max-width: 500px) { - ion-button { - --border-radius: 4px; - margin-top: 0.7rem; - } - - ion-item { - --border-radius: 4px; - } +.error { + display: block; + padding-top: 4px; } diff --git a/frontend/projects/ui/src/app/apps/login/login.page.ts b/frontend/projects/ui/src/app/apps/login/login.page.ts index 9e0b2f42b..86430ff36 100644 --- a/frontend/projects/ui/src/app/apps/login/login.page.ts +++ b/frontend/projects/ui/src/app/apps/login/login.page.ts @@ -8,6 +8,7 @@ import { LoadingService } from '@start9labs/shared' import { TuiDestroyService } from '@taiga-ui/cdk' import { takeUntil } from 'rxjs' import { DOCUMENT } from '@angular/common' +import { WINDOW } from '@ng-web-apis/common' @Component({ selector: 'login', @@ -19,30 +20,21 @@ export class LoginPage { password = '' unmasked = false error = '' - secure = this.config.isSecure() constructor( - @Inject(DOCUMENT) private readonly document: Document, private readonly destroy$: TuiDestroyService, private readonly router: Router, private readonly authService: AuthService, private readonly loader: LoadingService, private readonly api: ApiService, - private readonly config: ConfigService, + public readonly config: ConfigService, + @Inject(DOCUMENT) public readonly document: Document, + @Inject(WINDOW) private readonly windowRef: Window, ) {} - async ionViewDidEnter() { - if (!this.secure) { - try { - await this.api.getPubKey() - } catch (e: any) { - this.error = e.message - } - } - } - - toggleMask() { - this.unmasked = !this.unmasked + launchHttps() { + const host = this.config.getHost() + this.windowRef.open(`https://${host}`, '_self') } async submit() { @@ -60,9 +52,7 @@ export class LoginPage { return } await this.api.login({ - password: this.secure - ? this.password - : await this.api.encrypt(this.password), + password: this.password, metadata: { platforms: getPlatforms() }, }) diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/components/actions.component.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/components/actions.component.ts index 234e5ac90..5a3582b31 100644 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/components/actions.component.ts +++ b/frontend/projects/ui/src/app/apps/portal/routes/service/components/actions.component.ts @@ -3,26 +3,18 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core' import { ErrorService, LoadingService } from '@start9labs/shared' import { TuiDialogService } from '@taiga-ui/core' import { TuiButtonModule } from '@taiga-ui/experimental' -import { tuiPure } from '@taiga-ui/cdk' import { TUI_PROMPT } from '@taiga-ui/kit' -import { PatchDB } from 'patch-db-client' import { filter } from 'rxjs' import { - PackageStatus, - PrimaryStatus, - renderPkgStatus, -} from 'src/app/services/pkg-status-rendering.service' -import { - DataModel, InterfaceInfo, - PackageDataEntry, + PackageMainStatus, + PackagePlus, } from 'src/app/services/patch-db/data-model' import { ApiService } from 'src/app/services/api/embassy-api.service' import { FormDialogService } from 'src/app/services/form-dialog.service' import { hasCurrentDeps } from 'src/app/util/has-deps' import { ServiceConfigModal } from '../modals/config.component' import { PackageConfigData } from '../types/package-config-data' -import { ToDependenciesPipe } from '../pipes/to-dependencies.pipe' @Component({ selector: 'service-actions', @@ -69,12 +61,11 @@ import { ToDependenciesPipe } from '../pipes/to-dependencies.pipe' styles: [':host { display: flex; gap: 1rem }'], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, - providers: [ToDependenciesPipe], imports: [CommonModule, TuiButtonModule], }) export class ServiceActionsComponent { @Input({ required: true }) - service!: PackageDataEntry + service!: PackagePlus constructor( private readonly dialogs: TuiDialogService, @@ -82,51 +73,51 @@ export class ServiceActionsComponent { private readonly loader: LoadingService, private readonly embassyApi: ApiService, private readonly formDialog: FormDialogService, - private readonly patch: PatchDB, - private readonly dependencies: ToDependenciesPipe, ) {} private get id(): string { - return this.service.manifest.id + return this.service.pkg.manifest.id } get interfaceInfo(): Record { - return this.service.installed!['interfaceInfo'] + return this.service.pkg.installed!['interfaceInfo'] } get isConfigured(): boolean { - return this.service.installed!.status.configured + return this.service.pkg.installed!.status.configured } get isRunning(): boolean { - return this.getStatus(this.service).primary === PrimaryStatus.Running + return ( + this.service.pkg.installed?.status.main.status === + PackageMainStatus.Running + ) } get isStopped(): boolean { - return this.getStatus(this.service).primary === PrimaryStatus.Stopped - } - - @tuiPure - getStatus(service: PackageDataEntry): PackageStatus { - return renderPkgStatus(service) + return ( + this.service.pkg.installed?.status.main.status === + PackageMainStatus.Stopped + ) } presentModalConfig(): void { this.formDialog.open(ServiceConfigModal, { - label: `${this.service.manifest.title} configuration`, + label: `${this.service.pkg.manifest.title} configuration`, data: { pkgId: this.id }, }) } async tryStart(): Promise { - if (this.dependencies.transform(this.service)?.some(d => !!d.errorText)) { - const depErrMsg = `${this.service.manifest.title} has unmet dependencies. It will not work as expected.` + const pkg = this.service.pkg + if (Object.values(this.service.dependencies).some(dep => !!dep.errorText)) { + const depErrMsg = `${pkg.manifest.title} has unmet dependencies. It will not work as expected.` const proceed = await this.presentAlertStart(depErrMsg) if (!proceed) return } - const alertMsg = this.service.manifest.alerts.start + const alertMsg = pkg.manifest.alerts.start if (alertMsg) { const proceed = await this.presentAlertStart(alertMsg) @@ -138,10 +129,10 @@ export class ServiceActionsComponent { } async tryStop(): Promise { - const { title, alerts, id } = this.service.manifest + const { title, alerts } = this.service.pkg.manifest let content = alerts.stop || '' - if (await hasCurrentDeps(this.patch, id)) { + if (hasCurrentDeps(this.service.pkg)) { const depMessage = `Services that depend on ${title} will no longer work properly and may crash` content = content ? `${content}.\n\n${depMessage}` : depMessage } @@ -165,15 +156,13 @@ export class ServiceActionsComponent { } async tryRestart(): Promise { - const { id, title } = this.service.manifest - - if (await hasCurrentDeps(this.patch, id)) { + if (hasCurrentDeps(this.service.pkg)) { this.dialogs .open(TUI_PROMPT, { label: 'Warning', size: 's', data: { - content: `Services that depend on ${title} may temporarily experiences issues`, + content: `Services that depend on ${this.service.pkg.manifest} may temporarily experiences issues`, yes: 'Restart', no: 'Cancel', }, diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/components/interfaces.component.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/components/interfaces.component.ts index f70261748..993a1f9a8 100644 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/components/interfaces.component.ts +++ b/frontend/projects/ui/src/app/apps/portal/routes/service/components/interfaces.component.ts @@ -1,12 +1,11 @@ import { NgForOf } from '@angular/common' import { ChangeDetectionStrategy, Component, Input } from '@angular/core' -import { PackageDataEntry } from 'src/app/services/patch-db/data-model' +import { PackagePlus } from 'src/app/services/patch-db/data-model' import { PackageStatus, PrimaryStatus, } from 'src/app/services/pkg-status-rendering.service' import { InterfaceInfoPipe } from '../pipes/interface-info.pipe' -import { ToStatusPipe } from '../pipes/to-status.pipe' import { ServiceInterfaceComponent } from './interface.component' import { RouterLink } from '@angular/router' @@ -15,26 +14,20 @@ import { RouterLink } from '@angular/router' template: `

Interfaces

`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, - imports: [ - NgForOf, - RouterLink, - InterfaceInfoPipe, - ServiceInterfaceComponent, - ToStatusPipe, - ], + imports: [NgForOf, RouterLink, InterfaceInfoPipe, ServiceInterfaceComponent], }) export class ServiceInterfacesComponent { @Input({ required: true }) - service!: PackageDataEntry + service!: PackagePlus isRunning({ primary }: PackageStatus): boolean { return primary === PrimaryStatus.Running diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/modals/config.component.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/modals/config.component.ts index 681b0f87c..f5c095f35 100644 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/modals/config.component.ts +++ b/frontend/projects/ui/src/app/apps/portal/routes/service/modals/config.component.ts @@ -192,7 +192,7 @@ export class ServiceConfigModal { try { await this.uploadFiles(config, loader) - if (await hasCurrentDeps(this.patchDb, this.pkgId)) { + if (hasCurrentDeps(this.pkg!)) { await this.configureDeps(config, loader) } else { await this.configure(config, loader) diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/pipes/to-dependencies.pipe.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/pipes/to-dependencies.pipe.ts deleted file mode 100644 index 9e575e9ba..000000000 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/pipes/to-dependencies.pipe.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core' -import { NavigationExtras, Router } from '@angular/router' -import { Manifest } from '@start9labs/marketplace' -import { - DependencyErrorType, - PackageDataEntry, -} from 'src/app/services/patch-db/data-model' -import { DependentInfo } from 'src/app/types/dependent-info' -import { FormDialogService } from 'src/app/services/form-dialog.service' -import { ServiceConfigModal } from '../modals/config.component' -import { DependencyInfo } from '../types/dependency-info' -import { PackageConfigData } from '../types/package-config-data' -import { NavigationService } from '../../../services/navigation.service' -import { toRouterLink } from '../../../utils/to-router-link' - -@Pipe({ - name: 'toDependencies', - standalone: true, -}) -export class ToDependenciesPipe implements PipeTransform { - constructor( - private readonly router: Router, - private readonly formDialog: FormDialogService, - private readonly navigation: NavigationService, - ) {} - - transform(pkg: PackageDataEntry): DependencyInfo[] | null { - if (!pkg.installed) return null - - const deps = Object.keys(pkg.installed['current-dependencies']) - .filter(depId => pkg.manifest.dependencies[depId]) - .map(depId => this.setDepValues(pkg, depId)) - - return deps.length ? deps : null - } - - private setDepValues(pkg: PackageDataEntry, id: string): DependencyInfo { - const error = pkg.installed!.status['dependency-errors'][id] - const depInfo = pkg.installed!['dependency-info'][id] - const version = pkg.manifest.dependencies[id].version - const title = depInfo?.title || id - const icon = depInfo?.icon || '' - - let errorText = '' - let actionText = 'View' - let action = () => { - this.navigation.addTab({ icon, title, routerLink: toRouterLink(id) }) - this.router.navigate([`portal`, `service`, id]) - } - - if (error) { - // health checks failed - if (error.type === DependencyErrorType.HealthChecksFailed) { - errorText = 'Health check failed' - // not installed - } else if (error.type === DependencyErrorType.NotInstalled) { - errorText = 'Not installed' - actionText = 'Install' - action = () => this.fixDep(pkg, 'install', id) - // incorrect version - } else if (error.type === DependencyErrorType.IncorrectVersion) { - errorText = 'Incorrect version' - actionText = 'Update' - action = () => this.fixDep(pkg, 'update', id) - // not running - } else if (error.type === DependencyErrorType.NotRunning) { - errorText = 'Not running' - actionText = 'Start' - // config unsatisfied - } else if (error.type === DependencyErrorType.ConfigUnsatisfied) { - errorText = 'Config not satisfied' - actionText = 'Auto config' - action = () => this.fixDep(pkg, 'configure', id) - } else if (error.type === DependencyErrorType.Transitive) { - errorText = 'Dependency has a dependency issue' - } - errorText = `${errorText}. ${pkg.manifest.title} will not work as expected.` - } - - return { id, icon, title, version, errorText, actionText, action } - } - - async fixDep( - pkg: PackageDataEntry, - action: 'install' | 'update' | 'configure', - depId: string, - ): Promise { - switch (action) { - case 'install': - case 'update': - return this.installDep(pkg.manifest, depId) - case 'configure': - return this.formDialog.open(ServiceConfigModal, { - label: `${ - pkg.installed!['dependency-info'][depId].title - } configuration`, - data: { - pkgId: depId, - dependentInfo: pkg.manifest, - }, - }) - } - } - - private async installDep(manifest: Manifest, depId: string): Promise { - const version = manifest.dependencies[depId].version - - const dependentInfo: DependentInfo = { - id: manifest.id, - title: manifest.title, - version, - } - const navigationExtras: NavigationExtras = { - state: { dependentInfo }, - } - - await this.router.navigate(['marketplace', depId], navigationExtras) - } - - private async configureDep( - manifest: Manifest, - dependencyId: string, - ): Promise { - const dependentInfo: DependentInfo = { - id: manifest.id, - title: manifest.title, - } - - return this.formDialog.open(ServiceConfigModal, { - label: 'Config', - data: { - pkgId: dependencyId, - dependentInfo, - }, - }) - } -} diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/pipes/to-status.pipe.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/pipes/to-status.pipe.ts deleted file mode 100644 index 6d915b94c..000000000 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/pipes/to-status.pipe.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core' -import { PackageDataEntry } from 'src/app/services/patch-db/data-model' -import { - PackageStatus, - renderPkgStatus, -} from 'src/app/services/pkg-status-rendering.service' - -@Pipe({ - name: 'toStatus', - standalone: true, -}) -export class ToStatusPipe implements PipeTransform { - transform(pkg: PackageDataEntry): PackageStatus { - return renderPkgStatus(pkg) - } -} diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/routes/actions.component.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/routes/actions.component.ts index 2529d8535..b99b827b4 100644 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/routes/actions.component.ts +++ b/frontend/projects/ui/src/app/apps/portal/routes/service/routes/actions.component.ts @@ -136,13 +136,13 @@ export class ServiceActionsRoute { } async tryUninstall(pkg: PackageDataEntry): Promise { - const { title, alerts, id } = pkg.manifest + const { title, alerts } = pkg.manifest let content = alerts.uninstall || `Uninstalling ${title} will permanently delete its data` - if (await hasCurrentDeps(this.patch, id)) { + if (hasCurrentDeps(pkg)) { content = `${content}. Services that depend on ${title} will no longer work properly and may crash` } diff --git a/frontend/projects/ui/src/app/apps/portal/routes/service/routes/service.component.ts b/frontend/projects/ui/src/app/apps/portal/routes/service/routes/service.component.ts index 40b80d909..0e5ff0cd0 100644 --- a/frontend/projects/ui/src/app/apps/portal/routes/service/routes/service.component.ts +++ b/frontend/projects/ui/src/app/apps/portal/routes/service/routes/service.component.ts @@ -1,12 +1,13 @@ import { CommonModule } from '@angular/common' import { ChangeDetectionStrategy, Component, inject } from '@angular/core' -import { ActivatedRoute } from '@angular/router' +import { ActivatedRoute, NavigationExtras, Router } from '@angular/router' import { getPkgId, isEmptyObject } from '@start9labs/shared' import { PatchDB } from 'patch-db-client' -import { map } from 'rxjs' +import { combineLatest, map } from 'rxjs' import { DataModel, HealthCheckResult, + InstalledPackageInfo, MainStatus, PackageDataEntry, PackageState, @@ -16,6 +17,7 @@ import { PrimaryRendering, PrimaryStatus, StatusRendering, + renderPkgStatus, } from 'src/app/services/pkg-status-rendering.service' import { ConnectionService } from 'src/app/services/connection.service' import { ServiceProgressComponent } from '../components/progress.component' @@ -27,8 +29,19 @@ import { ServiceDependenciesComponent } from '../components/dependencies.compone import { ServiceMenuComponent } from '../components/menu.component' import { ServiceAdditionalComponent } from '../components/additional.component' import { ProgressDataPipe } from '../pipes/progress-data.pipe' -import { ToDependenciesPipe } from '../pipes/to-dependencies.pipe' -import { ToStatusPipe } from '../pipes/to-status.pipe' +import { + DepErrorService, + DependencyErrorType, + PkgDependencyErrors, +} from 'src/app/services/dep-error.service' +import { DependencyInfo } from '../types/dependency-info' +import { Manifest } from '@start9labs/marketplace' +import { NavigationService } from '../../../services/navigation.service' +import { toRouterLink } from '../../../utils/to-router-link' +import { PackageConfigData } from '../types/package-config-data' +import { ServiceConfigModal } from '../modals/config.component' +import { DependentInfo } from 'src/app/types/dependent-info' +import { FormDialogService } from 'src/app/services/form-dialog.service' const STATES = [ PackageState.Installing, @@ -39,8 +52,8 @@ const STATES = [ @Component({ template: ` - - + +

Downloading

Validating

Unpacking

@@ -48,31 +61,28 @@ const STATES = [
- -

Status

- - +

Status

+ + - - - - - - - + + + + + +
@@ -92,16 +102,29 @@ const STATES = [ ServiceAdditionalComponent, ProgressDataPipe, - ToDependenciesPipe, - ToStatusPipe, ], }) export class ServiceRoute { private readonly patch = inject(PatchDB) private readonly pkgId = getPkgId(inject(ActivatedRoute)) + private readonly depErrorService = inject(DepErrorService) + private readonly navigation = inject(NavigationService) + private readonly router = inject(Router) + private readonly formDialog = inject(FormDialogService) readonly connected$ = inject(ConnectionService).connected$ - readonly service$ = this.patch.watch$('package-data', this.pkgId) + readonly service$ = combineLatest([ + this.patch.watch$('package-data', this.pkgId), + this.depErrorService.getPkgDepErrors$(this.pkgId), + ]).pipe( + map(([pkg, depErrors]) => { + return { + pkg, + dependencies: this.getDepInfo(pkg, depErrors), + status: renderPkgStatus(pkg, depErrors), + } + }), + ) readonly health$ = this.patch .watch$('package-data', this.pkgId, 'installed', 'status', 'main') .pipe(map(toHealthCheck)) @@ -125,6 +148,141 @@ export class ServiceRoute { showProgress({ state }: PackageDataEntry): boolean { return STATES.includes(state) } + + private getDepInfo( + pkg: PackageDataEntry, + depErrors: PkgDependencyErrors, + ): DependencyInfo[] { + const pkgInstalled = pkg.installed + + if (!pkgInstalled) return [] + + const pkgManifest = pkg.manifest + + return Object.keys(pkgInstalled['current-dependencies']) + .filter(depId => !!pkg.manifest.dependencies[depId]) + .map(depId => + this.getDepValues(pkgInstalled, pkgManifest, depId, depErrors), + ) + } + + private getDepValues( + pkgInstalled: InstalledPackageInfo, + pkgManifest: Manifest, + depId: string, + depErrors: PkgDependencyErrors, + ): DependencyInfo { + const { errorText, fixText, fixAction } = this.getDepErrors( + pkgInstalled, + pkgManifest, + depId, + depErrors, + ) + + const depInfo = pkgInstalled['dependency-info'][depId] + + return { + id: depId, + version: pkgManifest.dependencies[depId].version, // do we want this version range? + title: depInfo?.title || depId, + icon: depInfo?.icon || '', + errorText: errorText + ? `${errorText}. ${pkgManifest.title} will not work as expected.` + : '', + actionText: fixText || 'View', + action: + fixAction || + (() => { + this.navigation.addTab({ + icon: depInfo.icon, + title: depInfo.title, + routerLink: toRouterLink(depId), + }) + this.router.navigate([`portal`, `service`, depId]) + }), + } + } + + private getDepErrors( + pkgInstalled: InstalledPackageInfo, + pkgManifest: Manifest, + depId: string, + depErrors: PkgDependencyErrors, + ) { + const depError = (depErrors[pkgManifest.id] as any)?.[depId] // @TODO fix + + let errorText: string | null = null + let fixText: string | null = null + let fixAction: (() => any) | null = null + + if (depError) { + if (depError.type === DependencyErrorType.NotInstalled) { + errorText = 'Not installed' + fixText = 'Install' + fixAction = () => + this.fixDep(pkgInstalled, pkgManifest, 'install', depId) + } else if (depError.type === DependencyErrorType.IncorrectVersion) { + errorText = 'Incorrect version' + fixText = 'Update' + fixAction = () => + this.fixDep(pkgInstalled, pkgManifest, 'update', depId) + } else if (depError.type === DependencyErrorType.ConfigUnsatisfied) { + errorText = 'Config not satisfied' + fixText = 'Auto config' + fixAction = () => + this.fixDep(pkgInstalled, pkgManifest, 'configure', depId) + } else if (depError.type === DependencyErrorType.NotRunning) { + errorText = 'Not running' + fixText = 'Start' + } else if (depError.type === DependencyErrorType.HealthChecksFailed) { + errorText = 'Required health check not passing' + } else if (depError.type === DependencyErrorType.Transitive) { + errorText = 'Dependency has a dependency issue' + } + } + + return { + errorText, + fixText, + fixAction, + } + } + + async fixDep( + pkgInstalled: InstalledPackageInfo, + pkgManifest: Manifest, + action: 'install' | 'update' | 'configure', + depId: string, + ): Promise { + switch (action) { + case 'install': + case 'update': + return this.installDep(pkgManifest, depId) + case 'configure': + return this.formDialog.open(ServiceConfigModal, { + label: `${pkgInstalled!['dependency-info'][depId].title} config`, + data: { + pkgId: depId, + dependentInfo: pkgManifest, + }, + }) + } + } + + private async installDep(manifest: Manifest, depId: string): Promise { + const version = manifest.dependencies[depId].version + + const dependentInfo: DependentInfo = { + id: manifest.id, + title: manifest.title, + version, + } + const navigationExtras: NavigationExtras = { + state: { dependentInfo }, + } + + await this.router.navigate(['marketplace', depId], navigationExtras) + } } function toHealthCheck(main: MainStatus): HealthCheckResult[] | null { diff --git a/frontend/projects/ui/src/app/apps/portal/routes/system/updates/components/item.component.ts b/frontend/projects/ui/src/app/apps/portal/routes/system/updates/components/item.component.ts index fe52087a2..5f4fb1983 100644 --- a/frontend/projects/ui/src/app/apps/portal/routes/system/updates/components/item.component.ts +++ b/frontend/projects/ui/src/app/apps/portal/routes/system/updates/components/item.component.ts @@ -8,8 +8,6 @@ import { } from '@start9labs/marketplace' import { EmverPipesModule, - isEmptyObject, - LoadingService, MarkdownPipeModule, SafeLinksDirective, SharedPipesModule, @@ -27,16 +25,9 @@ import { TuiProgressModule, } from '@taiga-ui/kit' import { NgDompurifyModule } from '@tinkoff/ng-dompurify' -import { PatchDB } from 'patch-db-client' -import { - DataModel, - PackageDataEntry, -} from 'src/app/services/patch-db/data-model' +import { PackageDataEntry } from 'src/app/services/patch-db/data-model' import { MarketplaceService } from 'src/app/services/marketplace.service' import { hasCurrentDeps } from 'src/app/util/has-deps' -import { ApiService } from 'src/app/services/api/embassy-api.service' -import { Breakages } from 'src/app/services/api/api.types' -import { getAllPackages } from 'src/app/util/get-package-data' import { InstallProgressPipe } from '../pipes/install-progress.pipe' @Component({ @@ -44,15 +35,15 @@ import { InstallProgressPipe } from '../pipes/install-progress.pipe' template: `
- +
- {{ pkg.manifest.title }} + {{ marketplacePkg.manifest.title }}
- {{ local.manifest.version || '' | displayEmver }} + {{ localPkg.manifest.version || '' | displayEmver }} - {{ pkg.manifest.version | displayEmver }} + {{ marketplacePkg.manifest.version | displayEmver }}
@@ -60,10 +51,10 @@ import { InstallProgressPipe } from '../pipes/install-progress.pipe'
+
+ +
diff --git a/frontend/projects/ui/src/app/common/widget-list/widget-card/widget-card.component.scss b/frontend/projects/ui/src/app/common/widget-list/widget-card/widget-card.component.scss index c52cc45cf..687370f0f 100644 --- a/frontend/projects/ui/src/app/common/widget-list/widget-card/widget-card.component.scss +++ b/frontend/projects/ui/src/app/common/widget-list/widget-card/widget-card.component.scss @@ -19,33 +19,35 @@ ion-card { font-family: 'Open Sans', sans-serif; padding: 0.6rem; font-weight: 600; - font-size: calc(12px + 0.5vw); - height: 3rem; + height: 2.4rem; } ion-card-content { - min-height: 9rem; + min-height: 8rem; display: flex; flex-direction: column; justify-content: center; align-items: center; ion-icon { - font-size: calc(90px + 0.5vw); + font-size: calc(90px + 0.4vw); --ionicon-stroke-width: 1rem; } } ion-footer { - padding: 1rem; - font-family: 'Open Sans', sans-serif; + padding: 0 1rem; + font-family: 'Open Sans'; font-size: clamp(1rem, calc(12px + 0.5vw), 1.3rem); - height: 9rem; + height: 4.5rem; width: clamp(13rem, 80%, 18rem); margin: 0 auto; * { max-width: 100%; } + p { + margin-top: 0; + } } .footer-md::before { @@ -54,10 +56,6 @@ ion-card { } @media (max-width: 900px) { - ion-card-title, - ion-footer { - height: auto !important; - } ion-footer { width: 10rem; } diff --git a/frontend/projects/ui/src/app/common/widget-list/widget-list.component.html b/frontend/projects/ui/src/app/common/widget-list/widget-list.component.html index 09de70b81..2c013d1c3 100644 --- a/frontend/projects/ui/src/app/common/widget-list/widget-list.component.html +++ b/frontend/projects/ui/src/app/common/widget-list/widget-list.component.html @@ -1,14 +1,7 @@
- + = - {} as ElementRef + @ViewChild('gridContent') + gridContent: ElementRef = {} as ElementRef @HostListener('window:resize', ['$event']) onResize() { this.setContainerDimensions() @@ -38,46 +38,46 @@ export class WidgetListComponent { cards: Card[] = [ { - title: 'Visit the Marketplace', + title: 'Server Info', + icon: 'information-circle-outline', + color: 'var(--alt-green)', + description: 'View information about your server', + link: '/system/specs', + }, + { + title: 'Browse', icon: 'storefront-outline', - color: 'var(--alt-blue)', - description: 'Shop for your favorite open source services', + color: 'var(--alt-purple)', + description: 'Browse for services to install', link: '/marketplace', qp: { back: 'true' }, }, - { - title: 'Root CA', - icon: 'ribbon-outline', - color: 'var(--alt-orange)', - description: `Download and trust your server's root certificate authority`, - link: '/system/root-ca', - }, { title: 'Create Backup', icon: 'duplicate-outline', - color: 'var(--alt-purple)', + color: 'var(--alt-blue)', description: 'Back up StartOS and service data', link: '/system/backup', }, { - title: 'Server Info', - icon: 'information-circle-outline', - color: 'var(--alt-green)', - description: 'View basic information about your server', - link: '/system/specs', + title: 'Monitor', + icon: 'pulse-outline', + color: 'var(--alt-orange)', + description: `View your system resource usage`, + link: '/system/metrics', }, { title: 'User Manual', icon: 'map-outline', color: 'var(--alt-yellow)', description: 'Discover what StartOS can do', - link: 'https://docs.start9.com/latest/user-manual/index', + link: 'https://docs.start9.com/0.3.5.x/user-manual/index', }, { title: 'Contact Support', icon: 'chatbubbles-outline', color: 'var(--alt-red)', - description: 'Get help from the Start9 team and community', + description: 'Get help from the Start9 community', link: 'https://start9.com/contact', }, ] diff --git a/frontend/projects/ui/src/app/services/api/api.fixures.ts b/frontend/projects/ui/src/app/services/api/api.fixures.ts index 916a0ede4..bfdadbc57 100644 --- a/frontend/projects/ui/src/app/services/api/api.fixures.ts +++ b/frontend/projects/ui/src/app/services/api/api.fixures.ts @@ -1,5 +1,4 @@ import { - DependencyErrorType, HealthResult, PackageDataEntry, PackageMainStatus, @@ -32,12 +31,14 @@ export module Mock { 'current-backup': null, 'update-progress': null, updated: true, + restarting: false, 'shutting-down': false, } export const MarketplaceEos: RR.GetMarketplaceEosRes = { - version: '0.3.4.4', + version: '0.3.5', headline: 'Our biggest release ever.', 'release-notes': { + '0.3.5': 'Some **Markdown** release _notes_ for 0.3.5', '0.3.4.4': 'Some **Markdown** release _notes_ for 0.3.4.4', '0.3.4.3': 'Some **Markdown** release _notes_ for 0.3.4.3', '0.3.4.2': 'Some **Markdown** release _notes_ for 0.3.4.2', @@ -381,29 +382,80 @@ export module Mock { export function getMetrics(): Metrics { return { general: { - temperature: (Math.random() * 100).toFixed(1), + temperature: { + value: '66.8', + unit: '°C', + }, }, memory: { - 'percentage-used': '20', - total: (Math.random() * 100).toFixed(2), - available: '18000', - used: '4000', - 'swap-total': '1000', - 'swap-free': Math.random().toFixed(2), - 'swap-used': '0', + 'percentage-used': { + value: '30.7', + unit: '%', + }, + total: { + value: '31971.10', + unit: 'MiB', + }, + available: { + value: '22150.66', + unit: 'MiB', + }, + used: { + value: '8784.97', + unit: 'MiB', + }, + 'zram-total': { + value: '7992.00', + unit: 'MiB', + }, + 'zram-available': { + value: '7882.50', + unit: 'MiB', + }, + 'zram-used': { + value: '109.50', + unit: 'MiB', + }, }, cpu: { - 'user-space': '100', - 'kernel-space': '50', - 'io-wait': String(Math.random() * 50), - idle: '80', - usage: '30', + 'percentage-used': { + value: '8.4', + unit: '%', + }, + 'user-space': { + value: '7.0', + unit: '%', + }, + 'kernel-space': { + value: '1.4', + unit: '%', + }, + wait: { + value: '0.5', + unit: '%', + }, + idle: { + value: '91.1', + unit: '%', + }, }, disk: { - size: '1000', - used: '900', - available: '100', - 'percentage-used': '90', + capacity: { + value: '1851.60', + unit: 'GB', + }, + used: { + value: '859.02', + unit: 'GB', + }, + available: { + value: '992.59', + unit: 'GB', + }, + 'percentage-used': { + value: '46.4', + unit: '%', + }, }, } } @@ -1258,7 +1310,7 @@ export module Mock { }, }, }, - 'dependency-errors': {}, + 'dependency-config-errors': {}, }, interfaceInfo: { rpc: { @@ -1297,6 +1349,7 @@ export module Mock { }, }, 'current-dependencies': {}, + 'current-dependents': {}, 'dependency-info': {}, 'marketplace-url': 'https://registry.start9.com/', 'developer-key': 'developer-key', @@ -1350,7 +1403,7 @@ export module Mock { main: { status: PackageMainStatus.Stopped, }, - 'dependency-errors': {}, + 'dependency-config-errors': {}, }, interfaceInfo: { rpc: { @@ -1371,6 +1424,7 @@ export module Mock { type: 'api', }, }, + 'current-dependents': {}, 'current-dependencies': { bitcoind: { 'health-checks': [], @@ -1378,8 +1432,8 @@ export module Mock { }, 'dependency-info': { bitcoind: { - title: 'Bitcoin Core', - icon: 'assets/img/service-icons/bitcoind.png', + title: Mock.MockManifestBitcoind.title, + icon: 'assets/img/service-icons/bitcoind.svg', }, }, 'marketplace-url': 'https://registry.start9.com/', @@ -1402,11 +1456,8 @@ export module Mock { main: { status: PackageMainStatus.Stopped, }, - 'dependency-errors': { - 'btc-rpc-proxy': { - type: DependencyErrorType.ConfigUnsatisfied, - error: 'This is a config unsatisfied error', - }, + 'dependency-config-errors': { + 'btc-rpc-proxy': 'Username not found', }, }, interfaceInfo: { @@ -1453,13 +1504,14 @@ export module Mock { 'health-checks': [], }, }, + 'current-dependents': {}, 'dependency-info': { bitcoind: { - title: 'Bitcoin Core', + title: Mock.MockManifestBitcoind.title, icon: 'assets/img/service-icons/bitcoind.svg', }, 'btc-rpc-proxy': { - title: 'Bitcoin Proxy', + title: Mock.MockManifestBitcoinProxy.title, icon: 'assets/img/service-icons/btc-rpc-proxy.png', }, }, diff --git a/frontend/projects/ui/src/app/services/api/api.types.ts b/frontend/projects/ui/src/app/services/api/api.types.ts index d74379104..8aa790aa9 100644 --- a/frontend/projects/ui/src/app/services/api/api.types.ts +++ b/frontend/projects/ui/src/app/services/api/api.types.ts @@ -3,11 +3,11 @@ import { MarketplacePkg, StoreInfo, Manifest } from '@start9labs/marketplace' import { InputSpec } from '@start9labs/start-sdk/lib/config/configTypes' import { DataModel, - DependencyError, DomainInfo, NetworkStrategy, OsOutboundProxy, ServiceOutboundProxy, + HealthCheckResult, } from 'src/app/services/patch-db/data-model' import { StartOSDiskInfo, LogsRes, ServerLogsReq } from '@start9labs/shared' import { customSmtp } from '@start9labs/start-sdk/lib/config/configConstants' @@ -25,7 +25,7 @@ export module RR { // auth export type LoginReq = { - password: Encrypted | string + password: string metadata: SessionMetadata } // auth.login - unauthed export type loginRes = null @@ -41,11 +41,14 @@ export module RR { // server - export type EchoReq = { message: string } // server.echo + export type EchoReq = { message: string; timeout?: number } // server.echo export type EchoRes = string export type GetSystemTimeReq = {} // server.time - export type GetSystemTimeRes = string + export type GetSystemTimeRes = { + now: string + uptime: number // seconds + } export type GetServerLogsReq = ServerLogsReq // server.logs & server.kernel-logs export type GetServerLogsRes = LogsRes @@ -309,9 +312,6 @@ export module RR { } // package.install export type InstallPackageRes = null - export type DryUpdatePackageReq = { id: string; version: string } // package.update.dry - export type DryUpdatePackageRes = Breakages - export type GetPackageConfigReq = { id: string } // package.config.get export type GetPackageConfigRes = { spec: InputSpec; config: object } @@ -421,31 +421,36 @@ export interface ActionResponse { qr: boolean } +interface MetricData { + value: string + unit: string +} + export interface Metrics { general: { - temperature: string + temperature: MetricData | null } memory: { - 'percentage-used': string - total: string - available: string - used: string - 'swap-total': string - 'swap-free': string - 'swap-used': string + total: MetricData + 'percentage-used': MetricData + used: MetricData + available: MetricData + 'zram-total': MetricData + 'zram-used': MetricData + 'zram-available': MetricData } cpu: { - 'user-space': string - 'kernel-space': string - 'io-wait': string - idle: string - usage: string + 'percentage-used': MetricData + idle: MetricData + 'user-space': MetricData + 'kernel-space': MetricData + wait: MetricData } disk: { - size: string - used: string - available: string - 'percentage-used': string + capacity: MetricData + 'percentage-used': MetricData + used: MetricData + available: MetricData } } @@ -621,3 +626,49 @@ export type Encrypted = { } export type CloudProvider = 'dropbox' | 'google-drive' + +export type DependencyError = + | DependencyErrorNotInstalled + | DependencyErrorNotRunning + | DependencyErrorIncorrectVersion + | DependencyErrorConfigUnsatisfied + | DependencyErrorHealthChecksFailed + | DependencyErrorTransitive + +export enum DependencyErrorType { + NotInstalled = 'not-installed', + NotRunning = 'not-running', + IncorrectVersion = 'incorrect-version', + ConfigUnsatisfied = 'config-unsatisfied', + HealthChecksFailed = 'health-checks-failed', + InterfaceHealthChecksFailed = 'interface-health-checks-failed', + Transitive = 'transitive', +} + +export interface DependencyErrorNotInstalled { + type: DependencyErrorType.NotInstalled +} + +export interface DependencyErrorNotRunning { + type: DependencyErrorType.NotRunning +} + +export interface DependencyErrorIncorrectVersion { + type: DependencyErrorType.IncorrectVersion + expected: string // version range + received: string // version +} + +export interface DependencyErrorConfigUnsatisfied { + type: DependencyErrorType.ConfigUnsatisfied + error: string +} + +export interface DependencyErrorHealthChecksFailed { + type: DependencyErrorType.HealthChecksFailed + check: HealthCheckResult +} + +export interface DependencyErrorTransitive { + type: DependencyErrorType.Transitive +} diff --git a/frontend/projects/ui/src/app/services/api/embassy-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-api.service.ts index f1da05098..e63c1d64a 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-api.service.ts @@ -1,29 +1,11 @@ -import { BehaviorSubject, Observable } from 'rxjs' +import { Observable } from 'rxjs' import { Update } from 'patch-db-client' -import { RR, Encrypted, BackupTargetType, Metrics } from './api.types' +import { RR, BackupTargetType, Metrics } from './api.types' import { DataModel } from 'src/app/services/patch-db/data-model' import { Log, SetupStatus } from '@start9labs/shared' import { WebSocketSubjectConfig } from 'rxjs/webSocket' -import type { JWK } from 'node-jose' export abstract class ApiService { - protected readonly jose = import('node-jose') - - readonly patchStream$ = new BehaviorSubject[]>([]) - pubkey?: JWK.Key - - async encrypt(toEncrypt: string): Promise { - const { pubkey } = this - - if (!pubkey) throw new Error('No pubkey found!') - - const encrypted = await this.jose.then(jose => - jose.JWE.createEncrypt(pubkey).update(toEncrypt).final(), - ) - - return { encrypted } - } - // http // for getting static files: ex icons, instructions, licenses @@ -43,8 +25,6 @@ export abstract class ApiService { // auth - abstract getPubKey(): Promise - abstract login(params: RR.LoginReq): Promise abstract logout(params: RR.LogoutReq): Promise @@ -59,7 +39,7 @@ export abstract class ApiService { // server - abstract echo(params: RR.EchoReq): Promise + abstract echo(params: RR.EchoReq, urlOverride?: string): Promise abstract openPatchWebsocket$(): Observable> @@ -286,10 +266,6 @@ export abstract class ApiService { params: RR.InstallPackageReq, ): Promise - abstract dryUpdatePackage( - params: RR.DryUpdatePackageReq, - ): Promise - abstract getPackageConfig( params: RR.GetPackageConfigReq, ): Promise diff --git a/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts index e9a72c818..247ce986a 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-live-api.service.ts @@ -1,6 +1,5 @@ import { Inject, Injectable } from '@angular/core' import { - decodeBase64, HttpOptions, HttpService, isRpcError, @@ -14,7 +13,7 @@ import { ApiService } from './embassy-api.service' import { BackupTargetType, Metrics, RR } from './api.types' import { ConfigService } from '../config.service' import { webSocket, WebSocketSubjectConfig } from 'rxjs/webSocket' -import { Observable } from 'rxjs' +import { Observable, filter, firstValueFrom } from 'rxjs' import { AuthService } from '../auth.service' import { DOCUMENT } from '@angular/common' import { DataModel } from '../patch-db/data-model' @@ -77,20 +76,8 @@ export class LiveApiService extends ApiService { // auth - /** - * We want to update the pubkey, which means that we will call in clearnet the - * getPubKey, and all the information is never in the clear, and only public - * information is sent across the network. - */ - async getPubKey() { - this.pubkey = await this.rpcRequest({ - method: 'auth.get-pubkey', - params: {}, - }) - } - async login(params: RR.LoginReq): Promise { - return this.rpcRequest({ method: 'auth.login', params }, false) + return this.rpcRequest({ method: 'auth.login', params }) } async logout(params: RR.LogoutReq): Promise { @@ -113,8 +100,8 @@ export class LiveApiService extends ApiService { // server - async echo(params: RR.EchoReq): Promise { - return this.rpcRequest({ method: 'echo', params }, false) + async echo(params: RR.EchoReq, urlOverride?: string): Promise { + return this.rpcRequest({ method: 'echo', params }, urlOverride) } openPatchWebsocket$(): Observable> { @@ -483,12 +470,6 @@ export class LiveApiService extends ApiService { return this.rpcRequest({ method: 'package.install', params }) } - async dryUpdatePackage( - params: RR.DryUpdatePackageReq, - ): Promise { - return this.rpcRequest({ method: 'package.update.dry', params }) - } - async getPackageConfig( params: RR.GetPackageConfigReq, ): Promise { @@ -588,41 +569,28 @@ export class LiveApiService extends ApiService { private async rpcRequest( options: RPCOptions, - addHeader = true, + urlOverride?: string, ): Promise { - if (addHeader) { - options.headers = { - 'x-patch-sequence': String(this.patch.cache$.value.sequence), - ...(options.headers || {}), - } - } + const res = await this.http.rpcRequest(options, urlOverride) + const body = res.body - const res = await this.http.rpcRequest(options) - const encodedUpdates = res.headers.get('x-patch-updates') - const encodedError = res.headers.get('x-patch-error') - - if (encodedUpdates) { - const decoded = decodeBase64(encodedUpdates) - const updates: Update[] = JSON.parse(decoded) - this.patchStream$.next(updates) - } - - if (encodedError) { - const error = decodeBase64(encodedError) - console.error(error) - } - - const rpcRes = res.body - - if (isRpcError(rpcRes)) { - if (rpcRes.error.code === 34) { + if (isRpcError(body)) { + if (body.error.code === 34) { console.error('Unauthenticated, logging out') this.auth.setUnverified() } - throw new RpcError(rpcRes.error) + throw new RpcError(body.error) } - return rpcRes.result + const patchSequence = res.headers.get('x-patch-sequence') + if (patchSequence) + await firstValueFrom( + this.patch.cache$.pipe( + filter(({ sequence }) => sequence >= Number(patchSequence)), + ), + ) + + return body.result } private async httpRequest(opts: HttpOptions): Promise { diff --git a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts index f397d1205..3fadcd504 100644 --- a/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts +++ b/frontend/projects/ui/src/app/services/api/embassy-mock-api.service.ts @@ -10,7 +10,6 @@ import { } from 'patch-db-client' import { DataModel, - DependencyErrorType, InstallProgress, PackageDataEntry, PackageMainStatus, @@ -26,7 +25,8 @@ import { interval, map, Observable, - ReplaySubject, + shareReplay, + Subject, switchMap, tap, timer, @@ -50,8 +50,8 @@ const PROGRESS: InstallProgress = { @Injectable() export class MockApiService extends ApiService { - readonly mockWsSource$ = new ReplaySubject>() - private readonly revertTime = 2000 + readonly mockWsSource$ = new Subject>() + private readonly revertTime = 1800 sequence = 0 constructor( @@ -64,7 +64,6 @@ export class MockApiService extends ApiService { .pipe( tap(() => { this.sequence = 0 - this.patchStream$.next([]) }), switchMap(verified => iif( @@ -111,29 +110,13 @@ export class MockApiService extends ApiService { value: params.value, }, ] - return this.withRevision(patch) + this.mockRevision(patch) + + return null } // auth - async getPubKey() { - await pauseFor(1000) - - // randomly generated - // const keystore = jose.JWK.createKeyStore() - // this.pubkey = await keystore.generate('EC', 'P-256') - - // generated from backend - this.pubkey = await this.jose.then(jose => - jose.JWK.asKey({ - kty: 'EC', - crv: 'P-256', - x: 'yHTDYSfjU809fkSv9MmN4wuojf5c3cnD7ZDN13n-jz4', - y: '8Mpkn744A5KDag0DmX2YivB63srjbugYZzWc3JOpQXI', - }), - ) - } - async login(params: RR.LoginReq): Promise { await pauseFor(2000) @@ -168,13 +151,20 @@ export class MockApiService extends ApiService { // server - async echo(params: RR.EchoReq): Promise { + async echo(params: RR.EchoReq, url?: string): Promise { + if (url) { + const num = Math.floor(Math.random() * 10) + 1 + if (num > 8) return params.message + throw new Error() + } await pauseFor(2000) return params.message } openPatchWebsocket$(): Observable> { - return this.mockWsSource$ + return this.mockWsSource$.pipe( + shareReplay({ bufferSize: 1, refCount: true }), + ) } openLogsWebsocket$(config: WebSocketSubjectConfig): Observable { @@ -205,7 +195,10 @@ export class MockApiService extends ApiService { params: RR.GetSystemTimeReq, ): Promise { await pauseFor(2000) - return new Date().toUTCString() + return { + now: new Date().toUTCString(), + uptime: 1234567, + } } async getServerLogs( @@ -312,7 +305,9 @@ export class MockApiService extends ApiService { value: initialProgress, }, ] - return this.withRevision(patch, 'updating') + this.mockRevision(patch) + + return 'updating' } async setServerClearnetAddress( @@ -326,13 +321,37 @@ export class MockApiService extends ApiService { value: params.domainInfo, }, ] - return this.withRevision(patch, null) + + this.mockRevision(patch) + + return null } async restartServer( params: RR.RestartServerReq, ): Promise { await pauseFor(2000) + + const patch = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/restarting', + value: true, + }, + ] + this.mockRevision(patch) + + setTimeout(() => { + const patch2 = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/restarting', + value: false, + }, + ] + this.mockRevision(patch2) + }, 2000) + return null } @@ -340,14 +359,34 @@ export class MockApiService extends ApiService { params: RR.ShutdownServerReq, ): Promise { await pauseFor(2000) + + const patch = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/shutting-down', + value: true, + }, + ] + this.mockRevision(patch) + + setTimeout(() => { + const patch2 = [ + { + op: PatchOp.REPLACE, + path: '/server-info/status-info/shutting-down', + value: false, + }, + ] + this.mockRevision(patch2) + }, 2000) + return null } async systemRebuild( - params: RR.RestartServerReq, - ): Promise { - await pauseFor(2000) - return null + params: RR.SystemRebuildReq, + ): Promise { + return this.restartServer(params) } async repairDisk(params: RR.RestartServerReq): Promise { @@ -369,7 +408,9 @@ export class MockApiService extends ApiService { value: params.enable, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async setOsOutboundProxy( @@ -384,7 +425,9 @@ export class MockApiService extends ApiService { value: params.proxy, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } // marketplace URLs @@ -437,7 +480,9 @@ export class MockApiService extends ApiService { value: 0, }, ] - return this.withRevision(patch, Mock.Notifications) + this.mockRevision(patch) + + return Mock.Notifications } async deleteNotification( @@ -485,7 +530,9 @@ export class MockApiService extends ApiService { ], }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async updateProxy(params: RR.UpdateProxyReq): Promise { @@ -500,7 +547,9 @@ export class MockApiService extends ApiService { value, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async deleteProxy(params: RR.DeleteProxyReq): Promise { @@ -512,7 +561,9 @@ export class MockApiService extends ApiService { value: [], }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } // domains @@ -534,7 +585,9 @@ export class MockApiService extends ApiService { }, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async deleteStart9ToDomain( @@ -548,7 +601,9 @@ export class MockApiService extends ApiService { value: null, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async addDomain(params: RR.AddDomainReq): Promise { @@ -569,7 +624,9 @@ export class MockApiService extends ApiService { ], }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async deleteDomain(params: RR.DeleteDomainReq): Promise { @@ -581,7 +638,9 @@ export class MockApiService extends ApiService { value: [], }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } // port forwards @@ -598,7 +657,9 @@ export class MockApiService extends ApiService { value: params.port, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } // wifi @@ -612,7 +673,9 @@ export class MockApiService extends ApiService { value: params.enable, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async getWifi(params: RR.GetWifiReq): Promise { @@ -653,8 +716,9 @@ export class MockApiService extends ApiService { value: params, }, ] + this.mockRevision(patch) - return this.withRevision(patch) + return null } // ssh @@ -838,7 +902,9 @@ export class MockApiService extends ApiService { }, ] - return this.withRevision(originalPatch) + this.mockRevision(originalPatch) + + return null } // package @@ -905,23 +971,9 @@ export class MockApiService extends ApiService { }, }, ] - return this.withRevision(patch) - } + this.mockRevision(patch) - async dryUpdatePackage( - params: RR.DryUpdatePackageReq, - ): Promise { - await pauseFor(2000) - return { - lnd: { - dependency: 'bitcoind', - error: { - type: DependencyErrorType.IncorrectVersion, - expected: '>0.23.0', - received: params.version, - }, - }, - } + return null } async getPackageConfig( @@ -952,7 +1004,9 @@ export class MockApiService extends ApiService { value: true, }, ] - return this.withRevision(patch) + this.mockRevision(patch) + + return null } async restorePackages( @@ -976,7 +1030,9 @@ export class MockApiService extends ApiService { } }) - return this.withRevision(patch) + this.mockRevision(patch) + + return null } async executePackageAction( @@ -1026,7 +1082,9 @@ export class MockApiService extends ApiService { }, ] - return this.withRevision(originalPatch) + this.mockRevision(originalPatch) + + return null } async restartPackage( @@ -1103,7 +1161,9 @@ export class MockApiService extends ApiService { }, ] - return this.withRevision(patch) + this.mockRevision(patch) + + return null } async stopPackage(params: RR.StopPackageReq): Promise { @@ -1129,7 +1189,9 @@ export class MockApiService extends ApiService { }, ] - return this.withRevision(patch) + this.mockRevision(patch) + + return null } async uninstallPackage( @@ -1155,7 +1217,9 @@ export class MockApiService extends ApiService { }, ] - return this.withRevision(patch) + this.mockRevision(patch) + + return null } async dryConfigureDependency( @@ -1196,7 +1260,9 @@ export class MockApiService extends ApiService { value: params.domainInfo, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } async setServiceOutboundProxy( @@ -1210,7 +1276,9 @@ export class MockApiService extends ApiService { value: params.proxy, }, ] - return this.withRevision(patch, null) + this.mockRevision(patch) + + return null } private async updateProgress(id: string): Promise { @@ -1337,23 +1405,4 @@ export class MockApiService extends ApiService { } this.mockWsSource$.next(revision) } - - private async withRevision( - patch: Operation[], - response: T | null = null, - ): Promise { - if (!this.sequence) { - const { sequence } = this.bootstrapper.init() - this.sequence = sequence - } - - this.patchStream$.next([ - { - id: ++this.sequence, - patch, - }, - ]) - - return response as T - } } diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index ae9e9b4d7..e0c3a61ee 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -36,7 +36,7 @@ export const mockPatchData: DataModel = { }, 'server-info': { id: 'abcdefgh', - version: '0.3.4', + version: '0.3.5', country: 'us', ui: { lanHostname: 'adjective-noun.local', @@ -94,11 +94,12 @@ export const mockPatchData: DataModel = { 'current-backup': null, updated: false, 'update-progress': null, + restarting: false, 'shutting-down': false, }, pubkey: 'npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m', 'ca-fingerprint': 'SHA-256: 63 2B 11 99 44 40 17 DF 37 FC C3 DF 0F 3D 15', - 'system-start-time': new Date(new Date().valueOf() - 360042).toUTCString(), + 'ntp-synced': false, zram: false, smtp: { server: '', @@ -109,6 +110,7 @@ export const mockPatchData: DataModel = { }, 'password-hash': '$argon2d$v=19$m=1024,t=1,p=1$YXNkZmFzZGZhc2RmYXNkZg$Ceev1I901G6UwU+hY0sHrFZ56D+o+LNJ', + platform: 'x86_64-nonfree', }, 'package-data': { bitcoind: { diff --git a/frontend/projects/ui/src/app/services/config.service.ts b/frontend/projects/ui/src/app/services/config.service.ts index fb421da66..a55c21d88 100644 --- a/frontend/projects/ui/src/app/services/config.service.ts +++ b/frontend/projects/ui/src/app/services/config.service.ts @@ -1,14 +1,9 @@ import { DOCUMENT } from '@angular/common' import { Inject, Injectable } from '@angular/core' import { WorkspaceConfig } from '@start9labs/shared' -import { - InstalledPackageInfo, - InterfaceInfo, -} from 'src/app/services/patch-db/data-model' +import { InterfaceInfo } from 'src/app/services/patch-db/data-model' const { - packageArch, - osArch, gitHash, useMocks, ui: { api, marketplace, mocks }, @@ -21,20 +16,20 @@ export class ConfigService { constructor(@Inject(DOCUMENT) private readonly document: Document) {} hostname = this.document.location.hostname + // includes port + host = this.document.location.host + // includes ":" (e.g. "http:") + protocol = this.document.location.protocol version = require('../../../../../package.json').version as string useMocks = useMocks mocks = mocks - packageArch = packageArch - osArch = osArch gitHash = gitHash api = api marketplace = marketplace skipStartupAlerts = useMocks && mocks.skipStartupAlerts isTor(): boolean { - return ( - this.hostname.endsWith('.onion') || (useMocks && mocks.maskAs === 'tor') - ) + return useMocks ? mocks.maskAs === 'tor' : this.hostname.endsWith('.onion') } isLocal(): boolean { @@ -69,6 +64,14 @@ export class ConfigService { ) } + isTorHttp(): boolean { + return this.isTor() && !this.isHttps() + } + + isLanHttp(): boolean { + return !this.isTor() && !this.isLocalhost() && !this.isHttps() + } + isSecure(): boolean { return window.isSecureContext || this.isTor() } @@ -84,6 +87,14 @@ export class ConfigService { ? `https://${info.addressInfo.domainInfo.subdomain}${info.addressInfo.domainInfo.domain}` : `https://${info.addressInfo.domainInfo?.domain}` } + + getHost(): string { + return this.host + } + + private isHttps(): boolean { + return useMocks ? mocks.maskAsHttps : this.protocol === 'https:' + } } export function isValidIpv4(address: string): boolean { diff --git a/frontend/projects/ui/src/app/services/dep-error.service.ts b/frontend/projects/ui/src/app/services/dep-error.service.ts new file mode 100644 index 000000000..551a594f1 --- /dev/null +++ b/frontend/projects/ui/src/app/services/dep-error.service.ts @@ -0,0 +1,222 @@ +import { Injectable } from '@angular/core' +import { Emver } from '@start9labs/shared' +import { distinctUntilChanged, map, shareReplay } from 'rxjs/operators' +import { PatchDB } from 'patch-db-client' +import { + DataModel, + HealthResult, + InstalledPackageInfo, + PackageMainStatus, +} from './patch-db/data-model' +import * as deepEqual from 'fast-deep-equal' +import { Manifest } from '@start9labs/marketplace' +import { Observable } from 'rxjs' + +export type AllDependencyErrors = Record +export type PkgDependencyErrors = Record + +@Injectable({ + providedIn: 'root', +}) +export class DepErrorService { + readonly depErrors$: Observable = this.patch + .watch$('package-data') + .pipe( + map(pkgs => + Object.keys(pkgs) + .map(id => ({ + id, + depth: dependencyDepth(pkgs, id), + })) + .sort((a, b) => (b.depth > a.depth ? -1 : 1)) + .reduce( + (errors, { id }): AllDependencyErrors => ({ + ...errors, + [id]: this.getDepErrors(pkgs, id, errors), + }), + {} as AllDependencyErrors, + ), + ), + distinctUntilChanged(deepEqual), + shareReplay({ bufferSize: 1, refCount: true }), + ) + + constructor( + private readonly emver: Emver, + private readonly patch: PatchDB, + ) {} + + getPkgDepErrors$(pkgId: string): Observable { + return this.depErrors$.pipe( + map(depErrors => depErrors[pkgId]), + distinctUntilChanged(deepEqual), + ) + } + + private getDepErrors( + pkgs: DataModel['package-data'], + pkgId: string, + outerErrors: AllDependencyErrors, + ): PkgDependencyErrors { + const pkgInstalled = pkgs[pkgId].installed + + if (!pkgInstalled) return {} + + return currentDeps(pkgs, pkgId).reduce( + (innerErrors, depId): PkgDependencyErrors => ({ + ...innerErrors, + [depId]: this.getDepError( + pkgs, + pkgInstalled, + pkgs[pkgId].manifest, + depId, + outerErrors, + ), + }), + {} as PkgDependencyErrors, + ) + } + + private getDepError( + pkgs: DataModel['package-data'], + pkgInstalled: InstalledPackageInfo, + pkgManifest: Manifest, + depId: string, + outerErrors: AllDependencyErrors, + ): DependencyError | null { + const depInstalled = pkgs[depId]?.installed + const depManifest = pkgs[depId]?.manifest + + // not installed + if (!depInstalled) { + return { + type: DependencyErrorType.NotInstalled, + } + } + + // incorrect version + if ( + !this.emver.satisfies( + depManifest.version, + pkgManifest.dependencies[depId].version, + ) + ) { + return { + type: DependencyErrorType.IncorrectVersion, + expected: pkgManifest.dependencies[depId].version, + received: depManifest.version, + } + } + + // invalid config + if ( + Object.values(pkgInstalled.status['dependency-config-errors']).some( + err => !!err, + ) + ) { + return { + type: DependencyErrorType.ConfigUnsatisfied, + } + } + + const depStatus = depInstalled.status.main.status + + // not running + if ( + depStatus !== PackageMainStatus.Running && + depStatus !== PackageMainStatus.Starting + ) { + return { + type: DependencyErrorType.NotRunning, + } + } + + // health check failure + if (depStatus === PackageMainStatus.Running) { + for (let id of pkgInstalled['current-dependencies'][depId][ + 'health-checks' + ]) { + if ( + depInstalled.status.main.health[id]?.result !== HealthResult.Success + ) { + return { + type: DependencyErrorType.HealthChecksFailed, + } + } + } + } + + // transitive + const transitiveError = currentDeps(pkgs, depId).some(transitiveId => + Object.values(outerErrors[transitiveId]).some(err => !!err), + ) + + if (transitiveError) { + return { + type: DependencyErrorType.Transitive, + } + } + + return null + } +} + +function currentDeps(pkgs: DataModel['package-data'], id: string): string[] { + return Object.keys( + pkgs[id]?.installed?.['current-dependencies'] || {}, + ).filter(depId => depId !== id) +} + +function dependencyDepth( + pkgs: DataModel['package-data'], + id: string, + depth = 0, +): number { + return currentDeps(pkgs, id).reduce( + (prev, depId) => dependencyDepth(pkgs, depId, prev + 1), + depth, + ) +} + +export type DependencyError = + | DependencyErrorNotInstalled + | DependencyErrorNotRunning + | DependencyErrorIncorrectVersion + | DependencyErrorConfigUnsatisfied + | DependencyErrorHealthChecksFailed + | DependencyErrorTransitive + +export enum DependencyErrorType { + NotInstalled = 'notInstalled', + NotRunning = 'notRunning', + IncorrectVersion = 'incorrectVersion', + ConfigUnsatisfied = 'configUnsatisfied', + HealthChecksFailed = 'healthChecksFailed', + Transitive = 'transitive', +} + +export interface DependencyErrorNotInstalled { + type: DependencyErrorType.NotInstalled +} + +export interface DependencyErrorNotRunning { + type: DependencyErrorType.NotRunning +} + +export interface DependencyErrorIncorrectVersion { + type: DependencyErrorType.IncorrectVersion + expected: string // version range + received: string // version +} + +export interface DependencyErrorConfigUnsatisfied { + type: DependencyErrorType.ConfigUnsatisfied +} + +export interface DependencyErrorHealthChecksFailed { + type: DependencyErrorType.HealthChecksFailed +} + +export interface DependencyErrorTransitive { + type: DependencyErrorType.Transitive +} diff --git a/frontend/projects/ui/src/app/services/marketplace.service.ts b/frontend/projects/ui/src/app/services/marketplace.service.ts index 721a69a34..a6a1bf2c6 100644 --- a/frontend/projects/ui/src/app/services/marketplace.service.ts +++ b/frontend/projects/ui/src/app/services/marketplace.service.ts @@ -75,7 +75,7 @@ export class MarketplaceService implements AbstractMarketplaceService { map(({ 'selected-url': url, 'known-hosts': hosts }) => toStoreIdentity(url, hosts[url]), ), - shareReplay(1), + shareReplay({ bufferSize: 1, refCount: true }), ) private readonly marketplace$ = this.knownHosts$.pipe( @@ -103,7 +103,7 @@ export class MarketplaceService implements AbstractMarketplaceService { }, {}, ), - shareReplay(1), + shareReplay({ bufferSize: 1, refCount: true }), ) private readonly filteredMarketplace$ = combineLatest([ diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index aeb60d79e..837459ea2 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -4,6 +4,8 @@ import { Manifest } from '@start9labs/marketplace' import { BackupJob } from '../api/api.types' import { customSmtp } from '@start9labs/start-sdk/lib/config/configConstants' import { NetworkInterfaceType } from '@start9labs/start-sdk/lib/util/utils' +import { DependencyInfo } from 'src/app/apps/portal/routes/service/types/dependency-info' +import { PackageStatus } from '../pkg-status-rendering.service' export interface DataModel { 'server-info': ServerInfo @@ -64,10 +66,11 @@ export interface ServerInfo { 'eos-version-compat': string pubkey: string 'ca-fingerprint': string - 'system-start-time': string + 'ntp-synced': boolean zram: boolean smtp: typeof customSmtp.validator._TYPE 'password-hash': string + platform: string } export type NetworkInfo = { @@ -156,9 +159,16 @@ export interface ServerStatusInfo { } updated: boolean 'update-progress': { size: number | null; downloaded: number } | null + restarting: boolean 'shutting-down': boolean } +export enum ServerStatus { + Running = 'running', + Updated = 'updated', + BackingUp = 'backing-up', +} + export interface PackageDataEntry { state: PackageState manifest: Manifest @@ -168,6 +178,12 @@ export interface PackageDataEntry { 'install-progress'?: InstallProgress // when: installing, updating, restoring } +export type PackagePlus = { + pkg: PackageDataEntry + status: PackageStatus + dependencies: DependencyInfo[] +} + // export type PackageDataEntry = // | PackageDataEntryInstalled // | PackageDataEntryNeedsUpdate @@ -224,6 +240,7 @@ export interface InstalledPackageInfo { 'last-backup': string | null 'installed-at': string 'current-dependencies': Record + 'current-dependents': Record 'dependency-info': Record interfaceInfo: Record 'marketplace-url': string | null @@ -262,7 +279,7 @@ export interface Action { export interface Status { configured: boolean main: MainStatus - 'dependency-errors': { [id: string]: DependencyError | null } + 'dependency-config-errors': { [id: string]: string | null } } export type MainStatus = @@ -354,51 +371,6 @@ export interface HealthCheckResultFailure { error: string } -export type DependencyError = - | DependencyErrorNotInstalled - | DependencyErrorNotRunning - | DependencyErrorIncorrectVersion - | DependencyErrorConfigUnsatisfied - | DependencyErrorHealthChecksFailed - | DependencyErrorTransitive - -export enum DependencyErrorType { - NotInstalled = 'not-installed', - NotRunning = 'not-running', - IncorrectVersion = 'incorrect-version', - ConfigUnsatisfied = 'config-unsatisfied', - HealthChecksFailed = 'health-checks-failed', - Transitive = 'transitive', -} - -export interface DependencyErrorNotInstalled { - type: DependencyErrorType.NotInstalled -} - -export interface DependencyErrorNotRunning { - type: DependencyErrorType.NotRunning -} - -export interface DependencyErrorIncorrectVersion { - type: DependencyErrorType.IncorrectVersion - expected: string // version range - received: string // version -} - -export interface DependencyErrorConfigUnsatisfied { - type: DependencyErrorType.ConfigUnsatisfied - error: string -} - -export interface DependencyErrorHealthChecksFailed { - type: DependencyErrorType.HealthChecksFailed - check: HealthCheckResult -} - -export interface DependencyErrorTransitive { - type: DependencyErrorType.Transitive -} - export interface InstallProgress { readonly size: number | null readonly downloaded: number diff --git a/frontend/projects/ui/src/app/services/patch-db/patch-db.factory.ts b/frontend/projects/ui/src/app/services/patch-db/patch-db.factory.ts index 3f43d1e49..a92672036 100644 --- a/frontend/projects/ui/src/app/services/patch-db/patch-db.factory.ts +++ b/frontend/projects/ui/src/app/services/patch-db/patch-db.factory.ts @@ -11,13 +11,13 @@ import { EMPTY, from, interval, - merge, Observable, } from 'rxjs' import { DataModel } from './data-model' import { AuthService } from '../auth.service' import { ConnectionService } from '../connection.service' import { ApiService } from '../api/embassy-api.service' +import { ConfigService } from '../config.service' export const PATCH_SOURCE = new InjectionToken[]>>( '', @@ -31,6 +31,9 @@ export function sourceFactory( const api = injector.get(ApiService) const authService = injector.get(AuthService) const connectionService = injector.get(ConnectionService) + const configService = injector.get(ConfigService) + const isTor = configService.isTor() + const timeout = isTor ? 16000 : 4000 const websocket$ = api.openPatchWebsocket$().pipe( bufferTime(250), @@ -38,9 +41,11 @@ export function sourceFactory( catchError((_, watch$) => { connectionService.websocketConnected$.next(false) - return interval(4000).pipe( + return interval(timeout).pipe( switchMap(() => - from(api.echo({ message: 'ping' })).pipe(catchError(() => EMPTY)), + from(api.echo({ message: 'ping', timeout })).pipe( + catchError(() => EMPTY), + ), ), take(1), switchMap(() => watch$), @@ -50,9 +55,7 @@ export function sourceFactory( ) return authService.isVerified$.pipe( - switchMap(verified => - verified ? merge(websocket$, api.patchStream$) : EMPTY, - ), + switchMap(verified => (verified ? websocket$ : EMPTY)), ) }) } diff --git a/frontend/projects/ui/src/app/services/patch-monitor.service.ts b/frontend/projects/ui/src/app/services/patch-monitor.service.ts index 41f69e344..fcf59bcbd 100644 --- a/frontend/projects/ui/src/app/services/patch-monitor.service.ts +++ b/frontend/projects/ui/src/app/services/patch-monitor.service.ts @@ -12,13 +12,9 @@ import { LocalStorageBootstrap } from './patch-db/local-storage-bootstrap' export class PatchMonitorService extends Observable { // @TODO not happy with Observable private readonly stream$ = this.authService.isVerified$.pipe( - tap(verified => { - if (verified) { - this.patch.start(this.bootstrapper) - } else { - this.patch.stop() - } - }), + tap(verified => + verified ? this.patch.start(this.bootstrapper) : this.patch.stop(), + ), ) constructor( diff --git a/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts b/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts index 421323e9e..9622d481a 100644 --- a/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts +++ b/frontend/projects/ui/src/app/services/pkg-status-rendering.service.ts @@ -1,11 +1,11 @@ -import { isEmptyObject } from '@start9labs/shared' import { - InstalledPackageInfo, PackageDataEntry, PackageMainStatus, + PackagePlus, PackageState, Status, } from 'src/app/services/patch-db/data-model' +import { PkgDependencyErrors } from './dep-error.service' export interface PackageStatus { primary: PrimaryStatus | PackageState | PackageMainStatus @@ -13,14 +13,17 @@ export interface PackageStatus { health: HealthStatus | null } -export function renderPkgStatus(pkg: PackageDataEntry): PackageStatus { +export function renderPkgStatus( + pkg: PackageDataEntry, + depErrors: PkgDependencyErrors, +): PackageStatus { let primary: PrimaryStatus | PackageState | PackageMainStatus let dependency: DependencyStatus | null = null let health: HealthStatus | null = null if (pkg.state === PackageState.Installed && pkg.installed) { primary = getPrimaryStatus(pkg.installed.status) - dependency = getDependencyStatus(pkg.installed) + dependency = getDependencyStatus(depErrors) health = getHealthStatus(pkg.installed.status) } else { primary = pkg.state @@ -37,15 +40,10 @@ function getPrimaryStatus(status: Status): PrimaryStatus | PackageMainStatus { } } -function getDependencyStatus( - installed: InstalledPackageInfo, -): DependencyStatus | null { - if (isEmptyObject(installed['current-dependencies'])) return null - - const depErrors = installed.status['dependency-errors'] - const depIds = Object.keys(depErrors).filter(key => !!depErrors[key]) - - return depIds.length ? DependencyStatus.Warning : DependencyStatus.Satisfied +function getDependencyStatus(depErrors: PkgDependencyErrors): DependencyStatus { + return Object.values(depErrors).some(err => !!err) + ? DependencyStatus.Warning + : DependencyStatus.Satisfied } function getHealthStatus(status: Status): HealthStatus | null { diff --git a/frontend/projects/ui/src/app/services/time-service.ts b/frontend/projects/ui/src/app/services/time-service.ts index 64ce0913d..641144dae 100644 --- a/frontend/projects/ui/src/app/services/time-service.ts +++ b/frontend/projects/ui/src/app/services/time-service.ts @@ -1,85 +1,59 @@ import { Injectable } from '@angular/core' +import { map, shareReplay, startWith, switchMap } from 'rxjs/operators' import { PatchDB } from 'patch-db-client' -import { - map, - startWith, - switchMap, - combineLatest, - from, - Observable, - timer, -} from 'rxjs' import { DataModel } from './patch-db/data-model' import { ApiService } from './api/embassy-api.service' - -export interface TimeInfo { - systemStartTime: number - systemCurrentTime: number - systemUptime: { - days: number - hours: number - minutes: number - seconds: number - } -} +import { combineLatest, interval, of } from 'rxjs' @Injectable({ providedIn: 'root', }) export class TimeService { - private readonly systemStartTime$ = this.patch - .watch$('server-info', 'system-start-time') - .pipe(map(startTime => new Date(startTime).valueOf())) + private readonly time$ = of({}).pipe( + switchMap(() => this.apiService.getSystemTime({})), + switchMap(({ now, uptime }) => { + const current = new Date(now).valueOf() + return interval(1000).pipe( + map(index => { + const incremented = index + 1 + return { + now: current + 1000 * incremented, + uptime: uptime + incremented, + } + }), + startWith({ + now: current, + uptime, + }), + ) + }), + shareReplay({ bufferSize: 1, refCount: true }), + ) + + readonly now$ = combineLatest([ + this.time$, + this.patch.watch$('server-info', 'ntp-synced'), + ]).pipe( + map(([time, synced]) => ({ + value: time.now, + synced, + })), + ) + + readonly uptime$ = this.time$.pipe( + map(({ uptime }) => { + const days = Math.floor(uptime / (24 * 60 * 60)) + const daysSec = uptime % (24 * 60 * 60) + const hours = Math.floor(daysSec / (60 * 60)) + const hoursSec = uptime % (60 * 60) + const minutes = Math.floor(hoursSec / 60) + const seconds = uptime % 60 + return { days, hours, minutes, seconds } + }), + ) constructor( private readonly patch: PatchDB, private readonly apiService: ApiService, ) {} - - getTimeInfo$(): Observable { - return combineLatest([ - this.systemStartTime$.pipe(), - this.getSystemCurrentTime$(), - ]).pipe( - map(([systemStartTime, systemCurrentTime]) => ({ - systemStartTime, - systemCurrentTime, - systemUptime: this.getSystemUptime(systemStartTime, systemCurrentTime), - })), - ) - } - - private getSystemCurrentTime$() { - return from(this.apiService.getSystemTime({})).pipe( - switchMap(utcStr => { - const dateObj = new Date(utcStr) - const current = dateObj.valueOf() - return timer(0, 1000).pipe( - map(index => { - const incremented = index + 1 - const msToAdd = 1000 * incremented - return current + msToAdd - }), - startWith(current), - ) - }), - ) - } - - private getSystemUptime(systemStartTime: number, systemCurrentTime: number) { - const ms = systemCurrentTime - systemStartTime - - const days = Math.floor(ms / (24 * 60 * 60 * 1000)) - const daysms = ms % (24 * 60 * 60 * 1000) - - const hours = Math.floor(daysms / (60 * 60 * 1000)) - const hoursms = ms % (60 * 60 * 1000) - - const minutes = Math.floor(hoursms / (60 * 1000)) - const minutesms = ms % (60 * 1000) - - const seconds = Math.floor(minutesms / 1000) - - return { days, hours, minutes, seconds } - } } diff --git a/frontend/projects/ui/src/app/services/ui-launcher.service.ts b/frontend/projects/ui/src/app/services/ui-launcher.service.ts deleted file mode 100644 index d987beecc..000000000 --- a/frontend/projects/ui/src/app/services/ui-launcher.service.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Inject, Injectable } from '@angular/core' -import { DOCUMENT } from '@angular/common' -import { InstalledPackageInfo } from 'src/app/services/patch-db/data-model' - -@Injectable({ - providedIn: 'root', -}) -export class UiLauncherService { - constructor(@Inject(DOCUMENT) private readonly document: Document) {} - - launch(addressInfo: InstalledPackageInfo['address-info']): void { - const UIs = Object.values(addressInfo) - .filter(info => info.ui) - .map(info => ({ - name: info.name, - addresses: info.addresses, - })) - - if (UIs.length === 1 && UIs[0].addresses.length === 1) { - this.document.defaultView?.open( - UIs[0].addresses[0], - '_blank', - 'noreferrer', - ) - } - } -} diff --git a/frontend/projects/ui/src/app/util/dry-update.ts b/frontend/projects/ui/src/app/util/dry-update.ts new file mode 100644 index 000000000..9b7ba44a3 --- /dev/null +++ b/frontend/projects/ui/src/app/util/dry-update.ts @@ -0,0 +1,17 @@ +import { Emver } from '@start9labs/shared' +import { DataModel } from '../services/patch-db/data-model' + +export function dryUpdate( + { id, version }: { id: string; version: string }, + pkgs: DataModel['package-data'], + emver: Emver, +): string[] { + return Object.values(pkgs) + .filter( + pkg => + Object.keys(pkg.installed?.['current-dependencies'] || {}).some( + pkgId => pkgId === id, + ) && !emver.satisfies(version, pkg.manifest.dependencies[id].version), + ) + .map(pkg => pkg.manifest.title) +} diff --git a/frontend/projects/ui/src/app/util/get-package-data.ts b/frontend/projects/ui/src/app/util/get-package-data.ts index 816471832..0645f3b3c 100644 --- a/frontend/projects/ui/src/app/util/get-package-data.ts +++ b/frontend/projects/ui/src/app/util/get-package-data.ts @@ -14,6 +14,6 @@ export async function getPackage( export async function getAllPackages( patch: PatchDB, -): Promise> { +): Promise { return firstValueFrom(patch.watch$('package-data')) } diff --git a/frontend/projects/ui/src/app/util/get-package-info.ts b/frontend/projects/ui/src/app/util/get-package-info.ts index 880a9bcb2..b72852ffd 100644 --- a/frontend/projects/ui/src/app/util/get-package-info.ts +++ b/frontend/projects/ui/src/app/util/get-package-info.ts @@ -8,9 +8,13 @@ import { } from '../services/pkg-status-rendering.service' import { PkgInfo } from '../types/pkg-info' import { packageLoadingProgress } from './package-loading-progress' +import { PkgDependencyErrors } from '../services/dep-error.service' -export function getPackageInfo(entry: PackageDataEntry): PkgInfo { - const statuses = renderPkgStatus(entry) +export function getPackageInfo( + entry: PackageDataEntry, + depErrors: PkgDependencyErrors, +): PkgInfo { + const statuses = renderPkgStatus(entry, depErrors) const primaryRendering = PrimaryRendering[statuses.primary] return { diff --git a/frontend/projects/ui/src/app/util/has-deps.ts b/frontend/projects/ui/src/app/util/has-deps.ts index bebd0dd42..94b3fa4cd 100644 --- a/frontend/projects/ui/src/app/util/has-deps.ts +++ b/frontend/projects/ui/src/app/util/has-deps.ts @@ -1,13 +1,7 @@ -import { PatchDB } from 'patch-db-client' -import { DataModel } from '../services/patch-db/data-model' -import { getAllPackages } from './get-package-data' +import { PackageDataEntry } from '../services/patch-db/data-model' -export async function hasCurrentDeps( - patch: PatchDB, - id: string, -): Promise { - const pkgs = await getAllPackages(patch) - return !!Object.keys(pkgs) - .filter(pkgId => pkgId !== id) - .find(pkgId => pkgs[pkgId].installed?.['current-dependencies'][pkgId]) +export function hasCurrentDeps(pkg: PackageDataEntry): boolean { + return !!Object.keys(pkg.installed?.['current-dependents'] || {}).filter( + depId => depId !== pkg.manifest.id, + ).length } diff --git a/frontend/projects/ui/src/manifest.webmanifest b/frontend/projects/ui/src/manifest.webmanifest index 94e6b08f9..a199ac1dd 100644 --- a/frontend/projects/ui/src/manifest.webmanifest +++ b/frontend/projects/ui/src/manifest.webmanifest @@ -5,11 +5,11 @@ "background_color": "#1e1e1e", "display": "standalone", "scope": ".", - "start_url": "/?version=0344", - "id": "/?version=0344", + "start_url": "/?version=035", + "id": "/?version=035", "icons": [ { - "src": "assets/img/icon_pwa.png", + "src": "assets/img/icon.png", "sizes": "256x256", "type": "image/png", "purpose": "any" diff --git a/frontend/projects/ui/src/polyfills.ts b/frontend/projects/ui/src/polyfills.ts index 034407983..a392d45cf 100644 --- a/frontend/projects/ui/src/polyfills.ts +++ b/frontend/projects/ui/src/polyfills.ts @@ -53,8 +53,7 @@ */ (window as any).global = window -global.Buffer = global.Buffer || require('buffer').Buffer; -(window as any).process = { env: { DEBUG: undefined }, browser: true } +; (window as any).process = { env: { DEBUG: undefined }, browser: true } import './zone-flags' @@ -62,8 +61,7 @@ import './zone-flags' * Zone JS is required by default for Angular itself. */ -import 'zone.js/dist/zone' // Included with Angular CLI. - +import 'zone.js/dist/zone' // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/frontend/projects/ui/src/styles.scss b/frontend/projects/ui/src/styles.scss index 789e4f7df..255b86188 100644 --- a/frontend/projects/ui/src/styles.scss +++ b/frontend/projects/ui/src/styles.scss @@ -474,3 +474,11 @@ button.g-action { @include scrollbar-hidden; overflow: auto !important; } + +p { + font-size: 1rem; +} + +svg:not(:root) { + overflow: auto; +} diff --git a/image-recipe/.gitignore b/image-recipe/.gitignore new file mode 100644 index 000000000..6c43811e0 --- /dev/null +++ b/image-recipe/.gitignore @@ -0,0 +1,2 @@ +results/ +*.deb \ No newline at end of file diff --git a/image-recipe/README.md b/image-recipe/README.md new file mode 100644 index 000000000..cbaf8944a --- /dev/null +++ b/image-recipe/README.md @@ -0,0 +1,23 @@ +# StartOS Image Recipes + +Code and `debos` recipes that are used to create the StartOS live and installer +images. + +If you want to build a local image in the exact same environment used to build +official StartOS images, you can use the `run-local-build.sh` helper script: + +```bash +# Prerequisites +sudo apt-get install -y debspawn +sudo mkdir -p /etc/debspawn/ && echo "AllowUnsafePermissions=true" | sudo tee /etc/debspawn/global.toml + +# Get dpkg +mkdir -p overlays/startos/root +wget -O overlays/startos/root/startos_0.3.x-1_amd64.deb + +# Build image +./run-local-build.sh +``` + +In order for the build to work properly, you will need debspawn >= 0.5.1, the +build may fail with prior versions. diff --git a/image-recipe/build.sh b/image-recipe/build.sh new file mode 100755 index 000000000..bfc7921d9 --- /dev/null +++ b/image-recipe/build.sh @@ -0,0 +1,347 @@ +#!/bin/bash +set -e + +MAX_IMG_SECTORS=7217792 # 4GB + +echo "==== StartOS Image Build ====" + +echo "Building for architecture: $IB_TARGET_ARCH" + +base_dir="$(dirname "$(readlink -f "$0")")" +prep_results_dir="$base_dir/images-prep" +if systemd-detect-virt -qc; then + RESULTS_DIR="/srv/artifacts" +else + RESULTS_DIR="$base_dir/results" +fi +echo "Saving results in: $RESULTS_DIR" + +IMAGE_BASENAME=startos-${VERSION_FULL}_${IB_TARGET_PLATFORM} + +mkdir -p $prep_results_dir + +cd $prep_results_dir + +QEMU_ARCH=${IB_TARGET_ARCH} +BOOTLOADERS=grub-efi,syslinux +if [ "$QEMU_ARCH" = 'amd64' ]; then + QEMU_ARCH=x86_64 +elif [ "$QEMU_ARCH" = 'arm64' ]; then + QEMU_ARCH=aarch64 + BOOTLOADERS=grub-efi +fi +NON_FREE= +if [[ "${IB_TARGET_PLATFORM}" =~ -nonfree$ ]] || [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + NON_FREE=1 +fi +IMAGE_TYPE=iso +if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ] || [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then + IMAGE_TYPE=img +fi + +ARCHIVE_AREAS="main contrib" +if [ "$NON_FREE" = 1 ]; then + if [ "$IB_SUITE" = "bullseye" ]; then + ARCHIVE_AREAS="$ARCHIVE_AREAS non-free" + elif [ "$IB_SUITE" = "bookworm" ]; then + ARCHIVE_AREAS="$ARCHIVE_AREAS non-free-firmware" + fi +fi + +PLATFORM_CONFIG_EXTRAS= +if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --firmware-binary false" + PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --firmware-chroot false" + # BEGIN stupid ugly hack + # The actual name of the package is `raspberrypi-kernel` + # live-build determines thte name of the package for the kernel by combining the `linux-packages` flag, with the `linux-flavours` flag + # the `linux-flavours` flag defaults to the architecture, so there's no way to remove the suffix. + # So we're doing this, cause thank the gods our package name contains a hypen. Cause if it didn't we'd be SOL + PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-packages raspberrypi" + PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-flavours kernel" + # END stupid ugly hack +elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then + PLATFORM_CONFIG_EXTRAS="$PLATFORM_CONFIG_EXTRAS --linux-flavours rockchip64" +fi + +cat > /etc/wgetrc << EOF +retry_connrefused = on +tries = 100 +EOF +lb config \ + --iso-application "StartOS v${VERSION_FULL} ${IB_TARGET_ARCH}" \ + --iso-volume "StartOS v${VERSION} ${IB_TARGET_ARCH}" \ + --iso-preparer "START9 LABS; HTTPS://START9.COM" \ + --iso-publisher "START9 LABS; HTTPS://START9.COM" \ + --backports true \ + --bootappend-live "boot=live noautologin" \ + --bootloaders $BOOTLOADERS \ + --mirror-bootstrap "https://deb.debian.org/debian/" \ + --mirror-chroot "https://deb.debian.org/debian/" \ + --mirror-chroot-security "https://security.debian.org/debian-security" \ + -d ${IB_SUITE} \ + -a ${IB_TARGET_ARCH} \ + --bootstrap-qemu-arch ${IB_TARGET_ARCH} \ + --bootstrap-qemu-static /usr/bin/qemu-${QEMU_ARCH}-static \ + --archive-areas "${ARCHIVE_AREAS}" \ + $PLATFORM_CONFIG_EXTRAS + +# Overlays + +mkdir -p config/includes.chroot/deb +cp $base_dir/deb/${IMAGE_BASENAME}.deb config/includes.chroot/deb/ + +if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + cp -r $base_dir/raspberrypi/squashfs/* config/includes.chroot/ +fi + +mkdir -p config/includes.chroot/etc +echo start > config/includes.chroot/etc/hostname +cat > config/includes.chroot/etc/hosts << EOT +127.0.0.1 localhost start +::1 localhost start ip6-localhost ip6-loopback +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +EOT + +# Bootloaders + +rm -rf config/bootloaders +cp -r /usr/share/live/build/bootloaders config/bootloaders + +cat > config/bootloaders/syslinux/syslinux.cfg << EOF +include menu.cfg +default vesamenu.c32 +prompt 0 +timeout 50 +EOF + +cat > config/bootloaders/isolinux/isolinux.cfg << EOF +include menu.cfg +default vesamenu.c32 +prompt 0 +timeout 50 +EOF + +rm config/bootloaders/syslinux_common/splash.svg +cp $base_dir/splash.png config/bootloaders/syslinux_common/splash.png +cp $base_dir/splash.png config/bootloaders/isolinux/splash.png +cp $base_dir/splash.png config/bootloaders/grub-pc/splash.png + +sed -i -e '2i set timeout=5' config/bootloaders/grub-pc/config.cfg + +# Archives + +mkdir -p config/archives + +if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + curl -fsSL https://archive.raspberrypi.org/debian/raspberrypi.gpg.key | gpg --dearmor -o config/archives/raspi.key + echo "deb https://archive.raspberrypi.org/debian/ bullseye main" > config/archives/raspi.list +fi + +if [ "${IB_SUITE}" = "bullseye" ]; then + cat > config/archives/backports.pref <<- EOF + Package: * + Pin: release a=bullseye-backports + Pin-Priority: 500 + EOF +fi + +if [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then + curl -fsSL https://apt.armbian.com/armbian.key | gpg --dearmor -o config/archives/armbian.key + echo "deb https://apt.armbian.com/ ${IB_SUITE} main" > config/archives/armbian.list +fi + +curl -fsSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc > config/archives/tor.key +echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/tor.key.gpg] https://deb.torproject.org/torproject.org ${IB_SUITE} main" > config/archives/tor.list + +curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o config/archives/docker.key +echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/docker.key.gpg] https://download.docker.com/linux/debian ${IB_SUITE} stable" > config/archives/docker.list + +curl -fsSL https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/Release.key | gpg --dearmor -o config/archives/podman.key +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/podman.key.gpg] https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/Debian_Testing/ /" > config/archives/podman.list + +# Dependencies + +## Base dependencies +dpkg-deb --fsys-tarfile $base_dir/deb/${IMAGE_BASENAME}.deb | tar --to-stdout -xvf - ./usr/lib/startos/depends > config/package-lists/embassy-depends.list.chroot + +## Firmware +if [ "$NON_FREE" = 1 ]; then + echo 'firmware-iwlwifi firmware-misc-nonfree firmware-brcm80211 firmware-realtek firmware-atheros firmware-libertas firmware-amd-graphics' > config/package-lists/nonfree.list.chroot +fi + +if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + echo 'raspberrypi-bootloader rpi-update parted' > config/package-lists/bootloader.list.chroot +else + echo 'grub-efi grub2-common' > config/package-lists/bootloader.list.chroot +fi +if [ "${IB_TARGET_ARCH}" = "amd64" ] || [ "${IB_TARGET_ARCH}" = "i386" ]; then + echo 'grub-pc-bin' >> config/package-lists/bootloader.list.chroot +fi + +cat > config/hooks/normal/9000-install-startos.hook.chroot << EOF +#!/bin/bash + +set -e + +apt-get install -y /deb/${IMAGE_BASENAME}.deb +rm -rf /deb + +if [ "${IB_SUITE}" = bookworm ]; then + echo 'deb https://deb.debian.org/debian/ bullseye main' > /etc/apt/sources.list.d/bullseye.list + apt-get update + apt-get install -y postgresql-13 + rm /etc/apt/sources.list.d/bullseye.list + apt-get update +fi + +if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + for f in /usr/lib/modules/*; do + v=\${f#/usr/lib/modules/} + echo "Configuring raspi kernel '\$v'" + extract-ikconfig "/usr/lib/modules/\$v/kernel/kernel/configs.ko.xz" > /boot/config-\$v + update-initramfs -c -k \$v + done + ln -sf /usr/bin/pi-beep /usr/local/bin/beep +fi + +useradd --shell /bin/bash -G embassy -m start9 +echo start9:embassy | chpasswd +usermod -aG sudo start9 + +echo "start9 ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/010_start9-nopasswd" + +if [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then + /usr/lib/startos/scripts/enable-kiosk +fi + +if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then + passwd -l start9 +fi + +EOF + +SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}" + +lb bootstrap +lb chroot +lb installer +lb binary_chroot +lb chroot_prep install all mode-apt-install-binary mode-archives-chroot +ln -sf /run/systemd/resolve/stub-resolv.conf chroot/chroot/etc/resolv.conf +lb binary_rootfs + +cp $prep_results_dir/binary/live/filesystem.squashfs $RESULTS_DIR/$IMAGE_BASENAME.squashfs + +if [ "${IMAGE_TYPE}" = iso ]; then + + lb binary_manifest + lb binary_package-lists + lb binary_linux-image + lb binary_memtest + lb binary_grub-legacy + lb binary_grub-pc + lb binary_grub_cfg + lb binary_syslinux + lb binary_disk + lb binary_loadlin + lb binary_win32-loader + lb binary_includes + lb binary_grub-efi + lb binary_hooks + lb binary_checksums + find binary -newermt "$(date -d@${SOURCE_DATE_EPOCH} '+%Y-%m-%d %H:%M:%S')" -printf "%y %p\n" -exec touch '{}' -d@${SOURCE_DATE_EPOCH} --no-dereference ';' > binary.modified_timestamps + lb binary_iso + lb binary_onie + lb binary_netboot + lb binary_tar + lb binary_hdd + lb binary_zsync + lb chroot_prep remove all mode-archives-chroot + lb source + + mv $prep_results_dir/live-image-${IB_TARGET_ARCH}.hybrid.iso $RESULTS_DIR/$IMAGE_BASENAME.iso + +elif [ "${IMAGE_TYPE}" = img ]; then + + function partition_for () { + if [[ "$1" =~ [0-9]+$ ]]; then + echo "$1p$2" + else + echo "$1$2" + fi + } + + ROOT_PART_END=$MAX_IMG_SECTORS + TARGET_NAME=$prep_results_dir/${IMAGE_BASENAME}.img + TARGET_SIZE=$[($ROOT_PART_END+1)*512] + truncate -s $TARGET_SIZE $TARGET_NAME + ( + echo o + echo x + echo i + echo "0xcb15ae4d" + echo r + echo n + echo p + echo 1 + echo 2048 + echo 526335 + echo t + echo c + echo n + echo p + echo 2 + echo 526336 + echo $ROOT_PART_END + echo a + echo 1 + echo w + ) | fdisk $TARGET_NAME + OUTPUT_DEVICE=$(losetup --show -fP $TARGET_NAME) + mkfs.ext4 `partition_for ${OUTPUT_DEVICE} 2` + mkfs.vfat `partition_for ${OUTPUT_DEVICE} 1` + + TMPDIR=$(mktemp -d) + + mount `partition_for ${OUTPUT_DEVICE} 2` $TMPDIR + mkdir $TMPDIR/boot + mount `partition_for ${OUTPUT_DEVICE} 1` $TMPDIR/boot + unsquashfs -f -d $TMPDIR $prep_results_dir/binary/live/filesystem.squashfs + + if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then + sed -i 's| boot=embassy| init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/cmdline.txt + rsync -a $base_dir/raspberrypi/img/ $TMPDIR/ + fi + + umount $TMPDIR/boot + umount $TMPDIR + + e2fsck -fy `partition_for ${OUTPUT_DEVICE} 2` + resize2fs -M `partition_for ${OUTPUT_DEVICE} 2` + + BLOCK_COUNT=$(dumpe2fs -h `partition_for ${OUTPUT_DEVICE} 2` | awk '/^Block count:/ { print $3 }') + BLOCK_SIZE=$(dumpe2fs -h `partition_for ${OUTPUT_DEVICE} 2` | awk '/^Block size:/ { print $3 }') + SECTOR_LEN=$[$BLOCK_COUNT*$BLOCK_SIZE/512] + + losetup -d $OUTPUT_DEVICE + + ( + echo d + echo 2 + echo n + echo p + echo 2 + echo 526336 + echo +$SECTOR_LEN + echo w + ) | fdisk $TARGET_NAME + + ROOT_PART_END=$[526336+$SECTOR_LEN] + TARGET_SIZE=$[($ROOT_PART_END+1)*512] + truncate -s $TARGET_SIZE $TARGET_NAME + + mv $TARGET_NAME $RESULTS_DIR/$IMAGE_BASENAME.img + +fi \ No newline at end of file diff --git a/image-recipe/prepare.sh b/image-recipe/prepare.sh new file mode 100755 index 000000000..1c6779608 --- /dev/null +++ b/image-recipe/prepare.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -e +set -x + +export DEBIAN_FRONTEND=noninteractive +apt-get install -yq \ + live-build \ + procps \ + systemd \ + binfmt-support \ + qemu-utils \ + qemu-user-static \ + qemu-system-x86 \ + qemu-system-aarch64 \ + xorriso \ + isolinux \ + ca-certificates \ + curl \ + gpg \ + fdisk \ + dosfstools \ + e2fsprogs \ + squashfs-tools \ + rsync diff --git a/build/raspberrypi/fstab b/image-recipe/raspberrypi/img/etc/fstab similarity index 100% rename from build/raspberrypi/fstab rename to image-recipe/raspberrypi/img/etc/fstab diff --git a/build/raspberrypi/init_resize.sh b/image-recipe/raspberrypi/img/usr/lib/startos/scripts/init_resize.sh similarity index 98% rename from build/raspberrypi/init_resize.sh rename to image-recipe/raspberrypi/img/usr/lib/startos/scripts/init_resize.sh index 401d83978..931649897 100755 --- a/build/raspberrypi/init_resize.sh +++ b/image-recipe/raspberrypi/img/usr/lib/startos/scripts/init_resize.sh @@ -114,7 +114,7 @@ mount / -o remount,ro beep if main; then - sed -i 's| init=/usr/lib/embassy/scripts/init_resize\.sh| boot=embassy|' /boot/cmdline.txt + sed -i 's| init=/usr/lib/startos/scripts/init_resize\.sh| boot=embassy|' /boot/cmdline.txt echo "Resized root filesystem. Rebooting in 5 seconds..." sleep 5 else diff --git a/image-recipe/raspberrypi/squashfs/boot/cmdline.txt b/image-recipe/raspberrypi/squashfs/boot/cmdline.txt new file mode 100644 index 000000000..02de34729 --- /dev/null +++ b/image-recipe/raspberrypi/squashfs/boot/cmdline.txt @@ -0,0 +1 @@ +usb-storage.quirks=152d:0562:u,14cd:121c:u,0781:cfcb:u console=serial0,115200 console=tty1 root=PARTUUID=cb15ae4d-02 rootfstype=ext4 fsck.repair=yes rootwait cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory quiet boot=embassy \ No newline at end of file diff --git a/image-recipe/raspberrypi/squashfs/boot/config.txt b/image-recipe/raspberrypi/squashfs/boot/config.txt new file mode 100644 index 000000000..17bd5dc4e --- /dev/null +++ b/image-recipe/raspberrypi/squashfs/boot/config.txt @@ -0,0 +1,86 @@ +# For more options and information see +# http://rpf.io/configtxt +# Some settings may impact device functionality. See link above for details + +# uncomment if you get no picture on HDMI for a default "safe" mode +#hdmi_safe=1 + +# uncomment the following to adjust overscan. Use positive numbers if console +# goes off screen, and negative if there is too much border +#overscan_left=16 +#overscan_right=16 +#overscan_top=16 +#overscan_bottom=16 + +# uncomment to force a console size. By default it will be display's size minus +# overscan. +#framebuffer_width=1280 +#framebuffer_height=720 + +# uncomment if hdmi display is not detected and composite is being output +#hdmi_force_hotplug=1 + +# uncomment to force a specific HDMI mode (this will force VGA) +#hdmi_group=1 +#hdmi_mode=1 + +# uncomment to force a HDMI mode rather than DVI. This can make audio work in +# DMT (computer monitor) modes +#hdmi_drive=2 + +# uncomment to increase signal to HDMI, if you have interference, blanking, or +# no display +#config_hdmi_boost=4 + +# uncomment for composite PAL +#sdtv_mode=2 + +#uncomment to overclock the arm. 700 MHz is the default. +#arm_freq=800 + +# Uncomment some or all of these to enable the optional hardware interfaces +#dtparam=i2c_arm=on +#dtparam=i2s=on +#dtparam=spi=on + +# Uncomment this to enable infrared communication. +#dtoverlay=gpio-ir,gpio_pin=17 +#dtoverlay=gpio-ir-tx,gpio_pin=18 + +# Additional overlays and parameters are documented /boot/overlays/README + +# Enable audio (loads snd_bcm2835) +dtparam=audio=on + +# Automatically load overlays for detected cameras +camera_auto_detect=1 + +# Automatically load overlays for detected DSI displays +display_auto_detect=1 + +# Enable DRM VC4 V3D driver +dtoverlay=vc4-kms-v3d +max_framebuffers=2 + +# Run in 64-bit mode +arm_64bit=1 + +# Disable compensation for displays with overscan +disable_overscan=1 + +[cm4] +# Enable host mode on the 2711 built-in XHCI USB controller. +# This line should be removed if the legacy DWC2 controller is required +# (e.g. for USB device mode) or if USB support is not required. +otg_mode=1 + +[all] + +[pi4] +# Run as fast as firmware / board allows +arm_boost=1 + +[all] +gpu_mem=16 +dtoverlay=pwm-2chan,disable-bt +initramfs initrd.img-6.1.21-v8+ diff --git a/image-recipe/raspberrypi/squashfs/etc/embassy/config.yaml b/image-recipe/raspberrypi/squashfs/etc/embassy/config.yaml new file mode 100644 index 000000000..7c81ad513 --- /dev/null +++ b/image-recipe/raspberrypi/squashfs/etc/embassy/config.yaml @@ -0,0 +1,6 @@ +os-partitions: + boot: /dev/mmcblk0p1 + root: /dev/mmcblk0p2 +ethernet-interface: end0 +wifi-interface: wlan0 +disable-encryption: true diff --git a/image-recipe/raspberrypi/squashfs/etc/modprobe.d/cfg80211.conf b/image-recipe/raspberrypi/squashfs/etc/modprobe.d/cfg80211.conf new file mode 100644 index 000000000..d2abd4efb --- /dev/null +++ b/image-recipe/raspberrypi/squashfs/etc/modprobe.d/cfg80211.conf @@ -0,0 +1 @@ +options cfg80211 ieee80211_regdom=US diff --git a/image-recipe/raspberrypi/squashfs/usr/bin/extract-ikconfig b/image-recipe/raspberrypi/squashfs/usr/bin/extract-ikconfig new file mode 100755 index 000000000..8df33e7d6 --- /dev/null +++ b/image-recipe/raspberrypi/squashfs/usr/bin/extract-ikconfig @@ -0,0 +1,69 @@ +#!/bin/sh +# ---------------------------------------------------------------------- +# extract-ikconfig - Extract the .config file from a kernel image +# +# This will only work when the kernel was compiled with CONFIG_IKCONFIG. +# +# The obscure use of the "tr" filter is to work around older versions of +# "grep" that report the byte offset of the line instead of the pattern. +# +# (c) 2009,2010 Dick Streefland +# Licensed under the terms of the GNU General Public License. +# ---------------------------------------------------------------------- + +cf1='IKCFG_ST\037\213\010' +cf2='0123456789' + +dump_config() +{ + if pos=`tr "$cf1\n$cf2" "\n$cf2=" < "$1" | grep -abo "^$cf2"` + then + pos=${pos%%:*} + tail -c+$(($pos+8)) "$1" | zcat > $tmp1 2> /dev/null + if [ $? != 1 ] + then # exit status must be 0 or 2 (trailing garbage warning) + cat $tmp1 + exit 0 + fi + fi +} + +try_decompress() +{ + for pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"` + do + pos=${pos%%:*} + tail -c+$pos "$img" | $3 > $tmp2 2> /dev/null + dump_config $tmp2 + done +} + +# Check invocation: +me=${0##*/} +img=$1 +if [ $# -ne 1 -o ! -s "$img" ] +then + echo "Usage: $me " >&2 + exit 2 +fi + +# Prepare temp files: +tmp1=/tmp/ikconfig$$.1 +tmp2=/tmp/ikconfig$$.2 +trap "rm -f $tmp1 $tmp2" 0 + +# Initial attempt for uncompressed images or objects: +dump_config "$img" + +# That didn't work, so retry after decompression. +try_decompress '\037\213\010' xy gunzip +try_decompress '\3757zXZ\000' abcde unxz +try_decompress 'BZh' xy bunzip2 +try_decompress '\135\0\0\0' xxx unlzma +try_decompress '\211\114\132' xy 'lzop -d' +try_decompress '\002\041\114\030' xyy 'lz4 -d -l' +try_decompress '\050\265\057\375' xxx unzstd + +# Bail out: +echo "$me: Cannot find kernel config." >&2 +exit 1 diff --git a/image-recipe/run-local-build.sh b/image-recipe/run-local-build.sh new file mode 100755 index 000000000..7f7ecd3d4 --- /dev/null +++ b/image-recipe/run-local-build.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -e + +DEB_PATH="$(realpath $1)" + +cd "$(dirname "${BASH_SOURCE[0]}")"/.. + +BASEDIR="$(pwd -P)" + +VERSION="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/VERSION.txt)" +GIT_HASH="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/GIT_HASH.txt)" +if [[ "$GIT_HASH" =~ ^@ ]]; then + GIT_HASH="unknown" +else + GIT_HASH="$(echo -n "$GIT_HASH" | head -c 7)" +fi +STARTOS_ENV="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/ENVIRONMENT.txt)" +PLATFORM="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/PLATFORM.txt)" + +if [ -z "$1" ]; then + PLATFORM="$(uname -m)" +fi +if [ "$PLATFORM" = "x86_64" ] || [ "$PLATFORM" = "x86_64-nonfree" ]; then + ARCH=amd64 + QEMU_ARCH=x86_64 +elif [ "$PLATFORM" = "aarch64" ] || [ "$PLATFORM" = "aarch64-nonfree" ] || [ "$PLATFORM" = "raspberrypi" ] || [ "$PLATFORM" = "rockchip64" ]; then + ARCH=arm64 + QEMU_ARCH=aarch64 +else + ARCH="$PLATFORM" + QEMU_ARCH="$PLATFORM" +fi + +SUITE=bookworm + +debspawn list | grep $SUITE || debspawn create $SUITE + +VERSION_FULL="${VERSION}-${GIT_HASH}" +if [ -n "$STARTOS_ENV" ]; then + VERSION_FULL="$VERSION_FULL~${STARTOS_ENV}" +fi + +if [ -z "$DSNAME" ]; then + DSNAME="$SUITE" +fi + +if [ "$QEMU_ARCH" != "$(uname -m)" ]; then + sudo update-binfmts --import qemu-$QEMU_ARCH +fi + +imgbuild_fname="$(mktemp /tmp/exec-mkimage.XXXXXX)" +cat > $imgbuild_fname < { // Output::ReadLineStderr(self.read_line_stderr(pid).await?) // } - Input::Log(LogParams { gid, level }) => { + Input::Log(LogParams { gid: _, level }) => { level.trace(); Output::Log } @@ -363,23 +363,23 @@ async fn main() { let req = serde_json::from_str::(&line?)?; match handler.handle(req.input).await { Ok(output) => { - if let Err(err) = w.lock().await.write_all( + if w.lock().await.write_all( format!("{}\n", json!({ "id": req.id, "jsonrpc": "2.0", "result": output })) .as_bytes(), ) - .await { + .await.is_err() { tracing::error!("Error sending to {id:?}", id = req.id); } } Err(e) => - if let Err(err) = w + if w .lock() .await .write_all( format!("{}\n", json!({ "id": req.id, "jsonrpc": "2.0", "error": e })) .as_bytes(), ) - .await { + .await.is_err() { tracing::error!("Handle + Error sending to {id:?}", id = req.id); }, diff --git a/libs/helpers/Cargo.toml b/libs/helpers/Cargo.toml index bc82a968b..0c6f5f028 100644 --- a/libs/helpers/Cargo.toml +++ b/libs/helpers/Cargo.toml @@ -8,13 +8,13 @@ edition = "2021" [dependencies] async-trait = "0.1.64" color-eyre = "0.6.2" -futures = "0.3.21" +futures = "0.3.28" lazy_async_pool = "0.3.3" models = { path = "../models" } -pin-project = "1.0.11" +pin-project = "1.1.3" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" -tokio = { version = "1.23", features = ["full"] } -tokio-stream = { version = "0.1.9", features = ["io-util", "sync"] } -tracing = "0.1.35" +tokio = { version = "1", features = ["full"] } +tokio-stream = { version = "0.1.14", features = ["io-util", "sync"] } +tracing = "0.1.39" yajrc = { version = "*", git = "https://github.com/dr-bonez/yajrc.git", branch = "develop" } diff --git a/libs/helpers/src/lib.rs b/libs/helpers/src/lib.rs index d8dcf6c6d..d7c51d5e1 100644 --- a/libs/helpers/src/lib.rs +++ b/libs/helpers/src/lib.rs @@ -72,11 +72,29 @@ pub async fn canonicalize( #[pin_project::pin_project(PinnedDrop)] pub struct NonDetachingJoinHandle(#[pin] JoinHandle); +impl NonDetachingJoinHandle { + pub async fn wait_for_abort(self) -> Result { + self.abort(); + self.await + } +} impl From> for NonDetachingJoinHandle { fn from(t: JoinHandle) -> Self { NonDetachingJoinHandle(t) } } + +impl Deref for NonDetachingJoinHandle { + type Target = JoinHandle; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for NonDetachingJoinHandle { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} #[pin_project::pinned_drop] impl PinnedDrop for NonDetachingJoinHandle { fn drop(self: std::pin::Pin<&mut Self>) { @@ -94,17 +112,6 @@ impl Future for NonDetachingJoinHandle { this.0.poll(cx) } } -impl Deref for NonDetachingJoinHandle { - type Target = JoinHandle; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl DerefMut for NonDetachingJoinHandle { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} pub struct AtomicFile { tmp_path: PathBuf, diff --git a/libs/helpers/src/rsync.rs b/libs/helpers/src/rsync.rs index 95f2df28d..862a1ebc4 100644 --- a/libs/helpers/src/rsync.rs +++ b/libs/helpers/src/rsync.rs @@ -74,7 +74,7 @@ impl Rsync { cmd.arg("--no-perms"); } let mut command = cmd - .arg("-acAXH") + .arg("-actAXH") .arg("--info=progress2") .arg("--no-inc-recursive") .arg(src.as_ref()) diff --git a/libs/js_engine/Cargo.toml b/libs/js_engine/Cargo.toml index 299eb9fdb..cdff104f0 100644 --- a/libs/js_engine/Cargo.toml +++ b/libs/js_engine/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-trait = "0.1.56" -dashmap = "5.3.4" -deno_core = "0.195.0" -deno_ast = { version = "0.27.2", features = ["transpiling"] } +async-trait = "0.1.74" +dashmap = "5.5.3" +deno_core = "=0.222.0" +deno_ast = { version = "=0.29.5", features = ["transpiling"] } embassy_container_init = { path = "../embassy_container_init" } -reqwest = { version = "0.11.11" } -sha2 = "0.10.2" -itertools = "0.10.5" +reqwest = { version = "0.11.22" } +sha2 = "0.10.8" +itertools = "0.11.0" lazy_static = "1.4.0" models = { path = "../models" } helpers = { path = "../helpers" } diff --git a/libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin b/libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin index b366410ca..305aa2d4c 100644 Binary files a/libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin and b/libs/js_engine/src/artifacts/ARM_JS_SNAPSHOT.bin differ diff --git a/libs/js_engine/src/artifacts/JS_SNAPSHOT.bin b/libs/js_engine/src/artifacts/JS_SNAPSHOT.bin index 0201d5a99..7f7d10689 100644 Binary files a/libs/js_engine/src/artifacts/JS_SNAPSHOT.bin and b/libs/js_engine/src/artifacts/JS_SNAPSHOT.bin differ diff --git a/libs/js_engine/src/lib.rs b/libs/js_engine/src/lib.rs index b2ce1a04e..514560077 100644 --- a/libs/js_engine/src/lib.rs +++ b/libs/js_engine/src/lib.rs @@ -13,8 +13,7 @@ use deno_core::{ ModuleSourceFuture, ModuleSpecifier, ModuleType, OpDecl, ResolutionKind, RuntimeOptions, Snapshot, }; -use embassy_container_init::ProcessGroupId; -use helpers::{script_dir, spawn_local, OsApi, Rsync, UnixRpcClient}; +use helpers::{script_dir, spawn_local, Rsync}; use models::{PackageId, ProcedureName, Version, VolumeId}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -105,8 +104,6 @@ struct JsContext { volumes: Arc, input: Value, variable_args: Vec, - container_process_gid: ProcessGroupId, - container_rpc_client: Option>, rsyncs: Arc)>>, callback_sender: mpsc::UnboundedSender<(Arc, Vec)>, } @@ -158,17 +155,17 @@ impl ModuleLoader for ModsLoader { "file:///deno_global.js" => Ok(ModuleSource::new( ModuleType::JavaScript, FastString::Static("const old_deno = Deno; Deno = null; export default old_deno"), - &*DENO_GLOBAL_JS, + &DENO_GLOBAL_JS, )), "file:///loadModule.js" => Ok(ModuleSource::new( ModuleType::JavaScript, FastString::Static(include_str!("./artifacts/loadModule.js")), - &*LOAD_MODULE_JS, + &LOAD_MODULE_JS, )), "file:///embassy.js" => Ok(ModuleSource::new( ModuleType::JavaScript, self.code.0.clone().into(), - &*EMBASSY_JS, + &EMBASSY_JS, )), x => Err(anyhow!("Not allowed to import: {}", x)), @@ -197,8 +194,6 @@ pub struct JsExecutionEnvironment { package_id: PackageId, version: Version, volumes: Arc, - container_process_gid: ProcessGroupId, - container_rpc_client: Option>, } impl JsExecutionEnvironment { @@ -208,9 +203,7 @@ impl JsExecutionEnvironment { package_id: &PackageId, version: &Version, volumes: Box, - container_process_gid: ProcessGroupId, - container_rpc_client: Option>, - ) -> Result { + ) -> Result { let data_dir = data_directory.as_ref(); let base_directory = data_dir; let js_code = JsCode({ @@ -244,8 +237,6 @@ impl JsExecutionEnvironment { version: version.clone(), volumes: volumes.into(), sandboxed: false, - container_process_gid, - container_rpc_client, }) } pub fn read_only_effects(mut self) -> Self { @@ -313,12 +304,7 @@ impl JsExecutionEnvironment { fns::get_variable_args::decl(), fns::set_value::decl(), fns::is_sandboxed::decl(), - fns::start_command::decl(), - fns::wait_command::decl(), fns::sleep::decl(), - fns::send_signal::decl(), - fns::chmod::decl(), - fns::signal_group::decl(), fns::rsync::decl(), fns::rsync_wait::decl(), fns::rsync_progress::decl(), @@ -359,16 +345,13 @@ impl JsExecutionEnvironment { sandboxed: self.sandboxed, input, variable_args, - container_process_gid: self.container_process_gid, - container_rpc_client: self.container_rpc_client.clone(), - callback_sender, rsyncs: Default::default(), }; let ext = Extension::builder("embassy") .ops(Self::declarations()) .state(move |state| { state.put(ext_answer_state.clone()); - state.put(js_ctx.clone()); + state.put(js_ctx); }) .build(); let loader = std::rc::Rc::new(self.module_loader.clone()); @@ -385,11 +368,7 @@ impl JsExecutionEnvironment { .load_main_module(&"file:///loadModule.js".parse().unwrap(), None) .await?; let evaluated = runtime.mod_evaluate(mod_id); - let res = RuntimeEventLoop { - runtime: &mut runtime, - callback_receiver, - } - .await; + let res = runtime.run_event_loop(false).await; res?; evaluated.await??; Ok::<_, AnyError>(()) @@ -425,7 +404,7 @@ impl<'a> Future for RuntimeEventLoop<'a> { if let Poll::Ready(Some((uuid, args))) = this.callback_receiver.poll_recv(cx) { match this.runtime.execute_script( "callback", - &format!("globalThis.runCallback(\"{uuid}\", {})", Value::Array(args)), + format!("globalThis.runCallback(\"{uuid}\", {})", Value::Array(args)).into(), ) { Ok(_) => (), Err(e) => return Poll::Ready(Err(e)), @@ -450,23 +429,17 @@ mod fns { use deno_core::anyhow::{anyhow, bail}; use deno_core::error::AnyError; use deno_core::*; - use embassy_container_init::{ - OutputParams, OutputStrategy, ProcessGroupId, ProcessId, RunCommand, RunCommandParams, - SendSignal, SendSignalParams, SignalGroup, SignalGroupParams, - }; - use helpers::{ - to_tmp_path, AddressSchemaLocal, AddressSchemaOnion, AtomicFile, Callback, Rsync, - RsyncOptions, - }; + use embassy_container_init::ProcessId; + use helpers::{to_tmp_path, AtomicFile, Rsync, RsyncOptions}; use itertools::Itertools; use models::{PackageId, VolumeId}; use serde::{Deserialize, Serialize}; - use serde_json::{json, Value}; + use serde_json::Value; use tokio::io::AsyncWriteExt; use tokio::process::Command; use super::{AnswerState, JsContext}; - use crate::{system_time_as_unix_ms, MetadataJs, ResultType}; + use crate::{system_time_as_unix_ms, MetadataJs}; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)] struct FetchOptions { @@ -650,7 +623,7 @@ mod fns { } let path_in = path_in.strip_prefix("/").unwrap_or(&path_in); - let new_file = volume_path.join(&path_in); + let new_file = volume_path.join(path_in); let parent_new_file = new_file .parent() .ok_or_else(|| anyhow!("Expecting that file is not root"))?; @@ -1082,11 +1055,9 @@ mod fns { let volume_path = { let state = state.borrow(); let ctx: &JsContext = state.borrow(); - let volume_path = ctx - .volumes + ctx.volumes .path_for(&ctx.datadir, &ctx.package_id, &ctx.version, &volume_id) - .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))?; - volume_path + .ok_or_else(|| anyhow!("There is no {} in volumes", volume_id))? }; let path_in = path_in.strip_prefix("/").unwrap_or(&path_in); let new_file = volume_path.join(path_in); @@ -1157,8 +1128,7 @@ mod fns { .stdout, )? .lines() - .skip(1) - .next() + .nth(1) .unwrap_or_default() .parse()?; let used = String::from_utf8( @@ -1188,8 +1158,7 @@ mod fns { .stdout, )? .lines() - .skip(1) - .next() + .nth(1) .unwrap_or_default() .split_ascii_whitespace() .next_tuple() @@ -1210,18 +1179,6 @@ mod fns { let state = state.borrow(); state.borrow::().clone() }; - if let Some(rpc_client) = ctx.container_rpc_client { - return rpc_client - .request( - embassy_container_init::Log, - embassy_container_init::LogParams { - gid: Some(ctx.container_process_gid), - level: embassy_container_init::LogLevel::Trace(input), - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data)); - } tracing::trace!( package_id = tracing::field::display(&ctx.package_id), run_function = tracing::field::display(&ctx.run_function), @@ -1236,18 +1193,6 @@ mod fns { let state = state.borrow(); state.borrow::().clone() }; - if let Some(rpc_client) = ctx.container_rpc_client { - return rpc_client - .request( - embassy_container_init::Log, - embassy_container_init::LogParams { - gid: Some(ctx.container_process_gid), - level: embassy_container_init::LogLevel::Warn(input), - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data)); - } tracing::warn!( package_id = tracing::field::display(&ctx.package_id), run_function = tracing::field::display(&ctx.run_function), @@ -1262,18 +1207,6 @@ mod fns { let state = state.borrow(); state.borrow::().clone() }; - if let Some(rpc_client) = ctx.container_rpc_client { - return rpc_client - .request( - embassy_container_init::Log, - embassy_container_init::LogParams { - gid: Some(ctx.container_process_gid), - level: embassy_container_init::LogLevel::Error(input), - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data)); - } tracing::error!( package_id = tracing::field::display(&ctx.package_id), run_function = tracing::field::display(&ctx.run_function), @@ -1288,18 +1221,6 @@ mod fns { let state = state.borrow(); state.borrow::().clone() }; - if let Some(rpc_client) = ctx.container_rpc_client { - return rpc_client - .request( - embassy_container_init::Log, - embassy_container_init::LogParams { - gid: Some(ctx.container_process_gid), - level: embassy_container_init::LogLevel::Debug(input), - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data)); - } tracing::debug!( package_id = tracing::field::display(&ctx.package_id), run_function = tracing::field::display(&ctx.run_function), @@ -1310,25 +1231,14 @@ mod fns { } #[op] async fn log_info(state: Rc>, input: String) -> Result<(), AnyError> { - let ctx = { + let (package_id, run_function) = { let state = state.borrow(); - state.borrow::().clone() + let ctx: JsContext = state.borrow::().clone(); + (ctx.package_id, ctx.run_function) }; - if let Some(rpc_client) = ctx.container_rpc_client { - return rpc_client - .request( - embassy_container_init::Log, - embassy_container_init::LogParams { - gid: Some(ctx.container_process_gid), - level: embassy_container_init::LogLevel::Info(input), - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data)); - } tracing::info!( - package_id = tracing::field::display(&ctx.package_id), - run_function = tracing::field::display(&ctx.run_function), + package_id = tracing::field::display(&package_id), + run_function = tracing::field::display(&run_function), "{}", input ); @@ -1364,174 +1274,12 @@ mod fns { Ok(ctx.sandboxed) } - #[op] - async fn send_signal( - state: Rc>, - pid: u32, - signal: u32, - ) -> Result<(), AnyError> { - let sandboxed = { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - ctx.sandboxed - }; - - if sandboxed { - bail!("Will not run sendSignal in sandboxed mode"); - } - - if let Some(rpc_client) = { - let state = state.borrow(); - let ctx = state.borrow::(); - ctx.container_rpc_client.clone() - } { - rpc_client - .request( - SendSignal, - SendSignalParams { - pid: ProcessId(pid), - signal, - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data))?; - - Ok(()) - } else { - Err(anyhow!("No RpcClient for command operations")) - } - } - - #[op] - async fn signal_group( - state: Rc>, - gid: u32, - signal: u32, - ) -> Result<(), AnyError> { - let sandboxed = { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - ctx.sandboxed - }; - - if sandboxed { - bail!("Will not run signalGroup in sandboxed mode"); - } - - if let Some(rpc_client) = { - let state = state.borrow(); - let ctx = state.borrow::(); - ctx.container_rpc_client.clone() - } { - rpc_client - .request( - SignalGroup, - SignalGroupParams { - gid: ProcessGroupId(gid), - signal, - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data))?; - - Ok(()) - } else { - Err(anyhow!("No RpcClient for command operations")) - } - } - #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct StartCommand { process_id: ProcessId, } - #[op] - async fn start_command( - state: Rc>, - command: String, - args: Vec, - output: OutputStrategy, - timeout: Option, - ) -> Result { - let sandboxed = { - let state = state.borrow(); - let ctx: &JsContext = state.borrow(); - ctx.sandboxed - }; - - if sandboxed { - bail!("Will not run command in sandboxed mode"); - } - - if let (gid, Some(rpc_client)) = { - let state = state.borrow(); - let ctx = state.borrow::(); - (ctx.container_process_gid, ctx.container_rpc_client.clone()) - } { - let pid = rpc_client - .request( - RunCommand, - RunCommandParams { - gid: Some(gid), - command, - args, - output, - }, - ) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data))?; - - if let Some(timeout) = timeout { - tokio::spawn(async move { - tokio::time::sleep(Duration::from_millis(timeout)).await; - if let Err(err) = rpc_client - .request(SendSignal, SendSignalParams { pid, signal: 9 }) - .await - .map_err(|e| anyhow!("{}: {:?}", e.message, e.data)) - { - tracing::warn!("Could not kill process {pid:?}"); - tracing::debug!("{err:?}"); - } - }); - } - - Ok(StartCommand { process_id: pid }) - } else { - Err(anyhow!("No RpcClient for command operations")) - } - } - - #[op] - async fn wait_command( - state: Rc>, - pid: ProcessId, - ) -> Result { - if let Some(rpc_client) = { - let state = state.borrow(); - let ctx = state.borrow::(); - ctx.container_rpc_client.clone() - } { - Ok( - match rpc_client - .request(embassy_container_init::Output, OutputParams { pid }) - .await - { - Ok(a) => ResultType::Result(json!(a)), - Err(e) => ResultType::ErrorCode( - e.code, - match e.data { - Some(Value::String(s)) => s, - e => format!("{:?}", e), - }, - ), - }, - ) - } else { - Err(anyhow!("No RpcClient for command operations")) - } - } - #[op] async fn sleep(time_ms: u64) -> Result<(), AnyError> { tokio::time::sleep(Duration::from_millis(time_ms)).await; diff --git a/libs/models/Cargo.toml b/libs/models/Cargo.toml index f9a4ec68e..9d75f92c4 100644 --- a/libs/models/Cargo.toml +++ b/libs/models/Cargo.toml @@ -6,33 +6,33 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bollard = "0.13.0" -color-eyre = "0.6.1" -ed25519-dalek = { version = "1.0.1", features = ["serde"] } +base64 = "0.21.4" +color-eyre = "0.6.2" +ed25519-dalek = { version = "2.0.0", features = ["serde"] } lazy_static = "1.4" -mbrman = "0.5.0" +mbrman = "0.5.2" emver = { version = "0.1", git = "https://github.com/Start9Labs/emver-rs.git", features = [ "serde", ] } -internment = { version = "0.7.0", features = ["arc", "serde"] } -ipnet = "2.7.1" -openssl = { version = "0.10.41", features = ["vendored"] } +ipnet = "2.8.0" +openssl = { version = "0.10.57", features = ["vendored"] } patch-db = { version = "*", path = "../../patch-db/patch-db", features = [ "trace", ] } -rand = "0.8" -regex = "1.7.1" -rpc-toolkit = "0.2.1" +rand = "0.8.5" +regex = "1.10.2" +reqwest = "0.11.22" +rpc-toolkit = "0.2.2" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" -sqlx = { version = "0.6.0", features = [ +sqlx = { version = "0.7.2", features = [ "chrono", - "offline", "runtime-tokio-rustls", "postgres", ] } -ssh-key = "0.5.1" +ssh-key = "0.6.2" thiserror = "1.0" tokio = { version = "1", features = ["full"] } torut = "0.2.1" -tracing = "0.1.35" +tracing = "0.1.39" +yasi = "0.1.5" diff --git a/libs/models/src/data_url.rs b/libs/models/src/data_url.rs new file mode 100644 index 000000000..e2141b15a --- /dev/null +++ b/libs/models/src/data_url.rs @@ -0,0 +1,171 @@ +use std::borrow::Cow; +use std::path::Path; + +use base64::Engine; +use color_eyre::eyre::eyre; +use reqwest::header::CONTENT_TYPE; +use serde::{Deserialize, Serialize}; +use tokio::io::{AsyncRead, AsyncReadExt}; +use yasi::InternedString; + +use crate::{mime, Error, ErrorKind, ResultExt}; + +#[derive(Clone)] +pub struct DataUrl<'a> { + mime: InternedString, + data: Cow<'a, [u8]>, +} +impl<'a> DataUrl<'a> { + pub const DEFAULT_MIME: &'static str = "application/octet-stream"; + pub const MAX_SIZE: u64 = 100 * 1024; + + // data:{mime};base64,{data} + pub fn to_string(&self) -> String { + use std::fmt::Write; + let mut res = String::with_capacity(self.data_url_len_without_mime() + self.mime.len()); + let _ = write!(res, "data:{};base64,", self.mime); + base64::engine::general_purpose::STANDARD.encode_string(&self.data, &mut res); + res + } + + fn data_url_len_without_mime(&self) -> usize { + 5 + 8 + (4 * self.data.len() / 3) + 3 + } + + pub fn data_url_len(&self) -> usize { + self.data_url_len_without_mime() + self.mime.len() + } + + pub fn from_slice(mime: &str, data: &'a [u8]) -> Self { + Self { + mime: InternedString::intern(mime), + data: Cow::Borrowed(data), + } + } +} +impl DataUrl<'static> { + pub async fn from_reader( + mime: &str, + rdr: impl AsyncRead + Unpin, + size_est: Option, + ) -> Result { + let check_size = |s| { + if s > Self::MAX_SIZE { + Err(Error::new( + eyre!("Data URLs must be smaller than 100KiB"), + ErrorKind::Filesystem, + )) + } else { + Ok(s) + } + }; + let mut buf = size_est + .map(check_size) + .transpose()? + .map(|s| Vec::with_capacity(s as usize)) + .unwrap_or_default(); + rdr.take(Self::MAX_SIZE + 1).read_to_end(&mut buf).await?; + check_size(buf.len() as u64)?; + + Ok(Self { + mime: InternedString::intern(mime), + data: Cow::Owned(buf), + }) + } + + pub async fn from_path(path: impl AsRef) -> Result { + let path = path.as_ref(); + let f = tokio::fs::File::open(path).await?; + let m = f.metadata().await?; + let mime = path + .extension() + .and_then(|s| s.to_str()) + .and_then(mime) + .unwrap_or(Self::DEFAULT_MIME); + Self::from_reader(mime, f, Some(m.len())).await + } + + pub async fn from_response(res: reqwest::Response) -> Result { + let mime = InternedString::intern( + res.headers() + .get(CONTENT_TYPE) + .and_then(|h| h.to_str().ok()) + .unwrap_or(Self::DEFAULT_MIME), + ); + let data = res.bytes().await.with_kind(ErrorKind::Network)?.to_vec(); + Ok(Self { + mime, + data: Cow::Owned(data), + }) + } + + pub fn from_vec(mime: &str, data: Vec) -> Self { + Self { + mime: InternedString::intern(mime), + data: Cow::Owned(data), + } + } +} + +impl<'a> std::fmt::Debug for DataUrl<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for DataUrl<'static> { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct Visitor; + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = DataUrl<'static>; + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(formatter, "a valid base64 data url") + } + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + v.strip_prefix("data:") + .and_then(|v| v.split_once(";base64,")) + .and_then(|(mime, data)| { + Some(DataUrl { + mime: InternedString::intern(mime), + data: Cow::Owned( + base64::engine::general_purpose::STANDARD + .decode(data) + .ok()?, + ), + }) + }) + .ok_or_else(|| { + E::invalid_value(serde::de::Unexpected::Str(v), &"a valid base64 data url") + }) + } + } + deserializer.deserialize_any(Visitor) + } +} + +impl<'a> Serialize for DataUrl<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +#[test] +fn doesnt_reallocate() { + let random: [u8; 10] = rand::random(); + for i in 0..10 { + let icon = DataUrl { + mime: InternedString::intern("png"), + data: Cow::Borrowed(&random[..i]), + }; + assert_eq!(dbg!(icon.to_string()).capacity(), icon.data_url_len()); + } +} diff --git a/libs/models/src/errors.rs b/libs/models/src/errors.rs index c429ccd7c..f22624d36 100644 --- a/libs/models/src/errors.rs +++ b/libs/models/src/errors.rs @@ -3,6 +3,7 @@ use std::fmt::Display; use color_eyre::eyre::eyre; use patch_db::Revision; use rpc_toolkit::hyper::http::uri::InvalidUri; +use rpc_toolkit::reqwest; use rpc_toolkit::yajrc::RpcError; use crate::InvalidId; @@ -77,6 +78,9 @@ pub enum ErrorKind { OpenSsh = 66, Zram = 67, Lshw = 68, + CpuSettings = 69, + Firmware = 70, + Timeout = 71, } impl ErrorKind { pub fn as_str(&self) -> &'static str { @@ -150,6 +154,9 @@ impl ErrorKind { OpenSsh => "OpenSSH Error", Zram => "Zram Error", Lshw => "LSHW Error", + CpuSettings => "CPU Settings Error", + Firmware => "Firmware Error", + Timeout => "Timeout Error", } } } @@ -235,19 +242,14 @@ impl From for Error { Error::new(e, ErrorKind::InvalidSignature) } } -impl From for Error { - fn from(e: bollard::errors::Error) -> Self { - Error::new(e, ErrorKind::Docker) +impl From for Error { + fn from(e: std::net::AddrParseError) -> Self { + Error::new(e, ErrorKind::ParseNetAddress) } } impl From for Error { fn from(e: torut::control::ConnError) -> Self { - Error::new(eyre!("{:?}", e), ErrorKind::Tor) - } -} -impl From for Error { - fn from(e: std::net::AddrParseError) -> Self { - Error::new(e, ErrorKind::ParseNetAddress) + Error::new(e, ErrorKind::Tor) } } impl From for Error { @@ -275,6 +277,28 @@ impl From for Error { Error::new(e, ErrorKind::OpenSsh) } } +impl From for Error { + fn from(e: reqwest::Error) -> Self { + let kind = match e { + _ if e.is_builder() => ErrorKind::ParseUrl, + _ if e.is_decode() => ErrorKind::Deserialization, + _ => ErrorKind::Network, + }; + Error::new(e, kind) + } +} +impl From for Error { + fn from(value: patch_db::value::Error) -> Self { + match value.kind { + patch_db::value::ErrorKind::Serialization => { + Error::new(value.source, ErrorKind::Serialization) + } + patch_db::value::ErrorKind::Deserialization => { + Error::new(value.source, ErrorKind::Deserialization) + } + } + } +} impl From for RpcError { fn from(e: Error) -> Self { @@ -388,6 +412,18 @@ where } } +pub trait OptionExt +where + Self: Sized, +{ + fn or_not_found(self, message: impl std::fmt::Display) -> Result; +} +impl OptionExt for Option { + fn or_not_found(self, message: impl std::fmt::Display) -> Result { + self.ok_or_else(|| Error::new(eyre!("{}", message), ErrorKind::NotFound)) + } +} + #[macro_export] macro_rules! ensure_code { ($x:expr, $c:expr, $fmt:expr $(, $arg:expr)*) => { diff --git a/libs/models/src/action_id.rs b/libs/models/src/id/action.rs similarity index 100% rename from libs/models/src/action_id.rs rename to libs/models/src/id/action.rs diff --git a/libs/models/src/id/address.rs b/libs/models/src/id/address.rs new file mode 100644 index 000000000..1bd670525 --- /dev/null +++ b/libs/models/src/id/address.rs @@ -0,0 +1,59 @@ +use std::path::Path; + +use serde::{Deserialize, Deserializer, Serialize}; + +use crate::Id; + +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] +pub struct AddressId(Id); +impl From for AddressId { + fn from(id: Id) -> Self { + Self(id) + } +} +impl std::fmt::Display for AddressId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", &self.0) + } +} +impl std::ops::Deref for AddressId { + type Target = str; + fn deref(&self) -> &Self::Target { + &*self.0 + } +} +impl AsRef for AddressId { + fn as_ref(&self) -> &str { + self.0.as_ref() + } +} +impl<'de> Deserialize<'de> for AddressId { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(AddressId(Deserialize::deserialize(deserializer)?)) + } +} +impl AsRef for AddressId { + fn as_ref(&self) -> &Path { + self.0.as_ref().as_ref() + } +} +impl<'q> sqlx::Encode<'q, sqlx::Postgres> for AddressId { + fn encode_by_ref( + &self, + buf: &mut >::ArgumentBuffer, + ) -> sqlx::encode::IsNull { + <&str as sqlx::Encode<'q, sqlx::Postgres>>::encode_by_ref(&&**self, buf) + } +} +impl sqlx::Type for AddressId { + fn type_info() -> sqlx::postgres::PgTypeInfo { + <&str as sqlx::Type>::type_info() + } + + fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool { + <&str as sqlx::Type>::compatible(ty) + } +} diff --git a/libs/models/src/health_check_id.rs b/libs/models/src/id/health_check.rs similarity index 100% rename from libs/models/src/health_check_id.rs rename to libs/models/src/id/health_check.rs diff --git a/libs/models/src/image_id.rs b/libs/models/src/id/image.rs similarity index 100% rename from libs/models/src/image_id.rs rename to libs/models/src/id/image.rs diff --git a/libs/models/src/interface_id.rs b/libs/models/src/id/interface.rs similarity index 61% rename from libs/models/src/interface_id.rs rename to libs/models/src/id/interface.rs index b2f82f83c..d062a3648 100644 --- a/libs/models/src/interface_id.rs +++ b/libs/models/src/id/interface.rs @@ -17,7 +17,7 @@ impl std::fmt::Display for InterfaceId { } } impl std::ops::Deref for InterfaceId { - type Target = String; + type Target = str; fn deref(&self) -> &Self::Target { &*self.0 } @@ -40,3 +40,20 @@ impl AsRef for InterfaceId { self.0.as_ref().as_ref() } } +impl<'q> sqlx::Encode<'q, sqlx::Postgres> for InterfaceId { + fn encode_by_ref( + &self, + buf: &mut >::ArgumentBuffer, + ) -> sqlx::encode::IsNull { + <&str as sqlx::Encode<'q, sqlx::Postgres>>::encode_by_ref(&&**self, buf) + } +} +impl sqlx::Type for InterfaceId { + fn type_info() -> sqlx::postgres::PgTypeInfo { + <&str as sqlx::Type>::type_info() + } + + fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool { + <&str as sqlx::Type>::compatible(ty) + } +} diff --git a/libs/models/src/invalid_id.rs b/libs/models/src/id/invalid_id.rs similarity index 100% rename from libs/models/src/invalid_id.rs rename to libs/models/src/id/invalid_id.rs diff --git a/libs/models/src/id.rs b/libs/models/src/id/mod.rs similarity index 53% rename from libs/models/src/id.rs rename to libs/models/src/id/mod.rs index 30a1818ec..ac32ceb22 100644 --- a/libs/models/src/id.rs +++ b/libs/models/src/id/mod.rs @@ -1,21 +1,37 @@ use std::borrow::Borrow; -use internment::ArcIntern; use regex::Regex; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use yasi::InternedString; -use crate::invalid_id::InvalidId; +mod action; +mod address; +mod health_check; +mod image; +mod interface; +mod invalid_id; +mod package; +mod volume; + +pub use action::ActionId; +pub use address::AddressId; +pub use health_check::HealthCheckId; +pub use image::ImageId; +pub use interface::InterfaceId; +pub use invalid_id::InvalidId; +pub use package::{PackageId, SYSTEM_PACKAGE_ID}; +pub use volume::VolumeId; lazy_static::lazy_static! { static ref ID_REGEX: Regex = Regex::new("^[a-z]+(-[a-z]+)*$").unwrap(); - pub static ref SYSTEM_ID: Id = Id(ArcIntern::from_ref("x_system")); + pub static ref SYSTEM_ID: Id = Id(InternedString::intern("x_system")); } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -pub struct Id(ArcIntern); -impl TryFrom> for Id { +pub struct Id(InternedString); +impl TryFrom for Id { type Error = InvalidId; - fn try_from(value: ArcIntern) -> Result { + fn try_from(value: InternedString) -> Result { if ID_REGEX.is_match(&*value) { Ok(Id(value)) } else { @@ -27,7 +43,7 @@ impl TryFrom for Id { type Error = InvalidId; fn try_from(value: String) -> Result { if ID_REGEX.is_match(&value) { - Ok(Id(ArcIntern::new(value))) + Ok(Id(InternedString::intern(value))) } else { Err(InvalidId) } @@ -37,14 +53,14 @@ impl TryFrom<&str> for Id { type Error = InvalidId; fn try_from(value: &str) -> Result { if ID_REGEX.is_match(&value) { - Ok(Id(ArcIntern::from_ref(value))) + Ok(Id(InternedString::intern(value))) } else { Err(InvalidId) } } } impl std::ops::Deref for Id { - type Target = String; + type Target = str; fn deref(&self) -> &Self::Target { &*self.0 } @@ -69,7 +85,7 @@ impl<'de> Deserialize<'de> for Id { where D: Deserializer<'de>, { - let unchecked: String = Deserialize::deserialize(deserializer)?; + let unchecked: InternedString = Deserialize::deserialize(deserializer)?; Id::try_from(unchecked).map_err(serde::de::Error::custom) } } @@ -78,6 +94,23 @@ impl Serialize for Id { where Ser: Serializer, { - serializer.serialize_str(self.as_ref()) + serializer.serialize_str(&*self) + } +} +impl<'q> sqlx::Encode<'q, sqlx::Postgres> for Id { + fn encode_by_ref( + &self, + buf: &mut >::ArgumentBuffer, + ) -> sqlx::encode::IsNull { + <&str as sqlx::Encode<'q, sqlx::Postgres>>::encode_by_ref(&&**self, buf) + } +} +impl sqlx::Type for Id { + fn type_info() -> sqlx::postgres::PgTypeInfo { + <&str as sqlx::Type>::type_info() + } + + fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool { + <&str as sqlx::Type>::compatible(ty) } } diff --git a/libs/models/src/package_id.rs b/libs/models/src/id/package.rs similarity index 73% rename from libs/models/src/package_id.rs rename to libs/models/src/id/package.rs index 9b534a4f5..14c29d88b 100644 --- a/libs/models/src/package_id.rs +++ b/libs/models/src/id/package.rs @@ -23,7 +23,7 @@ impl From for PackageId { } } impl std::ops::Deref for PackageId { - type Target = String; + type Target = str; fn deref(&self) -> &Self::Target { &*self.0 } @@ -69,3 +69,20 @@ impl Serialize for PackageId { Serialize::serialize(&self.0, serializer) } } +impl<'q> sqlx::Encode<'q, sqlx::Postgres> for PackageId { + fn encode_by_ref( + &self, + buf: &mut >::ArgumentBuffer, + ) -> sqlx::encode::IsNull { + <&str as sqlx::Encode<'q, sqlx::Postgres>>::encode_by_ref(&&**self, buf) + } +} +impl sqlx::Type for PackageId { + fn type_info() -> sqlx::postgres::PgTypeInfo { + <&str as sqlx::Type>::type_info() + } + + fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> bool { + <&str as sqlx::Type>::compatible(ty) + } +} diff --git a/libs/models/src/volume_id.rs b/libs/models/src/id/volume.rs similarity index 100% rename from libs/models/src/volume_id.rs rename to libs/models/src/id/volume.rs diff --git a/libs/models/src/lib.rs b/libs/models/src/lib.rs index 01edd65e8..ad9055f24 100644 --- a/libs/models/src/lib.rs +++ b/libs/models/src/lib.rs @@ -1,23 +1,13 @@ -mod action_id; +mod data_url; mod errors; -mod health_check_id; mod id; -mod image_id; -mod interface_id; -mod invalid_id; -mod package_id; +mod mime; mod procedure_name; mod version; -mod volume_id; -pub use action_id::*; +pub use data_url::*; pub use errors::*; -pub use health_check_id::*; pub use id::*; -pub use image_id::*; -pub use interface_id::*; -pub use invalid_id::*; -pub use package_id::*; +pub use mime::*; pub use procedure_name::*; pub use version::*; -pub use volume_id::*; diff --git a/libs/models/src/mime.rs b/libs/models/src/mime.rs new file mode 100644 index 000000000..ea02473d7 --- /dev/null +++ b/libs/models/src/mime.rs @@ -0,0 +1,47 @@ +pub fn mime(extension: &str) -> Option<&'static str> { + match extension { + "apng" => Some("image/apng"), + "avif" => Some("image/avif"), + "flif" => Some("image/flif"), + "gif" => Some("image/gif"), + "jpg" | "jpeg" | "jfif" | "pjpeg" | "pjp" => Some("image/jpeg"), + "jxl" => Some("image/jxl"), + "png" => Some("image/png"), + "svg" => Some("image/svg+xml"), + "webp" => Some("image/webp"), + "mng" | "x-mng" => Some("image/x-mng"), + "css" => Some("text/css"), + "csv" => Some("text/csv"), + "html" => Some("text/html"), + "php" => Some("text/php"), + "plain" | "md" | "txt" => Some("text/plain"), + "xml" => Some("text/xml"), + "js" => Some("text/javascript"), + "wasm" => Some("application/wasm"), + _ => None, + } +} + +pub fn unmime(mime: &str) -> Option<&'static str> { + match mime { + "image/apng" => Some("apng"), + "image/avif" => Some("avif"), + "image/flif" => Some("flif"), + "image/gif" => Some("gif"), + "jpg" | "jpeg" | "jfif" | "pjpeg" | "image/jpeg" => Some("pjp"), + "image/jxl" => Some("jxl"), + "image/png" => Some("png"), + "image/svg+xml" => Some("svg"), + "image/webp" => Some("webp"), + "mng" | "image/x-mng" => Some("x-mng"), + "text/css" => Some("css"), + "text/csv" => Some("csv"), + "text/html" => Some("html"), + "text/php" => Some("php"), + "plain" | "md" | "text/plain" => Some("txt"), + "text/xml" => Some("xml"), + "text/javascript" => Some("js"), + "application/wasm" => Some("wasm"), + _ => None, + } +} diff --git a/libs/models/src/procedure_name.rs b/libs/models/src/procedure_name.rs index ae71e3ad5..6a092955a 100644 --- a/libs/models/src/procedure_name.rs +++ b/libs/models/src/procedure_name.rs @@ -1,6 +1,8 @@ +use serde::{Deserialize, Serialize}; + use crate::{ActionId, HealthCheckId, PackageId}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum ProcedureName { Main, // Usually just run container CreateBackup, diff --git a/libs/models/src/version.rs b/libs/models/src/version.rs index 82b577820..1e4798ba1 100644 --- a/libs/models/src/version.rs +++ b/libs/models/src/version.rs @@ -2,7 +2,6 @@ use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::str::FromStr; -use patch_db::{HasModel, Model}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[derive(Debug, Clone)] @@ -105,6 +104,3 @@ impl Serialize for Version { self.string.serialize(serializer) } } -impl HasModel for Version { - type Model = Model; -} diff --git a/libs/snapshot_creator/Cargo.toml b/libs/snapshot_creator/Cargo.toml index 08876b517..628cd3161 100644 --- a/libs/snapshot_creator/Cargo.toml +++ b/libs/snapshot_creator/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] dashmap = "5.3.4" -deno_core = "0.195.0" -deno_ast = { version = "0.27.2", features = ["transpiling"] } +deno_core = "=0.222.0" +deno_ast = { version = "=0.29.5", features = ["transpiling"] } diff --git a/libs/snapshot_creator/src/main.rs b/libs/snapshot_creator/src/main.rs index dd14873b7..ad7330484 100644 --- a/libs/snapshot_creator/src/main.rs +++ b/libs/snapshot_creator/src/main.rs @@ -1,7 +1,7 @@ use deno_core::JsRuntimeForSnapshot; fn main() { - let runtime = JsRuntimeForSnapshot::new(Default::default(), Default::default()); + let runtime = JsRuntimeForSnapshot::new(Default::default()); let snapshot = runtime.snapshot(); let snapshot_slice: &[u8] = &*snapshot; diff --git a/patch-db b/patch-db index 8aeded332..6af2221ad 160000 --- a/patch-db +++ b/patch-db @@ -1 +1 @@ -Subproject commit 8aeded332160508dcfbf49268c42e3733fe734c3 +Subproject commit 6af2221add56f0a557b37a268ef9fb2299a05255 diff --git a/system-images/compat/Cargo.lock b/system-images/compat/Cargo.lock index 0d378082f..0b036859d 100644 --- a/system-images/compat/Cargo.lock +++ b/system-images/compat/Cargo.lock @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" dependencies = [ "cfg-if", - "cipher", + "cipher 0.3.0", "cpufeatures", "ctr", "opaque-debug", @@ -42,10 +42,22 @@ dependencies = [ ] [[package]] -name = "aho-corasick" -version = "0.7.20" +name = "ahash" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom 0.2.8", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -65,6 +77,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -126,9 +144,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.3.15" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +checksum = "f658e2baef915ba0f26f1f7c42bfb8e12f532a01f449a090ded75ae7a07e9ba2" dependencies = [ "brotli", "flate2", @@ -140,41 +158,42 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "atoi" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" dependencies = [ "num-traits", ] @@ -213,9 +232,9 @@ dependencies = [ [[package]] name = "base16ct" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base32" @@ -231,15 +250,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64ct" -version = "1.5.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-cookies" @@ -302,12 +321,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bitmaps" -version = "2.1.0" +name = "bitflags" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" dependencies = [ - "typenum", + "serde", ] [[package]] @@ -336,7 +355,7 @@ checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" dependencies = [ "arrayref", "arrayvec", - "constant_time_eq", + "constant_time_eq 0.1.5", ] [[package]] @@ -364,44 +383,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" -[[package]] -name = "bollard" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82e7850583ead5f8bbef247e2a3c37a19bd576e8420cd262a6711921827e1e5" -dependencies = [ - "base64 0.13.1", - "bollard-stubs", - "bytes", - "futures-core", - "futures-util", - "hex", - "http", - "hyper", - "hyperlocal", - "log", - "pin-project-lite", - "serde", - "serde_derive", - "serde_json", - "serde_urlencoded", - "thiserror", - "tokio", - "tokio-util", - "url", - "winapi", -] - -[[package]] -name = "bollard-stubs" -version = "1.42.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" -dependencies = [ - "serde", - "serde_with 1.14.0", -] - [[package]] name = "brotli" version = "3.3.4" @@ -431,16 +412,10 @@ checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", - "regex-automata", + "regex-automata 0.1.10", "serde", ] -[[package]] -name = "build_const" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" - [[package]] name = "bumpalo" version = "3.12.0" @@ -461,9 +436,12 @@ checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -473,18 +451,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "serde", - "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -493,14 +470,14 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23170228b96236b5a7299057ac284a321457700bc8c41a4476052f0f4ba5349d" dependencies = [ - "hashbrown", + "hashbrown 0.12.3", ] [[package]] name = "ciborium" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" dependencies = [ "ciborium-io", "ciborium-ll", @@ -509,15 +486,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" [[package]] name = "ciborium-ll" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" dependencies = [ "ciborium-io", "half", @@ -532,6 +509,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "2.34.0" @@ -540,7 +527,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim 0.8.0", "textwrap 0.11.0", "unicode-width", @@ -549,14 +536,14 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_lex", - "indexmap", + "indexmap 1.9.2", "strsim 0.10.0", "termcolor", "textwrap 0.16.0", @@ -593,7 +580,7 @@ dependencies = [ "indenter", "once_cell", "owo-colors", - "tracing-error 0.2.0", + "tracing-error", ] [[package]] @@ -605,7 +592,7 @@ dependencies = [ "once_cell", "owo-colors", "tracing-core", - "tracing-error 0.2.0", + "tracing-error", ] [[package]] @@ -618,7 +605,8 @@ dependencies = [ "dashmap", "emver", "failure", - "indexmap", + "imbl-value", + "indexmap 1.9.2", "itertools 0.10.5", "lazy_static", "linear-map", @@ -628,7 +616,7 @@ dependencies = [ "pest_derive", "rand 0.8.5", "regex", - "rust-argon2", + "rust-argon2 1.0.0", "serde", "serde_json", "serde_yaml 0.8.26", @@ -645,10 +633,43 @@ dependencies = [ ] [[package]] -name = "const-oid" -version = "0.9.1" +name = "console" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode 0.3.6", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "const_format" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] [[package]] name = "constant_time_eq" @@ -656,12 +677,27 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[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 = "cookie" version = "0.16.2" @@ -669,7 +705,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.3.17", + "time", + "version_check", +] + +[[package]] +name = "cookie" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "cookie" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cd91cf61412820176e137621345ee43b3f4423e589e7ae4e50d601d93e35ef8" +dependencies = [ + "time", "version_check", ] @@ -679,29 +736,30 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd" dependencies = [ - "cookie", + "cookie 0.16.2", "idna 0.2.3", "log", "publicsuffix", "serde", "serde_json", - "time 0.3.17", + "time", "url", ] [[package]] name = "cookie_store" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca9b3c618262fc0c85ecbc814c144e04be9c6eec08b315e7cd1cfbe0bb6ca84" +checksum = "387461abbc748185c3a6e1673d826918b450b87ff22639429c694619a83b6cf6" dependencies = [ - "cookie", + "cookie 0.17.0", "idna 0.3.0", "log", "publicsuffix", "serde", + "serde_derive", "serde_json", - "time 0.3.17", + "time", "url", ] @@ -723,22 +781,13 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -dependencies = [ - "build_const", -] - [[package]] name = "crc" version = "3.0.0" @@ -790,9 +839,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.4.9" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -848,7 +897,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" dependencies = [ - "cipher", + "cipher 0.3.0", ] [[package]] @@ -870,6 +919,34 @@ dependencies = [ "zeroize", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "cxx" version = "1.0.86" @@ -891,8 +968,8 @@ dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "scratch", "syn 1.0.107", ] @@ -909,79 +986,44 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", ] [[package]] name = "darling" -version = "0.13.4" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" -dependencies = [ - "darling_core 0.14.2", - "darling_macro 0.14.2", + "darling_core", + "darling_macro", ] [[package]] name = "darling_core" -version = "0.13.4" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "strsim 0.10.0", - "syn 1.0.107", -] - -[[package]] -name = "darling_core" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2 1.0.50", - "quote 1.0.23", - "strsim 0.10.0", - "syn 1.0.107", + "syn 2.0.37", ] [[package]] name = "darling_macro" -version = "0.13.4" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core 0.13.4", - "quote 1.0.23", - "syn 1.0.107", -] - -[[package]] -name = "darling_macro" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" -dependencies = [ - "darling_core 0.14.2", - "quote 1.0.23", - "syn 1.0.107", + "darling_core", + "quote", + "syn 2.0.37", ] [[package]] @@ -991,10 +1033,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.12.3", "lock_api", "once_cell", - "parking_lot_core 0.9.6", + "parking_lot_core", ] [[package]] @@ -1005,9 +1047,9 @@ checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" [[package]] name = "der" -version = "0.6.1" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "pem-rfc7468", @@ -1020,9 +1062,9 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", - "proc-macro2 1.0.50", - "quote 1.0.23", + "convert_case 0.4.0", + "proc-macro2", + "quote", "rustc_version", "syn 1.0.107", ] @@ -1044,9 +1086,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.3", "const-oid", @@ -1054,15 +1096,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs-next" version = "2.0.0" @@ -1073,17 +1106,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1107,6 +1129,15 @@ version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03d8c417d7a8cb362e0c37e5d815f5eb7c37f79ff93707329d5a194e42e54ca0" +[[package]] +name = "drain" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f1a0abf3fcefad9b4dd0e414207a7408e12b68414a01e6bb19b897d5bd7632d" +dependencies = [ + "tokio", +] + [[package]] name = "dyn-clone" version = "1.0.12" @@ -1115,26 +1146,16 @@ checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" [[package]] name = "ecdsa" -version = "0.14.8" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12844141594ad74185a926d030f3b605f6a903b4e3fec351f3ea338ac5b7637e" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ "der", + "digest 0.10.7", "elliptic-curve", "rfc6979", "signature 2.0.0", + "spki", ] [[package]] @@ -1142,10 +1163,19 @@ name = "ed25519" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "serde", - "signature 1.6.4", + "signature 2.0.0", ] [[package]] @@ -1154,15 +1184,29 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek", - "ed25519", + "curve25519-dalek 3.2.0", + "ed25519 1.5.3", "rand 0.7.3", "serde", - "serde_bytes", "sha2 0.9.9", "zeroize", ] +[[package]] +name = "ed25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +dependencies = [ + "curve25519-dalek 4.1.1", + "ed25519 2.2.3", + "rand_core 0.6.4", + "serde", + "sha2 0.10.8", + "signature 2.0.0", + "zeroize", +] + [[package]] name = "either" version = "1.8.0" @@ -1174,14 +1218,13 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.12.3" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" dependencies = [ "base16ct", "crypto-bigint", - "der", - "digest 0.10.6", + "digest 0.10.7", "ff", "generic-array", "group", @@ -1201,17 +1244,17 @@ dependencies = [ "color-eyre", "futures", "helpers", - "imbl 2.0.0", - "nix 0.25.1", + "imbl", + "nix 0.27.1", "procfs", "serde", "serde_json", "tokio", "tokio-stream", "tracing", - "tracing-error 0.2.0", + "tracing-error", "tracing-futures", - "tracing-subscriber 0.3.16", + "tracing-subscriber", "yajrc 0.1.0 (git+https://github.com/dr-bonez/yajrc.git?branch=develop)", ] @@ -1235,6 +1278,12 @@ dependencies = [ "log", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -1250,37 +1299,37 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - [[package]] name = "enum-as-inner" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ - "heck 0.4.0", - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "heck", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "env_logger" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "atty", "humantime", + "is-terminal", "log", "regex", "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.2.8" @@ -1302,6 +1351,17 @@ dependencies = [ "libc", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1334,8 +1394,8 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", "synstructure", ] @@ -1360,14 +1420,20 @@ dependencies = [ [[package]] name = "ff" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", "subtle", ] +[[package]] +name = "fiat-crypto" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" + [[package]] name = "filetime" version = "0.2.19" @@ -1396,6 +1462,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1419,9 +1496,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -1443,9 +1520,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -1458,9 +1535,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -1468,15 +1545,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -1485,49 +1562,49 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.11.2", + "parking_lot", ] [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -1543,12 +1620,13 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1579,45 +1657,23 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" -[[package]] -name = "git-version" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" -dependencies = [ - "git-version-macro", - "proc-macro-hack", -] - -[[package]] -name = "git-version-macro" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", -] - [[package]] name = "gpt" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd7365d734a70ac5dd7be791b0c96083852188df015b8c665bb2dadb108a743" +checksum = "8283e7331b8c93b9756e0cfdbcfb90312852f953c6faf9bf741e684cc3b6ad69" dependencies = [ - "bitflags", - "crc 1.8.1", + "bitflags 2.4.1", + "crc", "log", - "uuid 0.8.2", + "uuid", ] [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core 0.6.4", @@ -1626,9 +1682,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.15" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -1636,7 +1692,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.2", "slab", "tokio", "tokio-util", @@ -1655,32 +1711,38 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.6", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" + [[package]] name = "hashlink" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" dependencies = [ - "hashbrown", + "hashbrown 0.12.3", ] [[package]] name = "heck" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -1764,14 +1826,23 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", ] [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", @@ -1809,9 +1880,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -1824,7 +1895,7 @@ dependencies = [ "httpdate", "itoa 1.0.5", "pin-project-lite", - "socket2", + "socket2 0.4.7", "tokio", "tower-service", "tracing", @@ -1846,12 +1917,12 @@ dependencies = [ [[package]] name = "hyper-ws-listener" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3fb761e568fdb34ff794d284bfe1769efc5d16b9d716286451ab3a70ab82bea" +checksum = "dcbfe4981e45b0a7403a55d4af12f8d30e173e722409658c3857243990e72180" dependencies = [ "anyhow", - "base64 0.13.1", + "base64 0.21.4", "env_logger", "futures", "hyper", @@ -1861,19 +1932,6 @@ dependencies = [ "tokio-tungstenite", ] -[[package]] -name = "hyperlocal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" -dependencies = [ - "futures-util", - "hex", - "hyper", - "pin-project", - "tokio", -] - [[package]] name = "iana-time-zone" version = "0.1.53" @@ -1935,29 +1993,26 @@ dependencies = [ ] [[package]] -name = "imbl" -version = "1.0.1" +name = "idna" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "543682c9082b25e63d03b5acbd65ad111fd49dd93e70843e5175db4ff81d606b" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ - "bitmaps 2.1.0", - "rand_core 0.6.4", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "imbl" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2806b69cd9f4664844027b64465eacb444c67c1db9c778e341adff0c25cdb0d" +checksum = "85b4555023847ca2cd6fd11f20b553886e6981c7e8aee9b3e7e960b4b17fb440" dependencies = [ - "bitmaps 3.2.0", + "bitmaps", "imbl-sized-chunks", "rand_core 0.6.4", "rand_xoshiro", + "serde", "version_check", ] @@ -1967,7 +2022,19 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" dependencies = [ - "bitmaps 3.2.0", + "bitmaps", +] + +[[package]] +name = "imbl-value" +version = "0.1.0" +source = "git+https://github.com/Start9Labs/imbl-value.git#929395141c3a882ac366c12ac9402d0ebaa2201b" +dependencies = [ + "imbl", + "serde", + "serde_json", + "treediff", + "yasi", ] [[package]] @@ -1985,8 +2052,8 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", ] [[package]] @@ -2002,10 +2069,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", "serde", ] +[[package]] +name = "indexmap" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +dependencies = [ + "equivalent", + "hashbrown 0.14.1", + "serde", +] + +[[package]] +name = "indicatif" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "tokio", + "unicode-width", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -2015,20 +2116,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "internment" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a798d7677f07d6f1e77be484ea8626ddb1566194de399f1206306820c406371" -dependencies = [ - "ahash", - "dashmap", - "hashbrown", - "once_cell", - "parking_lot 0.12.1", - "serde", -] - [[package]] name = "io-lifetimes" version = "1.0.4" @@ -2041,9 +2128,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" dependencies = [ "serde", ] @@ -2107,6 +2194,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -2125,10 +2221,10 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb52eeac20f256459e909bd4a03bb8c4fab6a1fdbb8ed52d00f644152df48ece" dependencies = [ - "ahash", + "ahash 0.7.6", "dyn-clone", "hifijson", - "indexmap", + "indexmap 1.9.2", "itertools 0.10.5", "jaq-parse", "log", @@ -2159,12 +2255,12 @@ dependencies = [ [[package]] name = "josekit" -version = "0.8.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee6af62ad98bdf699ad2ecc8323479a1fdc7aa5faa6043d93119d83f6c5fca8" +checksum = "5754487a088f527b1407df470db8e654e4064dccbbe1fe850e0773721e9962b7" dependencies = [ "anyhow", - "base64 0.13.1", + "base64 0.21.4", "flate2", "once_cell", "openssl", @@ -2172,7 +2268,7 @@ dependencies = [ "serde", "serde_json", "thiserror", - "time 0.3.17", + "time", ] [[package]] @@ -2188,9 +2284,9 @@ dependencies = [ name = "json-patch" version = "0.2.7-alpha.0" dependencies = [ + "imbl-value", "json-ptr", "serde", - "serde_json", "treediff", ] @@ -2198,17 +2294,18 @@ dependencies = [ name = "json-ptr" version = "0.1.0" dependencies = [ + "imbl", + "imbl-value", "serde", - "serde_json", "thiserror", ] [[package]] name = "jsonpath_lib" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" +source = "git+https://github.com/Start9Labs/jsonpath.git#1cacbd64afa2e1941a21fef06bad14317ba92f30" dependencies = [ + "imbl-value", "log", "serde", "serde_json", @@ -2239,11 +2336,11 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.6.28", "string_cache", "term", "tiny-keccak", - "unicode-xid 0.2.4", + "unicode-xid", ] [[package]] @@ -2271,14 +2368,14 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] [[package]] name = "libc" -version = "0.2.139" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libm" @@ -2286,6 +2383,17 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linear-map" version = "1.2.0" @@ -2329,12 +2437,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "matchers" @@ -2342,7 +2447,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -2353,9 +2458,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mbrman" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b239f4755d00466e3ac1d55ddeaf77a66c7580352fc6cbc40d56c218fc94a9" +checksum = "9c487024623ae38584610237dd1be8932bb2b324474b23c37a25f9fbe6bf5e9e" dependencies = [ "bincode", "bitvec", @@ -2364,31 +2469,20 @@ dependencies = [ "thiserror", ] -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "md-5" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -2399,6 +2493,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -2422,25 +2525,23 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] name = "models" version = "0.1.0" dependencies = [ - "bollard", + "base64 0.21.4", "color-eyre", - "ed25519-dalek", + "ed25519-dalek 2.0.0", "emver", - "internment", "ipnet", "lazy_static", "mbrman", @@ -2448,6 +2549,7 @@ dependencies = [ "patch-db", "rand 0.8.5", "regex", + "reqwest", "rpc-toolkit", "serde", "serde_json", @@ -2457,6 +2559,7 @@ dependencies = [ "tokio", "torut", "tracing", + "yasi", ] [[package]] @@ -2493,38 +2596,16 @@ dependencies = [ "unicase", ] -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nix" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" -dependencies = [ - "bitflags", - "cc", - "cfg-if", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", ] [[package]] @@ -2534,13 +2615,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", - "memoffset", + "memoffset 0.6.5", "pin-utils", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "pin-utils", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + [[package]] name = "nom" version = "7.1.3" @@ -2563,9 +2668,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -2605,9 +2710,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" dependencies = [ "num-traits", ] @@ -2667,25 +2772,31 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.7" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.7" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.30.2" @@ -2697,9 +2808,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -2709,24 +2820,24 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssh-keys" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7249a699cdeea261ac73f1bf9350777cb867324f44373aafb5a287365bf1771" +checksum = "c75a0ec2d1b302412fb503224289325fcc0e44600176864804c7211b055cfd58" dependencies = [ - "base64 0.13.1", + "base64 0.21.4", "byteorder", - "md-5 0.9.1", - "sha2 0.9.9", + "md-5", + "sha2 0.10.8", "thiserror", ] [[package]] name = "openssl" -version = "0.10.45" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -2741,8 +2852,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", ] @@ -2754,20 +2865,19 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.24.0+1.1.1s" +version = "300.1.5+3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd" +checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.80" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ - "autocfg", "cc", "libc", "openssl-src", @@ -2795,47 +2905,26 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "p256" -version = "0.11.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve", - "sha2 0.10.6", -] - -[[package]] -name = "p256" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c124b3cbce43bcbac68c58ec181d98ed6cc7e6d0aa7c3ba97b2563410b0e55" -dependencies = [ - "ecdsa 0.15.1", + "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] name = "p384" -version = "0.11.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" dependencies = [ - "ecdsa 0.14.8", + "ecdsa", "elliptic-curve", - "sha2 0.10.6", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "primeorder", + "sha2 0.10.8", ] [[package]] @@ -2845,21 +2934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.6", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -2875,17 +2950,6 @@ dependencies = [ "windows-sys 0.42.0", ] -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "paste" version = "1.0.11" @@ -2899,19 +2963,19 @@ dependencies = [ "async-trait", "fd-lock-rs", "futures", - "imbl 1.0.1", + "imbl", + "imbl-value", "json-patch", "json-ptr", "lazy_static", - "nix 0.23.2", + "nix 0.26.4", "patch-db-macro", "serde", "serde_cbor 0.11.1", - "serde_json", "thiserror", "tokio", "tracing", - "tracing-error 0.1.2", + "tracing-error", ] [[package]] @@ -2919,7 +2983,7 @@ name = "patch-db-macro" version = "0.1.0" dependencies = [ "patch-db-macro-internals", - "proc-macro2 1.0.50", + "proc-macro2", "syn 1.0.107", ] @@ -2927,38 +2991,36 @@ dependencies = [ name = "patch-db-macro-internals" version = "0.1.0" dependencies = [ - "heck 0.3.3", - "proc-macro2 1.0.50", - "quote 1.0.23", + "heck", + "proc-macro2", + "quote", "syn 1.0.107", ] [[package]] name = "pbkdf2" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "hmac 0.12.1", - "password-hash", - "sha2 0.10.6", ] [[package]] name = "pem-rfc7468" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" @@ -2988,8 +3050,8 @@ checksum = "46b53634d8c8196302953c74d5352f33d0c512a9499bd2ce468fc9f4128fa27c" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", ] @@ -3001,7 +3063,7 @@ checksum = "0ef4f1332a8d4678b41966bb4cc1d0676880e84183a1ecc3f4b69f03e99c7a51" dependencies = [ "once_cell", "pest", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] @@ -3011,7 +3073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.2", ] [[package]] @@ -3031,29 +3093,29 @@ checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -3063,21 +3125,20 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs1" -version = "0.4.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ "der", "pkcs8", "spki", - "zeroize", ] [[package]] name = "pkcs8" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", @@ -3089,6 +3150,18 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "platforms" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" + +[[package]] +name = "portable-atomic" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -3108,7 +3181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" dependencies = [ "csv", - "encode_unicode", + "encode_unicode 1.0.0", "is-terminal", "lazy_static", "term", @@ -3117,9 +3190,9 @@ dependencies = [ [[package]] name = "primeorder" -version = "0.12.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b54f7131b3dba65a2f414cf5bd25b66d4682e4608610668eae785750ba4c5b2" +checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" dependencies = [ "elliptic-curve", ] @@ -3132,40 +3205,25 @@ checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ "once_cell", "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid 0.1.0", + "toml 0.5.10", ] [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.14.2" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" +checksum = "943ca7f9f29bab5844ecd8fdb3992c5969b6622bb9609b9502fef9b4310e3f1f" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "chrono", "flate2", @@ -3176,33 +3234,33 @@ dependencies = [ [[package]] name = "proptest" -version = "1.0.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", - "bitflags", - "byteorder", + "bit-vec", + "bitflags 2.4.1", "lazy_static", "num-traits", - "quick-error 2.0.1", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.7.5", "rusty-fork", "tempfile", + "unarray", ] [[package]] name = "proptest-derive" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90b46295382dc76166cb7cf2bb4a97952464e4b7ed5a43e6cd34e1fec3349ddc" +checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2", + "quote", + "syn 1.0.107", ] [[package]] @@ -3227,28 +3285,13 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quote" -version = "0.6.13" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 0.4.30", -] - -[[package]] -name = "quote" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" -dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2", ] [[package]] @@ -3257,16 +3300,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - [[package]] name = "rand" version = "0.7.3" @@ -3368,7 +3401,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3384,13 +3417,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -3399,7 +3433,18 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.28", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", ] [[package]] @@ -3408,6 +3453,18 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -3419,13 +3476,13 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.13.1", + "base64 0.21.4", "bytes", - "cookie", + "cookie 0.16.2", "cookie_store 0.16.1", "encoding_rs", "futures-core", @@ -3443,10 +3500,10 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "proc-macro-hack", "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-socks", @@ -3455,32 +3512,31 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "winreg", ] [[package]] name = "reqwest_cookie_store" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06b407c05de7a0f7e4cc2a56af5e9bd6468e509124e81078ce1f8bc2ed3536bf" +checksum = "ba529055ea150e42e4eb9c11dcd380a41025ad4d594b0cb4904ef28b037e1061" dependencies = [ "bytes", - "cookie", - "cookie_store 0.19.0", + "cookie_store 0.20.0", "reqwest", "url", ] [[package]] name = "rfc6979" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "crypto-bigint", "hmac 0.12.1", - "zeroize", + "subtle", ] [[package]] @@ -3492,7 +3548,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -3515,7 +3571,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5353673ffd8265292281141560d2b851e4da49e83e2f5e255fd473736d45ee10" dependencies = [ - "clap 3.2.23", + "clap 3.2.25", "futures", "hyper", "lazy_static", @@ -3537,7 +3593,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8e4b9cb00baf2d61bcd35e98d67dcb760382a3b4540df7e63b38d053c8a7b8b" dependencies = [ - "proc-macro2 1.0.50", + "proc-macro2", "rpc-toolkit-macro-internals", "syn 1.0.107", ] @@ -3548,19 +3604,20 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e2ce21b936feaecdab9c9a8e75b9dca64374ccc11951a58045ad6559b75f42" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", ] [[package]] name = "rsa" -version = "0.7.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" dependencies = [ "byteorder", - "digest 0.10.6", + "const-oid", + "digest 0.10.7", "num-bigint-dig", "num-integer", "num-iter", @@ -3568,8 +3625,9 @@ dependencies = [ "pkcs1", "pkcs8", "rand_core 0.6.4", - "signature 1.6.4", - "smallvec", + "sha2 0.10.8", + "signature 2.0.0", + "spki", "subtle", "zeroize", ] @@ -3592,10 +3650,21 @@ checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" dependencies = [ "base64 0.13.1", "blake2b_simd", - "constant_time_eq", + "constant_time_eq 0.1.5", "crossbeam-utils", ] +[[package]] +name = "rust-argon2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e71971821b3ae0e769e4a4328dbcb517607b434db7697e9aba17203ec14e46a" +dependencies = [ + "base64 0.21.4", + "blake2b_simd", + "constant_time_eq 0.3.0", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -3617,7 +3686,7 @@ version = "0.36.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -3627,14 +3696,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -3643,7 +3712,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.0", + "base64 0.21.4", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +dependencies = [ + "ring", + "untrusted", ] [[package]] @@ -3659,7 +3738,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ "fnv", - "quick-error 1.2.3", + "quick-error", "tempfile", "wait-timeout", ] @@ -3703,9 +3782,9 @@ dependencies = [ [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", @@ -3721,7 +3800,7 @@ version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -3762,15 +3841,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_bytes" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819" -dependencies = [ - "serde", -] - [[package]] name = "serde_cbor" version = "0.11.1" @@ -3795,8 +3865,8 @@ version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", ] @@ -3806,12 +3876,21 @@ version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "indexmap", + "indexmap 1.9.2", "itoa 1.0.5", "ryu", "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "serde_test" version = "1.0.152" @@ -3835,52 +3914,31 @@ dependencies = [ [[package]] name = "serde_with" -version = "1.14.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "serde", - "serde_with_macros 1.5.2", -] - -[[package]] -name = "serde_with" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d904179146de381af4c93d3af6ca4984b3152db687dacb9c3c35e86f39809c" -dependencies = [ - "base64 0.13.1", + "base64 0.21.4", "chrono", "hex", - "indexmap", + "indexmap 1.9.2", + "indexmap 2.0.2", "serde", "serde_json", - "serde_with_macros 2.2.0", - "time 0.3.17", + "serde_with_macros", + "time", ] [[package]] name = "serde_with_macros" -version = "1.5.2" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ - "darling 0.13.4", - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", -] - -[[package]] -name = "serde_with_macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1966009f3c05f095697c537312f5415d1e3ed31ce0a56942bac4c771c5c335e" -dependencies = [ - "darling 0.14.2", - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "darling", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] @@ -3889,7 +3947,7 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", + "indexmap 1.9.2", "ryu", "serde", "yaml-rust", @@ -3897,11 +3955,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.16" +version = "0.9.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" +checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" dependencies = [ - "indexmap", + "indexmap 2.0.2", "itoa 1.0.5", "ryu", "serde", @@ -3916,7 +3974,7 @@ checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3927,7 +3985,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3945,13 +4003,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3989,10 +4047,6 @@ name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.6", - "rand_core 0.6.4", -] [[package]] name = "signature" @@ -4000,7 +4054,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -4021,16 +4075,6 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps 2.1.0", - "typenum", -] - [[package]] name = "slab" version = "0.4.7" @@ -4056,6 +4100,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -4063,10 +4117,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "spki" -version = "0.6.0" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", "der", @@ -4085,161 +4148,304 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" +checksum = "0e50c216e3624ec8e7ecd14c6a6a6370aad6ee5d8cfc3ab30b5162eeeef2ed33" dependencies = [ "sqlx-core", "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", ] [[package]] name = "sqlx-core" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d" dependencies = [ - "ahash", + "ahash 0.8.3", "atoi", - "base64 0.13.1", - "bitflags", "byteorder", "bytes", "chrono", - "crc 3.0.0", + "crc", "crossbeam-queue", - "dirs", "dotenvy", "either", "event-listener", "futures-channel", "futures-core", "futures-intrusive", + "futures-io", "futures-util", "hashlink", "hex", - "hkdf", - "hmac 0.12.1", - "indexmap", - "itoa 1.0.5", - "libc", + "indexmap 2.0.2", "log", - "md-5 0.10.5", "memchr", "once_cell", "paste", "percent-encoding", - "rand 0.8.5", "rustls", "rustls-pemfile", "serde", "serde_json", - "sha1", - "sha2 0.10.6", + "sha2 0.10.8", "smallvec", "sqlformat", - "sqlx-rt", - "stringprep", "thiserror", + "tokio", "tokio-stream", + "tracing", "url", "webpki-roots", - "whoami", ] [[package]] name = "sqlx-macros" -version = "0.6.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" +checksum = "9a793bb3ba331ec8359c1853bd39eed32cdd7baaf22c35ccf5c92a7e8d1189ec" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.107", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4ee1e104e00dedb6aa5ffdd1343107b0a4702e862a84320ee7cc74782d96fc" dependencies = [ "dotenvy", "either", - "heck 0.4.0", + "heck", "hex", "once_cell", - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "sqlx-core", - "sqlx-rt", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", "syn 1.0.107", + "tempfile", + "tokio", "url", ] [[package]] -name = "sqlx-rt" -version = "0.6.2" +name = "sqlx-mysql" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" +checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db" dependencies = [ + "atoi", + "base64 0.21.4", + "bitflags 2.4.1", + "byteorder", + "bytes", + "chrono", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac 0.12.1", + "itoa 1.0.5", + "log", + "md-5", + "memchr", "once_cell", - "tokio", - "tokio-rustls", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624" +dependencies = [ + "atoi", + "base64 0.21.4", + "bitflags 2.4.1", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac 0.12.1", + "home", + "itoa 1.0.5", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59dc83cf45d89c555a577694534fcd1b55c545a816c816ce51f20bbe56a4f3f" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", +] + +[[package]] +name = "sscanf" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c713ebd15ce561dd4a13ed62bc2a0368e16806fc30dcaf66ecf1256b2a3fdde6" +dependencies = [ + "const_format", + "lazy_static", + "regex", + "sscanf_macro", +] + +[[package]] +name = "sscanf_macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84955aa74a157e5834d58a07be11af7f0ab923f0194a0bb2ea6b3db8b5d1611d" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "regex-syntax 0.6.28", + "strsim 0.10.0", + "syn 2.0.37", + "unicode-width", +] + +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher 0.4.4", + "ssh-encoding", ] [[package]] name = "ssh-encoding" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19cfdc32e0199062113edf41f344fbf784b8205a94600233c84eb838f45191e1" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" dependencies = [ "base64ct", "pem-rfc7468", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] name = "ssh-key" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288d8f5562af5a3be4bda308dd374b2c807b940ac370b5efa1c99311da91d9a1" +checksum = "2180b3bc4955efd5661a97658d3cf4c8107e0d132f619195afe9486c13cca313" dependencies = [ - "ed25519-dalek", - "p256 0.11.1", + "ed25519-dalek 2.0.0", + "p256", "p384", "rand_core 0.6.4", "rsa", "sec1", - "sha2 0.10.6", - "signature 1.6.4", + "sha2 0.10.8", + "signature 2.0.0", + "ssh-cipher", "ssh-encoding", + "subtle", "zeroize", ] [[package]] name = "start-os" -version = "0.3.4-rev.4" +version = "0.3.5" dependencies = [ "aes", "async-compression", "async-stream", "async-trait", "base32", - "base64 0.13.1", + "base64 0.21.4", "base64ct", "basic-cookies", - "bollard", "bytes", "chrono", "ciborium", - "clap 3.2.23", + "clap 3.2.25", "color-eyre", - "cookie", - "cookie_store 0.19.0", + "console", + "cookie 0.18.0", + "cookie_store 0.20.0", "current_platform", - "digest 0.10.6", - "digest 0.9.0", + "digest 0.10.7", "divrem", - "ed25519", - "ed25519-dalek", + "ed25519 2.2.3", + "ed25519-dalek 1.0.1", + "ed25519-dalek 2.0.0", "embassy_container_init", "emver", "fd-lock-rs", "futures", - "git-version", "gpt", "helpers", "hex", @@ -4247,13 +4453,15 @@ dependencies = [ "http", "hyper", "hyper-ws-listener", - "imbl 2.0.0", + "imbl", + "imbl-value", "include_dir", - "indexmap", + "indexmap 2.0.2", + "indicatif", "ipnet", "iprange", "isocountry", - "itertools 0.10.5", + "itertools 0.11.0", "jaq-core", "jaq-std", "josekit", @@ -4264,13 +4472,13 @@ dependencies = [ "mbrman", "models", "new_mime_guess", - "nix 0.25.1", + "nix 0.27.1", "nom", "num", "num_enum", "openssh-keys", "openssl", - "p256 0.12.0", + "p256", "patch-db", "pbkdf2", "pin-project", @@ -4278,23 +4486,22 @@ dependencies = [ "prettytable-rs", "proptest", "proptest-derive", - "rand 0.7.3", "rand 0.8.5", "regex", "reqwest", "reqwest_cookie_store", "rpassword", "rpc-toolkit", - "rust-argon2", + "rust-argon2 2.0.0", "scopeguard", "serde", "serde_json", - "serde_with 2.2.0", - "serde_yaml 0.9.16", - "sha2 0.10.6", - "sha2 0.9.9", + "serde_with", + "serde_yaml 0.9.25", + "sha2 0.10.8", "simple-logging", "sqlx", + "sscanf", "ssh-key", "stderrlog", "tar", @@ -4306,17 +4513,18 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml", + "toml 0.8.2", "torut", "tracing", - "tracing-error 0.2.0", + "tracing-error", "tracing-futures", - "tracing-subscriber 0.3.16", + "tracing-journald", + "tracing-subscriber", "trust-dns-server", "typed-builder", "url", "urlencoding", - "uuid 1.2.2", + "uuid", "zeroize", ] @@ -4341,7 +4549,7 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "phf_shared", "precomputed-hash", ] @@ -4374,25 +4582,25 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] - [[package]] name = "syn" version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote", "unicode-ident", ] @@ -4402,10 +4610,31 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", - "unicode-xid 0.2.4", + "unicode-xid", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -4416,13 +4645,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", - "xattr", + "xattr 1.0.1", ] [[package]] @@ -4476,22 +4705,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] @@ -4514,17 +4743,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.17" @@ -4578,40 +4796,39 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.24.1" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.4", "tokio-macros", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -4619,13 +4836,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] @@ -4642,9 +4858,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -4663,14 +4879,14 @@ dependencies = [ "redox_syscall 0.2.16", "tokio", "tokio-stream", - "xattr", + "xattr 0.2.3", ] [[package]] name = "tokio-tungstenite" -version = "0.17.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", @@ -4682,9 +4898,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", @@ -4703,6 +4919,65 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "torut" version = "0.2.1" @@ -4712,7 +4987,7 @@ dependencies = [ "base32", "base64 0.13.1", "derive_more", - "ed25519-dalek", + "ed25519-dalek 1.0.1", "hex", "hmac 0.11.0", "rand 0.7.3", @@ -4731,11 +5006,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" dependencies = [ - "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4743,35 +5018,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-error" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" -dependencies = [ - "tracing", - "tracing-subscriber 0.2.25", -] - [[package]] name = "tracing-error" version = "0.2.0" @@ -4779,7 +5044,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" dependencies = [ "tracing", - "tracing-subscriber 0.3.16", + "tracing-subscriber", ] [[package]] @@ -4792,6 +5057,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-journald" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd" +dependencies = [ + "libc", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.1.3" @@ -4805,20 +5081,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.2.25" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" -dependencies = [ - "sharded-slab", - "thread_local", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -4841,31 +5106,11 @@ dependencies = [ "serde_json", ] -[[package]] -name = "trust-dns-client" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c408c32e6a9dbb38037cece35740f2cf23c875d8ca134d33631cec83f74d3fe" -dependencies = [ - "cfg-if", - "data-encoding", - "futures-channel", - "futures-util", - "lazy_static", - "radix_trie", - "rand 0.8.5", - "thiserror", - "time 0.3.17", - "tokio", - "tracing", - "trust-dns-proto", -] - [[package]] name = "trust-dns-proto" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" +checksum = "559ac980345f7f5020883dd3bcacf176355225e01916f8c2efecad7534f682c6" dependencies = [ "async-trait", "cfg-if", @@ -4874,9 +5119,9 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna 0.2.3", + "idna 0.4.0", "ipnet", - "lazy_static", + "once_cell", "rand 0.8.5", "smallvec", "thiserror", @@ -4888,23 +5133,23 @@ dependencies = [ [[package]] name = "trust-dns-server" -version = "0.22.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cf9f8a359c9f16fdf760b79cb2be3f261b98db8027f81959c7a4f6645e2c" +checksum = "f4307166910ddf09378e651e9d4730c44900e9e0e1f157a6b955e48b539cd1d6" dependencies = [ "async-trait", "bytes", "cfg-if", + "drain", "enum-as-inner", "futures-executor", "futures-util", "serde", "thiserror", - "time 0.3.17", + "time", "tokio", - "toml", + "toml 0.7.8", "tracing", - "trust-dns-client", "trust-dns-proto", ] @@ -4916,19 +5161,19 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" -version = "0.17.3" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", "native-tls", "rand 0.8.5", - "sha-1", + "sha1", "thiserror", "url", "utf-8", @@ -4936,13 +5181,22 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.10.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" +checksum = "b1c6a006a6d3d6a6f143fda41cf4d1ad35110080687628c9f2117bd3cc7924f3" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", - "syn 1.0.107", + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fa054ee5e2346187d631d2f1d1fd3b33676772d6d03a2d84e1c5213b31674ee" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", ] [[package]] @@ -4957,6 +5211,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicase" version = "2.6.0" @@ -4968,9 +5228,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" @@ -4999,12 +5259,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "unicode-xid" version = "0.2.4" @@ -5019,9 +5273,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "unsafe-libyaml" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" [[package]] name = "untrusted" @@ -5031,21 +5285,21 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", - "idna 0.3.0", + "idna 0.4.0", "percent-encoding", "serde", ] [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf-8" @@ -5055,18 +5309,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "0.8.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom 0.2.8", -] - -[[package]] -name = "uuid" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ "getrandom 0.2.8", ] @@ -5120,12 +5365,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5151,8 +5390,8 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", "wasm-bindgen-shared", ] @@ -5175,7 +5414,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.23", + "quote", "wasm-bindgen-macro-support", ] @@ -5185,8 +5424,8 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -5198,6 +5437,19 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +[[package]] +name = "wasm-streams" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.60" @@ -5208,23 +5460,13 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki-roots" -version = "0.22.6" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" dependencies = [ - "webpki", + "rustls-webpki", ] [[package]] @@ -5232,10 +5474,6 @@ name = "whoami" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45dbc71f0cdca27dc261a9bd37ddec174e4a0af2b900b890f378460f745426e3" -dependencies = [ - "wasm-bindgen", - "web-sys", -] [[package]] name = "winapi" @@ -5274,13 +5512,13 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", ] [[package]] @@ -5289,7 +5527,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -5298,13 +5545,28 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -5313,36 +5575,72 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_i686_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_msvc" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_x86_64_gnu" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_msvc" version = "0.42.1" @@ -5350,12 +5648,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] -name = "winreg" -version = "0.10.1" +name = "windows_x86_64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ - "winapi", + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", ] [[package]] @@ -5376,6 +5690,15 @@ dependencies = [ "libc", ] +[[package]] +name = "xattr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +dependencies = [ + "libc", +] + [[package]] name = "yajrc" version = "0.1.0" @@ -5409,10 +5732,22 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "1.5.7" +name = "yasi" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +checksum = "7f355ab62ebe30b758c1f4ab096a306722c4b7dbfb9d8c07d18c70d71a945588" +dependencies = [ + "ahash 0.8.3", + "hashbrown 0.13.2", + "lazy_static", + "serde", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" dependencies = [ "zeroize_derive", ] @@ -5423,8 +5758,8 @@ version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" dependencies = [ - "proc-macro2 1.0.50", - "quote 1.0.23", + "proc-macro2", + "quote", "syn 1.0.107", "synstructure", ] diff --git a/system-images/compat/Cargo.toml b/system-images/compat/Cargo.toml index 735667a36..199b7e1c5 100644 --- a/system-images/compat/Cargo.toml +++ b/system-images/compat/Cargo.toml @@ -17,6 +17,7 @@ emver = { version = "0.1.7", git = "https://github.com/Start9Labs/emver-rs.git", ] } failure = "0.1.8" indexmap = { version = "1.6.2", features = ["serde"] } +imbl-value = { git = "https://github.com/Start9Labs/imbl-value.git" } itertools = "0.10.0" lazy_static = "1.4" linear-map = { version = "1.2", features = ["serde_impl"] } diff --git a/system-images/compat/Makefile b/system-images/compat/Makefile index 3dc8560b8..f1ba3cd4b 100644 --- a/system-images/compat/Makefile +++ b/system-images/compat/Makefile @@ -1,4 +1,4 @@ - COMPAT_SRC := $(shell find ./src) Cargo.toml Cargo.lock +COMPAT_SRC := $(shell find ./src) Cargo.toml Cargo.lock .DELETE_ON_ERROR: @@ -15,7 +15,10 @@ docker-images/aarch64.tar: Dockerfile target/aarch64-unknown-linux-musl/release/ docker buildx build --build-arg ARCH=aarch64 --tag start9/x_system/compat --platform=linux/arm64 -o type=docker,dest=docker-images/aarch64.tar . docker-images/x86_64.tar: Dockerfile target/x86_64-unknown-linux-musl/release/compat docker-images - docker buildx build --build-arg ARCH=aarch64 --tag start9/x_system/compat --platform=linux/amd64 -o type=docker,dest=docker-images/x86_64.tar . + docker buildx build --build-arg ARCH=x86_64 --tag start9/x_system/compat --platform=linux/amd64 -o type=docker,dest=docker-images/x86_64.tar . -target/aarch64-unknown-linux-musl/release/compat target/x86_64-unknown-linux-musl/release/compat: $(COMPAT_SRC) - ./build.sh +target/aarch64-unknown-linux-musl/release/compat: $(COMPAT_SRC) ../../backend/Cargo.lock + ARCH=aarch64 ./build.sh + +target/x86_64-unknown-linux-musl/release/compat: $(COMPAT_SRC) ../../backend/Cargo.lock + ARCH=x86_64 ./build.sh diff --git a/system-images/compat/build.sh b/system-images/compat/build.sh index f81cb30b5..d84f2657b 100755 --- a/system-images/compat/build.sh +++ b/system-images/compat/build.sh @@ -3,9 +3,8 @@ set -e shopt -s expand_aliases -if [ -z "$OS_ARCH" ]; then - >&2 echo '$OS_ARCH is required' - exit 1 +if [ -z "$ARCH" ]; then + ARCH=$(uname -m) fi if [ "$0" != "./build.sh" ]; then @@ -18,12 +17,10 @@ if tty -s; then USE_TTY="-it" fi -alias 'rust-arm64-musl-builder'='docker run $USE_TTY --rm -e "OS_ARCH=$OS_ARCH" -v "$HOME"/.cargo/registry:/root/.cargo/registry -v "$(pwd)":/home/rust/src messense/rust-musl-cross:aarch64-musl' -alias 'rust-x86_64-musl-builder'='docker run $USE_TTY --rm -e "OS_ARCH=$OS_ARCH" -v "$HOME"/.cargo/registry:/root/.cargo/registry -v "$(pwd)":/home/rust/src messense/rust-musl-cross:x86_64-musl' +alias 'rust-musl-builder'='docker run $USE_TTY --rm -v "$HOME"/.cargo/registry:/root/.cargo/registry -v "$(pwd)":/home/rust/src messense/rust-musl-cross:${ARCH}-musl' cd ../.. -rust-arm64-musl-builder sh -c "(git config --global --add safe.directory '*'; cd system-images/compat && cargo build --release --target=aarch64-unknown-linux-musl --no-default-features)" -rust-x86_64-musl-builder sh -c "(git config --global --add safe.directory '*'; cd system-images/compat && cargo build --release --target=x86_64-unknown-linux-musl --no-default-features)" +rust-musl-builder sh -c "(git config --global --add safe.directory '*'; cd system-images/compat && cargo build --release --target=${ARCH}-unknown-linux-musl --no-default-features)" cd system-images/compat sudo chown -R $USER target diff --git a/system-images/compat/src/config/mod.rs b/system-images/compat/src/config/mod.rs index b80af0cf1..ce591b06a 100644 --- a/system-images/compat/src/config/mod.rs +++ b/system-images/compat/src/config/mod.rs @@ -60,11 +60,7 @@ pub fn validate_configuration( )?; std::fs::rename(config_path.with_extension("tmp"), config_path)?; // return set result - Ok(SetResult { - depends_on, - // sending sigterm so service is restarted - in 0.3.x services, this is whatever signal is needed to send to the process to pick up the configuration - signal: Some(nix::sys::signal::SIGTERM), - }) + Ok(SetResult { depends_on }) } Err(e) => Err(anyhow!("{}", e)), } @@ -83,7 +79,7 @@ pub fn validate_dependency_configuration( if let Some(config) = config { cfgs.insert(name, Cow::Borrowed(&config)) } else { - cfgs.insert(name, Cow::Owned(serde_json::Map::new())) + cfgs.insert(name, Cow::Owned(imbl_value::InOMap::new())) }; let rule_check = rules .into_iter() @@ -108,7 +104,7 @@ pub fn apply_dependency_configuration( cfgs.insert(dependency_id, Cow::Owned(dep_config.clone())); match config { Some(config) => cfgs.insert(package_id, Cow::Owned(config.clone())), - None => cfgs.insert(package_id, Cow::Owned(serde_json::Map::new())), + None => cfgs.insert(package_id, Cow::Owned(imbl_value::InOMap::new())), }; let rule_check = rules .into_iter() diff --git a/system-images/compat/src/config/rules.rs b/system-images/compat/src/config/rules.rs index ea2650237..a74ae195c 100644 --- a/system-images/compat/src/config/rules.rs +++ b/system-images/compat/src/config/rules.rs @@ -1,11 +1,11 @@ use std::borrow::Cow; use std::sync::Arc; +use imbl_value::{InternedString, Value}; use linear_map::LinearMap; use pest::iterators::Pairs; use pest::Parser; use rand::SeedableRng; -use serde_json::Value; use startos::config::util::STATIC_NULL; use startos::config::Config; @@ -382,7 +382,7 @@ fn compile_var_rec(mut ident: Pairs) -> Option { match idx.as_rule() { Rule::list_access_function_first => { let mut pred_iter = idx.into_inner(); - let item_var = pred_iter.next().unwrap().as_str().to_owned(); + let item_var: InternedString = pred_iter.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pred_iter.next().unwrap().into_inner()); Box::new(move |v, cfgs| match v { Value::Array(l) => VarRes::Exactly( @@ -411,7 +411,7 @@ fn compile_var_rec(mut ident: Pairs) -> Option { } Rule::list_access_function_last => { let mut pred_iter = idx.into_inner(); - let item_var = pred_iter.next().unwrap().as_str().to_owned(); + let item_var: InternedString = pred_iter.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pred_iter.next().unwrap().into_inner()); Box::new(move |v, cfgs| match v { Value::Array(l) => VarRes::Exactly( @@ -440,7 +440,7 @@ fn compile_var_rec(mut ident: Pairs) -> Option { } Rule::list_access_function_any => { let mut pred_iter = idx.into_inner(); - let item_var = pred_iter.next().unwrap().as_str().to_owned(); + let item_var: InternedString = pred_iter.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pred_iter.next().unwrap().into_inner()); Box::new(move |v, cfgs| match v { Value::Array(l) => VarRes::Any( @@ -469,7 +469,7 @@ fn compile_var_rec(mut ident: Pairs) -> Option { } Rule::list_access_function_all => { let mut pred_iter = idx.into_inner(); - let item_var = pred_iter.next().unwrap().as_str().to_owned(); + let item_var: InternedString = pred_iter.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pred_iter.next().unwrap().into_inner()); Box::new(move |v, cfgs| match v { Value::Array(l) => VarRes::All( @@ -506,7 +506,7 @@ fn compile_var_rec(mut ident: Pairs) -> Option { let idx = idx.as_str().to_owned(); Box::new(move |v, _| match v { Value::Object(o) => { - VarRes::Exactly(o.get(&idx).unwrap_or(&STATIC_NULL)) + VarRes::Exactly(o.get(&*idx).unwrap_or(&STATIC_NULL)) } _ => VarRes::Exactly(&STATIC_NULL), }) @@ -514,8 +514,9 @@ fn compile_var_rec(mut ident: Pairs) -> Option { Rule::sub_ident_regular_expr => { let idx = compile_str_expr(idx.into_inner().next().unwrap().into_inner()); Box::new(move |v, dep_cfg| match v { - Value::Object(o) => idx(&Config::default(), dep_cfg) - .map(|idx| idx.and_then(|idx| o.get(&idx)).unwrap_or(&STATIC_NULL)), + Value::Object(o) => idx(&Config::default(), dep_cfg).map(|idx| { + idx.and_then(|idx| o.get(&*idx)).unwrap_or(&STATIC_NULL) + }), _ => VarRes::Exactly(&STATIC_NULL), }) } @@ -575,7 +576,7 @@ fn compile_var(mut var: Pairs) -> CompiledExpr> { return VarRes::Exactly(Value::Null); }; } - let val = cfg.get(&first_seg_string).unwrap_or(&STATIC_NULL); + let val = cfg.get(&*first_seg_string).unwrap_or(&STATIC_NULL); if let Some(accessor) = &accessor { accessor(val, cfgs).map(|v| v.clone()) } else { @@ -593,7 +594,7 @@ fn compile_var_mut_rec(mut ident: Pairs) -> Result, fa match idx.as_rule() { Rule::list_access_function_first => { let mut pred_iter = idx.into_inner(); - let item_var = pred_iter.next().unwrap().as_str().to_owned(); + let item_var: InternedString = pred_iter.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pred_iter.next().unwrap().into_inner()); Box::new(move |v, cfgs| match v { Value::Array(l) => l @@ -618,7 +619,7 @@ fn compile_var_mut_rec(mut ident: Pairs) -> Result, fa } Rule::list_access_function_last => { let mut pred_iter = idx.into_inner(); - let item_var = pred_iter.next().unwrap().as_str().to_owned(); + let item_var: InternedString = pred_iter.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pred_iter.next().unwrap().into_inner()); Box::new(move |v, cfgs| match v { Value::Array(l) => l @@ -651,14 +652,14 @@ fn compile_var_mut_rec(mut ident: Pairs) -> Result, fa let idx = idx.into_inner().next().unwrap(); match idx.as_rule() { Rule::sub_ident_regular_base => { - let idx = idx.as_str().to_owned(); + let idx: InternedString = idx.as_str().into(); Box::new(move |v, _| match v { Value::Object(ref mut o) => { - if o.contains_key(&idx) { - o.get_mut(&idx) + if o.contains_key(&*idx) { + o.get_mut(&*idx) } else { o.insert(idx.clone(), Value::Null); - o.get_mut(&idx) + o.get_mut(&*idx) } } _ => None, @@ -669,11 +670,11 @@ fn compile_var_mut_rec(mut ident: Pairs) -> Result, fa Box::new( move |v, dep_cfg| match (v, idx(&Config::default(), dep_cfg)) { (Value::Object(ref mut o), VarRes::Exactly(Some(ref idx))) => { - if o.contains_key(idx) { - o.get_mut(idx) + if o.contains_key(&**idx) { + o.get_mut(&**idx) } else { o.insert(idx.clone(), Value::Null); - o.get_mut(idx) + o.get_mut(&**idx) } } _ => None, @@ -693,7 +694,7 @@ fn compile_var_mut_rec(mut ident: Pairs) -> Result, fa if l.len() > idx { l.get_mut(idx) } else if idx == l.len() { - l.push(Value::Null); + l.push_back(Value::Null); l.get_mut(idx) } else { None @@ -711,7 +712,7 @@ fn compile_var_mut_rec(mut ident: Pairs) -> Result, fa if l.len() > idx { l.get_mut(idx) } else if idx == l.len() { - l.push(Value::Null); + l.push_back(Value::Null); l.get_mut(idx) } else { None @@ -741,11 +742,11 @@ fn compile_var_mut(mut var: Pairs) -> Result) -> CompiledRule { } } -fn compile_str_var(var: Pairs) -> CompiledExpr>> { +fn compile_str_var(var: Pairs) -> CompiledExpr>> { let var = compile_var(var); Box::new(move |cfg, cfgs| { var(cfg, cfgs).map(|a| match a { - Value::String(s) => Some(s), - Value::Number(n) => Some(format!("{}", n)), - Value::Bool(b) => Some(format!("{}", b)), + Value::String(s) => Some(InternedString::from(&*s)), + Value::Number(n) => Some(InternedString::from_display(&n)), + Value::Bool(b) => Some(InternedString::from_display(&b)), _ => None, }) }) } -fn compile_str(str_str: &str) -> CompiledExpr>> { +fn compile_str(str_str: &str) -> CompiledExpr>> { let str_str = &str_str[1..str_str.len() - 1]; let mut out = String::with_capacity(str_str.len()); let mut escape = false; @@ -904,11 +905,11 @@ fn compile_str(str_str: &str) -> CompiledExpr>> { } } } - let res = VarRes::Exactly(Some(out)); + let res = VarRes::Exactly(Some(out.into())); Box::new(move |_, _| res.clone()) } -fn compile_str_expr(pairs: Pairs) -> CompiledExpr>> { +fn compile_str_expr(pairs: Pairs) -> CompiledExpr>> { STR_PREC_CLIMBER.climb( pairs, |pair| match pair.as_rule() { @@ -921,9 +922,9 @@ fn compile_str_expr(pairs: Pairs) -> CompiledExpr>> Rule::add => Box::new(move |cfg, cfgs| { lhs(cfg, cfgs).and_then(|lhs| { rhs(cfg, cfgs).map(|rhs| { - let lhs = lhs.clone()?; + let lhs = lhs.as_ref()?.to_string(); let rhs = rhs?; - Some(lhs + &rhs) + Some(InternedString::from(lhs + &*rhs)) }) }) }), @@ -941,7 +942,7 @@ fn compile_str_cmp_expr(mut pairs: Pairs) -> CompiledRule { lhs(cfg, cfgs) .and_then(|lhs| { rhs(cfg, cfgs).map(|rhs| match (&lhs, &rhs) { - (Some(lhs), Some(rhs)) => rhs.contains(lhs) && lhs.len() < rhs.len(), + (Some(lhs), Some(rhs)) => rhs.contains(&**lhs) && lhs.len() < rhs.len(), _ => false, }) }) @@ -951,7 +952,7 @@ fn compile_str_cmp_expr(mut pairs: Pairs) -> CompiledRule { lhs(cfg, cfgs) .and_then(|lhs| { rhs(cfg, cfgs).map(|rhs| match (&lhs, &rhs) { - (Some(lhs), Some(rhs)) => rhs.contains(lhs), + (Some(lhs), Some(rhs)) => rhs.contains(&**lhs), _ => false, }) }) @@ -983,7 +984,7 @@ fn compile_str_cmp_expr(mut pairs: Pairs) -> CompiledRule { lhs(cfg, cfgs) .and_then(|lhs| { rhs(cfg, cfgs).map(|rhs| match (&lhs, &rhs) { - (Some(lhs), Some(rhs)) => lhs.contains(rhs) && lhs.len() > rhs.len(), + (Some(lhs), Some(rhs)) => lhs.contains(&**rhs) && lhs.len() > rhs.len(), _ => true, }) }) @@ -993,7 +994,7 @@ fn compile_str_cmp_expr(mut pairs: Pairs) -> CompiledRule { lhs(cfg, cfgs) .and_then(|lhs| { rhs(cfg, cfgs).map(|rhs| match (&lhs, &rhs) { - (Some(lhs), Some(rhs)) => lhs.contains(rhs), + (Some(lhs), Some(rhs)) => lhs.contains(&**rhs), _ => true, }) }) @@ -1037,7 +1038,10 @@ fn compile_value_expr(mut pairs: Pairs) -> CompiledExpr> { Rule::str_expr => { let expr = compile_str_expr(expr.into_inner()); Box::new(move |cfg, cfgs| { - expr(cfg, cfgs).map(|s| s.map(Value::String).unwrap_or(Value::Null)) + expr(cfg, cfgs).map(|s| { + s.map(|s| Value::String(Arc::new(s.to_string()))) + .unwrap_or(Value::Null) + }) }) } Rule::num_expr => { @@ -1059,7 +1063,7 @@ fn compile_value_expr(mut pairs: Pairs) -> CompiledExpr> { fn compile_del_action(mut pairs: Pairs) -> Result { let list_mut = compile_var_mut(pairs.next().unwrap().into_inner())?; - let var = pairs.next().unwrap().as_str().to_owned(); + let var: InternedString = pairs.next().unwrap().as_str().into(); let predicate = compile_bool_expr(pairs.next().unwrap().into_inner()); Ok(Box::new(move |cfg, cfgs| match (&list_mut)(cfg, cfgs) { Some(Value::Array(ref mut l)) => { @@ -1093,7 +1097,7 @@ fn compile_push_action(mut pairs: Pairs, value: Value) -> Result a, _ => return, }; - vec.push(value.clone()) + vec.push_back(value.clone()) })) } @@ -1122,7 +1126,9 @@ fn compile_set_action(var: &str, to: &SetVariant) -> Result&2 echo "TARGET is required" + exit 1 +fi + +if [ -z "$KEY" ]; then + >&2 echo "KEY is required" + exit 1 +fi + +PLATFORM="$(cat ./PLATFORM.txt)" +VERSION="$(cat ./VERSION.txt)" +GIT_HASH="$(cat ./GIT_HASH.txt)" +if [[ "$GIT_HASH" =~ ^@ ]]; then + GIT_HASH=unknown +else + GIT_HASH="$(echo -n "$GIT_HASH" | head -c 7)" +fi +STARTOS_ENV="$(cat ./ENVIRONMENT.txt)" +if [ -n "$STARTOS_ENV" ]; then + GIT_HASH="$GIT_HASH~${STARTOS_ENV}" +fi + +BASENAME="startos-${VERSION}-${GIT_HASH}_${PLATFORM}" + +SHASUM=$(sha256sum results/$BASENAME.squashfs | awk '{print $1}') + +curl --fail-with-body -T results/${BASENAME}.squashfs "https://${TARGET}:8443/upload.cgi?key=${KEY}&gitHash=${GIT_HASH}&version=${VERSION}&platform=${PLATFORM}&shasum=${SHASUM}" \ No newline at end of file