commit 2b65b6a1c5d874ffca8198aa9c87e7d92a54ddcb Author: Dominic Grimm Date: Mon Dec 12 17:54:07 2022 +0100 Init diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..045e248 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,25 @@ +--- +kind: pipeline +type: docker +name: default + +steps: + - name: ameba + image: veelenga/ameba + commands: + - cd bvplan + - ameba src + - name: build + image: tmaier/docker-compose + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - docker-compose build --build-arg BUILD_ENV=development bvplan + depends_on: + - ameba + +volumes: + - name: dockersock + host: + path: /var/run/docker.sock diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..af95812 --- /dev/null +++ b/.env.example @@ -0,0 +1,11 @@ +POSTGRES_USER="bvplan" +POSTGRES_PASSWORD="bvplan" + +RABBITMQ_USER="bvplan" +RABBITMQ_PASSWORD="bvplan" + +BACKEND_UNTIS_API_URL="https://mese.webuntis.com/WebUntis/api/" +BACKEND_UNTIS_RPC_URL="https://mese.webuntis.com/WebUntis/jsonrpc.do" +BACKEND_UNTIS_SCHOOL= +BACKEND_UNTIS_USERNAME= +BACKEND_UNTIS_PASSWORD= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03bd412 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.env diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d6d7152 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +.PHONY: all dev prod + +all: prod + +dev: + docker-compose build --build-arg BUILD_ENV=development + +prod: + docker-compose build diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 0000000..1b321f5 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,21 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +dist/ +Dockerfile +.gitignore +.dockerignore +vendor/ +.editorconfig diff --git a/backend/.editorconfig b/backend/.editorconfig new file mode 100644 index 0000000..373508e --- /dev/null +++ b/backend/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.rs] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1 @@ +/target diff --git a/backend/Cargo.lock b/backend/Cargo.lock new file mode 100644 index 0000000..c4eb9d7 --- /dev/null +++ b/backend/Cargo.lock @@ -0,0 +1,3337 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "actix" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3720d0064a0ce5c0de7bd93bdb0a6caebab2a9b5668746145d7b3b0c5da02914" +dependencies = [ + "actix-rt", + "actix_derive", + "bitflags", + "bytes", + "crossbeam-channel", + "futures-core", + "futures-sink", + "futures-task", + "futures-util", + "log", + "once_cell", + "parking_lot 0.11.2", + "pin-project-lite", + "smallvec", + "tokio", + "tokio-util 0.6.10", +] + +[[package]] +name = "actix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f728064aca1c318585bf4bb04ffcfac9e75e508ab4e8b1bd9ba5dfe04e2cbed5" +dependencies = [ + "actix-rt", + "bitflags", + "bytes", + "crossbeam-channel", + "futures-core", + "futures-sink", + "futures-task", + "futures-util", + "log", + "once_cell", + "parking_lot 0.12.1", + "pin-project-lite", + "smallvec", + "tokio", + "tokio-util 0.7.4", +] + +[[package]] +name = "actix-codec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-sink", + "log", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util 0.7.4", +] + +[[package]] +name = "actix-cors" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b340e9cfa5b08690aae90fb61beb44e9b06f44fe3d0f93781aaa58cfba86245e" +dependencies = [ + "actix-utils", + "actix-web", + "derive_more", + "futures-util", + "log", + "once_cell", + "smallvec", +] + +[[package]] +name = "actix-http" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash", + "base64", + "bitflags", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "futures-core", + "h2", + "http", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand 0.8.5", + "sha1 0.10.5", + "smallvec", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "actix-router" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" +dependencies = [ + "bytestring", + "http", + "regex", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "num_cpus", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "http", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2", + "time 0.3.17", + "url", +] + +[[package]] +name = "actix-web-actors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31efe7896f3933ce03dd4710be560254272334bb321a18fd8ff62b1a557d9d19" +dependencies = [ + "actix 0.13.0", + "actix-codec", + "actix-http", + "actix-web", + "bytes", + "bytestring", + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "actix-web-codegen" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "actix_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "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.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "amq-protocol" +version = "7.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acc7cad07d1b4533fcb46f0819a6126fa201fd0385469aba75e405424f3fe009" +dependencies = [ + "amq-protocol-tcp", + "amq-protocol-types", + "amq-protocol-uri", + "cookie-factory", + "nom", + "serde", +] + +[[package]] +name = "amq-protocol-tcp" +version = "7.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8b20aba8c35a0b885e1e978eff456ced925730a4e012e63e4ff89a1deb602b" +dependencies = [ + "amq-protocol-uri", + "tcp-stream", + "tracing", +] + +[[package]] +name = "amq-protocol-types" +version = "7.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e245e0e9083b6a6db5f8c10013074cb382266eb9e2a37204d19c651b8d3b8114" +dependencies = [ + "cookie-factory", + "nom", + "serde", + "serde_json", +] + +[[package]] +name = "amq-protocol-uri" +version = "7.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56987108bf48d2eb500cae8896cd9291564eedd8744776ecc5c3338a8b2ca5f8" +dependencies = [ + "amq-protocol-types", + "percent-encoding", + "url", +] + +[[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 = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +dependencies = [ + "backtrace", +] + +[[package]] +name = "arc-swap" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164" + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-global-executor-trait" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dd14c5a15affd2abcff50d84efd4009ada28a860f01c14f9d654f3e81b3f75" +dependencies = [ + "async-global-executor", + "async-trait", + "executor-trait", +] + +[[package]] +name = "async-io" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" +dependencies = [ + "async-lock", + "autocfg", + "concurrent-queue", + "futures-lite", + "libc", + "log", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "windows-sys 0.42.0", +] + +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + +[[package]] +name = "async-reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6012d170ad00de56c9ee354aef2e358359deb1ec504254e0e5a3774771de0e" +dependencies = [ + "async-io", + "async-trait", + "futures-core", + "reactor-trait", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + +[[package]] +name = "async-trait" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backend" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-web", + "anyhow", + "celery", + "chrono", + "cookie", + "diesel", + "env_logger", + "envconfig", + "juniper", + "juniper_actix", + "lazy_static", + "log", + "now", + "reqwest", + "serde", + "serde_json", + "tikv-jemallocator", + "tokio", + "url", +] + +[[package]] +name = "backtrace" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide 0.5.4", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[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.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a90ec2df9600c28a01c56c4784c9207a96d2451833aeceb8cc97e4c9548bb78" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", +] + +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bson" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0aa578035b938855a710ba58d43cfb4d435f3619f99236fb35922a574d6cb1" +dependencies = [ + "base64", + "chrono", + "hex", + "lazy_static", + "linked-hash-map", + "rand 0.7.3", + "serde", + "serde_json", + "uuid", +] + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + +[[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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "bytestring" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" +dependencies = [ + "bytes", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +dependencies = [ + "jobserver", +] + +[[package]] +name = "celery" +version = "0.4.0-rcn.11" +source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#1bf8729cd107e7e0919eda19224f4cd2be428f88" +dependencies = [ + "async-trait", + "base64", + "celery-codegen", + "chrono", + "colored", + "futures", + "globset", + "hostname", + "lapin", + "log", + "once_cell", + "rand 0.8.5", + "redis", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-executor-trait", + "tokio-reactor-trait", + "tokio-stream", + "uuid", +] + +[[package]] +name = "celery-codegen" +version = "0.4.0-rcn.11" +source = "git+https://github.com/rusty-celery/rusty-celery.git?branch=main#1bf8729cd107e7e0919eda19224f4cd2be428f88" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "serde", + "time 0.1.45", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" +dependencies = [ + "crypto-common", + "inout", +] + +[[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 = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util 0.7.4", +] + +[[package]] +name = "concurrent-queue" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b" +dependencies = [ + "crossbeam-utils", +] + +[[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.17", + "version_check", +] + +[[package]] +name = "cookie-factory" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b" + +[[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 = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[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 = "cxx" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "derive_utils" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532b4c15dccee12c7044f1fcad956e98410860b22231e44a3b827464797ca7bf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "des" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" +dependencies = [ + "cipher", +] + +[[package]] +name = "diesel" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c186a7418a2aac330bb76cde82f16c36b03a66fb91db32d20214311f9f6545" +dependencies = [ + "bitflags", + "byteorder", + "chrono", + "diesel_derives", + "itoa", + "pq-sys", + "r2d2", +] + +[[package]] +name = "diesel_derives" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b758c91dbc3fe1fdcb0dba5bd13276c6a66422f2ef5795b58488248a310aa" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "envconfig" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea81cc7e21f55a9d9b1efb6816904978d0bfbe31a50347cb24b2e75564bcac9b" +dependencies = [ + "envconfig_derive", +] + +[[package]] +name = "envconfig_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfca278e5f84b45519acaaff758ebfa01f18e96998bc24b8f1b722dd804b9bf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "executor-trait" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a1052dd43212a7777ec6a69b117da52f5e52f07aec47d00c1a2b33b85d06b08" +dependencies = [ + "async-trait", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide 0.6.2", +] + +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.4", +] + +[[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 = "fs_extra" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" + +[[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-enum" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3422d14de7903a52e9dbc10ae05a7e14445ec61890100e098754e120b2bd7b1e" +dependencies = [ + "derive_utils", + "quote", + "syn", +] + +[[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-io" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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", + "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", + "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 = "globset" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "graphql-parser" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1abd4ce5247dfc04a03ccde70f87a048458c9356c7e41d21ad8c407b3dde6f2" +dependencies = [ + "combine 3.8.1", + "thiserror", +] + +[[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 0.7.4", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[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 = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "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 = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +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 = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", + "serde", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "ipnet" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec947b7a4ce12e3b87e353abae7ce124d025b6c7d6c5aea5cc0bcf92e9510ded" + +[[package]] +name = "is-terminal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330" +dependencies = [ + "hermit-abi 0.2.6", + "io-lifetimes", + "rustix", + "windows-sys 0.42.0", +] + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + +[[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 = "juniper" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f478f229a8ab52ff242f3250c8b3b8fe0a59b5b934f9706b7bdbc980991a7b6" +dependencies = [ + "async-trait", + "bson", + "chrono", + "fnv", + "futures", + "futures-enum", + "graphql-parser", + "indexmap", + "juniper_codegen", + "serde", + "smartstring", + "static_assertions", + "url", + "uuid", +] + +[[package]] +name = "juniper_actix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc44af18ae1f551076171e24eb453c52132a19c219d1f1a1c3068ab363b946b5" +dependencies = [ + "actix 0.12.0", + "actix-http", + "actix-web", + "actix-web-actors", + "anyhow", + "futures", + "http", + "juniper", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "juniper_codegen" +version = "0.15.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aee97671061ad50301ba077d054d295e01d31a1868fbd07902db651f987e71db" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lapin" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd03ea5831b44775e296239a64851e2fd14a80a363d202ba147009ffc994ff0f" +dependencies = [ + "amq-protocol", + "async-global-executor-trait", + "async-reactor-trait", + "async-trait", + "executor-trait", + "flume", + "futures-core", + "futures-io", + "parking_lot 0.12.1", + "pinky-swear", + "reactor-trait", + "serde", + "tracing", + "waker-fn", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" + +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f" + +[[package]] +name = "local-channel" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" +dependencies = [ + "futures-core", + "futures-sink", + "futures-util", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" + +[[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", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[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 = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +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 = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[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 = "now" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0" +dependencies = [ + "chrono", +] + +[[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-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.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +dependencies = [ + "hermit-abi 0.1.19", + "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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "openssl" +version = "0.10.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29d971fd5722fec23977260f6e81aa67d2f22cadbdc2aa049f1022d9a3be1566" +dependencies = [ + "bitflags", + "cfg-if", + "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", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5454462c0eced1e97f2ec09036abc8da362e66802f66fd20f86854d9d8cbcbc4" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "p12" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4873306de53fe82e7e484df31e1e947d61514b6ea2ed6cd7b45d63006fd9224" +dependencies = [ + "cbc", + "cipher", + "des", + "getrandom 0.2.8", + "hmac", + "lazy_static", + "rc2", + "sha1 0.10.5", + "yasna", +] + +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + +[[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.5", +] + +[[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 0.9.5", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.42.0", +] + +[[package]] +name = "paste" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[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", + "quote", + "syn", +] + +[[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 = "pinky-swear" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d894b67aa7a4bf295db5e85349078c604edaa6fa5c8721e8eca3c7729a27f2ac" +dependencies = [ + "doc-comment", + "flume", + "parking_lot 0.12.1", + "tracing", +] + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "polling" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "166ca89eb77fd403230b9c156612965a81e094ec6ec3aa13663d4c8b113fa748" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "pq-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b845d6d8ec554f972a2c5298aad68953fd64e7441e846075450b44656a016d1" +dependencies = [ + "vcpkg", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[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 = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot 0.12.1", + "scheduled-thread-pool", +] + +[[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 = "rc2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62c64daa8e9438b84aaae55010a93f396f8e60e3911590fcba770d04643fc1dd" +dependencies = [ + "cipher", +] + +[[package]] +name = "reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "438a4293e4d097556730f4711998189416232f009c137389e0f961d2bc0ddc58" +dependencies = [ + "async-trait", + "futures-core", + "futures-io", +] + +[[package]] +name = "redis" +version = "0.21.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571c252c68d09a2ad3e49edd14e9ee48932f3e0f27b06b4ea4c9b2a706d31103" +dependencies = [ + "arc-swap", + "async-trait", + "bytes", + "combine 4.6.6", + "futures", + "futures-util", + "itoa", + "percent-encoding", + "pin-project-lite", + "ryu", + "sha1 0.6.1", + "tokio", + "tokio-util 0.7.4", + "url", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[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.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +dependencies = [ + "base64", + "bytes", + "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", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.42.0", +] + +[[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-connector" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6a18f8d10f71bce9bca6eaeb80429460e652f3bcf0381f0c5f8954abf7b3b8" +dependencies = [ + "log", + "rustls", + "rustls-native-certs", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64", +] + +[[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 = "scheduled-thread-pool" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" +dependencies = [ + "parking_lot 0.12.1", +] + +[[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 = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" + +[[package]] +name = "serde" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" +dependencies = [ + "indexmap", + "itoa", + "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", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" +dependencies = [ + "sha1_smol", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[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 = "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 = "smartstring" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e714dff2b33f2321fdcd475b71cec79781a692d846f37f415fb395a1d2bcd48e" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" +dependencies = [ + "lock_api", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tcp-stream" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a4b0a70bac0a58ca6a7659d1328e34ee462339c70b0fa49f72bad1f278910a" +dependencies = [ + "cfg-if", + "p12", + "rustls-connector", + "rustls-pemfile", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "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 = "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", + "quote", + "syn", +] + +[[package]] +name = "tikv-jemalloc-sys" +version = "0.5.2+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec45c14da997d0925c7835883e4d5c181f196fa142f8c19d7643d1e9af2592c3" +dependencies = [ + "cc", + "fs_extra", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20612db8a13a6c06d57ec83953694185a367e16945f66565e8028d2c0bd76979" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[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.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot 0.12.1", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-executor-trait" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b78630814cbcdf383c949bd8f17c3cfe3142e93b0d5801bdcae4b2a5275db7e" +dependencies = [ + "async-trait", + "executor-trait", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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-reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9481a72f36bd9cbb8d6dd349227c4783e234e4332cfe806225bc929c4b92486" +dependencies = [ + "async-trait", + "futures-core", + "futures-io", + "reactor-trait", + "tokio", + "tokio-stream", +] + +[[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", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + +[[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 = "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", + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[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-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[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", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[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 = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[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", + "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", + "quote", + "syn", + "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", + "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", + "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", + "quote", + "syn", + "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 = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[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 = "yasna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c" + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.4+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" +dependencies = [ + "cc", + "libc", +] diff --git a/backend/Cargo.toml b/backend/Cargo.toml new file mode 100644 index 0000000..e1f67be --- /dev/null +++ b/backend/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "backend" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "api" + +[[bin]] +name = "worker" + +[profile.release] +codegen-units = 1 +lto = "fat" +strip = true +panic = "abort" + +[dependencies] +actix-cors = "0.6.4" +actix-web = "4.2.1" +anyhow = { version = "1.0.66", features = ["backtrace"] } +celery = { git = "https://github.com/rusty-celery/rusty-celery.git", branch = "main" } +chrono = { version = "0.4.23", features = ["serde"] } +cookie = "0.16.1" +diesel = { version = "2.0.2", features = ["i-implement-a-third-party-backend-and-opt-into-breaking-changes", "postgres", "chrono", "r2d2"] } +env_logger = "0.10.0" +envconfig = "0.10.0" +juniper = "0.15.10" +juniper_actix = "0.4.0" +lazy_static = "1.4.0" +log = "0.4.17" +now = "0.1.3" +reqwest = { version = "0.11.13", features = ["json"] } +serde = "1.0.148" +serde_json = "1.0.89" +tokio = { version = "1.22.0", features = ["full"] } +url = "2.3.1" + +[target.'cfg(not(target_env = "msvc"))'.dependencies] +tikv-jemallocator = "0.5" diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..42ac1e0 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,31 @@ +FROM lukemathwalker/cargo-chef:latest-rust-1.65.0 as chef +WORKDIR /usr/src/backend + +FROM chef as planner +RUN mkdir src && touch src/main.rs +COPY ./Cargo.toml . +RUN cargo chef prepare --recipe-path recipe.json + +FROM chef as builder +RUN cargo install diesel_cli --no-default-features --features postgres +COPY --from=planner /usr/src/backend/recipe.json . +RUN cargo chef cook --release --recipe-path recipe.json +COPY ./src ./src +RUN cargo build --release + +FROM debian:buster-slim as runner +RUN apt update +RUN apt install -y libpq5 +RUN apt install -y ca-certificates +RUN apt-get clean +RUN apt-get autoremove --yes +RUN rm -rf /var/lib/{apt,dpkg,cache,log}/ +WORKDIR /usr/local/bin +COPY --from=builder /usr/local/cargo/bin/diesel . +WORKDIR /usr/src/backend +COPY ./run.sh . +RUN chmod +x ./run.sh +COPY ./migrations ./migrations +COPY --from=builder /usr/src/backend/target/release/api /usr/src/backend/target/release/worker ./bin/ +EXPOSE 80 +ENTRYPOINT [ "./run.sh" ] diff --git a/backend/migrations/2022-12-03-124501_init/down.sql b/backend/migrations/2022-12-03-124501_init/down.sql new file mode 100644 index 0000000..1f1c408 --- /dev/null +++ b/backend/migrations/2022-12-03-124501_init/down.sql @@ -0,0 +1,39 @@ +DROP TABLE substitution_query_results; + +DROP TABLE substitution_queries; + +DROP TABLE substitution_planned_queries; + +DROP TABLE substitution_room; + +DROP TABLE substitution_subject; + +DROP TABLE substitution_teacher; + +DROP TABLE substitution_class; + +DROP TABLE substitutions; + +DROP TYPE substitution_type; + +DROP TABLE timegrid_time_unit; + +DROP TABLE timegrid_days; + +DROP TABLE timegrids; + +DROP TABLE holidays; + +DROP TABLE departments; + +DROP TABLE rooms; + +DROP TABLE subjects; + +DROP TABLE classes; + +DROP TABLE teachers; + +DROP TABLE tenants; + +DROP TABLE schoolyears; \ No newline at end of file diff --git a/backend/migrations/2022-12-03-124501_init/up.sql b/backend/migrations/2022-12-03-124501_init/up.sql new file mode 100644 index 0000000..610af28 --- /dev/null +++ b/backend/migrations/2022-12-03-124501_init/up.sql @@ -0,0 +1,199 @@ +CREATE TABLE schoolyears( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + name VARCHAR NOT NULL, + start_date DATE NOT NULL, + end_date DATE NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE tenants( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + active BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE UNIQUE INDEX ON tenants(active) +WHERE + active; + +CREATE TABLE teachers( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + forename VARCHAR, + display_name VARCHAR NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE classes( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + long_name VARCHAR NOT NULL, + active BOOLEAN NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE subjects( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + long_name VARCHAR NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE rooms( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + long_name VARCHAR NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE departments( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + long_name VARCHAR NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE holidays( + id SERIAL PRIMARY KEY, + untis_id INTEGER NOT NULL UNIQUE, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + name VARCHAR NOT NULL, + long_name VARCHAR NOT NULL, + start_date DATE NOT NULL, + end_date DATE NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE timegrids( + id SERIAL PRIMARY KEY, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE timegrid_days( + id SERIAL PRIMARY KEY, + timegrid_id INTEGER NOT NULL REFERENCES timegrids(id), + day_index SMALLINT NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE timegrid_time_unit( + id SERIAL PRIMARY KEY, + timegrid_day_id INTEGER NOT NULL REFERENCES timegrid_days(id), + start_time TIME NOT NULL, + end_time TIME NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TYPE substitution_type AS ENUM ( + 'cancel', + 'subst', + 'add', + 'shift', + 'rmchg', + 'rmlk', + 'bs', + 'oh', + 'sb', + 'other', + 'free', + 'exam', + 'ac', + 'holi', + 'stxt' +); + +CREATE TABLE substitutions( + id SERIAL PRIMARY KEY, + subst_type substitution_type NOT NULL, + lesson_id INTEGER NOT NULL, + start_time TIME NOT NULL, + end_time TIME NOT NULL, + text VARCHAR, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE substitution_classes( + id SERIAL PRIMARY KEY, + substitution_id INTEGER NOT NULL REFERENCES substitutions(id), + class_id INTEGER NOT NULL REFERENCES classes(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE substitution_teachers( + id SERIAL PRIMARY KEY, + substitution_id INTEGER NOT NULL REFERENCES substitutions(id), + teacher_id INTEGER NOT NULL REFERENCES teachers(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE substitution_subjects( + id SERIAL PRIMARY KEY, + substitution_id INTEGER NOT NULL REFERENCES substitutions(id), + subject_id INTEGER NOT NULL REFERENCES subjects(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE substitution_rooms( + id SERIAL PRIMARY KEY, + substitution_id INTEGER NOT NULL REFERENCES substitutions(id), + room_id INTEGER NOT NULL REFERENCES rooms(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE substitution_planned_queries( + id SERIAL PRIMARY KEY, + schoolyear_id INTEGER NOT NULL REFERENCES schoolyears(id), + date DATE NOT NULL UNIQUE, + active BOOLEAN NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE INDEX ON substitution_planned_queries(active); + +CREATE TABLE substitution_queries( + id SERIAL PRIMARY KEY, + substitution_planned_query_id INTEGER NOT NULL REFERENCES substitution_planned_queries(id), + queried_at TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); + +CREATE TABLE substitution_query_results( + id SERIAL PRIMARY KEY, + substitution_query_id INTEGER NOT NULL REFERENCES substitution_queries(id), + substitution_id INTEGER NOT NULL REFERENCES substitutions(id), + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP +); \ No newline at end of file diff --git a/backend/run.sh b/backend/run.sh new file mode 100644 index 0000000..5f48551 --- /dev/null +++ b/backend/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +DATABASE_URL="$BACKEND_DB_URL" diesel setup \ + --migration-dir ./migrations \ + --locked-schema && + RUST_BACKTRACE=full "./bin/$1" diff --git a/backend/src/bin/api.rs b/backend/src/bin/api.rs new file mode 100644 index 0000000..5f9522f --- /dev/null +++ b/backend/src/bin/api.rs @@ -0,0 +1,55 @@ +#[cfg(not(target_env = "msvc"))] +use tikv_jemallocator::Jemalloc; + +#[cfg(not(target_env = "msvc"))] +#[global_allocator] +static GLOBAL: Jemalloc = Jemalloc; + +async fn graphql_route( + req: actix_web::HttpRequest, + payload: actix_web::web::Payload, + schema: actix_web::web::Data, +) -> Result { + juniper_actix::graphql_handler( + &schema, + &backend::graphql::Context { + pool: backend::db::POOL.clone(), + }, + req, + payload, + ) + .await +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "info"); + env_logger::init(); + + let server = actix_web::HttpServer::new(move || { + actix_web::App::new() + .app_data(actix_web::web::Data::new(backend::graphql::schema())) + .wrap( + actix_cors::Cors::default() + .allow_any_origin() + .allowed_methods(vec!["POST", "GET"]) + .allowed_headers(vec![ + actix_web::http::header::AUTHORIZATION, + actix_web::http::header::ACCEPT, + ]) + .allowed_header(actix_web::http::header::CONTENT_TYPE) + .supports_credentials() + .max_age(3600), + ) + .wrap(actix_web::middleware::Compress::default()) + .wrap(actix_web::middleware::Logger::default()) + .service( + actix_web::web::resource("/") + .route(actix_web::web::post().to(graphql_route)) + .route(actix_web::web::get().to(graphql_route)), + ) + }); + println!("Starting server on port 80!"); + + server.bind("0.0.0.0:80")?.run().await +} diff --git a/backend/src/bin/worker.rs b/backend/src/bin/worker.rs new file mode 100644 index 0000000..d500dc4 --- /dev/null +++ b/backend/src/bin/worker.rs @@ -0,0 +1,37 @@ +use std::thread; +#[cfg(not(target_env = "msvc"))] +use tikv_jemallocator::Jemalloc; + +#[cfg(not(target_env = "msvc"))] +#[global_allocator] +static GLOBAL: Jemalloc = Jemalloc; + +#[tokio::main] +async fn main() { + std::env::set_var("RUST_LOG", "info"); + env_logger::init(); + + println!("Starting worker!"); + + backend::worker::init_blocking(); + + thread::spawn(|| { + tokio::runtime::Runtime::new().unwrap().block_on(async { + backend::worker::beat() + .await + .unwrap() + .start() + .await + .unwrap(); + println!("asdnkjndfkjlewnflj"); + }); + }); + + let app = backend::worker::APP.lock().unwrap(); + let app = app.as_ref().unwrap(); + + app.display_pretty().await; + app.consume_from(&[backend::worker::QUEUE_NAME]) + .await + .unwrap(); +} diff --git a/backend/src/config.rs b/backend/src/config.rs new file mode 100644 index 0000000..27dd549 --- /dev/null +++ b/backend/src/config.rs @@ -0,0 +1,30 @@ +use envconfig::Envconfig; +use lazy_static::lazy_static; + +#[derive(Envconfig, Debug)] +pub struct Config { + #[envconfig(from = "BACKEND_DB_URL")] + pub db_url: String, + + #[envconfig(from = "BACKEND_AMQP_URL")] + pub amqp_url: String, + + #[envconfig(from = "BACKEND_UNTIS_API_URL")] + pub untis_api_url: String, + + #[envconfig(from = "BACKEND_UNTIS_RPC_URL")] + pub untis_rpc_url: String, + + #[envconfig(from = "BACKEND_UNTIS_SCHOOL")] + pub untis_school: String, + + #[envconfig(from = "BACKEND_UNTIS_USERNAME")] + pub untis_username: String, + + #[envconfig(from = "BACKEND_UNTIS_PASSWORD")] + pub untis_password: String, +} + +lazy_static! { + pub static ref CONFIG: Config = Config::init_from_env().unwrap(); +} diff --git a/backend/src/db/mod.rs b/backend/src/db/mod.rs new file mode 100644 index 0000000..53fa54b --- /dev/null +++ b/backend/src/db/mod.rs @@ -0,0 +1,28 @@ +use anyhow::Result; +use diesel::pg::PgConnection; +use diesel::prelude::*; +use diesel::r2d2::{ConnectionManager, Pool}; +use lazy_static::lazy_static; + +use crate::config; + +pub mod models; +pub mod schema; + +pub type DbPool = Pool>; + +pub fn establish_connection() -> ConnectionResult { + PgConnection::establish(&config::CONFIG.db_url) +} + +pub fn pool() -> Result { + Ok( + Pool::builder().build(ConnectionManager::::new( + &config::CONFIG.db_url, + ))?, + ) +} + +lazy_static! { + pub static ref POOL: DbPool = pool().unwrap(); +} diff --git a/backend/src/db/models.rs b/backend/src/db/models.rs new file mode 100644 index 0000000..d98e29e --- /dev/null +++ b/backend/src/db/models.rs @@ -0,0 +1,446 @@ +use chrono::prelude::*; +use diesel::prelude::*; +use std::io::Write; + +use crate::db::schema; +use crate::untis; + +#[derive(Identifiable, Queryable, Debug)] +#[diesel(table_name = schema::schoolyears)] +pub struct Schoolyear { + pub id: i32, + pub untis_id: i32, + pub name: String, + pub start_date: NaiveDate, + pub end_date: NaiveDate, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::schoolyears)] +pub struct NewSchoolyear<'a> { + pub untis_id: i32, + pub name: &'a str, + pub start_date: NaiveDate, + pub end_date: NaiveDate, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::tenants)] +#[diesel(belongs_to(Schoolyear))] +pub struct Tenant { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub active: bool, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::tenants)] +pub struct NewTenant<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub active: bool, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::teachers)] +#[diesel(belongs_to(Schoolyear))] +pub struct Teacher { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub forename: Option, + pub display_name: String, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::teachers)] +pub struct NewTeacher<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub forename: Option<&'a str>, + pub display_name: &'a str, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::classes)] +#[diesel(belongs_to(Schoolyear))] +pub struct Class { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub long_name: String, + pub active: bool, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::classes)] +pub struct NewClass<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub long_name: &'a str, + pub active: bool, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::subjects)] +#[diesel(belongs_to(Schoolyear))] +pub struct Subject { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub long_name: String, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::subjects)] +pub struct NewSubject<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub long_name: &'a str, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::rooms)] +#[diesel(belongs_to(Schoolyear))] +pub struct Room { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub long_name: String, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::rooms)] +pub struct NewRoom<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub long_name: &'a str, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::departments)] +#[diesel(belongs_to(Schoolyear))] +pub struct Department { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub long_name: String, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::departments)] +pub struct NewDepartment<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub long_name: &'a str, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::holidays)] +#[diesel(belongs_to(Schoolyear))] +pub struct Holiday { + pub id: i32, + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: String, + pub long_name: String, + pub start_date: NaiveDate, + pub end_date: NaiveDate, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::holidays)] +pub struct NewHoliday<'a> { + pub untis_id: i32, + pub schoolyear_id: i32, + pub name: &'a str, + pub long_name: &'a str, + pub start_date: NaiveDate, + pub end_date: NaiveDate, +} + +#[derive(diesel::FromSqlRow, diesel::AsExpression, PartialEq, Eq, Debug)] +#[diesel(sql_type = schema::sql_types::SubstitutionType)] +pub enum SubstitutionType { + Cancel, + Substitution, + Additional, + Shifted, + RoomChange, + Locked, + BreakSupervision, + OfficeHour, + Standby, + Other, + Free, + Exam, + Activity, + Holiday, + Text, +} + +impl diesel::serialize::ToSql + for SubstitutionType +{ + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, diesel::pg::Pg>, + ) -> diesel::serialize::Result { + match *self { + Self::Cancel => out.write_all(b"cancel")?, + Self::Substitution => out.write_all(b"subst")?, + Self::Additional => out.write_all(b"add")?, + Self::Shifted => out.write_all(b"shift")?, + Self::RoomChange => out.write_all(b"rmchg")?, + Self::Locked => out.write_all(b"rmlk")?, + Self::BreakSupervision => out.write_all(b"bs")?, + Self::OfficeHour => out.write_all(b"oh")?, + Self::Standby => out.write_all(b"sb")?, + Self::Other => out.write_all(b"other")?, + Self::Free => out.write_all(b"free")?, + Self::Exam => out.write_all(b"exam")?, + Self::Activity => out.write_all(b"ac")?, + Self::Holiday => out.write_all(b"holi")?, + Self::Text => out.write_all(b"stxt")?, + } + + Ok(diesel::serialize::IsNull::No) + } +} + +impl diesel::deserialize::FromSql + for SubstitutionType +{ + fn from_sql( + bytes: diesel::backend::RawValue<'_, diesel::pg::Pg>, + ) -> diesel::deserialize::Result { + match bytes.as_bytes() { + b"cancel" => Ok(Self::Cancel), + b"subst" => Ok(Self::Substitution), + b"add" => Ok(Self::Additional), + b"shift" => Ok(Self::Shifted), + b"rmchg" => Ok(Self::RoomChange), + b"rmlk" => Ok(Self::Locked), + b"bs" => Ok(Self::BreakSupervision), + b"oh" => Ok(Self::OfficeHour), + b"sb" => Ok(Self::Standby), + b"other" => Ok(Self::Other), + b"free" => Ok(Self::Free), + b"exam" => Ok(Self::Exam), + b"ac" => Ok(Self::Activity), + b"holi" => Ok(Self::Holiday), + b"stxt" => Ok(Self::Text), + _ => Err("Unrecognized enum variant".into()), + } + } +} + +impl From for SubstitutionType { + fn from(x: untis::RpcSubstitionType) -> Self { + match x { + untis::RpcSubstitionType::Cancel => Self::Cancel, + untis::RpcSubstitionType::Substitution => Self::Substitution, + untis::RpcSubstitionType::Additional => Self::Additional, + untis::RpcSubstitionType::Shifted => Self::Shifted, + untis::RpcSubstitionType::RoomChange => Self::RoomChange, + untis::RpcSubstitionType::Locked => Self::Locked, + untis::RpcSubstitionType::BreakSupervision => Self::BreakSupervision, + untis::RpcSubstitionType::OfficeHour => Self::OfficeHour, + untis::RpcSubstitionType::Standby => Self::Standby, + untis::RpcSubstitionType::Other => Self::Other, + untis::RpcSubstitionType::Free => Self::Free, + untis::RpcSubstitionType::Exam => Self::Exam, + untis::RpcSubstitionType::Activity => Self::Activity, + untis::RpcSubstitionType::Holiday => Self::Holiday, + untis::RpcSubstitionType::Text => Self::Text, + } + } +} + +#[derive(Identifiable, Queryable, Debug)] +#[diesel(table_name = schema::substitutions)] +pub struct Substitution { + pub id: i32, + pub substitution_query_id: i32, + pub subst_type: SubstitutionType, + pub lesson_id: i32, + pub start_time: NaiveTime, + pub end_time: NaiveTime, + pub text: Option, + pub active: bool, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitutions)] +pub struct NewSubstitution<'a> { + pub subst_type: SubstitutionType, + pub lesson_id: i32, + pub start_time: NaiveTime, + pub end_time: NaiveTime, + pub text: Option<&'a str>, + pub active: bool, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_classes)] +#[diesel(belongs_to(Substitution))] +#[diesel(belongs_to(Class))] +pub struct SubstitutionClass { + pub id: i32, + pub substitution_id: i32, + pub class_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_classes)] +pub struct NewSubstitutionClass { + pub substitution_id: i32, + pub class_id: i32, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_teachers)] +#[diesel(belongs_to(Substitution))] +#[diesel(belongs_to(Teacher))] +pub struct SubstitutionTeacher { + pub id: i32, + pub substitution_id: i32, + pub teacher_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_teachers)] +pub struct NewSubstitutionTeacher { + pub substitution_id: i32, + pub teacher_id: i32, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_subjects)] +#[diesel(belongs_to(Substitution))] +#[diesel(belongs_to(Subject))] +pub struct SubstitutionSubject { + pub id: i32, + pub substitution_id: i32, + pub subject_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_subjects)] +pub struct NewSubstitutionSubject { + pub substitution_id: i32, + pub subject_id: i32, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_rooms)] +#[diesel(belongs_to(Substitution))] +#[diesel(belongs_to(Room))] +pub struct SubstitutionRoom { + pub id: i32, + pub substitution_id: i32, + pub room_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_rooms)] +pub struct NewSubstitutionRoom { + pub substitution_id: i32, + pub room_id: i32, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_planned_queries)] +#[diesel(belongs_to(Schoolyear))] +pub struct SubstitutionPlannedQuery { + pub id: i32, + pub schoolyear_id: i32, + pub date: NaiveDate, + pub active: bool, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_planned_queries)] +pub struct NewSubstitutionPlannedQuery { + pub schoolyear_id: i32, + pub date: NaiveDate, + pub active: bool, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_queries)] +#[diesel(belongs_to(SubstitutionPlannedQuery))] +pub struct SubstitutionQuery { + pub id: i32, + pub substitution_planned_query_id: i32, + pub queried_at: NaiveDateTime, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_queries)] +pub struct NewSubstitutionQuery { + pub substitution_planned_query_id: i32, + pub queried_at: NaiveDateTime, +} + +#[derive(Identifiable, Queryable, Associations, Debug)] +#[diesel(table_name = schema::substitution_query_results)] +#[diesel(belongs_to(SubstitutionQuery))] +#[diesel(belongs_to(Substitution))] +pub struct SubstitutionQueryResult { + pub id: i32, + pub substitution_query_id: i32, + pub substitution_id: i32, + pub created_at: NaiveDateTime, + pub updated_at: Option, +} + +#[derive(Insertable, Debug)] +#[diesel(table_name = schema::substitution_query_results)] +pub struct NewSubstitutionQueryResult { + pub substitution_query_id: i32, + pub substitution_id: i32, +} diff --git a/backend/src/db/schema.rs b/backend/src/db/schema.rs new file mode 100644 index 0000000..c904a19 --- /dev/null +++ b/backend/src/db/schema.rs @@ -0,0 +1,225 @@ +pub mod sql_types { + #[derive(diesel::sql_types::SqlType)] + #[diesel(postgres_type(name = "substitution_type"))] + pub struct SubstitutionType; +} + +diesel::table! { + schoolyears { + id -> Integer, + untis_id -> Integer, + name -> VarChar, + start_date -> Date, + end_date -> Date, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + tenants { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + active -> Bool, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + teachers { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + forename -> Nullable, + display_name -> VarChar, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + classes { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + long_name -> VarChar, + active -> Bool, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + subjects { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + long_name -> VarChar, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + rooms { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + long_name -> VarChar, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + departments { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + long_name -> VarChar, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + holidays { + id -> Integer, + untis_id -> Integer, + schoolyear_id -> Integer, + name -> VarChar, + long_name -> VarChar, + start_date -> Date, + end_date -> Date, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + timegrids { + id -> Integer, + schoolyear_id -> Integer, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + timegrid_days { + id -> Integer, + timegrid_id -> Integer, + #[sql_name = "day_index"] + day -> SmallInt, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + timegrid_time_unit { + id -> Integer, + timegrid_id -> Integer, + start_time -> Time, + end_time -> Time, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + use diesel::sql_types::*; + + use super::sql_types::SubstitutionType; + + substitutions { + id -> Integer, + subst_type -> SubstitutionType, + lesson_id -> Integer, + start_time -> Time, + end_time -> Time, + text -> Nullable, + active -> Bool, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_classes { + id -> Integer, + substitution_id -> Integer, + class_id -> Integer, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_teachers { + id -> Integer, + substitution_id -> Integer, + teacher_id -> Integer, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_subjects { + id -> Integer, + substitution_id -> Integer, + subject_id -> Integer, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_rooms { + id -> Integer, + substitution_id -> Integer, + room_id -> Integer, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_planned_queries { + id -> Integer, + schoolyear_id -> Integer, + date -> Date, + active -> Bool, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_queries { + id -> Integer, + substitution_planned_query_id -> Integer, + queried_at -> Timestamp, + created_at -> Timestamp, + updated_at -> Nullable, + } +} + +diesel::table! { + substitution_query_results { + id -> Integer, + substitution_query_id -> Integer, + substitution_id -> Integer, + created_at -> Timestamp, + updated_at -> Nullable, + } +} diff --git a/backend/src/graphql.rs b/backend/src/graphql.rs new file mode 100644 index 0000000..59cbe91 --- /dev/null +++ b/backend/src/graphql.rs @@ -0,0 +1,75 @@ +use juniper::{graphql_object, EmptyMutation, EmptySubscription, FieldResult, RootNode}; + +use crate::config; +use crate::db; + +#[derive(Clone, Debug)] +pub struct Context { + pub pool: db::DbPool, +} + +impl juniper::Context for Context {} + +#[derive(Clone, Debug)] + +pub struct Config; + +#[graphql_object(context = Context)] +impl Config { + fn name(&self) -> &str { + "BVplan" + } + + fn school(&self) -> &str { + &config::CONFIG.untis_school + } + + fn version(&self) -> &str { + env!("CARGO_PKG_VERSION") + } +} + +#[derive(Clone, Debug)] +pub struct Teacher { + pub id: i32, + pub display_name: String, +} + +#[graphql_object(context = Context)] +impl Teacher { + fn id(&self) -> i32 { + self.id + } + + fn display_name(&self) -> &str { + &self.display_name + } +} + +#[derive(Clone, Copy, Debug)] +pub struct Query; + +#[graphql_object(context = Context)] +impl Query { + fn ping() -> &str { + "pong" + } + + fn config() -> Config { + Config + } + + async fn teachers() -> Vec { + vec![] + } +} + +pub type Schema = RootNode<'static, Query, EmptyMutation, EmptySubscription>; + +pub fn schema() -> Schema { + Schema::new( + Query, + EmptyMutation::::new(), + EmptySubscription::::new(), + ) +} diff --git a/backend/src/lib.rs b/backend/src/lib.rs new file mode 100644 index 0000000..5f89f11 --- /dev/null +++ b/backend/src/lib.rs @@ -0,0 +1,5 @@ +pub mod config; +pub mod db; +pub mod graphql; +pub mod untis; +pub mod worker; diff --git a/backend/src/untis.rs b/backend/src/untis.rs new file mode 100644 index 0000000..4760420 --- /dev/null +++ b/backend/src/untis.rs @@ -0,0 +1,717 @@ +use anyhow::{bail, Context, Result}; +use chrono::Datelike; +use cookie::Cookie; +use serde::Deserialize; +use serde_json::json; + +pub const CLIENT_NAME: &str = "BVplan@OHG-Furtwangen"; + +fn deserialize_date<'de, D>(deserializer: D) -> Result +where + D: serde::de::Deserializer<'de>, +{ + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = chrono::NaiveDate; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a naive date serialized as an unsigned integer") + } + + fn visit_u64(self, mut v: u64) -> Result + where + E: serde::de::Error, + { + let y = (v / 10000) as i32; + v %= 10000; + let m = (v / 100) as u32; + v %= 100; + + match chrono::NaiveDate::from_ymd_opt(y, m, v as u32) { + Some(x) => Ok(x), + None => Err(E::custom(format!("No such date: {}-{}-{}", y, m, v))), + } + } + } + + deserializer.deserialize_u64(Visitor) +} + +fn serialize_date(date: chrono::NaiveDate) -> u64 { + date.year() as u64 * 10000 + date.month() as u64 * 100 + date.day() as u64 +} + +fn deserialize_time<'de, D>(deserializer: D) -> Result +where + D: serde::de::Deserializer<'de>, +{ + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = chrono::NaiveTime; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a naive time serialized as an unsigned integer") + } + + fn visit_u64(self, mut v: u64) -> Result + where + E: serde::de::Error, + { + let h = v / 100; + v %= 100; + + match chrono::NaiveTime::from_hms_opt(h as u32, v as u32, 0) { + Some(x) => Ok(x), + None => Err(E::custom(format!("No such time: {}:{}", h, v))), + } + } + } + + deserializer.deserialize_u64(Visitor) +} + +#[derive(Deserialize, Debug)] +pub struct RpcError { + pub message: String, + pub code: i32, +} + +#[derive(Deserialize, Debug)] +pub struct RpcResponse { + pub jsonrpc: String, + pub id: String, + pub result: Option, + pub error: Option, +} + +#[derive(Deserialize, Debug)] +struct RpcEmptyResult; + +#[derive(Deserialize, Debug)] +pub struct RpcLogin { + #[serde(rename = "sessionId")] + pub session_id: String, + #[serde(rename = "personType")] + pub person_type: i32, + #[serde(rename = "personId")] + pub person_id: i32, + #[serde(rename = "klasseId")] + pub class_id: i32, +} + +#[derive(Deserialize, Debug)] +pub struct RpcClass { + pub id: i32, + pub name: String, + #[serde(rename = "longName")] + pub long_name: String, + pub active: bool, +} + +#[derive(Deserialize, Debug)] +pub struct RpcSubject { + pub id: i32, + pub name: String, + #[serde(rename = "longName")] + pub long_name: String, +} + +#[derive(Deserialize, Debug)] +pub struct RpcRoom { + pub id: i32, + pub name: String, + #[serde(rename = "longName")] + pub long_name: String, +} + +#[derive(Deserialize, Debug)] +pub struct RpcDepartment { + pub id: i32, + pub name: String, + #[serde(rename = "longName")] + pub long_name: String, +} + +#[derive(Deserialize, Debug)] +pub struct RpcHoliday { + pub id: i32, + pub name: String, + #[serde(rename = "longName")] + pub long_name: String, + #[serde(rename = "startDate", deserialize_with = "deserialize_date")] + pub start_date: chrono::NaiveDate, + #[serde(rename = "endDate", deserialize_with = "deserialize_date")] + pub end_date: chrono::NaiveDate, +} + +#[derive(Deserialize, Debug)] +pub struct RpcTimegridDayTimeUnit { + #[serde(rename = "startTime", deserialize_with = "deserialize_time")] + pub start_time: chrono::NaiveTime, + #[serde(rename = "endTime", deserialize_with = "deserialize_time")] + pub end_time: chrono::NaiveTime, +} + +#[derive(Deserialize, Debug)] +pub struct RpcTimegridDay { + pub day: u8, + #[serde(rename = "timeUnits")] + pub time_units: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct RpcSchoolyear { + pub id: i32, + pub name: String, + #[serde(rename = "startDate", deserialize_with = "deserialize_date")] + pub start_date: chrono::NaiveDate, + #[serde(rename = "endDate", deserialize_with = "deserialize_date")] + pub end_date: chrono::NaiveDate, +} + +#[derive(Deserialize, Clone, Copy, Debug)] +pub enum RpcSubstitionType { + #[serde(rename = "cancel")] + Cancel, + #[serde(rename = "subst")] + Substitution, + #[serde(rename = "add")] + Additional, + #[serde(rename = "shift")] + Shifted, + #[serde(rename = "rmchg")] + RoomChange, + #[serde(rename = "rmlk")] + Locked, + #[serde(rename = "bs")] + BreakSupervision, + #[serde(rename = "oh")] + OfficeHour, + #[serde(rename = "sb")] + Standby, + #[serde(rename = "other")] + Other, + #[serde(rename = "free")] + Free, + #[serde(rename = "exam")] + Exam, + #[serde(rename = "ac")] + Activity, + #[serde(rename = "holi")] + Holiday, + #[serde(rename = "stxt")] + Text, +} + +#[derive(Deserialize, Debug)] +pub struct RpcSubstitutionId { + pub id: i32, + pub name: Option, +} + +#[derive(Deserialize, Debug)] +pub struct RpcSubstitutionReschedule { + #[serde(deserialize_with = "deserialize_date")] + pub date: chrono::NaiveDate, + #[serde(rename = "startTime", deserialize_with = "deserialize_time")] + pub start_time: chrono::NaiveTime, + #[serde(rename = "endTime", deserialize_with = "deserialize_time")] + pub end_time: chrono::NaiveTime, +} + +#[derive(Deserialize, Debug)] +pub struct RpcSubstitution { + #[serde(rename = "type")] + pub subst_type: RpcSubstitionType, + #[serde(rename = "lsid")] + pub lesson_id: i32, + #[serde(rename = "startTime", deserialize_with = "deserialize_time")] + pub start_time: chrono::NaiveTime, + #[serde(rename = "endTime", deserialize_with = "deserialize_time")] + pub end_time: chrono::NaiveTime, + #[serde(rename = "txt")] + pub text: Option, + #[serde(rename = "kl")] + pub classes: Vec, + #[serde(rename = "te")] + pub teachers: Vec, + #[serde(rename = "su")] + pub subjects: Vec, + #[serde(rename = "ro")] + pub rooms: Vec, + pub reschedule: Option, +} + +#[derive(Deserialize, Debug)] +pub struct ApiTenant { + pub id: i32, + #[serde(rename = "displayName")] + pub display_name: String, +} + +#[derive(Deserialize, Debug)] +struct ApiDataResponse { + tenant: ApiTenant, +} + +#[derive(Deserialize, Debug)] +pub struct ApiTeacher { + pub id: i32, + pub name: String, + pub forename: String, + #[serde(rename = "longName")] + pub long_name: String, + #[serde(rename = "displayname")] + pub display_name: String, +} + +#[derive(Deserialize, Debug)] +struct ApiTeachersResponseData { + elements: Vec, +} + +#[derive(Deserialize, Debug)] +struct ApiTeachersResponse { + data: ApiTeachersResponseData, +} + +#[derive(Debug)] +pub struct Client { + pub api_url: url::Url, + pub rpc_url: url::Url, + pub username: String, + pub password: String, + pub session: Option, + pub authorization: Option, +} + +impl Client { + pub fn gen_rpc_url(mut endpoint: url::Url, school: &str) -> url::Url { + endpoint.query_pairs_mut().append_pair("school", school); + + endpoint + } + + pub async fn login_rpc(&mut self) -> Result { + let resp: RpcResponse = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .json(&json!({ + "id": "ID", + "method": "authenticate", + "params": { + "user": self.username, + "password": self.password, + "client": CLIENT_NAME, + }, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + self.session = Some( + Cookie::new( + "JSESSIONID", + &resp + .result + .as_ref() + .context("Result null event though error not")? + .session_id, + ) + .to_string(), + ); + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn login_api(&mut self) -> Result { + let jwt = reqwest::Client::new() + .get(self.api_url.join("token/new")?) + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .send() + .await? + .text() + .await?; + self.authorization = Some(jwt.to_string()); + + Ok(jwt) + } + + pub async fn login(&mut self) -> Result<()> { + self.login_rpc().await?; + self.login_api().await?; + + Ok(()) + } + + pub async fn logout(&mut self) -> Result<()> { + let resp: RpcResponse = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "logout", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + self.session = None; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + Ok(()) + } + + pub async fn classes(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getKlassen", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn subjects(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getSubjects", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn rooms(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getRooms", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn departments(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getDepartments", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn holidays(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getHolidays", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn timegrid(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getTimegridUnits", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn current_schoolyear(&self) -> Result { + let resp: RpcResponse = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getCurrentSchoolyear", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn schoolyears(&self) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getSchoolyears", + "params": {}, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub async fn substitutions( + &self, + from: &chrono::NaiveDate, + to: &chrono::NaiveDate, + department: Option, + ) -> Result> { + let resp: RpcResponse> = reqwest::Client::new() + .get(self.rpc_url.as_str()) + .header(reqwest::header::CONTENT_TYPE, "application/json") + .header(reqwest::header::ACCEPT, "application/json-rpc") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .json(&json!({ + "id": "ID", + "method": "getSubstitutions", + "params": { + "startDate": serialize_date(*from), + "endDate": serialize_date(*to), + "departmentId": department.map_or(0, |d| d) + }, + "jsonrpc": "2.0" + })) + .send() + .await? + .json() + .await?; + if let Some(e) = resp.error { + bail!("RPC error: {:?}", e); + } + + if let Some(x) = resp.result { + Ok(x) + } else { + bail!("RPC result is null"); + } + } + + pub fn construct_bearer(auth: &str) -> String { + format!("Bearer {}", auth) + } + + pub async fn current_tenant(&self) -> Result { + let resp: ApiDataResponse = reqwest::Client::new() + .get(self.api_url.join("rest/view/v1/app/data")?) + .header(reqwest::header::ACCEPT, "application/json") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .header( + reqwest::header::AUTHORIZATION, + Client::construct_bearer(&self.authorization.as_ref().context("Not logged in")?), + ) + .send() + .await? + .json() + .await?; + + Ok(resp.tenant) + } + + pub async fn teachers(&self) -> Result> { + let mut url = self.api_url.join("public/timetable/weekly/pageconfig")?; + url.query_pairs_mut().append_pair("type", "2"); + let resp: ApiTeachersResponse = reqwest::Client::new() + .get(url) + .header(reqwest::header::ACCEPT, "application/json") + .header( + reqwest::header::COOKIE, + self.session.as_ref().context("Not logged in")?, + ) + .header( + reqwest::header::AUTHORIZATION, + Client::construct_bearer(&self.authorization.as_ref().context("Not logged in")?), + ) + .send() + .await? + .json() + .await?; + + Ok(resp.data.elements) + } + + pub async fn exams(&self) -> Result<()> { + Ok(()) + } +} diff --git a/backend/src/worker/mod.rs b/backend/src/worker/mod.rs new file mode 100644 index 0000000..3d323cc --- /dev/null +++ b/backend/src/worker/mod.rs @@ -0,0 +1,76 @@ +use celery::beat::DeltaSchedule; +use celery::broker::AMQPBroker; +use lazy_static::lazy_static; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time; + +use crate::config; + +pub mod update_info; + +pub const QUEUE_NAME: &str = "celery"; + +lazy_static! { + pub static ref APP: Mutex>>> = Mutex::new(None); +} + +#[tokio::main] +pub async fn init() { + *APP.lock().unwrap() = Some( + celery::app!( + broker = AMQPBroker { &config::CONFIG.amqp_url }, + tasks = [ + update_info::update_info, + ], + task_routes = [ + "*" => QUEUE_NAME, + ], + prefetch_count = 2, + heartbeat = Some(10) + ) + .await + .unwrap(), + ); +} + +pub fn init_blocking() { + thread::spawn(|| { + tokio::runtime::Runtime::new().unwrap().spawn_blocking(init); + }); + + let dur = time::Duration::from_secs(1); + let mut i = 0; + loop { + if APP.lock().unwrap().is_some() { + break; + } + thread::sleep(dur); + i += 1; + + if i >= 10 { + panic!("Worker not initialized after 10 seconds!"); + } + } +} + +pub fn beat() -> impl std::future::Future< + Output = Result< + celery::beat::Beat, + celery::error::BeatError, + >, +> { + celery::beat!( + broker = AMQPBroker { &config::CONFIG.amqp_url }, + tasks = [ + "update_info_" => { + update_info::update_info, + schedule = DeltaSchedule::new(time::Duration::from_secs(60)), + args = (), + } + ], + task_routes = [ + "*" => QUEUE_NAME, + ] + ) +} diff --git a/backend/src/worker/update_info.rs b/backend/src/worker/update_info.rs new file mode 100644 index 0000000..871c81a --- /dev/null +++ b/backend/src/worker/update_info.rs @@ -0,0 +1,356 @@ +use anyhow::Result; +use celery::error::TaskError; +use celery::task::TaskResult; +use chrono::prelude::*; +use diesel::prelude::*; +use now::DateTimeNow; + +use crate::config; +use crate::db; +use crate::untis; + +async fn fetch_schoolyears(client: &untis::Client, conn: &mut PgConnection) -> Result { + let existing_schoolyears = db::schema::schoolyears::table + .select(db::schema::schoolyears::untis_id) + .load::(conn)?; + diesel::insert_into(db::schema::schoolyears::table) + .values( + &client + .schoolyears() + .await? + .iter() + .filter(|y| !existing_schoolyears.contains(&y.id)) + .map(|y| db::models::NewSchoolyear { + untis_id: y.id, + name: &y.name, + start_date: y.start_date, + end_date: y.end_date, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(db::schema::schoolyears::table + .filter(db::schema::schoolyears::untis_id.eq(client.current_schoolyear().await?.id)) + .select(db::schema::schoolyears::id) + .first(conn)?) +} + +async fn fetch_current_tenant( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let tenant = client.current_tenant().await?; + if diesel::select(diesel::dsl::not(diesel::expression::exists::exists( + db::schema::tenants::table.filter(db::schema::tenants::untis_id.eq(tenant.id)), + ))) + .get_result::(conn)? + { + diesel::update(db::schema::tenants::table) + .filter(db::schema::tenants::active) + .set(db::schema::tenants::active.eq(false)) + .execute(conn)?; + diesel::insert_into(db::schema::tenants::table) + .values(db::models::NewTenant { + untis_id: tenant.id, + schoolyear_id, + name: &tenant.display_name, + active: true, + }) + .execute(conn)?; + } else if diesel::select(diesel::expression::exists::exists( + db::schema::tenants::table + .filter(db::schema::tenants::untis_id.eq(tenant.id)) + .filter(db::schema::tenants::active.eq(false)), + )) + .get_result::(conn)? + { + diesel::update(db::schema::tenants::table) + .filter(db::schema::tenants::active) + .set(( + db::schema::tenants::active.eq(false), + db::schema::tenants::updated_at.eq(diesel::dsl::now), + )) + .execute(conn)?; + diesel::update(db::schema::tenants::table) + .filter(db::schema::tenants::untis_id.eq(tenant.id)) + .set(( + db::schema::tenants::active.eq(true), + db::schema::tenants::updated_at.eq(diesel::dsl::now), + )) + .execute(conn)?; + } + + Ok(()) +} + +async fn fetch_teachers( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let existing_teachers = db::schema::teachers::table + .select(db::schema::teachers::untis_id) + .filter(db::schema::teachers::schoolyear_id.eq(schoolyear_id)) + .load::(conn)?; + diesel::insert_into(db::schema::teachers::table) + .values( + &client + .teachers() + .await? + .iter() + .filter(|t| !existing_teachers.contains(&t.id)) + .map(|t| db::models::NewTeacher { + untis_id: t.id, + schoolyear_id, + name: &t.name, + forename: if t.forename.is_empty() { + None + } else { + Some(&t.forename) + }, + display_name: &t.display_name, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(()) +} + +async fn fetch_classes( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let existing_classes = db::schema::classes::table + .select(db::schema::classes::untis_id) + .filter(db::schema::classes::schoolyear_id.eq(schoolyear_id)) + .load::(conn)?; + diesel::insert_into(db::schema::classes::table) + .values( + &client + .classes() + .await? + .iter() + .filter(|c| !existing_classes.contains(&c.id)) + .map(|c| db::models::NewClass { + untis_id: c.id, + schoolyear_id, + name: &c.name, + long_name: &c.long_name, + active: c.active, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(()) +} + +async fn fetch_subjects( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let existing_classes = db::schema::subjects::table + .select(db::schema::subjects::untis_id) + .filter(db::schema::subjects::schoolyear_id.eq(schoolyear_id)) + .load::(conn)?; + diesel::insert_into(db::schema::subjects::table) + .values( + &client + .subjects() + .await? + .iter() + .filter(|c| !existing_classes.contains(&c.id)) + .map(|c| db::models::NewSubject { + untis_id: c.id, + schoolyear_id, + name: &c.name, + long_name: &c.long_name, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(()) +} + +async fn fetch_rooms( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let existing_classes = db::schema::rooms::table + .select(db::schema::rooms::untis_id) + .filter(db::schema::rooms::schoolyear_id.eq(schoolyear_id)) + .load::(conn)?; + diesel::insert_into(db::schema::rooms::table) + .values( + &client + .rooms() + .await? + .iter() + .filter(|c| !existing_classes.contains(&c.id)) + .map(|c| db::models::NewRoom { + untis_id: c.id, + schoolyear_id, + name: &c.name, + long_name: &c.long_name, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(()) +} + +async fn fetch_departments( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let existing_classes = db::schema::departments::table + .select(db::schema::departments::untis_id) + .filter(db::schema::departments::schoolyear_id.eq(schoolyear_id)) + .load::(conn)?; + diesel::insert_into(db::schema::departments::table) + .values( + &client + .departments() + .await? + .iter() + .filter(|c| !existing_classes.contains(&c.id)) + .map(|c| db::models::NewDepartment { + untis_id: c.id, + schoolyear_id, + name: &c.name, + long_name: &c.long_name, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(()) +} + +async fn fetch_holidays( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let existing_classes = db::schema::holidays::table + .select(db::schema::holidays::untis_id) + .filter(db::schema::holidays::schoolyear_id.eq(schoolyear_id)) + .load::(conn)?; + diesel::insert_into(db::schema::holidays::table) + .values( + &client + .holidays() + .await? + .iter() + .filter(|c| !existing_classes.contains(&c.id)) + .map(|c| db::models::NewHoliday { + untis_id: c.id, + schoolyear_id, + name: &c.name, + long_name: &c.long_name, + start_date: c.start_date, + end_date: c.end_date, + }) + .collect::>(), + ) + .execute(conn)?; + + Ok(()) +} + +async fn fetch_substitutions( + client: &untis::Client, + conn: &mut PgConnection, + schoolyear_id: i32, +) -> Result<()> { + let now = Utc::now(); + let beginning_of_week = now.beginning_of_week().date_naive(); + let end_of_week = now.end_of_week().date_naive(); + // if diesel::select(diesel::dsl::not(diesel::expression::exists::exists( + // db::schema::substitution_queries::table + // .filter(db::schema::substitution_queries::active) + // .filter(db::schema::substitution_queries::end_date.eq(end_of_week)), + // ))) + // .get_result::(conn)? + // {} + + // for query in db::schema::substitution_queries::table + // .filter(db::schema::substitution_queries::active) + // .load::(conn)? + // { + // dbg!(&query); + // } + + Ok(()) +} + +#[celery::task] +pub async fn update_info() -> TaskResult<()> { + let mut client = untis::Client { + api_url: match url::Url::parse(&config::CONFIG.untis_api_url) { + Ok(x) => x, + Err(e) => return Err(TaskError::UnexpectedError(e.to_string())), + }, + rpc_url: match url::Url::parse(&config::CONFIG.untis_rpc_url) { + Ok(x) => untis::Client::gen_rpc_url(x, &config::CONFIG.untis_school), + Err(e) => return Err(TaskError::UnexpectedError(e.to_string())), + }, + username: config::CONFIG.untis_username.to_owned(), + password: config::CONFIG.untis_password.to_owned(), + session: None, + authorization: None, + }; + + if let Err(e) = client.login().await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + + let conn = &mut match db::POOL.get() { + Ok(x) => x, + Err(e) => return Err(TaskError::UnexpectedError(e.to_string())), + }; + + let schoolyear_id = match fetch_schoolyears(&client, conn).await { + Ok(x) => x, + Err(e) => return Err(TaskError::UnexpectedError(e.to_string())), + }; + if let Err(e) = fetch_current_tenant(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_teachers(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_classes(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_subjects(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_rooms(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_departments(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_holidays(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + if let Err(e) = fetch_substitutions(&client, conn, schoolyear_id).await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + + if let Err(e) = client.logout().await { + return Err(TaskError::UnexpectedError(e.to_string())); + } + + Ok(()) +} diff --git a/config/nginx/nginx.conf b/config/nginx/nginx.conf new file mode 100644 index 0000000..5d3b6a3 --- /dev/null +++ b/config/nginx/nginx.conf @@ -0,0 +1,51 @@ +events { + worker_connections 1024; +} + +http { + server_tokens off; + more_clear_headers Server; + + server { + # location / { + # proxy_pass http://frontend/; + # } + + location /graphql { + proxy_pass http://api/; + proxy_buffering off; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /adminer { + proxy_pass http://adminer:8080/; + proxy_buffering off; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~* /rabbitmq/api/(.*?)/(.*) { + proxy_pass http://rabbitmq:15672/api/$1/%2F/$2?$query_string; + proxy_buffering off; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~* /rabbitmq/(.*) { + rewrite ^/rabbitmq/(.*)$ /$1 break; + proxy_pass http://rabbitmq:15672; + proxy_buffering off; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..616230a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,81 @@ +version: "3" + +services: + nginx: + image: docker.io/byjg/nginx-extras + restart: always + volumes: + - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + ports: + - 80:80 + depends_on: + - adminer + - rabbitmq + - api + + postgres: + image: docker.io/postgres:alpine + restart: always + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - postgres:/var/lib/postgresql/data + + adminer: + image: docker.io/adminer:standalone + restart: always + depends_on: + - postgres + + rabbitmq: + image: docker.io/rabbitmq:3-management-alpine + restart: always + environment: + RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} + RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} + volumes: + - rabbitmq:/var/lib/rabbitmq + + worker: + image: git.dergrimm.net/dergrimm/bvplan_backend:latest + build: + context: ./backend + restart: always + command: worker + depends_on: + - postgres + - rabbitmq + environment: + BACKEND_DB_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_USER} + BACKEND_AMQP_URL: amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672 + BACKEND_UNTIS_API_URL: ${BACKEND_UNTIS_API_URL} + BACKEND_UNTIS_RPC_URL: ${BACKEND_UNTIS_RPC_URL} + BACKEND_UNTIS_SCHOOL: ${BACKEND_UNTIS_SCHOOL} + BACKEND_UNTIS_USERNAME: ${BACKEND_UNTIS_USERNAME} + BACKEND_UNTIS_PASSWORD: ${BACKEND_UNTIS_PASSWORD} + + api: + image: git.dergrimm.net/dergrimm/bvplan_backend:latest + build: + context: ./backend + restart: always + command: api + depends_on: + - postgres + - rabbitmq + - worker + environment: + BACKEND_DB_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_USER} + BACKEND_AMQP_URL: amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@rabbitmq:5672 + BACKEND_UNTIS_API_URL: ${BACKEND_UNTIS_API_URL} + BACKEND_UNTIS_RPC_URL: ${BACKEND_UNTIS_RPC_URL} + BACKEND_UNTIS_SCHOOL: ${BACKEND_UNTIS_SCHOOL} + BACKEND_UNTIS_USERNAME: ${BACKEND_UNTIS_USERNAME} + BACKEND_UNTIS_PASSWORD: ${BACKEND_UNTIS_PASSWORD} + +volumes: + postgres: + rabbitmq: + +