diff --git a/.env b/.env index 073a82a..4877cfb 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ -DATABASE_URL="auditorium_booking.sqlite3" +DATABASE_URL="auditorium__booking.sled.db" +SA_SECRET="epsteindidintkillhimself" diff --git a/.gitignore b/.gitignore index 55c8a99..c940294 100644 --- a/.gitignore +++ b/.gitignore @@ -155,4 +155,4 @@ dmypy.json .pyre/ # database -auditorium_booking.sqlite3 +auditorium__booking.sled.db/ diff --git a/Cargo.lock b/Cargo.lock index 151dfc9..8817cd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,22 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.13" @@ -27,13 +43,40 @@ name = "backend" version = "0.1.0" dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ferris_print 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rocket_cors 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scanln 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "sled 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tungstenite 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -58,16 +101,67 @@ name = "base64" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bincode" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.47" @@ -78,6 +172,31 @@ name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chrono" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -97,6 +216,58 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "core-foundation" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "devise" version = "0.2.0" @@ -127,30 +298,48 @@ dependencies = [ ] [[package]] -name = "diesel" -version = "1.4.3" +name = "digest" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "diesel_derives" -version = "1.4.1" +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "error-chain" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "dotenv" -version = "0.15.0" +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ferris-says" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ferris_print" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ferris-says 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "filetime" @@ -163,6 +352,33 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fsevent" version = "0.4.0" @@ -194,6 +410,37 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "half" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hermit-abi" version = "0.1.3" @@ -202,6 +449,16 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.4" @@ -235,6 +492,16 @@ dependencies = [ "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.3.0" @@ -261,6 +528,14 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "input_buffer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iovec" version = "0.1.4" @@ -303,15 +578,6 @@ name = "libc" version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libsqlite3-sys" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lock_api" version = "0.3.2" @@ -351,6 +617,14 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memoffset" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime" version = "0.2.6" @@ -399,6 +673,23 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "native-tls" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" @@ -409,6 +700,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "notify" version = "4.0.14" @@ -427,6 +723,23 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num_cpus" version = "1.11.1" @@ -436,25 +749,62 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl" +version = "0.10.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot" -version = "0.10.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.7.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -483,11 +833,21 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pkg-config" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -521,13 +881,40 @@ dependencies = [ ] [[package]] -name = "r2d2" -version = "0.8.7" +name = "rand" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scheduled-thread-pool 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -551,6 +938,14 @@ name = "regex-syntax" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ring" version = "0.13.5" @@ -600,27 +995,13 @@ name = "rocket_contrib" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", - "r2d2 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket_contrib_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rocket_contrib_codegen" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rocket_cors" version = "0.5.1" @@ -652,6 +1033,19 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ryu" version = "1.0.2" @@ -671,11 +1065,17 @@ dependencies = [ ] [[package]] -name = "scheduled-thread-pool" -version = "0.2.3" +name = "scanln" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "schannel" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -683,6 +1083,38 @@ name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "security-framework" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "1.0.103" @@ -691,6 +1123,24 @@ dependencies = [ "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_bytes" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_cbor" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_derive" version = "1.0.103" @@ -711,11 +1161,46 @@ dependencies = [ "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "sled" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "smallvec" version = "0.6.13" @@ -734,6 +1219,11 @@ name = "state" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" version = "0.15.44" @@ -754,6 +1244,27 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread_local" version = "0.3.6" @@ -785,11 +1296,35 @@ name = "traitobject" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "tungstenite" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "input_buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicase" version = "1.4.2" @@ -831,6 +1366,11 @@ dependencies = [ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -856,9 +1396,29 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "url" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf-8" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -881,6 +1441,11 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -939,35 +1504,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" +"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3" "checksum devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7" "checksum devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487" -"checksum diesel 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d7cc03b910de9935007861dce440881f69102aaaedfd4bc5a6f40340ca5840c" -"checksum diesel_derives 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum ferris-says 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07a21339b4ddc37834c200a769f0fa58919bfda64950abcc1b6438e8b50b32fd" +"checksum ferris_print 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "551b7de36d95eed82a45ccf641a5bb1d78ceb488dec4f1ecd17b3906d8cd8a23" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0" "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" +"checksum input_buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e1b822cc844905551931d6f81608ed5f50a79c1078a4e2b4d42dbc7c1eedfbf" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -975,73 +1572,108 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum libsqlite3-sys 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5b95e89c330291768dc840238db7f9e204fd208511ab6319b56193a7f2ae25" "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" -"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c26d2b92e47063ffce70d3e3b1bd097af121a9e0db07ca38a6cc1cf0cc85ff25" "checksum pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum r2d2 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "22b5c5fc5fba064373f03887337b412e0e1562d63023393db77251146cb75553" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a" "checksum rocket 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "42c1e9deb3ef4fa430d307bfccd4231434b707ca1328fae339c43ad1201cc6f7" "checksum rocket_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "79aa1366f9b2eccddc05971e17c5de7bb75a5431eb12c2b5c66545fd348647f4" "checksum rocket_contrib 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e0fa5c1392135adc0f96a02ba150ac4c765e27c58dbfd32aa40678e948f6e56f" -"checksum rocket_contrib_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "343da6694fc3cfd901242fd6efafc823e7a3a7f4948017a7dda7311775055092" "checksum rocket_cors 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "270a960cba5a0b7928ad74268db7773ce932da6b550478383cefebe9f46c4e13" "checksum rocket_http 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1391457ee4e80b40d4b57fa5765c0f2836b20d73bcbee4e3f35d93cf3b80817" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum scheduled-thread-pool 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f5de7bc31f28f8e6c28df5e1bf3d10610f5fdc14cc95f272853512c70a2bd779" +"checksum scanln 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b44c6898b219e294163a3c23916596b2c6225b1fefe468824d4c0c002c0a8bc6" +"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +"checksum serde_bytes 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45af0182ff64abaeea290235eb67da3825a576c5d53e642c4d5b652e12e6effc" +"checksum serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7081ed758ec726a6ed8ee7e92f5d3f6e6f8c3901b1f972e3a4a2f2599fad14f" "checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" "checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum sled 0.29.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d7c3453de0f6a77abdd17cc9f68d6650214abd088b052b13302f86fa9a5b286e" +"checksum smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" "checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +"checksum tungstenite 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a0c2bd5aeb7dcd2bb32e472c8872759308495e5eccc942e929a513cd8d36110" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicase_serde 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef53697679d874d69f3160af80bc28de12730a985d57bdf2b47456ccb8b11f1" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" +"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" +"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 5099664..05791a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,19 +3,30 @@ name = "backend" version = "0.1.0" authors = ["Dawid J. Kubis ", "Lukáš Hozda ", "Lukáš Veškrna "] edition = "2018" +default-run = "backend" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rocket = "0.4.2" dotenv = "0.15.0" -diesel = "1.4.3" serde = { version = "1.0.103", features = ["derive"] } serde_json = "1.0.42" rocket_cors = "0.5.1" base64 = "0.11.0" +sled = "0.29" +lazy_static = "1.4" +serde_cbor = "0.10.2" +ferris_print = "0.1" +scanln = "0.1" +yansi = "0.5" +tungstenite = "0.9.2" + +[dependencies.chrono] +version = "0.4.10" +features = ["serde"] [dependencies.rocket_contrib] version = "0.4.2" default-features = false -features = ["diesel_sqlite_pool", "json"] +features = ["json"] diff --git a/Dockerfile b/Dockerfile index 10adc14..77909f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,8 @@ FROM archlinux/base # dependencies -RUN pacman -Suy --noconfirm rustup make gcc pkgconf sqlite \ -python python-sqlalchemy yarn python-google-api-python-client python-pip -RUN pip install google_auth_oauthlib && rustup install nightly +RUN pacman -Suy --noconfirm rustup make gcc pkgconf yarn +RUN rustup install nightly # workdir WORKDIR /cw diff --git a/Rocket.toml b/Rocket.toml index 64d6599..337b8f2 100644 --- a/Rocket.toml +++ b/Rocket.toml @@ -1,5 +1,2 @@ -[global.databases] -postgres_db = { url = "auditorium_booking.sqlite3" } - [production] port = 8000 diff --git a/diesel.toml b/diesel.toml deleted file mode 100644 index 92267c8..0000000 --- a/diesel.toml +++ /dev/null @@ -1,5 +0,0 @@ -# For documentation on how to configure this file, -# see diesel.rs/guides/configuring-diesel-cli - -[print_schema] -file = "src/schema.rs" diff --git a/frontend b/frontend index 1644a3c..3222c4d 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 1644a3ca57ec9c1d7662e4cff996dac7b8e3e3d6 +Subproject commit 3222c4d1624aef3271c4e7e41ac0deba09aa777e diff --git a/rgi/booking/mail.py b/mail.py similarity index 100% rename from rgi/booking/mail.py rename to mail.py diff --git a/migrations/.gitkeep b/migrations/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/migrations/2019-11-26-164900_reservations/down.sql b/migrations/2019-11-26-164900_reservations/down.sql deleted file mode 100644 index 8b807d3..0000000 --- a/migrations/2019-11-26-164900_reservations/down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE "booking" diff --git a/migrations/2019-11-26-164900_reservations/up.sql b/migrations/2019-11-26-164900_reservations/up.sql deleted file mode 100644 index 71a07a0..0000000 --- a/migrations/2019-11-26-164900_reservations/up.sql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE TABLE "booking" ( - "id" INTEGER NOT NULL UNIQUE, - "name" TEXT NOT NULL, - "description" TEXT NOT NULL, - "author" TEXT NOT NULL, - "rooms" INTEGER NOT NULL, - "begin_time" TEXT NOT NULL, - "end_time" TEXT NOT NULL, - "layout" INTEGER NOT NULL, - "approved" INTEGER NOT NULL, - PRIMARY KEY("id") -); diff --git a/migrations/2019-11-28-112102_users/down.sql b/migrations/2019-11-28-112102_users/down.sql deleted file mode 100644 index e60ba1b..0000000 --- a/migrations/2019-11-28-112102_users/down.sql +++ /dev/null @@ -1,2 +0,0 @@ --- This file should undo anything in `up.sql` -DROP TABLE "users" diff --git a/migrations/2019-11-28-112102_users/up.sql b/migrations/2019-11-28-112102_users/up.sql deleted file mode 100644 index 2fd6966..0000000 --- a/migrations/2019-11-28-112102_users/up.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Your SQL goes here -CREATE TABLE "users" ( - "id" INTEGER NOT NULL UNIQUE, - "name" TEXT NOT NULL, - "email" TEXT NOT NULL, - "role" TEXT NOT NULL, - PRIMARY KEY("id") -) diff --git a/migrations/2019-11-28-120105_people_amount/down.sql b/migrations/2019-11-28-120105_people_amount/down.sql deleted file mode 100644 index 291a97c..0000000 --- a/migrations/2019-11-28-120105_people_amount/down.sql +++ /dev/null @@ -1 +0,0 @@ --- This file should undo anything in `up.sql` \ No newline at end of file diff --git a/migrations/2019-11-28-120105_people_amount/up.sql b/migrations/2019-11-28-120105_people_amount/up.sql deleted file mode 100644 index 12b8a6a..0000000 --- a/migrations/2019-11-28-120105_people_amount/up.sql +++ /dev/null @@ -1,3 +0,0 @@ --- Your SQL goes here -ALTER TABLE "booking" - ADD COLUMN "people" UNSIGNED INT NOT NULL DEFAULT '0'; diff --git a/rgi/booking/booking.py b/rgi/booking/booking.py deleted file mode 100755 index 6fb75c5..0000000 --- a/rgi/booking/booking.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 - -from sqlalchemy.ext.declarative import DeclarativeMeta -from sqlalchemy.ext.automap import automap_base -from sqlalchemy.orm import Session -from sqlalchemy import create_engine -from mail import send_request, send_approval, send_denial -import sys -import json -import os -import re - - -Base = automap_base() -engine = create_engine("sqlite:///" + os.getenv("DATABASE_URL")) -Base.prepare(engine, reflect=True) -Booking = Base.classes.booking -User = Base.classes.users -session = Session(engine) - -approver = "xsicp01@gjk.cz" - - -class AlchemyEncoder(json.JSONEncoder): - - def default(self, obj): - if isinstance(obj.__class__, DeclarativeMeta): - # an SQLAlchemy class - fields = {} - for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']: - if field == "classes" or field == "prepare": - continue - data = obj.__getattribute__(field) - try: - json.dumps(data) # this will fail on non-encodable values, like other classes - fields[field] = data - except TypeError: - fields[field] = None - # a json-encodable dict - return fields - - return json.JSONEncoder.default(self, obj) - - -def get(data): - """ - Get data from the database - :param data: {id} - :return: Booking dictionary or {result: number} - """ - results = session.query(Booking).filter(Booking.id == data["args"]["id"]).all() - if len(results) == 1: - result = results[0] - user = session.query(Booking).filter(User.email == result.author).all() - setattr(result, "author_name", user[0].name) - return json.dumps(result, cls=AlchemyEncoder) - else: - return json.dumps({"result": 1}) - - -def list_(data): - """ - List all the data - :param data: - :return: {results: array of result} - """ - results = session.query(Booking).all() - return json.dumps(results, cls=AlchemyEncoder) - - -def post(data): - """ - Adds new data to db - :param data: Booking dictionary by it's id - :return: {result: number} - """ - - result = Booking() - for key, value in data["data"].items(): - if value is None: - continue - setattr(result, key, value) - setattr(result, "approved", False) - setattr(result, "author", data["args"]["email"]) - - events = session.query(Booking).filter(Booking.approved == 1).\ - filter(Booking.begin_time <= result.end_time).\ - filter(Booking.end_time >= result.begin_time) - for event in events: - if event.rooms == 3: - return json.dumps({"result": 2}) - elif event.rooms == result.rooms: - return json.dumps({"result": 2}) - - session.add(result) - session.commit() - return json.dumps({"result": 0, "id": result.id}) - - -def filter(data): - """ - filer data by room flag, begin_time and start_time - :param data: roomflag(0/1/2/3), begin_time and start_time - :return: {results: array of result} - """ - - reservations = session.query(Booking).filter(Booking.begin_time <= data["args"]["end_time"]).\ - filter(Booking.end_time >= data["args"]["begin_time"]) - if data["args"]["rooms"] != 3: - reservations.filter(Booking.rooms == data["args"]["rooms"]) - - results = reservations.all() - return json.dumps({"results": results}, cls=AlchemyEncoder) - - - -def patch(data): - """ - Update data in the database - :param data: Booking dictionary - :return: {result: number} - """ - - results = session.query(Booking).filter(Booking.id == data["args"]["id"]).all() - if len(results) == 1: - result = results[0] - for key, value in data["data"].items(): - setattr(result, key, value) - session.add(result) - session.commit() - return json.dumps({"result": 0}) - else: - return json.dumps({"result": 1}) # no result found by the id - -def delete(data): - """ - Deletes event by it's id - :param data: {id} - :return: {result: number} - """ - - results = session.query(Booking).filter(Booking.id == data["args"]["id"]).all() - if len(results) == 1: - session.delete(results[0]) - session.commit() - return json.dumps({"result": 0}) - else: - return json.dumps({"result": 1}) # no result found by the id - -def approve(data): - """ - Approvs event by it's id - :param data: {id} - :return: ? - """ - - results = session.query(Booking).filter(Booking.id == data["args"]["id"]).all() - if len(results) == 1: - result = results[0] - events = session.query(Booking).filter(Booking.approved == 1).\ - filter(Booking.begin_time <= result.end_time).\ - filter(Booking.end_time >= result.begin_time) - for event in events: - if event.rooms == 3: - return json.dumps({"result": 2}) - elif event.rooms == result.rooms: - return json.dumps({"result": 2}) - - #send_approval("xsicp01@gjk.cz", "xsicp01@gjk.cz", result.rooms, result.begin_time, result.end_time) - result.approved = 1 - session.add(result) - session.commit() - return json.dumps({"result": 0}) - else: - return json.dumps({"result": 1}) # no result found by the id - - -methods = {"list": list_, "get": get, "post": post, "patch": patch, "delete": delete, "approve" : approve} -txt = sys.stdin.read() -txt = re.sub(",[ \t\r\n]+}", "}", txt) -txt = re.sub(",[ \t\r\n]+\]", "]", txt) -print(txt, file=sys.stderr) -data = json.loads(txt) -if len(sys.argv) < 2: - sys.stdout.write(methods["get"](data)) -else: - sys.stdout.write(methods[sys.argv[1].lower()](data)) -sys.stdout.flush() diff --git a/rgi/booking/curltest b/rgi/booking/curltest deleted file mode 100755 index fa3cb1f..0000000 --- a/rgi/booking/curltest +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -curl -H application/json localhost:8000/rgi/events/1 diff --git a/rgi/booking/mod.rs b/rgi/booking/mod.rs deleted file mode 100644 index 4473232..0000000 --- a/rgi/booking/mod.rs +++ /dev/null @@ -1,174 +0,0 @@ -use rocket::Route; -use rocket_contrib::json::Json; - -use crate::auth::AuthToken; -use crate::auth::roles::{Noob, Approver, Role}; - -use crate::db; -use crate::db::{NewReservation, UpdateReservation, Reservation}; - -use diesel::prelude::*; - -/* -** TODO proper type for response, handle RGI responses -*/ - -/// vrací všechny rezervace -/// -/// GET /events "application/json" -#[get("/events")] -pub fn list() -> String { - rgi! { - LIST "rgi/booking/booking.py" - } -} - -/// vrátí JSON dané rezervace -/// -/// GET /events/ application/json -/// -/// parametry: -/// - `id`: identifikátor dané rezervace -#[get("/events/")] -pub fn get(id: i32, _u: AuthToken) -> Option { - if id < 0 { - None? - } - - Some(rgi! { - GET "rgi/booking/booking.py" - arg: id - }) -} - -/// vrátí JSON dané rezervace -/// -/// POST /events application/json -/// -/// data: [`NewReservation`] -#[post("/events", data = "<_input>")] -pub fn post(_input: Json, usr: AuthToken) -> String { - let name = usr.user.name.clone(); - let user_id = usr.user.id.clone(); - let email = usr.user.email.clone(); - - rgi! { - POST "rgi/booking/booking.py" - arg: user_id, - arg: email, - arg: name - data: (&_input.into_inner()) - } -} - -/// upraví danou rezervaci -/// -/// PATCH /events/ application/json -/// -/// parametry: -/// - `id`: identifikátor dané rezervace -/// -/// data:[`UpdateReservation`] -#[patch("/events/", data = "<_input>")] -pub fn patch(r_id: i32, _input: Json, usr: AuthToken) -> Option { - let name = usr.user.name.clone(); - let user_id = usr.user.id.clone(); - let email = usr.user.email.clone(); - - // TODO return error instead of None on invalid states - if r_id < 0 { - None? - } - - if usr.user.role.to_lowercase() != Approver::name() { - use crate::schema::booking::dsl::*; - - let con = db::get_con(); - let reservation = booking.filter(id.eq(r_id)).first::(&con).ok()?; - - if reservation.author.trim() != usr.user.email.trim() { - None? // you shouldn't be able to edit others' events - } - } - - let id = r_id; - Some(rgi! { - PATCH "rgi/booking/booking.py" - arg: id, - arg: user_id, - arg: name, - arg: email - data: (&_input.into_inner()) - }) -} - -/// vymaže danou rezervaci -/// -/// DEL/// -/// parametry: -/// - `id`: identifikátor dané rezervace -#[delete("/events/")] -pub fn delete(r_id: i32, usr: AuthToken) -> Option { - // TODO return error instead of None on invalid states - if r_id < 0 { - None? - } - - if usr.user.role.to_lowercase() != Approver::name() { - use crate::schema::booking::dsl::*; - - let con = db::get_con(); - let reservation = booking.filter(id.eq(r_id)).first::(&con).ok()?; - - /*if reservation.author.trim() != usr.user.email.trim() { - println!("fuck"); - None? // you shouldn't be able to delete others' either - }*/ - } - - let id = r_id; - Some(rgi! { - DELETE "rgi/booking/booking.py" - arg: id - }) -} - -/// filtruje podle data -/// -/// GET /events/filter///end_time> -/// -/// parametry: -/// - `rooms`: bitflagy pro místnosti, viz [`Reservation`] -/// - `begin_time`: počáteční čas -/// - `end_time`: čas konce -#[get("/events/filter///")] -pub fn date_filter(rooms: i32, begin_time: String, end_time: String, _u: AuthToken) -> String { - rgi! { - FILTER "rgi/booking/booking.py" - arg: rooms, - arg: begin_time, - arg: end_time - } -} - -/// schválí endpoint -/// -/// POST /events//approve -/// -/// parametry: -/// - `id`: id rezervace -#[post("/events//approve")] -pub fn approve(id: i32, _u: AuthToken) -> Option { - if _u.user.role.to_lowercase() != Approver::name() { - None? - } - Some(rgi! { - APPROVE "rgi/booking/booking.py" - arg: id - }) -} - -/// vrací seznam endpointů pro nabindování do Rocketu -pub fn routes() -> Vec { - routes![date_filter, list, approve, get, post, patch, delete,] -} diff --git a/rgi/mod.rs b/rgi/mod.rs deleted file mode 100644 index 45599de..0000000 --- a/rgi/mod.rs +++ /dev/null @@ -1,83 +0,0 @@ -//! kořenový rgi modul (endpointy jsou tady, yee-haw) -//! -//! _"je to jako CGI, ale s Rustem"_ -//! -//! - -use rocket::Route; - -/// makro, které vygeneruje boilerplate pro volání daného rgi -/// -/// syntaxe (hranaté závorky značí, že parametr není povinný): -/// ```no_run -/// rgi! { -/// HTTP_METODA "rgi/cesta/k/rgi/binarce" -/// [arg: identifikátor]* // argumentem se myslí parametr z URL -/// [data: ]? // někdy je potřeba obalit do závorek () -/// } -/// ``` -/// (všechny argumenty a data musí implementovat `serialize` ze `serde`) -/// -/// příklad: -/// rgi! { -/// GET "rgi/lol/lol.py" -/// arg: name -/// arg: password -/// data: (Objekt) -/// } -#[macro_export] -macro_rules! rgi { - {$method:ident $name:literal $(arg: $arg:ident),* $(data: $data:tt)? } => { - { - // we need this lint to avoid warnings caused by extra parens - // which are not extra since they help the parser - #![allow(unused_parens)] - #[allow(unused_imports)] - use std::process::{Command, Stdio}; - #[allow(unused_imports)] - use std::io::{Read, Write}; - - let mut cmd = Command::new($name) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .arg(stringify!($method)) - .spawn() - .expect("kinda gay"); - - if let Some(ref mut stdin) = &mut cmd.stdin { - let _ = writeln!(stdin, "{{"); - let _ = writeln!(stdin, "\t\"args\": {{"); - $(let _ = writeln!(stdin, "\t\t\"{}\": \"{}\",", stringify!($arg), ($arg).to_string());)* - let _ = writeln!(stdin, "\t}},"); - $(let _ = writeln!(stdin, "\t\"data\": {}", serde_json::to_string($data).unwrap());)? - let _ = writeln!(stdin, "}}"); - } - - let cmd = cmd.wait_with_output().unwrap(); - - String::from_utf8_lossy(&cmd.stdout).to_string() - } - } -} - -/// modul obsahující endpointy pro CRUD na rezervaci -pub mod booking; - -/// sbírá jednotlivé endpointy -/// -/// přidání nového rgi -/// ```no_run -/// // deklarace modulu -/// mod muj_modul; -/// -/// // v routes.. -/// routes.extend(self::muj_modul::routes()); -/// ``` -pub fn routes() -> Vec { - let mut routes = vec![]; - - /*routes() funkce volat tady*/ - routes.extend(self::booking::routes()); - - routes -} diff --git a/src/admin.rs b/src/admin.rs new file mode 100644 index 0000000..4df5d44 --- /dev/null +++ b/src/admin.rs @@ -0,0 +1,55 @@ +//! a module containing admin functions +use rocket::Route; +use rocket_contrib::json::Json; + +use std::env; + +use crate::auth::AuthToken; +use crate::auth::roles::{Role, Superadmin}; + +use crate::db::{ + Database, + table::Reservations, + table::Users, +}; + +use crate::models::{User, Reservation}; + +/// generates a superadmin +#[post("/generate_sa//")] +pub fn generate_superadmin(email: String, password: String, mut db: Database) -> Option<()> { + if password != env::var("SA_SECRET").unwrap() { return None } + + db.write() + .insert(&email, User { email: email.clone(), name: "Superadmin".to_string(), role: Superadmin::name().to_string() }) + .ok()? + .map(|_| ()) +} + +/// get all users +#[get("/users", format = "application/json")] +pub fn users(db: Database, _u: AuthToken) -> Json> { + Json(db.read().iter().collect::>()) +} + +/// change user role +#[patch("/users//", format = "application/json")] +pub fn change_role(email: String, new_role: String, mut db: Database, _u: AuthToken) -> Option<()> { + if !["Noob", "Superadmin", "Approver", "FacilityManager"].contains(&new_role.as_str()) { + return None; + } + + db.write() + .update::<_, User, _>(email, |x| if let Some(mut x) = x { + x.role = new_role.clone(); + Some(x) + } else {None}).ok()?; + + Some(()) +} + + +/// returns a list of endpoints for rocket binding +pub fn routes() -> Vec { + routes![users, generate_superadmin, change_role] +} diff --git a/src/auth.rs b/src/auth.rs index b03a5df..f129c33 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,11 +1,11 @@ -//! modul s autentifikačními funkcemi +//! module with authentification functions //! -//! ## přidání autorizace k endpointu -//! stačí přidat AuthToken parametr s typem +//! ## adding authorization to endpoint +//! it's sufficient to add a AuthToken parameter with the corresponding type //! ```no_run //! #[get("/supersecretstuff")] //! pub fn example(_u: AuthToken) { -//! +//! ... //! } //!``` @@ -17,87 +17,120 @@ use rocket::http::Status; use base64::decode; -use diesel::prelude::*; - use std::marker::PhantomData; -use crate::db; -use crate::db::{NewUser, User}; +use crate::db::{ + Database, + table::Users, +}; +use crate::models::User; -/// autorizační token, tak jak je přijat -#[derive(Serialize, Deserialize)] +/// authorization token, the way it's recieved +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct AuthTokenRaw { - /// jméno uživatele + /// user name pub name: String, - /// email uživatele + /// user email pub email: String, } -/// autorizační token po vyřešení údajů s databází -#[derive(Serialize, Deserialize)] -pub struct AuthToken { - /// nalezený uživatel +impl AuthTokenRaw { + /// converts a raw AuthToken into user + pub fn into_user(self) -> User { + use self::roles::Role; + + User { + name: self.name, + email: self.email, + role: roles::Noob::name().to_string(), + } + } +} + +/// authorization token after resolving the details with the database +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct AuthToken { + /// the found user pub user: User, + /// marker for role resolution + pub _m: PhantomData, } -impl AuthToken { +impl AuthToken { /// sestrojí nový AuthToken z instace [`User`] pub fn from_user(user: User) -> Self { - AuthToken { user } + AuthToken { user, _m: PhantomData } } } -/// obsahuje nulové typy pro role -/// tento design umožňužje zneužít funkce Rustu pro deklarativní -/// ověření -> pouze stačí do routy přidat parametr s typem `AuthToken`. +/// contains zero-sized types that describe roles +/// this design allows abusing Rust's functionality for declarative +/// verification - it's sufficient to add AuthToken to route parameters /// -/// současné role a jejich stringy (stringy jsou case-insensitive): +/// the roles and their strings (case-insensitive) : /// - [`roles::Noob`] -> `noob` /// - [`roles::Approver`] -> `approver` /// - [`roles::FacilityManager`] -> `facilitymanager` pub mod roles { #![allow(dead_code, missing_docs)] - /// sdílený trait pro role - /// velmi rudimentárním způsobem reprezentuje hierarchii + /// common trait for roles + /// comes with basic compile-time hierarchy pub trait Role { - /// jméno role jako string + /// this role's daddy, can be set to self if role is root + type Daddy: Role; + + /// name of role as str fn name() -> &'static str; - /// jméno rodiše jako string - fn daddy() -> Option<&'static str> { - None + + /// whether the role is root role + fn is_root() -> bool { false } + + /// the parent's name as string + fn resolve_daddy() -> Vec<&'static str> { + if Self::is_root() { + vec![] + } else { + let mut v = vec![Self::name()]; + v.append(&mut Self::Daddy::resolve_daddy()); + v + } } } macro_rules! role_gen { - {$(($role:ident -> $daddy:expr))*} => { + {$($role:ident [$daddy:ident] $(-> $is_root:literal)? ),* $(,)?} => { $( pub struct $role; impl Role for $role { + type Daddy = $daddy; fn name() -> &'static str { stringify!($role) } - fn daddy() -> Option<&'static str> { $daddy } + $(fn is_root() -> bool { $is_root })? } )* } } role_gen! { - (Noob -> None) - (Approver -> Some("noob")) - (FacilityManager -> Some("noob")) + Noob[Noob] -> true, + Approver[Noob] -> false, + FacilityManager[Noob] -> false, + Superadmin[Approver] -> false, } } -impl<'a, 'r> FromRequest<'a, 'r> for AuthToken { +impl<'a, 'r, T: roles::Role> FromRequest<'a, 'r> for AuthToken { type Error = String; fn from_request(request: &'a Request<'r>) -> Outcome { - use crate::schema::users::dsl::*; + let mut db = match Database::::open() { + Some(d) => d, + None => return Outcome::Failure((Status::InternalServerError, "failed to connect to db".to_string())), + }; let keys: Vec<_> = request.headers().get("Authorization").collect(); match keys.get(0).unwrap_or(&"").split(' ').nth(1) { Some(ref token) => { - eprintln!("decoding"); let body = match decode(token) { Ok(bod) => bod, Err(_) => @@ -107,7 +140,6 @@ impl<'a, 'r> FromRequest<'a, 'r> for AuthToken { )), }; - eprintln!("parsing"); let token: AuthTokenRaw = match serde_json::from_str(&String::from_utf8_lossy(&body).to_string()) { Ok(tok) => tok, Err(e) => @@ -119,43 +151,30 @@ impl<'a, 'r> FromRequest<'a, 'r> for AuthToken { //... pošéfit databázi zde - let connection = db::get_con(); - - let result = users - .filter(email.eq(&token.email)) - .first::(&connection) - .optional() - .expect("failed to connect to db") - .unwrap_or_else(|| { - // unfortunately, SQLite does not support the RETURNING clause, so one has to do this atrocity - diesel::insert_into(users) - .values(NewUser { - name: token.name.clone(), - email: token.email.clone(), - role: "noob".to_string(), - }) - .execute(&connection) - .expect("failed to connect to db or insert item"); - - users - .filter(email.eq(&token.email)) - .first::(&connection) - .unwrap_or_else(|_| unreachable!("uh oh, this shouldn't happen, is your DB okay?")) - }); - - //if T::name().to_lowercase() == result.role.to_lowercase() { - // Outcome::Success(AuthToken::from_user(result)) - //} else if let Some(daddy) = T::daddy() { - // println!("{}", daddy); - // match daddy.to_lowercase() == result.role.to_lowercase() { - // true => - Outcome::Success(AuthToken::from_user(result)) - // false => Outcome::Failure((Status::Forbidden, "you don't have the required role".to_string())), - // } - //} else { - // println!("yeetus that feetus?"); - // Outcome::Failure((Status::Forbidden, "you don't have the required role".to_string())) - //} + let result = if let Some((_, u)) = db.read() + .iter() + .find(|(_, u)| u.email == token.email) + { u } else { + let new_u = token.clone().into_user(); + + if db.write() + .insert(token.email, &new_u) + .is_err() + { + return Outcome::Failure(( + Status::InternalServerError, + "failed to insert user into DB".to_string(), + )) + } + + new_u + }; + + if T::name() == result.role || T::resolve_daddy().contains(&result.role.as_str()) { + Outcome::Success(AuthToken::from_user(result)) + } else { + Outcome::Failure((Status::Forbidden, "you don't have the required role".to_string())) + } } x => { println!("{:?}", x); @@ -165,8 +184,8 @@ impl<'a, 'r> FromRequest<'a, 'r> for AuthToken { } } -/// vrací informace o uživatelu +/// returns user information #[get("/me")] -pub fn me(_u: AuthToken) -> Json { - Json(_u.user) +pub fn me(_u: AuthToken) -> Json { + Json(_u.user) } diff --git a/src/bin/superadmin_generator.rs b/src/bin/superadmin_generator.rs new file mode 100644 index 0000000..4412752 --- /dev/null +++ b/src/bin/superadmin_generator.rs @@ -0,0 +1,40 @@ +extern crate backend; + +#[macro_use] +extern crate ferris_print; +#[macro_use] +extern crate scanln; + +extern crate rocket; +extern crate yansi; + +use yansi::Paint; +use backend::init; + +use rocket::http::Status; +use rocket::local::Client; + +use std::env; + +fn main() { + let rocket = init(); + let client = Client::new(rocket).expect("rocket instance is not valid"); + + println!(); + ferrisprint!("Superadmin generator v1"); + + let admin_email = scanln!("[{}] {}", Paint::magenta("rust booking"), Paint::yellow("please insert superadmin login email:")); + + println!("[{}] {}", Paint::magenta("rust booking"), Paint::yellow("reading super secret password")); + + let password = env::var("SA_SECRET").unwrap(); + + println!("[{}] {}", Paint::magenta("rust booking"), Paint::yellow("generating superadmin")); + let req = client.post(format!("/admin/generate_sa/{}/{}", admin_email, password)).dispatch(); + + if req.status() == Status::NotFound { + println!("[{}] {}", Paint::magenta("rust booking"), Paint::yellow("failed to generate superadmin account")) + } else { + println!("[{}] {}", Paint::magenta("rust booking"), Paint::yellow("successfully generated superadmin account")) + } +} diff --git a/src/booking.rs b/src/booking.rs new file mode 100644 index 0000000..44306f6 --- /dev/null +++ b/src/booking.rs @@ -0,0 +1,199 @@ +//! a module containing booking functionality +use rocket::Route; +use rocket_contrib::json::Json; + +use crate::auth::AuthToken; +use crate::auth::roles::{Noob, Approver}; + +use crate::db::{Database, table::Reservations}; + +use crate::models::{NewReservation, UpdateReservation, Reservation}; + +use crate::response::Response; + +/* +** TODO proper type for response, handle RGI responses +*/ + +/// returns all reservations +/// +/// GET /events "application/json" +#[get("/events", format = "application/json")] +pub fn list(db: Database) -> Response { + Response::Ok(Json(db.read().iter().collect::>())) +} + +/// returns JSON of particular reservation +/// +/// GET /events/ application/json +/// +/// parameters: +/// - `id`: identification number of the reservation +#[get("/events/")] +pub fn get(id: u64, db: Database, _u: AuthToken) -> Option> { + db.read() + .get(id) // can't fail + .map(Json) +} + +/// returns JSON of particular reservation +/// +/// POST /events application/json +/// +/// data: [`NewReservation`] +#[post("/events", data = "")] +pub fn post(input: Json, mut db: Database, usr: AuthToken) -> Option<()> { + let has_conflict = db.read().iter().any(|(_, x)| { + x.approved + && x.begin_time <= input.end_time + && x.end_time >= input.begin_time + && (x.rooms == 3 || x.rooms == input.rooms) + }); + + if has_conflict { + return None; // todo proper errors + } + + let mut new_res: Reservation = input.into_inner().into(); + + new_res.author = usr.user.email; + + db.write().insert(Database::::get_key().unwrap(), new_res).ok()?.map(|_| ()) +} + +/// edits a particular reservation +/// +/// PATCH /events/ application/json +/// +/// parameters: +/// - `id`: identification number of the reservation +/// +/// data:[`UpdateReservation`] +#[patch("/events/", data = "")] +pub fn patch( + id: u64, + input: Json, + mut db: Database, + usr: AuthToken, +) -> Option<()> { + let event = db.read().get(id)?; + + // TODO roles are uggly + if event.author != usr.user.email || usr.user.role != "approver" { + return None; + } + + let update_result = db + .write() + .update::<_, Reservation, _>(id, |val| { + if let Some(mut val) = val { + match input.clone() { + UpdateReservation { name, description, rooms, begin_time, end_time, layout, people } => { + name.map(|x| { val.name = x }); + description.map(|x| { val.description = x }); + rooms.map(|x| { val.rooms = x }); + begin_time.map(|x| { val.begin_time = x }); + end_time.map(|x| { val.end_time = x }); + layout.map(|x| { val.layout = x }); + people.map(|x| { val.people = x }); + } + } + + val.approved = false; + + Some(val) + } else { + None + } + }); + + if update_result.is_err() { + return None; + } + + Some(()) +} + +/// deletes the reservation +/// +/// DELETE /events// +/// parameters: +/// - `id`: identification number of the reservation +#[delete("/events/")] +pub fn delete(id: u64, mut db: Database, usr: AuthToken) -> Option<()> { + use crate::auth::roles::Role; + + let event = db.read().get(id)?; + + // TODO roles are uggly + if event.author != usr.user.email || usr.user.role != Approver::name() { + None? + } + + db.write().delete(id).ok()?; + + Some(()) +} + +/// filters by data +/// +/// GET /events/filter///end_time> +/// +/// parameters: +/// - `rooms`: room bitflags +/// - `begin_time`: begin time :D +/// - `end_time`: end time :D +#[get("/events/filter///")] +pub fn date_filter( + rooms: u8, + begin_time: String, + end_time: String, + db: Database, + _u: AuthToken, +) -> Option>> { + use chrono::{DateTime, offset::Utc}; + let begin_time = DateTime::::from(DateTime::parse_from_rfc3339(&begin_time).ok()?); + let end_time = DateTime::::from(DateTime::parse_from_rfc3339(&end_time).ok()?); + + Some(Json( + db.read() + .iter() + .filter(|(_, v)| v.begin_time >= begin_time && v.begin_time <= end_time) + .filter(|(_, v)| v.rooms == rooms) + .collect::>(), + )) +} + +/// approves the endpoint +/// +/// POST /events//approve +/// +/// parameters: +/// - `id`: identification number of the reservation +#[post("/events//approve")] +pub fn approve(id: u64, mut db: Database, _u: AuthToken) -> Option<()> { + let event = db.read().get(id)?; + + // TODO maybe also delete conflicting events + let has_conflict = db.read().iter().any(|(_, x)| { + x.approved + && x.begin_time <= event.end_time + && x.end_time >= event.begin_time + && (x.rooms == 3 || x.rooms == event.rooms) + }); + + if !has_conflict { + db.write() + .update::<_, Reservation, _>(id, |x| if let Some(mut x) = x { + x.approved = true; + Some(x) + } else {None}).ok()?; + } + + Some(()) +} + +/// returns a list of endpoints for rocket binding +pub fn routes() -> Vec { + routes![date_filter, list, approve, get, post, patch, delete,] +} diff --git a/src/db.rs b/src/db.rs index a9f8b0d..ea90fbb 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,134 +1,220 @@ -//! obsahuje modely -//! pro přidávání nového modelu viz [dokumentace Diesel ORM](https://diesel.rs) +//! contains models + +use rocket::request::{FromRequest, Request, Outcome}; +use rocket::http::Status; -use rocket_contrib::databases::diesel; use serde::{Serialize, Deserialize}; -use diesel::Connection; +use sled::{Db, Tree}; +use serde_cbor; use std::env; -use crate::schema::*; +use std::ops::Drop; +use std::sync::RwLock; +use std::borrow::Borrow; +use std::iter::Iterator; +use std::marker::PhantomData; + +lazy_static! { + /// a global handle to the Sled database + pub static ref DB: RwLock = RwLock::new({ + Db::open(&env::var("DATABASE_URL").expect("failed to read DATABASE_URL environment variable")) + .expect("failed to open database") + }); +} + +/// manages a tree and ensures it's type safety +/// also allows automatic type conversions +pub struct TreeMan +where + for<'a> K: Serialize + Deserialize<'a>, + for<'b> V: Serialize + Deserialize<'b>, +{ + /// tree + pub tree: Tree, + _k: PhantomData, + _v: PhantomData, +} + +impl TreeMan +where + for<'a> K: Serialize + Deserialize<'a>, + for<'b> V: Serialize + Deserialize<'b>, +{ + /// create a new tree manager from a tree + pub fn from_tree(tree: Tree) -> Self { + Self { tree, _k: PhantomData, _v: PhantomData } + } -#[database("postgres_db")] -pub struct DbConn(diesel::SqliteConnection); + /// creates an iterator over (K, V) + pub fn iter(&self) -> impl Iterator { + self.tree.iter().filter_map(|res| { + if let Ok((k, v)) = res { + Some((serde_cbor::from_slice::(&k).ok()?, serde_cbor::from_slice::(&v).ok()?)) + } else { + None + } + }) + } -/// vrací připojení k databázi -pub fn get_con() -> diesel::SqliteConnection { - diesel::SqliteConnection::establish(&env::var("DATABASE_URL").expect("DATABASE_URL not in env")) - .expect("error connecting to db") + /// try to get a value from the database + pub fn get>(&self, k: Key) -> Option { + self.tree + .get(serde_cbor::to_vec(k.borrow()).unwrap()) // can't fail + .ok() + .flatten() + .map(|v| serde_cbor::from_slice::(&*v).ok()) + .flatten() + } + + /// try to insert into database + pub fn insert, Value: Borrow>(&mut self, k: Key, v: Value) -> sled::Result> { + let tmp = self.tree.insert(serde_cbor::to_vec(k.borrow()).unwrap(), serde_cbor::to_vec(v.borrow()).unwrap()); + println!("{:?}", tmp); + tmp + // can't fail + } + + /// update a key + pub fn update(&mut self, k: Key, fun: F) -> sled::Result> + where + Key: Borrow, + Value: Borrow, + F: Fn(Option) -> Option, + { + self.tree.update_and_fetch(serde_cbor::to_vec(k.borrow()).unwrap(), |value| { + let value = value.and_then(|val| serde_cbor::from_slice(val.borrow()).ok()); + let res = fun(value); + res.and_then(|v| serde_cbor::to_vec(v.borrow()).ok()) + }) + } + + /// remove a value + pub fn delete>(&mut self, k: Key) -> sled::Result> { + self.tree.remove(serde_cbor::to_vec(k.borrow()).unwrap()) + } } -/// Model rezervace, tak jak je uložena v databázi -#[derive(Queryable, Debug, Clone, Serialize, Deserialize)] -pub struct Reservation { - /// primární klíč - pub id: i32, - /// název události - pub name: String, - /// popis události - pub description: String, - /// "rezervujitel" události :^) - pub author: String, - /// místnosti, které si "rezervujitel" přeje zarezervovat - /// - /// funguje na bázi bitflagů: - /// ``` - /// 0b00 -> žádná místnosti (nemělo by se stát :D) - /// 0b01 -> north - /// 0b10 -> south - /// 0b11 -> celé auditorium - /// ``` - pub rooms: i32, - /// počáteční čas rezervace - pub begin_time: String, - /// čas, kdy rezervace končí - pub end_time: String, - /// rozložení nábytku v audioriu - pub layout: i32, - /// zda byla rezervace schválena - pub approved: i32, - /// počet lidí - pub people: i32, +/// wraps the database +/// +/// the reasons are two: +/// 1. to allow FromRequest implementation +/// 2. declarative table access +pub struct Database(TreeMan, PhantomData); + +impl Database { + /// read-only access to tree + pub fn read(&self) -> &TreeMan { + &self.0 + } + + /// read and write access to tree + pub fn write(&mut self) -> &mut TreeMan { + &mut self.0 + } + + /// procures a new random u64 key + pub fn get_key() -> sled::Result { + let lock = DB.read().expect("the rwlock has been poisoned"); + lock.generate_id() + } + + /// opens the databasse + pub fn open() -> Option { + if T::has_get_tree() { + match T::get_tree() { + Ok(t) => Some(Database(TreeMan::from_tree(t), PhantomData)), + Err(_) => None, + } + } else { + match T::get_tree_naive() { + Ok(t) => Some(Database(TreeMan::from_tree(t), PhantomData)), + Err(_) => None, + } + } + } } -/// Model rezervace pro přidání do databáze -#[derive(Serialize, Deserialize, Debug, Clone)] -#[allow(dead_code)] -pub struct NewReservation { - /// název události - pub name: String, - /// popis události - pub description: String, - /// místnosti, které si "rezervujitel" přeje zarezervovat - /// - /// funguje na bázi bitflagů: - /// ``` - /// 0b00 -> žádná místnosti (nemělo by se stát :D) - /// 0b01 -> north - /// 0b10 -> south - /// 0b11 -> celé auditorium - /// ``` - pub rooms: u8, - /// počáteční čas rezervace - pub begin_time: String, - /// čas, kdy rezervace končí - pub end_time: String, - /// rozložení nábytku v audioriu - pub layout: u16, - /// počet lidí - pub people: u16, +/// trait for the Table marker types +pub trait Table { + /// opening a table might not always work, + /// this type should explain what's the issue + type TableError = sled::Error; + /// type of the key/ID + type Key: Serialize + for<'a> Deserialize<'a>; + /// type of the value + type Value: Serialize + for<'b> Deserialize<'b>; + + /// name (actually prefix) of the table + fn name() -> &'static str; + /// gets the actual tree, should do it using the global DB handle + fn get_tree_naive() -> Result { + let lock = DB.read().expect("the database rwlock has been poisoned"); + // ^ this usually implies a deeper underlying problem, + // so it's probably okay to hard crash + + lock.open_tree(&Self::name()) + } + + /// should return true if a custom get tree function is available + fn has_get_tree() -> bool { + false + } + + /// optional custom function for fetching a tree, + /// can call [`Table::get_tree_naive`] + fn get_tree() -> Result { + unimplemented!() + } } -/// Weird quick models -#[derive(Serialize, Deserialize, Debug, Clone)] -#[allow(dead_code)] -pub struct UpdateReservation { - /// název události - pub name: Option, - /// popis události - pub description: Option, - /// místnosti, které si "rezervujitel" přeje zarezervovat - /// - /// funguje na bázi bitflagů: - /// ``` - /// 0b00 -> žádná místnosti (nemělo by se stát :D) - /// 0b01 -> north - /// 0b10 -> south - /// 0b11 -> celé auditorium - /// ``` - pub rooms: Option, - /// počáteční čas rezervace - pub begin_time: Option, - /// čas, kdy rezervace končí - pub end_time: Option, - /// rozložení nábytku v audioriu - pub layout: Option, - /// počet lidí - pub people: Option, +/// module containing table markers +pub mod table { + use super::Table; + use crate::models::{Reservation, User}; + + /// Reservation database table marker + pub struct Reservations; + + impl Table for Reservations { + type Key = u64; + type Value = Reservation; + + fn name() -> &'static str { + "reservation" + } + } + + /// Users database table marker + pub struct Users; + + impl Table for Users { + type Key = String; + type Value = User; + + fn name() -> &'static str { + "user" + } + } } -/// Model usera -#[derive(Serialize, Deserialize, Debug, Clone, Queryable)] -#[allow(dead_code)] -pub struct User { - /// identifikátor - pub id: i32, - /// jméno uživatele - pub name: String, - /// email - pub email: String, - /// role - pub role: String, +impl<'a, 'r, T: Table> FromRequest<'a, 'r> for Database { + type Error = &'static str; + + fn from_request(_: &'a Request<'r>) -> Outcome { + if let Some(db) = Database::::open() { + Outcome::Success(db) + } else { + Outcome::Failure((Status::InternalServerError, match T::has_get_tree() { + true => "failed to run custom db-loading function", + false => "failed to load database", + })) + } + } } -/// Model usera pro vložení do databáze -#[derive(Serialize, Deserialize, Debug, Clone, Insertable)] -#[table_name = "users"] -#[allow(dead_code)] -pub struct NewUser { - /// jmeno - pub name: String, - /// email - pub email: String, - /// role - pub role: String, +impl Drop for Database { + fn drop(&mut self) { + self.0.tree.flush(); + println!("tree {}: {}", String::from_utf8_lossy(&self.0.tree.name()), self.0.tree.len()) + } } diff --git a/src/lib.rs b/src/lib.rs index 83e3583..a4aa3ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,77 +1,124 @@ -//! ## backend rezervačního systému pro auditorium -//! Dokumentace backendu. -//! Jako webový framework projekt používá [Rocket](https://rocket.rs), na -//! komunikaci s databází [Diesel](https://diesel.rs). +//! ## backend of the reservation system for auditorium +//! Backend documentation +//! +//! Uses [Rocket](https://rocket.rs) as the web framework +//! and [sled](https://sled.rs) as the database. //! //! Modus operandi tohoto serveru spočívá v přijímání požadavků, validaci dat //! a volání správného RGI, viz [`rgi!`] //! -//! Struktura: +//! Structure: //! ```bash,no_run //! . -//! ├── build.rs - build skript -//! ├── Cargo.lock - lockfile, nemazat! (deterministické buildy) -//! ├── Cargo.toml - manifest balíčku -//! ├── diesel.toml - konfigurace Diesel.rs +//! ├── Cargo.lock - lockfile, do not delete! (deterministic builds) +//! ├── Cargo.toml - manifest of the package //! ├── Dockerfile - dockerfile -//! ├── frontend - submodul s frontendem +//! ├── frontend - submodule with the frontend //! ├── Makefile - make -//! ├── migrations - migrace -//! │   ├── 00000000000000_diesel_initial_setup -//! │   │   ├── down.sql -//! │   │   └── up.sql -//! │   └── 2019-11-25-143159_reservations - migrace relace reservations -//! │   ├── down.sql -//! │   └── up.sql //! ├── README.md - README -//! ├── rgi - obsahuje RGI, viz modul rgi -//! │   ├── booking - booking rgi -//! │   │   ├── booking.py -//! │   │   ├── curltest -//! │   │   └── mod.rs -//! │   └── mod.rs -//! ├── Rocket.toml - konfigurační soubor Rocketu -//! ├── rustfmt.toml - pravidla pro automatické formátování kódu -//! └── src - zdrojové soubory -//! ├── db.rs - databázové modely, utility -//! ├── main.rs - entrypoint programu -//! ├── rgi -> ../rgi/ - symlink -//! ├── schema.rs - schéma databáze (vygenerováno Dieselem, neupravovat!) -//! └── static_server.rs - statický server +//! ├── Rocket.toml - Rocket configuration +//! ├── rustfmt.toml- for automatic code formatting +//! └── src - source files +//! ├── admin.rs - admin functions +//! ├── auth.rs - authentification functions +//! ├── bin - additional binaries +//! │   └── superadmin_generator.rs - cli app for generating superadmins +//! ├── booking.rs - booking endpoints +//! ├── db.rs - database access functions +//! ├── lib.rs - root; collects external crates and modules +//! ├── main.rs - inicializes Rocket +//! ├── models.rs - models as structures +//! ├── response.rs - responses +//! └── static_server.rs - static file serving //! ``` #![feature(proc_macro_hygiene, decl_macro)] +#![feature(associated_type_defaults)] +#![allow(clippy::match_bool, clippy::option_map_unit_fn)] #![deny(missing_docs)] #[macro_use] extern crate rocket; -#[macro_use] extern crate rocket_contrib; + #[macro_use] -extern crate diesel; +extern crate lazy_static; + +extern crate tungstenite; +extern crate serde_cbor; extern crate dotenv; +extern crate chrono; +extern crate serde; +extern crate sled; + +use std::thread; +use std::sync::RwLock; +use std::net::{TcpListener, TcpStream}; use dotenv::dotenv; use rocket::http::Method; -use rocket_cors::{AllowedHeaders, AllowedOrigins, Error}; +use rocket_cors::{AllowedHeaders, AllowedOrigins}; -use std::str::FromStr; +use tungstenite::{ + server::accept, + WebSocket, + Message, +}; -pub mod auth; -pub mod rgi; -pub mod db; pub mod static_server; +pub mod booking; +pub mod admin; +pub mod auth; -/// schéma databáze (vygenerováno Dieselem) -#[allow(missing_docs)] -pub mod schema; +pub mod db; +pub mod models; +pub mod response; -use db::DbConn; +lazy_static! { + /// clients + pub static ref CLIENTS: RwLock>> = RwLock::new(vec![]); +} /// Vrací instanci Rocketu pub fn init() -> rocket::Rocket { dotenv().ok(); let allowed_origins = AllowedOrigins::all(); + + thread::spawn(|| { + let server = TcpListener::bind("0.0.0.0:6969").unwrap(); + + let responder = thread::spawn(|| { + println!("responder thread"); + let d = db::Database::::open().unwrap(); + let users = d.read(); + + for _ in users.tree.watch_prefix(vec![]) { + println!("prefix update"); + let mut c = CLIENTS.write().unwrap(); + + let mut to_kill = vec![]; + + for (i, l) in c.iter_mut().enumerate() { + if l.write_message(Message::text("update!")).is_err() { + to_kill.push(i); + } + } + + to_kill.iter().for_each(|x| { c.remove(*x); }); + to_kill.clear(); + } + }); + + println!("ws start"); + for stream in server.incoming() { + println!("websocket"); + let websocket = accept(stream.unwrap()).unwrap(); + CLIENTS.write().unwrap().push(websocket); + } + + responder.join() + }); + // You can also deserialize this let cors = rocket_cors::CorsOptions { allowed_origins, @@ -89,7 +136,7 @@ pub fn init() -> rocket::Rocket { rocket::ignite() .register(catchers![static_server::not_found]) .mount("/", routes![static_server::index, static_server::frontend, static_server::favicon, auth::me]) - .mount("/rgi/", rgi::routes()) + .mount("/api/", booking::routes()) + .mount("/admin/", admin::routes()) .attach(cors) - .attach(DbConn::fairing()) } diff --git a/src/models.rs b/src/models.rs new file mode 100644 index 0000000..64d6d7f --- /dev/null +++ b/src/models.rs @@ -0,0 +1,121 @@ +//! contains database models and helper structs + +use serde::{Serialize, Deserialize}; +use chrono::{DateTime, offset::Utc}; + +use std::convert::From; + +/// reservation model, as is saved in the database +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Reservation { + /// event name + pub name: String, + /// event description + pub description: String, + /// reservation author + pub author: String, + /// rooms that the author wills to reserve + /// + /// bitflag based: + /// ``` + /// 0b00 -> no room - nothing happens + /// 0b01 -> north + /// 0b10 -> south + /// 0b11 -> the whole auditorium + /// ``` + pub rooms: u8, + /// begin time of the reservation + pub begin_time: DateTime, + /// end time of the reservation + pub end_time: DateTime, + /// furniture layout + pub layout: u8, + /// is the reservation approved? + pub approved: bool, + /// amount of people + pub people: u16, +} + +/// reservation model for adding to the database +#[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(dead_code)] +pub struct NewReservation { + /// event name + pub name: String, + /// event description + pub description: String, + /// rooms that the author wills to reserve + /// + /// bitflag based: + /// ``` + /// 0b00 -> no room - nothing happens + /// 0b01 -> north + /// 0b10 -> south + /// 0b11 -> the whole auditorium + /// ``` + pub rooms: u8, + /// begin time + pub begin_time: DateTime, + /// end time + pub end_time: DateTime, + /// furniture layout + pub layout: u8, + /// amount of people + pub people: u16, +} + +impl From for Reservation { + fn from(src: NewReservation) -> Reservation { + Reservation { + name: src.name, + description: src.description, + author: String::new(), + rooms: src.rooms, + begin_time: src.begin_time, + end_time: src.end_time, + layout: src.layout, + approved: false, + people: src.people, + } + } +} + +/// Weird quick models +#[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(dead_code)] +pub struct UpdateReservation { + /// event name + pub name: Option, + /// event description + pub description: Option, + /// rooms that the author wills to reserve + /// + /// bitflag based: + /// ``` + /// 0b00 -> no room - nothing happens + /// 0b01 -> north + /// 0b10 -> south + /// 0b11 -> the whole auditorium + /// ``` + pub rooms: Option, + /// begin time + pub begin_time: Option>, + /// end time + pub end_time: Option>, + /// furniture layout + pub layout: Option, + /// amount of people + pub people: Option, +} + +/// user model +#[derive(Serialize, Deserialize, Debug, Clone)] +#[allow(dead_code)] +pub struct User { + /// user name + pub name: String, + /// user email + pub email: String, + /// user role + pub role: String, +} diff --git a/src/response.rs b/src/response.rs new file mode 100644 index 0000000..6b94950 --- /dev/null +++ b/src/response.rs @@ -0,0 +1,62 @@ +//! includes model describing the server responses + +use std::convert::From; + +use rocket::response::Responder; +use rocket_contrib::json::Json; + +use crate::models::Reservation; + +type S = String; +/// Ok type as in Result +pub type OK = Json>; +/// Err type as in Result +pub type ERR = (u16, Option); + +/// describes possible responses +#[derive(Responder)] +pub enum Response { + /// Ok - 200 + #[response(status = 200, content_type = "json")] + Ok(Json>), + + /// Bad Request - 400 + #[response(status = 400, content_type = "json")] + BadRequest(Option), + + /// Forbidden - 403 + #[response(status = 403, content_type = "json")] + Forbidden(Option), + + /// Not Found - 404 + #[response(status = 404, content_type = "json")] + NotFound(Option), + + /// Internal Server Error - 500 + #[response(status = 500, content_type = "json")] + InternalServerError(Option), +} + +impl From> for Response { + fn from(x: Result) -> Self { + match x { + Ok(s) => Self::Ok(s), + Err((id, content)) => match id { + 400 => {Self::BadRequest(content)}, + 403 => {Self::Forbidden(content)}, + 404 => {Self::NotFound(content)}, + 500 => {Self::InternalServerError(content)}, + _ => panic!("Error parsing http status code : {}", id) + } + } + } +} + +impl From> for Response { + fn from(x: Option) -> Self { + match x { + Some(s) => Self::Ok(s), + None => Self::NotFound(None) + } + } +} diff --git a/src/rgi b/src/rgi deleted file mode 120000 index e3ab9e5..0000000 --- a/src/rgi +++ /dev/null @@ -1 +0,0 @@ -../rgi/ \ No newline at end of file diff --git a/src/schema.rs b/src/schema.rs deleted file mode 100644 index df1ed25..0000000 --- a/src/schema.rs +++ /dev/null @@ -1,25 +0,0 @@ -table! { - booking (id) { - id -> Integer, - name -> Text, - description -> Text, - author -> Text, - rooms -> Integer, - begin_time -> Text, - end_time -> Text, - layout -> Integer, - approved -> Integer, - people -> Integer, - } -} - -table! { - users (id) { - id -> Integer, - name -> Text, - email -> Text, - role -> Text, - } -} - -allow_tables_to_appear_in_same_query!(booking, users,); diff --git a/src/static_server.rs b/src/static_server.rs index 83109bc..fd9ff72 100644 --- a/src/static_server.rs +++ b/src/static_server.rs @@ -1,42 +1,42 @@ -//! statický webserver pro posílání frontendu +//! static file serving //! //! posílá následující soubory skrze tyto routy: +//! serves the following files //! - [`index`] -> __frontend/index.html__ -//! - [`frontend`] -> soubory ze složky __frontend/build__ -//! - [`not_found`] -> 404 soubor +//! - [`frontend`] -> files from __frontend/build__ +//! - [`not_found`] -> 404.html //! -//! přidání nové statické routy: +//! adding new static route //! ```no_run //! #[get("/url/")] //! pub fn moje_route(path: PathBuf) -> NamedFile { -//! NamedFile::open(Path::new("cesta/ke/slozce/").join(path)) -//! .expect("nepodařilo se otevřít soubor") +//! NamedFile::open(Path::new("path/to/file").join(path)) +//! .expect("unable to open file") //! } //! ``` -//! -//! následně je zapotřebí routu zapnout v main.rs +//! it is needed to activate the route in main.rs use std::path::{Path, PathBuf}; use rocket::response::NamedFile; -/// servuje index +/// serves the index #[get("/")] pub fn index() -> NamedFile { NamedFile::open("frontend/index.html").expect("index.html not found") } -/// vrací statické soubory frontendu +/// returns static files of frontend #[get("/static/")] pub fn frontend(name: PathBuf) -> Option { NamedFile::open(Path::new("frontend/build/static/").join(name)).ok() } -/// vraci favicon +/// return favicon #[get("/favicon.ico")] pub fn favicon() -> Option { NamedFile::open("frontend/favicon.ico").ok() } -/// catcher pro 404 +/// 404 catcher #[catch(404)] pub fn not_found() -> NamedFile { NamedFile::open("frontend/404.html").expect("404.html not found") diff --git a/tests/booking.rs b/tests/booking.rs deleted file mode 100644 index c241fd0..0000000 --- a/tests/booking.rs +++ /dev/null @@ -1,32 +0,0 @@ -extern crate rocket; -extern crate backend; -extern crate serde_json; -use rocket::local::Client; -use rocket::http::ContentType; - -#[test] -pub fn test_booking() { - let cli = Client::new(backend::init()).expect("wtf? the virtual client failed"); - assert_eq!(cli.get("/rgi/events/").dispatch().body_string().unwrap(), "[]"); - - let mut req = cli.post("/rgi/events/").header(ContentType::JSON); - req.set_body(r#"{ "name": "test", "description": "test stuff", "author": "hozdic", "begin_time": "2019-12-12T12:30", "end_time": "2019-12-13T13:25", "rooms": 3, "layout": 0, "people": 30}"#); - assert_eq!(req.dispatch().body_string().unwrap(), r#"{"result": 0, "id": 1}"#); - - let v: backend::db::Reservation = - serde_json::from_str(&cli.get("/rgi/events/1").dispatch().body_string().unwrap()).unwrap(); - assert_eq!(v.approved, 0); - - cli.post("/rgi/events/1/approve/").header(ContentType::JSON).dispatch(); - - let v: backend::db::Reservation = - serde_json::from_str(&cli.get("/rgi/events/1").dispatch().body_string().unwrap()).unwrap(); - assert_eq!(v.approved, 1); - - let mut req = cli.post("/rgi/events/").header(ContentType::JSON); - req.set_body(r#"{ "name": "test2", "description": "test stuff2", "author": "hozdic2", "begin_time": "2019-12-12T11:30", "end_time": "2019-12-13T13:25", "rooms": 3, "layout": 0, "people": 100}"#); - assert_eq!(req.dispatch().body_string().unwrap(), r#"{"result": 2}"#); - - cli.delete("/rgi/events/1").header(ContentType::JSON).dispatch(); - assert_eq!(cli.get("/rgi/events/").dispatch().body_string().unwrap(), "[]"); -}