commit a1272c71901016cb4ec617547e600377423277ec
parent 0a6b4e9961872963888a95ae2b06b5a14770f941
Author: Daniel GarcĂa <dani-garcia@users.noreply.github.com>
Date: Thu, 13 Dec 2018 17:49:55 +0100
Merge branch 'rocket-0.4'
Diffstat:
44 files changed, 1361 insertions(+), 1974 deletions(-)
diff --git a/.env b/.env
@@ -18,6 +18,17 @@
# WEBSOCKET_ADDRESS=0.0.0.0
# WEBSOCKET_PORT=3012
+## Enable extended logging
+## This shows timestamps and allows logging to file and to syslog
+### To enable logging to file, use the LOG_FILE env variable
+### To enable syslog, you need to compile with `cargo build --features=enable_syslog'
+# EXTENDED_LOGGING=true
+
+## Logging to file
+## This requires extended logging
+## It's recommended to also set 'ROCKET_CLI_COLORS=off'
+# LOG_FILE=/path/to/log
+
## Controls if new users can register
# SIGNUPS_ALLOWED=true
diff --git a/.travis.yml b/.travis.yml
@@ -5,3 +5,5 @@ dist: trusty # so we get a VM with higher specs
cache: cargo
rust:
- nightly
+script:
+- cargo build --verbose --all-features
diff --git a/Cargo.lock b/Cargo.lock
@@ -8,7 +8,7 @@ name = "aho-corasick"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -18,7 +18,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "arrayvec"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -41,7 +41,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -52,24 +52,7 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "base64"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "base64"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -91,6 +74,11 @@ dependencies = [
[[package]]
name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -105,26 +93,28 @@ dependencies = [
"diesel 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel_migrations 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dotenv 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "jsonwebtoken 4.0.1",
+ "fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonwebtoken 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lettre 0.9.0 (git+https://github.com/lettre/lettre?rev=c988b1760ad81)",
"lettre_email 0.9.0 (git+https://github.com/lettre/lettre?rev=c988b1760ad81)",
"libsqlite3-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "multipart 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "multipart 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"oath 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rmpv 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "rocket_codegen 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "rocket_contrib 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rocket_contrib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "u2f 0.1.2 (git+https://github.com/wisespace-io/u2f-rs?rev=193de35093a44)",
+ "syslog 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "u2f 0.1.2 (git+https://github.com/wisespace-io/u2f-rs?rev=75b9fa5afb4c5)",
"uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
"yubico 0.4.0 (git+https://github.com/dani-garcia/yubico-rs)",
@@ -132,12 +122,11 @@ dependencies = [
[[package]]
name = "buf_redux"
-version = "0.7.1"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "slice-deque 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -146,11 +135,6 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "build_const"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "byte-tools"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -218,11 +202,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cookie"
-version = "0.9.2"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -233,7 +217,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -241,24 +225,15 @@ name = "core-foundation-sys"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crc"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "crossbeam-deque"
-version = "0.2.0"
+name = "crc32fast"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -267,70 +242,72 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
-version = "0.3.1"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "crossbeam-epoch"
-version = "0.6.1"
+name = "crossbeam-utils"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "crossbeam-utils"
-version = "0.2.2"
+name = "crypto-mac"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "crossbeam-utils"
-version = "0.5.0"
+name = "data-encoding"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "crossbeam-utils"
-version = "0.6.1"
+name = "devise"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "crypto-mac"
-version = "0.3.0"
+name = "devise_codegen"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "generic-array 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "data-encoding"
-version = "2.1.1"
+name = "devise_core"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "diesel"
@@ -387,7 +364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -468,7 +445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "encoding_rs"
-version = "0.8.12"
+version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -478,6 +455,9 @@ dependencies = [
name = "error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "failure"
@@ -495,7 +475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -513,6 +493,25 @@ dependencies = [
]
[[package]]
+name = "fern"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syslog 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "filetime"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.43 (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"
@@ -531,6 +530,24 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "fsevent"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fsevent-sys"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -579,18 +596,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "h2"
-version = "0.1.13"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -609,13 +626,13 @@ name = "hostname"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "http"
-version = "0.1.13"
+version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -648,38 +665,39 @@ dependencies = [
[[package]]
name = "hyper"
-version = "0.12.14"
+version = "0.12.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hyper-sync-rustls"
-version = "0.1.0"
+version = "0.3.0-rc.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustls 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webpki-roots 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -689,7 +707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -710,11 +728,33 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "inotify"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "inotify-sys"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "iovec"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -739,8 +779,8 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -751,16 +791,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonwebtoken"
-version = "4.0.1"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -779,17 +819,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "lazy_static"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazycell"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -806,8 +841,8 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -828,17 +863,17 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.43"
+version = "0.2.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libflate"
-version = "0.1.18"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -877,25 +912,17 @@ dependencies = [
]
[[package]]
-name = "mach"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
-version = "2.1.1"
+version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -969,8 +996,8 @@ dependencies = [
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -983,7 +1010,7 @@ name = "mio-extras"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -995,7 +1022,7 @@ version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1017,17 +1044,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "multipart"
-version = "0.15.3"
+version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "buf_redux 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
"iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "nickel 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nickel 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1051,7 +1078,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1059,7 +1086,7 @@ dependencies = [
"schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1068,13 +1095,13 @@ version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nickel"
-version = "0.10.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1084,7 +1111,7 @@ dependencies = [
"modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1101,7 +1128,25 @@ name = "nom"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "notify"
+version = "4.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1112,7 +1157,7 @@ dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1141,7 +1186,7 @@ name = "num_cpus"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1165,7 +1210,7 @@ dependencies = [
"cfg-if 0.1.6 (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.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1180,17 +1225,12 @@ version = "0.9.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "ordermap"
-version = "0.2.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "owning_ref"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1227,9 +1267,9 @@ name = "parking_lot_core"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1238,23 +1278,29 @@ name = "parking_lot_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (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.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pear"
-version = "0.0.20"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "pear_codegen"
-version = "0.0.20"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1370,7 +1416,7 @@ version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1380,7 +1426,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1391,23 +1437,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
-version = "0.6.0"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_isaac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1446,7 +1492,7 @@ dependencies = [
[[package]]
name = "rand_isaac"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1470,64 +1516,25 @@ dependencies = [
]
[[package]]
-name = "rayon"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "redox_syscall"
-version = "0.1.42"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "regex"
-version = "0.2.11"
+version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
[[package]]
name = "regex"
-version = "1.0.6"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1548,20 +1555,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "encoding_rs 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libflate 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1569,14 +1576,13 @@ dependencies = [
[[package]]
name = "ring"
-version = "0.11.0"
+version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1599,59 +1605,74 @@ dependencies = [
[[package]]
name = "rocket"
-version = "0.3.17"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "cookie 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper-sync-rustls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "pear 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "pear_codegen 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustls 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rocket_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "yansi 0.4.0 (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_codegen"
-version = "0.3.17"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "yansi 0.4.0 (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_contrib"
-version = "0.3.17"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
+name = "rocket_http"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper-sync-rustls 0.3.0-rc.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "rust-crypto"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1682,15 +1703,15 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.9.0"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webpki 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1709,6 +1730,14 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "same-file"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "schannel"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1731,13 +1760,22 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "sct"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "security-framework"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1747,7 +1785,7 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1765,17 +1803,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
-version = "1.0.80"
+version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
-version = "1.0.80"
+version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1785,7 +1823,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1795,7 +1833,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1839,18 +1877,8 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "slice-deque"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "smallvec"
-version = "0.6.6"
+version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1868,7 +1896,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "string"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -1893,7 +1921,7 @@ dependencies = [
[[package]]
name = "syn"
-version = "0.15.21"
+version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1916,11 +1944,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
+name = "syslog"
+version = "4.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1931,13 +1970,13 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.0.4"
+version = "3.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1947,8 +1986,8 @@ name = "thread-id"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1973,8 +2012,8 @@ name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1993,23 +2032,24 @@ dependencies = [
[[package]]
name = "tokio"
-version = "0.1.11"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2024,7 +2064,7 @@ dependencies = [
[[package]]
name = "tokio-current-thread"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2046,7 +2086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2061,10 +2101,10 @@ dependencies = [
[[package]]
name = "tokio-reactor"
-version = "0.1.6"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2086,29 +2126,29 @@ dependencies = [
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-threadpool"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-timer"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2116,7 +2156,7 @@ dependencies = [
[[package]]
name = "tokio-udp"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2125,31 +2165,32 @@ dependencies = [
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-uds"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
-version = "0.4.8"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2167,7 +2208,7 @@ name = "twoway"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2191,19 +2232,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "u2f"
version = "0.1.2"
-source = "git+https://github.com/wisespace-io/u2f-rs?rev=193de35093a44#193de35093a44576edba6cc94d9b54f2a1cbdcd1"
+source = "git+https://github.com/wisespace-io/u2f-rs?rev=75b9fa5afb4c5#75b9fa5afb4c5230255136b6689df2a359f41472"
dependencies = [
- "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webpki 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2268,7 +2309,7 @@ dependencies = [
[[package]]
name = "untrusted"
-version = "0.5.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -2310,41 +2351,41 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "want"
-version = "0.0.6"
+name = "walkdir"
+version = "2.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "webpki"
-version = "0.14.0"
+name = "want"
+version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "webpki"
-version = "0.16.0"
+version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "webpki-roots"
-version = "0.11.0"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webpki 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -2372,6 +2413,14 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "winapi-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2416,13 +2465,18 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "yansi"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "yubico"
version = "0.4.0"
source = "git+https://github.com/dani-garcia/yubico-rs#a3a8143611f651d1ff6ec9a2d12599d0aaaea0c6"
dependencies = [
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2433,19 +2487,17 @@ dependencies = [
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
-"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
+"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc"
"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14"
"checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
-"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
-"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9"
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
-"checksum buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c6687a26c9ce967594b78038c06139a0d3a5b3005d16572284d543924a01aa"
+"checksum buf_redux 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f25c67abbf523ff8457771622fb731ac4a2391439de33bc60febcdee1749c9"
"checksum bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8"
-"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
"checksum byte-tools 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0919189ba800c7ffe8778278116b7e0de3905ab81c72abb69c85cbfef7991279"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
@@ -2456,19 +2508,18 @@ dependencies = [
"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
-"checksum cookie 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "477eb650753e319be2ae77ec368a58c638f9f0c4d941c39bad95e950fb1d1d0d"
+"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
-"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
-"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
+"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
"checksum crossbeam-deque 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe1b6f945f824c7a25afe44f62e25d714c0cc523f8e99d8db5cd1026e1269d3"
-"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150"
"checksum crossbeam-epoch 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2449aaa4ec7ef96e5fb24db16024b935df718e9ae1cec0a1e68feeca2efca7b8"
-"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
-"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
-"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816"
+"checksum crossbeam-utils 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e07fc155212827475223f0bcfae57e945e694fc90950ddf3f6695bbfd5555c72"
"checksum crypto-mac 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dba62c86c26dcba13c278afcaac0c7452486fe604a2668a0dfa4e0edc98d8a9e"
"checksum data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df0571a74bf0d97fb8b2ed22abdd9a48475c96bd327db968b7d9cace99655e"
+"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.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "164080ac16a4d1d80a50f0a623e4ddef41cb2779eee85bcc76907d340dfc98cc"
"checksum diesel_derives 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03bcaf77491f53e400d5ee3bdd57142ea4e1c47fe9217b3361ff9a76ca0e3d37"
"checksum diesel_migrations 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b42c35d1ce9e8d57a3e7001b4127f2bc1b073a89708bb7019f5be27c991c28"
@@ -2484,15 +2535,19 @@ dependencies = [
"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
-"checksum encoding_rs 0.8.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ca20350a7cb5aab5b9034731123d6d412caf3e92d4985e739e411ba0955fd0eb"
+"checksum encoding_rs 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1a8fa54e6689eb2549c4efed8d00d7f3b2b994a064555b0e8df4ae3764bcc4be"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
"checksum fast_chemail 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "115e1df89e36c3300a0f88b8b81c41ad24f7bf2b291912e405824d98a553704b"
+"checksum fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b48af88aaf938b11baef948a5599e66e709cf92854aa2b87c71f1bcf20f80a01"
+"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
"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 fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05"
+"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874"
"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 futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
@@ -2500,37 +2555,38 @@ dependencies = [
"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
"checksum generic-array 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe043cf9b85297937897087de81f590361686e1ac2d4d471b45435de5dfb6a6"
"checksum groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57"
-"checksum h2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd33bafe2e6370e6c8eb0cf1b8c5f93390b90acde7e9b03723f166b28b648ed"
+"checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0"
"checksum hmac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb5aa9647ba4711e9d6968dc1c810cd23989ed435443ca962e1bf6d8b8b83ff"
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
-"checksum http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "24f58e8c2d8e886055c3ead7b28793e1455270b5fb39650984c224bc538ba581"
+"checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab"
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
"checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c"
-"checksum hyper 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2f60ae467ef4fc5eba9a34d31648c9c8ed902faf45a217f6734ce9ea64779ac7"
-"checksum hyper-sync-rustls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6df6f419a9f116cc93b5f39a5ded1161e088a2c8424c8fcd1d4049193424a4"
+"checksum hyper 0.12.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c49a75385d35ff5e9202755f09beb0b878a05c4c363fcc52b23eeb5dcb6782cc"
+"checksum hyper-sync-rustls 0.3.0-rc.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d1a443a90413a118ac6739e024f6a5180aa3b3f43f7de65f9d388a961cff19b"
"checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
+"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 iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8e17268922834707e1c29e8badbf9c712c9c43378e1b6a3388946baff10be2"
"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
+"checksum jsonwebtoken 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d438ea707d465c230305963b67f8357a1d56fcfad9434797d7cb1c46c2e41df"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
-"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
-"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0"
+"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum lettre 0.9.0 (git+https://github.com/lettre/lettre?rev=c988b1760ad81)" = "<none>"
"checksum lettre_email 0.9.0 (git+https://github.com/lettre/lettre?rev=c988b1760ad81)" = "<none>"
-"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
-"checksum libflate 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "21138fc6669f438ed7ae3559d5789a5f0ba32f28c1f0608d1e452b0bb06ee936"
+"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
+"checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b"
"checksum libsqlite3-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d3711dfd91a1081d2458ad2d06ea30a8755256e74038be2ad927d94e1c955ca8"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
-"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
+"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum migrations_internals 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8cf7c8c4f83fa9f47440c0b4af99973502de55e6e7b875f693bd263e03f93e7e"
"checksum migrations_macros 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79f12499ef7353bdeca2d081bc61edd8351dac09a33af845952009b5a3d68c1a"
@@ -2543,13 +2599,14 @@ dependencies = [
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58"
-"checksum multipart 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bd50d71866514b14d2ca09823d81390d92daa40bc835f83a908c52ab0a802e"
+"checksum multipart 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adba94490a79baf2d6a23eac897157047008272fa3eecb3373ae6377b91eca28"
"checksum mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb004e419334fc9172d0a5ff91c0770bdd6239091b0b343eb5926101f0a7d13"
"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
-"checksum nickel 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22b40e35b9f46a076dcbd8193125cea0e4130b1c015f68655038010f3e826e04"
+"checksum nickel 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da8f6d24c912e56ae0b595fed54326dc49e8d7c8a13f303861fd0c2c3021e746"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
+"checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078"
"checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
@@ -2559,15 +2616,14 @@ dependencies = [
"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.39 (registry+https://github.com/rust-lang/crates.io-index)" = "278c1ad40a89aa1e741a1eed089a2f60b18fab8089c3139b542140fc7d674106"
-"checksum ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b81cf3b8cb96aa0e73bbedfcdc9708d09fec2854ba8d474be4e6f666d7379e8b"
"checksum owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d52571ddcb42e9c900c901a18d8d67e393df723fcd51dd59c5b1a85d0acb6cc"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
"checksum parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa12d706797d42551663426a45e2db2e0364bd1dbf6aeada87e89c5f981f43e9"
"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c"
-"checksum pear 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "353fe88ff7a430c0f39ca4ec19e1f8fa0062f696370e8df3080ac40139a63301"
-"checksum pear_codegen 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0f3ef1db2d855e0c00fad8e5a8216a70df6d9c1c7f7a7ac9f1cf50675142b7"
+"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 phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6"
"checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad"
@@ -2585,47 +2641,46 @@ dependencies = [
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
-"checksum rand 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de3f08319b5395bd19b70e73c4c465329495db02dafeb8ca711a20f1c2bd058c"
+"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a"
"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a"
"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
-"checksum rand_isaac 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6ecfe9ebf36acd47a49d150990b047a5f7db0a7236ee2414b7ff5cc1097c7b"
+"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3"
-"checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a"
-"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
-"checksum redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cf8fb82a4d1c9b28f1c26c574a5b541f5ffb4315f6c9a791fa47b6a04438fe93"
-"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
-"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467"
-"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
-"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e"
+"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d"
+"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
+"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab52e462d1e15891441aeefadff68bdea005174328ce3da0a314f2ad313ec837"
-"checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724"
+"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
"checksum rmp 0.8.7 (git+https://github.com/dani-garcia/msgpack-rust)" = "<none>"
"checksum rmpv 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29af0205707de955a396a1d3c657677c65f791ebabb63c0596c0b2fec0bf6325"
-"checksum rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "a61d746c68f1d357f6e011985570474c4af368aa81900320074098d34ed0c64e"
-"checksum rocket_codegen 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7873d65adfa3e440ac373a28240341853da170913aad7e4207c0198389e5d0e9"
-"checksum rocket_contrib 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2348e3b2458e173203f1e51f3b2e00495a092b70bd9506d2ce2ac64e129d14"
+"checksum rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "242154377a85c2a9e036fc31ffc8c200b9e1f22a196e47baa3b57716606ca89d"
+"checksum rocket_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d907d6d458c859651c1cf4c8fa99b77685082bde0561db6a4600b365058f710"
+"checksum rocket_contrib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f73e161dad5730435f51c815a5c6831d2e57b6b4299b1bf609d31b09aa9a2fa7"
+"checksum rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba9d4f2ce5bba6e1b6d3100493bbad63879e99bbf6b4365d61e6f781daab324d"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-"checksum rustls 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17727f4b991294da2c84d75a43c003151ff58072212768800f66c56ee46dca43"
+"checksum rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7891791343c75b73ed9a18cadcafd8c8563d11a88ebe2d87f5b8a3182654d9"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
+"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56"
"checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
+"checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a"
"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0"
"checksum security-framework-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab01dfbe5756785b5b4d46e0289e5a18071dfa9a7c2b24213ea00b9ef9b665bf"
"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.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
-"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
+"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6"
+"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154"
"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2"
"checksum sha-1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8347606816471548cd60f0abd5ef0d513a81f5202dbdab9c09f17a15b5248484"
@@ -2633,43 +2688,43 @@ dependencies = [
"checksum sha2 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "84920f9ac881e94e33ec89e1b3dcd36040523a308a92548e01217ce35d8cf6a8"
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
-"checksum slice-deque 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bf9114aa87a7c0ce55425e175d553fa0bef683c7bb2add185a878a2ff8643529"
-"checksum smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "622df2d454c29a4d89b30dc3b27b42d7d90d6b9e587dbf8f67652eb7514da484"
+"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028"
-"checksum string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00caf261d6f90f588f8450b8e1230fa0d5be49ee6140fdfbcb55335aff350970"
+"checksum string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98998cced76115b1da46f63388b909d118a37ae0be0f82ad35773d4a4bc9d18d"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
-"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823"
+"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
+"checksum syslog 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0641142b4081d3d44beffa4eefd7346a228cdf91ed70186db2ca2cef762d327"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
-"checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b"
+"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63"
-"checksum tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6e93c78d23cc61aa245a8acd2c4a79c4d7fa7fb5c3ca90d5737029f043a84895"
+"checksum tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "a7817d4c98cc5be21360b3b37d6036fe9b7aefa5b7a201b7b16ff33423822f7d"
"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f"
-"checksum tokio-current-thread 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f90fcd90952f0a496d438a976afba8e5c205fb12123f813d8ab3aa1c8436638c"
+"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6"
"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde"
"checksum tokio-fs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae25f6b17d25116d2cba342083abe5255d3c2c79cb21ea11aa049c53bf7c75"
"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21"
-"checksum tokio-reactor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4b26fd37f1125738b2170c80b551f69ff6fecb277e6e5ca885e53eec2b005018"
+"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5"
"checksum tokio-tcp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad235e9dadd126b2d47f6736f65aa1fdcd6420e66ca63f44177bc78df89f912"
-"checksum tokio-threadpool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3929aee321c9220ed838ed6c3928be7f9b69986b0e3c22c972a66dbf8a298c68"
-"checksum tokio-timer 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3a52f00c97fedb6d535d27f65cccb7181c8dd4c6edc3eda9ea93f6d45d05168e"
-"checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c"
-"checksum tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df195376b43508f01570bacc73e13a1de0854dc59e79d1ec09913e8db6dd2a70"
-"checksum toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2ecc31b0351ea18b3fe11274b8db6e4d82bce861bbb22e6dbed40417902c65"
+"checksum tokio-threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "56c5556262383032878afad66943926a1d1f0967f17e94bd7764ceceb3b70e7f"
+"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8"
+"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92"
+"checksum tokio-uds 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "99ce87382f6c1a24b513a72c048b2c8efe66cb5161c9061d00bee510f08dc168"
+"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 try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
-"checksum u2f 0.1.2 (git+https://github.com/wisespace-io/u2f-rs?rev=193de35093a44)" = "<none>"
+"checksum u2f 0.1.2 (git+https://github.com/wisespace-io/u2f-rs?rev=75b9fa5afb4c5)" = "<none>"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90"
@@ -2679,24 +2734,26 @@ dependencies = [
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
-"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
+"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 utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6"
"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
-"checksum webpki 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e499345fc4c6b7c79a5b8756d4592c4305510a13512e79efafe00dfbd67bbac6"
-"checksum webpki 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "493012e46177f3f4ee9cd58fd0c81ecb77e6d6cc6ebce55989b9c33376fbe5ee"
-"checksum webpki-roots 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bfb3f50499f21ad2317f442845e3b5805b007f1e728f59885c99e61b8c181a7"
+"checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f"
+"checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e"
"checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c3b48c9cdec42fb06b3b84b5b087405e1fa1c644a1af3930e4dfafe93de48"
+"checksum yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
"checksum yubico 0.4.0 (git+https://github.com/dani-garcia/yubico-rs)" = "<none>"
diff --git a/Cargo.toml b/Cargo.toml
@@ -2,21 +2,24 @@
name = "bitwarden_rs"
version = "1.0.0"
authors = ["Daniel GarcĂa <dani-garcia@users.noreply.github.com>"]
+edition = "2018"
+
+[features]
+enable_syslog = ["syslog", "fern/syslog-4"]
[dependencies]
# Web framework for nightly with a focus on ease-of-use, expressibility, and speed.
-rocket = { version = "0.3.17", features = ["tls"] }
-rocket_codegen = "0.3.17"
-rocket_contrib = "0.3.17"
+rocket = { version = "0.4.0", features = ["tls"], default-features = false }
+rocket_contrib = "0.4.0"
# HTTP client
-reqwest = "0.9.2"
+reqwest = "0.9.5"
# multipart/form-data support
-multipart = "0.15.3"
+multipart = "0.15.4"
# WebSockets library
-ws = "0.7.8"
+ws = "0.7.9"
# MessagePack library
rmpv = "0.4.0"
@@ -25,9 +28,14 @@ rmpv = "0.4.0"
chashmap = "2.2.0"
# A generic serialization/deserialization framework
-serde = "1.0.79"
-serde_derive = "1.0.79"
-serde_json = "1.0.31"
+serde = "1.0.82"
+serde_derive = "1.0.82"
+serde_json = "1.0.33"
+
+# Logging
+log = "0.4.6"
+fern = "0.5.7"
+syslog = { version = "4.0.1", optional = true }
# A safe, extensible ORM and Query builder
diesel = { version = "1.3.3", features = ["sqlite", "chrono", "r2d2"] }
@@ -37,7 +45,7 @@ diesel_migrations = { version = "1.3.0", features = ["sqlite"] }
libsqlite3-sys = { version = "0.9.3", features = ["bundled"] }
# Crypto library
-ring = { version = "= 0.11.0", features = ["rsa_signing"] }
+ring = { version = "0.13.5", features = ["rsa_signing"] }
# UUID generation
uuid = { version = "0.7.1", features = ["v4"] }
@@ -52,7 +60,7 @@ oath = "0.10.2"
data-encoding = "2.1.1"
# JWT library
-jsonwebtoken = "= 4.0.1"
+jsonwebtoken = "5.0.1"
# U2F library
u2f = "0.1.2"
@@ -64,7 +72,7 @@ yubico = { version = "=0.4.0", features = ["online"], default-features = false }
dotenv = { version = "0.13.0", default-features = false }
# Lazy static macro
-lazy_static = "1.1.0"
+lazy_static = { version = "1.2.0", features = ["nightly"] }
# Numerical libraries
num-traits = "0.2.6"
@@ -73,20 +81,21 @@ num-derive = "0.2.3"
# Email libraries
lettre = "0.9.0"
lettre_email = "0.9.0"
-native-tls = "0.2.1"
+native-tls = "0.2.2"
# Number encoding library
-byteorder = "1.2.6"
+byteorder = "1.2.7"
[patch.crates-io]
- # Make jwt use ring 0.11, to match rocket
-jsonwebtoken = { path = "libs/jsonwebtoken" }
+# Add support for Timestamp type
rmp = { git = 'https://github.com/dani-garcia/msgpack-rust' }
+
+# Use new native_tls version 0.2
lettre = { git = 'https://github.com/lettre/lettre', rev = 'c988b1760ad81' }
lettre_email = { git = 'https://github.com/lettre/lettre', rev = 'c988b1760ad81' }
# Version 0.1.2 from crates.io lacks a commit that fixes a certificate error
-u2f = { git = 'https://github.com/wisespace-io/u2f-rs', rev = '193de35093a44' }
+u2f = { git = 'https://github.com/wisespace-io/u2f-rs', rev = '75b9fa5afb4c5' }
# Allows optional libusb support
yubico = { git = 'https://github.com/dani-garcia/yubico-rs' }
diff --git a/Dockerfile b/Dockerfile
@@ -2,9 +2,9 @@
# https://docs.docker.com/develop/develop-images/multistage-build/
# https://whitfin.io/speeding-up-rust-docker-builds/
####################### VAULT BUILD IMAGE #######################
-FROM node:8-alpine as vault
+FROM node:10-alpine as vault
-ENV VAULT_VERSION "v2.5.0"
+ENV VAULT_VERSION "v2.6.1"
ENV URL "https://github.com/bitwarden/web.git"
@@ -41,7 +41,6 @@ WORKDIR /app
# Copies over *only* your manifests and vendored dependencies
COPY ./Cargo.* ./
-COPY ./libs ./libs
COPY ./rust-toolchain ./rust-toolchain
# Builds your dependencies and removes the
@@ -54,6 +53,9 @@ RUN find . -not -path "./target*" -delete
# To avoid copying unneeded files, use .dockerignore
COPY . .
+# Make sure that we actually build the project
+RUN touch src/main.rs
+
# Builds again, this time it'll just be
# your actual source files being built
RUN cargo build --release
@@ -64,6 +66,7 @@ RUN cargo build --release
FROM debian:stretch-slim
ENV ROCKET_ENV "staging"
+ENV ROCKET_PORT=80
ENV ROCKET_WORKERS=10
# Install needed libraries
diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64
@@ -2,9 +2,9 @@
# https://docs.docker.com/develop/develop-images/multistage-build/
# https://whitfin.io/speeding-up-rust-docker-builds/
####################### VAULT BUILD IMAGE #######################
-FROM node:8-alpine as vault
+FROM node:10-alpine as vault
-ENV VAULT_VERSION "v2.5.0"
+ENV VAULT_VERSION "v2.6.1"
ENV URL "https://github.com/bitwarden/web.git"
@@ -69,6 +69,7 @@ RUN cargo build --release --target=aarch64-unknown-linux-gnu -v
FROM balenalib/aarch64-debian:stretch
ENV ROCKET_ENV "staging"
+ENV ROCKET_PORT=80
ENV ROCKET_WORKERS=10
RUN [ "cross-build-start" ]
@@ -95,4 +96,4 @@ COPY --from=vault /web-vault ./web-vault
COPY --from=build /app/target/aarch64-unknown-linux-gnu/release/bitwarden_rs .
# Configures the startup!
-CMD ./bitwarden_rs
-\ No newline at end of file
+CMD ./bitwarden_rs
diff --git a/Dockerfile.alpine b/Dockerfile.alpine
@@ -2,9 +2,9 @@
# https://docs.docker.com/develop/develop-images/multistage-build/
# https://whitfin.io/speeding-up-rust-docker-builds/
####################### VAULT BUILD IMAGE #######################
-FROM node:8-alpine as vault
+FROM node:10-alpine as vault
-ENV VAULT_VERSION "v2.5.0"
+ENV VAULT_VERSION "v2.6.1"
ENV URL "https://github.com/bitwarden/web.git"
@@ -26,7 +26,7 @@ RUN npm run dist \
########################## BUILD IMAGE ##########################
# Musl build image for statically compiled binary
-FROM clux/muslrust:nightly-2018-10-03 as build
+FROM clux/muslrust:nightly-2018-11-30 as build
ENV USER "root"
@@ -45,6 +45,7 @@ RUN cargo build --release
FROM alpine:3.8
ENV ROCKET_ENV "staging"
+ENV ROCKET_PORT=80
ENV ROCKET_WORKERS=10
ENV SSL_CERT_DIR=/etc/ssl/certs
diff --git a/Dockerfile.armv7 b/Dockerfile.armv7
@@ -2,9 +2,9 @@
# https://docs.docker.com/develop/develop-images/multistage-build/
# https://whitfin.io/speeding-up-rust-docker-builds/
####################### VAULT BUILD IMAGE #######################
-FROM node:8-alpine as vault
+FROM node:10-alpine as vault
-ENV VAULT_VERSION "v2.5.0"
+ENV VAULT_VERSION "v2.6.1"
ENV URL "https://github.com/bitwarden/web.git"
@@ -69,6 +69,7 @@ RUN cargo build --release --target=armv7-unknown-linux-gnueabihf -v
FROM balenalib/armv7hf-debian:stretch
ENV ROCKET_ENV "staging"
+ENV ROCKET_PORT=80
ENV ROCKET_WORKERS=10
RUN [ "cross-build-start" ]
diff --git a/libs/jsonwebtoken/Cargo.toml b/libs/jsonwebtoken/Cargo.toml
@@ -1,20 +0,0 @@
-[package]
-name = "jsonwebtoken"
-version = "4.0.1"
-authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
-license = "MIT"
-readme = "README.md"
-description = "Create and parse JWT in a strongly typed way."
-homepage = "https://github.com/Keats/rust-jwt"
-repository = "https://github.com/Keats/rust-jwt"
-keywords = ["jwt", "web", "api", "token", "json"]
-
-[dependencies]
-error-chain = { version = "0.11", default-features = false }
-serde_json = "1.0"
-serde_derive = "1.0"
-serde = "1.0"
-ring = { version = "0.11.0", features = ["rsa_signing", "dev_urandom_fallback"] }
-base64 = "0.9"
-untrusted = "0.5"
-chrono = "0.4"
diff --git a/libs/jsonwebtoken/LICENSE b/libs/jsonwebtoken/LICENSE
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Vincent Prouillet
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/libs/jsonwebtoken/src/crypto.rs b/libs/jsonwebtoken/src/crypto.rs
@@ -1,120 +0,0 @@
-use std::sync::Arc;
-
-use base64;
-use ring::{rand, digest, hmac, signature};
-use ring::constant_time::verify_slices_are_equal;
-use untrusted;
-
-use errors::{Result, ErrorKind};
-
-
-/// The algorithms supported for signing/verifying
-#[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize)]
-pub enum Algorithm {
- /// HMAC using SHA-256
- HS256,
- /// HMAC using SHA-384
- HS384,
- /// HMAC using SHA-512
- HS512,
-
- /// RSASSA-PKCS1-v1_5 using SHA-256
- RS256,
- /// RSASSA-PKCS1-v1_5 using SHA-384
- RS384,
- /// RSASSA-PKCS1-v1_5 using SHA-512
- RS512,
-}
-
-/// The actual HS signing + encoding
-fn sign_hmac(alg: &'static digest::Algorithm, key: &[u8], signing_input: &str) -> Result<String> {
- let signing_key = hmac::SigningKey::new(alg, key);
- let digest = hmac::sign(&signing_key, signing_input.as_bytes());
-
- Ok(
- base64::encode_config::<hmac::Signature>(&digest, base64::URL_SAFE_NO_PAD)
- )
-}
-
-/// The actual RSA signing + encoding
-/// Taken from Ring doc https://briansmith.org/rustdoc/ring/signature/index.html
-fn sign_rsa(alg: Algorithm, key: &[u8], signing_input: &str) -> Result<String> {
- let ring_alg = match alg {
- Algorithm::RS256 => &signature::RSA_PKCS1_SHA256,
- Algorithm::RS384 => &signature::RSA_PKCS1_SHA384,
- Algorithm::RS512 => &signature::RSA_PKCS1_SHA512,
- _ => unreachable!(),
- };
-
- let key_pair = Arc::new(
- signature::RSAKeyPair::from_der(untrusted::Input::from(key))
- .map_err(|_| ErrorKind::InvalidKey)?
- );
- let mut signing_state = signature::RSASigningState::new(key_pair)
- .map_err(|_| ErrorKind::InvalidKey)?;
- let mut signature = vec![0; signing_state.key_pair().public_modulus_len()];
- let rng = rand::SystemRandom::new();
- signing_state.sign(ring_alg, &rng, signing_input.as_bytes(), &mut signature)
- .map_err(|_| ErrorKind::InvalidKey)?;
-
- Ok(
- base64::encode_config::<[u8]>(&signature, base64::URL_SAFE_NO_PAD)
- )
-}
-
-/// Take the payload of a JWT, sign it using the algorithm given and return
-/// the base64 url safe encoded of the result.
-///
-/// Only use this function if you want to do something other than JWT.
-pub fn sign(signing_input: &str, key: &[u8], algorithm: Algorithm) -> Result<String> {
- match algorithm {
- Algorithm::HS256 => sign_hmac(&digest::SHA256, key, signing_input),
- Algorithm::HS384 => sign_hmac(&digest::SHA384, key, signing_input),
- Algorithm::HS512 => sign_hmac(&digest::SHA512, key, signing_input),
-
- Algorithm::RS256 | Algorithm::RS384 | Algorithm::RS512 => sign_rsa(algorithm, key, signing_input),
-// TODO: if PKCS1 is made prublic, remove the line above and uncomment below
-// Algorithm::RS256 => sign_rsa(&signature::RSA_PKCS1_SHA256, key, signing_input),
-// Algorithm::RS384 => sign_rsa(&signature::RSA_PKCS1_SHA384, key, signing_input),
-// Algorithm::RS512 => sign_rsa(&signature::RSA_PKCS1_SHA512, key, signing_input),
- }
-}
-
-/// See Ring RSA docs for more details
-fn verify_rsa(alg: &signature::RSAParameters, signature: &str, signing_input: &str, key: &[u8]) -> Result<bool> {
- let signature_bytes = base64::decode_config(signature, base64::URL_SAFE_NO_PAD)?;
- let public_key_der = untrusted::Input::from(key);
- let message = untrusted::Input::from(signing_input.as_bytes());
- let expected_signature = untrusted::Input::from(signature_bytes.as_slice());
-
- let res = signature::verify(alg, public_key_der, message, expected_signature);
-
- Ok(res.is_ok())
-}
-
-/// Compares the signature given with a re-computed signature for HMAC or using the public key
-/// for RSA.
-///
-/// Only use this function if you want to do something other than JWT.
-///
-/// `signature` is the signature part of a jwt (text after the second '.')
-///
-/// `signing_input` is base64(header) + "." + base64(claims)
-pub fn verify(signature: &str, signing_input: &str, key: &[u8], algorithm: Algorithm) -> Result<bool> {
- match algorithm {
- Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
- // we just re-sign the data with the key and compare if they are equal
- let signed = sign(signing_input, key, algorithm)?;
- Ok(verify_slices_are_equal(signature.as_ref(), signed.as_ref()).is_ok())
- },
- Algorithm::RS256 => verify_rsa(&signature::RSA_PKCS1_2048_8192_SHA256, signature, signing_input, key),
- Algorithm::RS384 => verify_rsa(&signature::RSA_PKCS1_2048_8192_SHA384, signature, signing_input, key),
- Algorithm::RS512 => verify_rsa(&signature::RSA_PKCS1_2048_8192_SHA512, signature, signing_input, key),
- }
-}
-
-impl Default for Algorithm {
- fn default() -> Self {
- Algorithm::HS256
- }
-}
diff --git a/libs/jsonwebtoken/src/errors.rs b/libs/jsonwebtoken/src/errors.rs
@@ -1,68 +0,0 @@
-use base64;
-use serde_json;
-use ring;
-
-error_chain! {
- errors {
- /// When a token doesn't have a valid JWT shape
- InvalidToken {
- description("invalid token")
- display("Invalid token")
- }
- /// When the signature doesn't match
- InvalidSignature {
- description("invalid signature")
- display("Invalid signature")
- }
- /// When the secret given is not a valid RSA key
- InvalidKey {
- description("invalid key")
- display("Invalid Key")
- }
-
- // Validation error
-
- /// When a token’s `exp` claim indicates that it has expired
- ExpiredSignature {
- description("expired signature")
- display("Expired Signature")
- }
- /// When a token’s `iss` claim does not match the expected issuer
- InvalidIssuer {
- description("invalid issuer")
- display("Invalid Issuer")
- }
- /// When a token’s `aud` claim does not match one of the expected audience values
- InvalidAudience {
- description("invalid audience")
- display("Invalid Audience")
- }
- /// When a token’s `aud` claim does not match one of the expected audience values
- InvalidSubject {
- description("invalid subject")
- display("Invalid Subject")
- }
- /// When a token’s `iat` claim is in the future
- InvalidIssuedAt {
- description("invalid issued at")
- display("Invalid Issued At")
- }
- /// When a token’s nbf claim represents a time in the future
- ImmatureSignature {
- description("immature signature")
- display("Immature Signature")
- }
- /// When the algorithm in the header doesn't match the one passed to `decode`
- InvalidAlgorithm {
- description("Invalid algorithm")
- display("Invalid Algorithm")
- }
- }
-
- foreign_links {
- Unspecified(ring::error::Unspecified) #[doc = "An error happened while signing/verifying a token with RSA"];
- Base64(base64::DecodeError) #[doc = "An error happened while decoding some base64 text"];
- Json(serde_json::Error) #[doc = "An error happened while serializing/deserializing JSON"];
- Utf8(::std::string::FromUtf8Error) #[doc = "An error happened while trying to convert the result of base64 decoding to a String"];
- }
-}
diff --git a/libs/jsonwebtoken/src/header.rs b/libs/jsonwebtoken/src/header.rs
@@ -1,64 +0,0 @@
-use crypto::Algorithm;
-
-
-/// A basic JWT header, the alg defaults to HS256 and typ is automatically
-/// set to `JWT`. All the other fields are optional.
-#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
-pub struct Header {
- /// The type of JWS: it can only be "JWT" here
- ///
- /// Defined in [RFC7515#4.1.9](https://tools.ietf.org/html/rfc7515#section-4.1.9).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub typ: Option<String>,
- /// The algorithm used
- ///
- /// Defined in [RFC7515#4.1.1](https://tools.ietf.org/html/rfc7515#section-4.1.1).
- pub alg: Algorithm,
- /// Content type
- ///
- /// Defined in [RFC7519#5.2](https://tools.ietf.org/html/rfc7519#section-5.2).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub cty: Option<String>,
- /// JSON Key URL
- ///
- /// Defined in [RFC7515#4.1.2](https://tools.ietf.org/html/rfc7515#section-4.1.2).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub jku: Option<String>,
- /// Key ID
- ///
- /// Defined in [RFC7515#4.1.4](https://tools.ietf.org/html/rfc7515#section-4.1.4).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kid: Option<String>,
- /// X.509 URL
- ///
- /// Defined in [RFC7515#4.1.5](https://tools.ietf.org/html/rfc7515#section-4.1.5).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub x5u: Option<String>,
- /// X.509 certificate thumbprint
- ///
- /// Defined in [RFC7515#4.1.7](https://tools.ietf.org/html/rfc7515#section-4.1.7).
- #[serde(skip_serializing_if = "Option::is_none")]
- pub x5t: Option<String>,
-}
-
-impl Header {
- /// Returns a JWT header with the algorithm given
- pub fn new(algorithm: Algorithm) -> Header {
- Header {
- typ: Some("JWT".to_string()),
- alg: algorithm,
- cty: None,
- jku: None,
- kid: None,
- x5u: None,
- x5t: None,
- }
- }
-}
-
-impl Default for Header {
- /// Returns a JWT header using the default Algorithm, HS256
- fn default() -> Self {
- Header::new(Algorithm::default())
- }
-}
diff --git a/libs/jsonwebtoken/src/lib.rs b/libs/jsonwebtoken/src/lib.rs
@@ -1,142 +0,0 @@
-//! Create and parses JWT (JSON Web Tokens)
-//!
-//! Documentation: [stable](https://docs.rs/jsonwebtoken/)
-#![recursion_limit = "300"]
-#![deny(missing_docs)]
-#![allow(unused_doc_comments)]
-#![allow(renamed_and_removed_lints)]
-
-#[macro_use]
-extern crate error_chain;
-#[macro_use]
-extern crate serde_derive;
-extern crate serde_json;
-extern crate serde;
-extern crate base64;
-extern crate ring;
-extern crate untrusted;
-extern crate chrono;
-
-/// All the errors, generated using error-chain
-pub mod errors;
-mod header;
-mod crypto;
-mod serialization;
-mod validation;
-
-pub use header::Header;
-pub use crypto::{
- Algorithm,
- sign,
- verify,
-};
-pub use validation::Validation;
-pub use serialization::TokenData;
-
-
-use serde::de::DeserializeOwned;
-use serde::ser::Serialize;
-
-use errors::{Result, ErrorKind};
-use serialization::{from_jwt_part, from_jwt_part_claims, to_jwt_part};
-use validation::{validate};
-
-
-/// Encode the header and claims given and sign the payload using the algorithm from the header and the key
-///
-/// ```rust,ignore
-/// #[macro_use]
-/// extern crate serde_derive;
-/// use jsonwebtoken::{encode, Algorithm, Header};
-///
-/// /// #[derive(Debug, Serialize, Deserialize)]
-/// struct Claims {
-/// sub: String,
-/// company: String
-/// }
-///
-/// let my_claims = Claims {
-/// sub: "b@b.com".to_owned(),
-/// company: "ACME".to_owned()
-/// };
-///
-/// // my_claims is a struct that implements Serialize
-/// // This will create a JWT using HS256 as algorithm
-/// let token = encode(&Header::default(), &my_claims, "secret".as_ref()).unwrap();
-/// ```
-pub fn encode<T: Serialize>(header: &Header, claims: &T, key: &[u8]) -> Result<String> {
- let encoded_header = to_jwt_part(&header)?;
- let encoded_claims = to_jwt_part(&claims)?;
- let signing_input = [encoded_header.as_ref(), encoded_claims.as_ref()].join(".");
- let signature = sign(&*signing_input, key.as_ref(), header.alg)?;
-
- Ok([signing_input, signature].join("."))
-}
-
-/// Used in decode: takes the result of a rsplit and ensure we only get 2 parts
-/// Errors if we don't
-macro_rules! expect_two {
- ($iter:expr) => {{
- let mut i = $iter;
- match (i.next(), i.next(), i.next()) {
- (Some(first), Some(second), None) => (first, second),
- _ => return Err(ErrorKind::InvalidToken.into())
- }
- }}
-}
-
-/// Decode a token into a struct containing 2 fields: `claims` and `header`.
-///
-/// If the token or its signature is invalid or the claims fail validation, it will return an error.
-///
-/// ```rust,ignore
-/// #[macro_use]
-/// extern crate serde_derive;
-/// use jsonwebtoken::{decode, Validation, Algorithm};
-///
-/// #[derive(Debug, Serialize, Deserialize)]
-/// struct Claims {
-/// sub: String,
-/// company: String
-/// }
-///
-/// let token = "a.jwt.token".to_string();
-/// // Claims is a struct that implements Deserialize
-/// let token_data = decode::<Claims>(&token, "secret", &Validation::new(Algorithm::HS256));
-/// ```
-pub fn decode<T: DeserializeOwned>(token: &str, key: &[u8], validation: &Validation) -> Result<TokenData<T>> {
- let (signature, signing_input) = expect_two!(token.rsplitn(2, '.'));
- let (claims, header) = expect_two!(signing_input.rsplitn(2, '.'));
- let header: Header = from_jwt_part(header)?;
-
- if !verify(signature, signing_input, key, header.alg)? {
- return Err(ErrorKind::InvalidSignature.into());
- }
-
- if !validation.algorithms.contains(&header.alg) {
- return Err(ErrorKind::InvalidAlgorithm.into());
- }
-
- let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?;
-
- validate(&claims_map, validation)?;
-
- Ok(TokenData { header: header, claims: decoded_claims })
-}
-
-/// Decode a token and return the Header. This is not doing any kind of validation: it is meant to be
-/// used when you don't know which `alg` the token is using and want to find out.
-///
-/// If the token has an invalid format, it will return an error.
-///
-/// ```rust,ignore
-/// use jsonwebtoken::decode_header;
-///
-/// let token = "a.jwt.token".to_string();
-/// let header = decode_header(&token);
-/// ```
-pub fn decode_header(token: &str) -> Result<Header> {
- let (_, signing_input) = expect_two!(token.rsplitn(2, '.'));
- let (_, header) = expect_two!(signing_input.rsplitn(2, '.'));
- from_jwt_part(header)
-}
diff --git a/libs/jsonwebtoken/src/serialization.rs b/libs/jsonwebtoken/src/serialization.rs
@@ -1,42 +0,0 @@
-use base64;
-use serde::de::DeserializeOwned;
-use serde::ser::Serialize;
-use serde_json::{from_str, to_string, Value};
-use serde_json::map::Map;
-
-use errors::{Result};
-use header::Header;
-
-
-/// The return type of a successful call to decode
-#[derive(Debug)]
-pub struct TokenData<T> {
- /// The decoded JWT header
- pub header: Header,
- /// The decoded JWT claims
- pub claims: T
-}
-
-/// Serializes to JSON and encodes to base64
-pub fn to_jwt_part<T: Serialize>(input: &T) -> Result<String> {
- let encoded = to_string(input)?;
- Ok(base64::encode_config(encoded.as_bytes(), base64::URL_SAFE_NO_PAD))
-}
-
-/// Decodes from base64 and deserializes from JSON to a struct
-pub fn from_jwt_part<B: AsRef<str>, T: DeserializeOwned>(encoded: B) -> Result<T> {
- let decoded = base64::decode_config(encoded.as_ref(), base64::URL_SAFE_NO_PAD)?;
- let s = String::from_utf8(decoded)?;
-
- Ok(from_str(&s)?)
-}
-
-/// Decodes from base64 and deserializes from JSON to a struct AND a hashmap
-pub fn from_jwt_part_claims<B: AsRef<str>, T: DeserializeOwned>(encoded: B) -> Result<(T, Map<String, Value>)> {
- let decoded = base64::decode_config(encoded.as_ref(), base64::URL_SAFE_NO_PAD)?;
- let s = String::from_utf8(decoded)?;
-
- let claims: T = from_str(&s)?;
- let map: Map<_,_> = from_str(&s)?;
- Ok((claims, map))
-}
diff --git a/libs/jsonwebtoken/src/validation.rs b/libs/jsonwebtoken/src/validation.rs
@@ -1,377 +0,0 @@
-use chrono::Utc;
-use serde::ser::Serialize;
-use serde_json::{Value, from_value, to_value};
-use serde_json::map::Map;
-
-use errors::{Result, ErrorKind};
-use crypto::Algorithm;
-
-
-/// Contains the various validations that are applied after decoding a token.
-///
-/// All time validation happen on UTC timestamps.
-///
-/// ```rust
-/// use jsonwebtoken::Validation;
-///
-/// // Default value
-/// let validation = Validation::default();
-///
-/// // Changing one parameter
-/// let mut validation = Validation {leeway: 60, ..Default::default()};
-///
-/// // Setting audience
-/// let mut validation = Validation::default();
-/// validation.set_audience(&"Me"); // string
-/// validation.set_audience(&["Me", "You"]); // array of strings
-/// ```
-#[derive(Debug, Clone, PartialEq)]
-pub struct Validation {
- /// Add some leeway (in seconds) to the `exp`, `iat` and `nbf` validation to
- /// account for clock skew.
- ///
- /// Defaults to `0`.
- pub leeway: i64,
- /// Whether to validate the `exp` field.
- ///
- /// It will return an error if the time in the `exp` field is past.
- ///
- /// Defaults to `true`.
- pub validate_exp: bool,
- /// Whether to validate the `iat` field.
- ///
- /// It will return an error if the time in the `iat` field is in the future.
- ///
- /// Defaults to `true`.
- pub validate_iat: bool,
- /// Whether to validate the `nbf` field.
- ///
- /// It will return an error if the current timestamp is before the time in the `nbf` field.
- ///
- /// Defaults to `true`.
- pub validate_nbf: bool,
- /// If it contains a value, the validation will check that the `aud` field is the same as the
- /// one provided and will error otherwise.
- /// Since `aud` can be either a String or a Vec<String> in the JWT spec, you will need to use
- /// the [set_audience](struct.Validation.html#method.set_audience) method to set it.
- ///
- /// Defaults to `None`.
- pub aud: Option<Value>,
- /// If it contains a value, the validation will check that the `iss` field is the same as the
- /// one provided and will error otherwise.
- ///
- /// Defaults to `None`.
- pub iss: Option<String>,
- /// If it contains a value, the validation will check that the `sub` field is the same as the
- /// one provided and will error otherwise.
- ///
- /// Defaults to `None`.
- pub sub: Option<String>,
- /// If it contains a value, the validation will check that the `alg` of the header is contained
- /// in the ones provided and will error otherwise.
- ///
- /// Defaults to `vec![Algorithm::HS256]`.
- pub algorithms: Vec<Algorithm>,
-}
-
-impl Validation {
- /// Create a default validation setup allowing the given alg
- pub fn new(alg: Algorithm) -> Validation {
- let mut validation = Validation::default();
- validation.algorithms = vec![alg];
- validation
- }
-
- /// Since `aud` can be either a String or an array of String in the JWT spec, this method will take
- /// care of serializing the value.
- pub fn set_audience<T: Serialize>(&mut self, audience: &T) {
- self.aud = Some(to_value(audience).unwrap());
- }
-}
-
-impl Default for Validation {
- fn default() -> Validation {
- Validation {
- leeway: 0,
-
- validate_exp: true,
- validate_iat: true,
- validate_nbf: true,
-
- iss: None,
- sub: None,
- aud: None,
-
- algorithms: vec![Algorithm::HS256],
- }
- }
-}
-
-
-
-pub fn validate(claims: &Map<String, Value>, options: &Validation) -> Result<()> {
- let now = Utc::now().timestamp();
-
- if let Some(iat) = claims.get("iat") {
- if options.validate_iat && from_value::<i64>(iat.clone())? > now + options.leeway {
- return Err(ErrorKind::InvalidIssuedAt.into());
- }
- }
-
- if let Some(exp) = claims.get("exp") {
- if options.validate_exp && from_value::<i64>(exp.clone())? < now - options.leeway {
- return Err(ErrorKind::ExpiredSignature.into());
- }
- }
-
- if let Some(nbf) = claims.get("nbf") {
- if options.validate_nbf && from_value::<i64>(nbf.clone())? > now + options.leeway {
- return Err(ErrorKind::ImmatureSignature.into());
- }
- }
-
- if let Some(iss) = claims.get("iss") {
- if let Some(ref correct_iss) = options.iss {
- if from_value::<String>(iss.clone())? != *correct_iss {
- return Err(ErrorKind::InvalidIssuer.into());
- }
- }
- }
-
- if let Some(sub) = claims.get("sub") {
- if let Some(ref correct_sub) = options.sub {
- if from_value::<String>(sub.clone())? != *correct_sub {
- return Err(ErrorKind::InvalidSubject.into());
- }
- }
- }
-
- if let Some(aud) = claims.get("aud") {
- if let Some(ref correct_aud) = options.aud {
- if aud != correct_aud {
- return Err(ErrorKind::InvalidAudience.into());
- }
- }
- }
-
- Ok(())
-}
-
-
-#[cfg(test)]
-mod tests {
- use serde_json::{to_value};
- use serde_json::map::Map;
- use chrono::Utc;
-
- use super::{validate, Validation};
-
- use errors::ErrorKind;
-
- #[test]
- fn iat_in_past_ok() {
- let mut claims = Map::new();
- claims.insert("iat".to_string(), to_value(Utc::now().timestamp() - 10000).unwrap());
- let res = validate(&claims, &Validation::default());
- assert!(res.is_ok());
- }
-
- #[test]
- fn iat_in_future_fails() {
- let mut claims = Map::new();
- claims.insert("iat".to_string(), to_value(Utc::now().timestamp() + 100000).unwrap());
- let res = validate(&claims, &Validation::default());
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::InvalidIssuedAt => (),
- _ => assert!(false),
- };
- }
-
- #[test]
- fn iat_in_future_but_in_leeway_ok() {
- let mut claims = Map::new();
- claims.insert("iat".to_string(), to_value(Utc::now().timestamp() + 50).unwrap());
- let validation = Validation {
- leeway: 1000 * 60,
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn exp_in_future_ok() {
- let mut claims = Map::new();
- claims.insert("exp".to_string(), to_value(Utc::now().timestamp() + 10000).unwrap());
- let res = validate(&claims, &Validation::default());
- assert!(res.is_ok());
- }
-
- #[test]
- fn exp_in_past_fails() {
- let mut claims = Map::new();
- claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 100000).unwrap());
- let res = validate(&claims, &Validation::default());
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::ExpiredSignature => (),
- _ => assert!(false),
- };
- }
-
- #[test]
- fn exp_in_past_but_in_leeway_ok() {
- let mut claims = Map::new();
- claims.insert("exp".to_string(), to_value(Utc::now().timestamp() - 500).unwrap());
- let validation = Validation {
- leeway: 1000 * 60,
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn nbf_in_past_ok() {
- let mut claims = Map::new();
- claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() - 10000).unwrap());
- let res = validate(&claims, &Validation::default());
- assert!(res.is_ok());
- }
-
- #[test]
- fn nbf_in_future_fails() {
- let mut claims = Map::new();
- claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 100000).unwrap());
- let res = validate(&claims, &Validation::default());
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::ImmatureSignature => (),
- _ => assert!(false),
- };
- }
-
- #[test]
- fn nbf_in_future_but_in_leeway_ok() {
- let mut claims = Map::new();
- claims.insert("nbf".to_string(), to_value(Utc::now().timestamp() + 500).unwrap());
- let validation = Validation {
- leeway: 1000 * 60,
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn iss_ok() {
- let mut claims = Map::new();
- claims.insert("iss".to_string(), to_value("Keats").unwrap());
- let validation = Validation {
- iss: Some("Keats".to_string()),
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn iss_not_matching_fails() {
- let mut claims = Map::new();
- claims.insert("iss".to_string(), to_value("Hacked").unwrap());
- let validation = Validation {
- iss: Some("Keats".to_string()),
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::InvalidIssuer => (),
- _ => assert!(false),
- };
- }
-
- #[test]
- fn sub_ok() {
- let mut claims = Map::new();
- claims.insert("sub".to_string(), to_value("Keats").unwrap());
- let validation = Validation {
- sub: Some("Keats".to_string()),
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn sub_not_matching_fails() {
- let mut claims = Map::new();
- claims.insert("sub".to_string(), to_value("Hacked").unwrap());
- let validation = Validation {
- sub: Some("Keats".to_string()),
- ..Default::default()
- };
- let res = validate(&claims, &validation);
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::InvalidSubject => (),
- _ => assert!(false),
- };
- }
-
- #[test]
- fn aud_string_ok() {
- let mut claims = Map::new();
- claims.insert("aud".to_string(), to_value("Everyone").unwrap());
- let mut validation = Validation::default();
- validation.set_audience(&"Everyone");
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn aud_array_of_string_ok() {
- let mut claims = Map::new();
- claims.insert("aud".to_string(), to_value(["UserA", "UserB"]).unwrap());
- let mut validation = Validation::default();
- validation.set_audience(&["UserA", "UserB"]);
- let res = validate(&claims, &validation);
- assert!(res.is_ok());
- }
-
- #[test]
- fn aud_type_mismatch_fails() {
- let mut claims = Map::new();
- claims.insert("aud".to_string(), to_value("Everyone").unwrap());
- let mut validation = Validation::default();
- validation.set_audience(&["UserA", "UserB"]);
- let res = validate(&claims, &validation);
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::InvalidAudience => (),
- _ => assert!(false),
- };
- }
-
- #[test]
- fn aud_correct_type_not_matching_fails() {
- let mut claims = Map::new();
- claims.insert("aud".to_string(), to_value("Everyone").unwrap());
- let mut validation = Validation::default();
- validation.set_audience(&"None");
- let res = validate(&claims, &validation);
- assert!(res.is_err());
-
- match res.unwrap_err().kind() {
- &ErrorKind::InvalidAudience => (),
- _ => assert!(false),
- };
- }
-}
diff --git a/migrations/2018-11-27-152651_add_att_key_columns/down.sql b/migrations/2018-11-27-152651_add_att_key_columns/down.sql
diff --git a/migrations/2018-11-27-152651_add_att_key_columns/up.sql b/migrations/2018-11-27-152651_add_att_key_columns/up.sql
@@ -0,0 +1,3 @@
+ALTER TABLE attachments
+ ADD COLUMN
+ key TEXT;
+\ No newline at end of file
diff --git a/rust-toolchain b/rust-toolchain
@@ -1 +1 @@
-nightly-2018-10-03
+nightly-2018-12-01
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
@@ -1,13 +1,37 @@
-use rocket_contrib::Json;
-
-use db::DbConn;
-use db::models::*;
-
-use api::{PasswordData, JsonResult, EmptyResult, JsonUpcase, NumberOrString};
-use auth::Headers;
-use mail;
-
-use CONFIG;
+use rocket_contrib::json::Json;
+
+use crate::db::models::*;
+use crate::db::DbConn;
+
+use crate::api::{EmptyResult, JsonResult, JsonUpcase, NumberOrString, PasswordData, UpdateType, WebSocketUsers};
+use crate::auth::Headers;
+use crate::mail;
+
+use crate::CONFIG;
+
+use rocket::{Route, State};
+
+pub fn routes() -> Vec<Route> {
+ routes![
+ register,
+ profile,
+ put_profile,
+ post_profile,
+ get_public_keys,
+ post_keys,
+ post_password,
+ post_kdf,
+ post_rotatekey,
+ post_sstamp,
+ post_email_token,
+ post_email,
+ delete_account,
+ post_delete_account,
+ revision_date,
+ password_hint,
+ prelogin,
+ ]
+}
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
@@ -33,23 +57,22 @@ struct KeysData {
fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
let data: RegisterData = data.into_inner().data;
-
let mut user = match User::find_by_mail(&data.Email, &conn) {
- Some(mut user) => {
+ Some(user) => {
if Invitation::take(&data.Email, &conn) {
for mut user_org in UserOrganization::find_invited_by_user(&user.uuid, &conn).iter_mut() {
user_org.status = UserOrgStatus::Accepted as i32;
if user_org.save(&conn).is_err() {
err!("Failed to accept user to organization")
}
- };
+ }
user
} else if CONFIG.signups_allowed {
- err!("Account with this email already exists")
+ err!("Account with this email already exists")
} else {
- err!("Registration not allowed")
+ err!("Registration not allowed")
}
- },
+ }
None => {
if CONFIG.signups_allowed || Invitation::take(&data.Email, &conn) {
User::new(data.Email)
@@ -86,7 +109,7 @@ fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
match user.save(&conn) {
Ok(()) => Ok(()),
- Err(_) => err!("Failed to save user")
+ Err(_) => err!("Failed to save user"),
}
}
@@ -99,7 +122,7 @@ fn profile(headers: Headers, conn: DbConn) -> JsonResult {
#[allow(non_snake_case)]
struct ProfileData {
#[serde(rename = "Culture")]
- _Culture: String, // Ignored, always use en-US
+ _Culture: String, // Ignored, always use en-US
MasterPasswordHint: Option<String>,
Name: String,
}
@@ -122,7 +145,7 @@ fn post_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -
};
match user.save(&conn) {
Ok(()) => Ok(Json(user.to_json(&conn))),
- Err(_) => err!("Failed to save user profile")
+ Err(_) => err!("Failed to save user profile"),
}
}
@@ -130,7 +153,7 @@ fn post_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -
fn get_public_keys(uuid: String, _headers: Headers, conn: DbConn) -> JsonResult {
let user = match User::find_by_uuid(&uuid, &conn) {
Some(user) => user,
- None => err!("User doesn't exist")
+ None => err!("User doesn't exist"),
};
Ok(Json(json!({
@@ -151,12 +174,10 @@ fn post_keys(data: JsonUpcase<KeysData>, headers: Headers, conn: DbConn) -> Json
match user.save(&conn) {
Ok(()) => Ok(Json(user.to_json(&conn))),
- Err(_) => err!("Failed to save the user's keys")
+ Err(_) => err!("Failed to save the user's keys"),
}
}
-
-
#[derive(Deserialize)]
#[allow(non_snake_case)]
struct ChangePassData {
@@ -178,7 +199,7 @@ fn post_password(data: JsonUpcase<ChangePassData>, headers: Headers, conn: DbCon
user.key = data.Key;
match user.save(&conn) {
Ok(()) => Ok(()),
- Err(_) => err!("Failed to save password")
+ Err(_) => err!("Failed to save password"),
}
}
@@ -208,10 +229,86 @@ fn post_kdf(data: JsonUpcase<ChangeKdfData>, headers: Headers, conn: DbConn) ->
user.key = data.Key;
match user.save(&conn) {
Ok(()) => Ok(()),
- Err(_) => err!("Failed to save password settings")
+ Err(_) => err!("Failed to save password settings"),
}
}
+#[derive(Deserialize)]
+#[allow(non_snake_case)]
+struct UpdateFolderData {
+ Id: String,
+ Name: String,
+}
+
+use super::ciphers::CipherData;
+
+#[derive(Deserialize)]
+#[allow(non_snake_case)]
+struct KeyData {
+ Ciphers: Vec<CipherData>,
+ Folders: Vec<UpdateFolderData>,
+ Key: String,
+ PrivateKey: String,
+ MasterPasswordHash: String,
+}
+
+#[post("/accounts/key", data = "<data>")]
+fn post_rotatekey(data: JsonUpcase<KeyData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> EmptyResult {
+ let data: KeyData = data.into_inner().data;
+
+ if !headers.user.check_valid_password(&data.MasterPasswordHash) {
+ err!("Invalid password")
+ }
+
+ let user_uuid = &headers.user.uuid;
+
+ // Update folder data
+ for folder_data in data.Folders {
+ let mut saved_folder = match Folder::find_by_uuid(&folder_data.Id, &conn) {
+ Some(folder) => folder,
+ None => err!("Folder doesn't exist"),
+ };
+
+ if &saved_folder.user_uuid != user_uuid {
+ err!("The folder is not owned by the user")
+ }
+
+ saved_folder.name = folder_data.Name;
+ if saved_folder.save(&conn).is_err() {
+ err!("Failed to save folder")
+ }
+ }
+
+ // Update cipher data
+ use super::ciphers::update_cipher_from_data;
+
+ for cipher_data in data.Ciphers {
+ let mut saved_cipher = match Cipher::find_by_uuid(cipher_data.Id.as_ref().unwrap(), &conn) {
+ Some(cipher) => cipher,
+ None => err!("Cipher doesn't exist"),
+ };
+
+ if saved_cipher.user_uuid.as_ref().unwrap() != user_uuid {
+ err!("The cipher is not owned by the user")
+ }
+
+ update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &conn, &ws, UpdateType::SyncCipherUpdate)?
+ }
+
+ // Update user data
+ let mut user = headers.user;
+
+ user.key = data.Key;
+ user.private_key = Some(data.PrivateKey);
+ user.reset_security_stamp();
+
+ if user.save(&conn).is_err() {
+ err!("Failed modify user key");
+ }
+
+ Ok(())
+}
+
#[post("/accounts/security-stamp", data = "<data>")]
fn post_sstamp(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> EmptyResult {
let data: PasswordData = data.into_inner().data;
@@ -224,7 +321,7 @@ fn post_sstamp(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -
user.reset_security_stamp();
match user.save(&conn) {
Ok(()) => Ok(()),
- Err(_) => err!("Failed to reset security stamp")
+ Err(_) => err!("Failed to reset security stamp"),
}
}
@@ -255,7 +352,7 @@ fn post_email_token(data: JsonUpcase<EmailTokenData>, headers: Headers, conn: Db
struct ChangeEmailData {
MasterPasswordHash: String,
NewEmail: String,
-
+
Key: String,
NewMasterPasswordHash: String,
#[serde(rename = "Token")]
@@ -276,13 +373,13 @@ fn post_email(data: JsonUpcase<ChangeEmailData>, headers: Headers, conn: DbConn)
}
user.email = data.NewEmail;
-
+
user.set_password(&data.NewMasterPasswordHash);
user.key = data.Key;
match user.save(&conn) {
Ok(()) => Ok(()),
- Err(_) => err!("Failed to save email address")
+ Err(_) => err!("Failed to save email address"),
}
}
@@ -299,10 +396,10 @@ fn delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn
if !user.check_valid_password(&data.MasterPasswordHash) {
err!("Invalid password")
}
-
+
match user.delete(&conn) {
Ok(()) => Ok(()),
- Err(_) => err!("Failed deleting user account, are you the only owner of some organization?")
+ Err(_) => err!("Failed deleting user account, are you the only owner of some organization?"),
}
}
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
@@ -1,35 +1,76 @@
+use std::collections::{HashSet, HashMap};
use std::path::Path;
-use std::collections::HashSet;
-use rocket::State;
-use rocket::Data;
use rocket::http::ContentType;
+use rocket::{request::Form, Data, Route, State};
-use rocket_contrib::{Json, Value};
+use rocket_contrib::json::Json;
+use serde_json::Value;
-use multipart::server::{Multipart, SaveResult};
use multipart::server::save::SavedData;
+use multipart::server::{Multipart, SaveResult};
use data_encoding::HEXLOWER;
-use db::DbConn;
-use db::models::*;
-
-use crypto;
-
-use api::{self, PasswordData, JsonResult, EmptyResult, JsonUpcase, WebSocketUsers, UpdateType};
-use auth::Headers;
-
-use CONFIG;
-
-#[derive(FromForm)]
-#[allow(non_snake_case)]
+use crate::db::models::*;
+use crate::db::DbConn;
+
+use crate::crypto;
+
+use crate::api::{self, EmptyResult, JsonResult, JsonUpcase, PasswordData, UpdateType, WebSocketUsers};
+use crate::auth::Headers;
+
+use crate::CONFIG;
+
+pub fn routes() -> Vec<Route> {
+ routes![
+ sync,
+ get_ciphers,
+ get_cipher,
+ get_cipher_admin,
+ get_cipher_details,
+ post_ciphers,
+ put_cipher_admin,
+ post_ciphers_admin,
+ post_ciphers_create,
+ post_ciphers_import,
+ post_attachment,
+ post_attachment_admin,
+ post_attachment_share,
+ delete_attachment_post,
+ delete_attachment_post_admin,
+ delete_attachment,
+ delete_attachment_admin,
+ post_cipher_admin,
+ post_cipher_share,
+ put_cipher_share,
+ put_cipher_share_seleted,
+ post_cipher,
+ put_cipher,
+ delete_cipher_post,
+ delete_cipher_post_admin,
+ delete_cipher,
+ delete_cipher_admin,
+ delete_cipher_selected,
+ delete_cipher_selected_post,
+ delete_all,
+ move_cipher_selected,
+ move_cipher_selected_put,
+
+ post_collections_update,
+ post_collections_admin,
+ put_collections_admin,
+ ]
+}
+
+#[derive(FromForm, Default)]
struct SyncData {
- excludeDomains: bool,
+ #[form(field = "excludeDomains")]
+ exclude_domains: bool, // Default: 'false'
}
-#[get("/sync?<data>")]
-fn sync(data: SyncData, headers: Headers, conn: DbConn) -> JsonResult {
+#[get("/sync?<data..>")]
+fn sync(data: Form<SyncData>, headers: Headers, conn: DbConn) -> JsonResult {
let user_json = headers.user.to_json(&conn);
let folders = Folder::find_by_user(&headers.user.uuid, &conn);
@@ -41,7 +82,7 @@ fn sync(data: SyncData, headers: Headers, conn: DbConn) -> JsonResult {
let ciphers = Cipher::find_by_user(&headers.user.uuid, &conn);
let ciphers_json: Vec<Value> = ciphers.iter().map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)).collect();
- let domains_json = if data.excludeDomains { Value::Null } else { api::core::get_eq_domains(headers).unwrap().into_inner() };
+ let domains_json = if data.exclude_domains { Value::Null } else { api::core::get_eq_domains(headers).unwrap().into_inner() };
Ok(Json(json!({
"Profile": user_json,
@@ -53,14 +94,6 @@ fn sync(data: SyncData, headers: Headers, conn: DbConn) -> JsonResult {
})))
}
-#[get("/sync")]
-fn sync_no_query(headers: Headers, conn: DbConn) -> JsonResult {
- let sync_data = SyncData {
- excludeDomains: false,
- };
- sync(sync_data, headers, conn)
-}
-
#[get("/ciphers")]
fn get_ciphers(headers: Headers, conn: DbConn) -> JsonResult {
let ciphers = Cipher::find_by_user(&headers.user.uuid, &conn);
@@ -103,7 +136,7 @@ fn get_cipher_details(uuid: String, headers: Headers, conn: DbConn) -> JsonResul
#[allow(non_snake_case)]
pub struct CipherData {
// Id is optional as it is included only in bulk share
- Id: Option<String>,
+ pub Id: Option<String>,
// Folder id is not included in import
FolderId: Option<String>,
// TODO: Some of these might appear all the time, no need for Option
@@ -129,13 +162,25 @@ pub struct CipherData {
Favorite: Option<bool>,
PasswordHistory: Option<Value>,
+
+ // These are used during key rotation
+ #[serde(rename = "Attachments")]
+ _Attachments: Option<Value>, // Unused, contains map of {id: filename}
+ Attachments2: Option<HashMap<String, Attachments2Data>>
+}
+
+#[derive(Deserialize, Debug)]
+#[allow(non_snake_case)]
+pub struct Attachments2Data {
+ FileName: String,
+ Key: String,
}
#[post("/ciphers/admin", data = "<data>")]
fn post_ciphers_admin(data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> JsonResult {
let data: ShareCipherData = data.into_inner().data;
- let mut cipher = Cipher::new(data.Cipher.Type.clone(), data.Cipher.Name.clone());
+ let mut cipher = Cipher::new(data.Cipher.Type, data.Cipher.Name.clone());
cipher.user_uuid = Some(headers.user.uuid.clone());
match cipher.save(&conn) {
Ok(()) => (),
@@ -188,6 +233,28 @@ pub fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &
}
}
+ // Modify attachments name and keys when rotating
+ if let Some(attachments) = data.Attachments2 {
+ for (id, attachment) in attachments {
+ let mut saved_att = match Attachment::find_by_id(&id, &conn) {
+ Some(att) => att,
+ None => err!("Attachment doesn't exist")
+ };
+
+ if saved_att.cipher_uuid != cipher.uuid {
+ err!("Attachment is not owned by the cipher")
+ }
+
+ saved_att.key = Some(attachment.Key);
+ saved_att.file_name = attachment.FileName;
+
+ match saved_att.save(&conn) {
+ Ok(()) => (),
+ Err(_) => err!("Failed to save attachment")
+ };
+ }
+ }
+
let type_data_opt = match data.Type {
1 => data.Login,
2 => data.SecureNote,
@@ -219,7 +286,7 @@ pub fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &
match cipher.save(&conn) {
Ok(()) => (),
- Err(_) => println!("Error: Failed to save cipher")
+ Err(_) => err!("Failed to save cipher")
};
ws.send_cipher_update(ut, &cipher, &cipher.update_users_revision(&conn));
@@ -266,7 +333,6 @@ fn post_ciphers_import(data: JsonUpcase<ImportData>, headers: Headers, conn: DbC
}
// Read the relations between folders and ciphers
- use std::collections::HashMap;
let mut relations_map = HashMap::new();
for relation in data.FolderRelationships {
@@ -509,37 +575,52 @@ fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers
let base_path = Path::new(&CONFIG.attachments_folder).join(&cipher.uuid);
+ let mut attachment_key = None;
+
Multipart::with_body(data.open(), boundary).foreach_entry(|mut field| {
- // This is provided by the client, don't trust it
- let name = field.headers.filename.expect("No filename provided");
-
- let file_name = HEXLOWER.encode(&crypto::get_random(vec![0; 10]));
- let path = base_path.join(&file_name);
-
- let size = match field.data.save()
- .memory_threshold(0)
- .size_limit(None)
- .with_path(path) {
- SaveResult::Full(SavedData::File(_, size)) => size as i32,
- SaveResult::Full(other) => {
- println!("Attachment is not a file: {:?}", other);
- return;
+ match field.headers.name.as_str() {
+ "key" => {
+ use std::io::Read;
+ let mut key_buffer = String::new();
+ if field.data.read_to_string(&mut key_buffer).is_ok() {
+ attachment_key = Some(key_buffer);
+ }
},
- SaveResult::Partial(_, reason) => {
- println!("Partial result: {:?}", reason);
- return;
+ "data" => {
+ // This is provided by the client, don't trust it
+ let name = field.headers.filename.expect("No filename provided");
+
+ let file_name = HEXLOWER.encode(&crypto::get_random(vec![0; 10]));
+ let path = base_path.join(&file_name);
+
+ let size = match field.data.save()
+ .memory_threshold(0)
+ .size_limit(None)
+ .with_path(path) {
+ SaveResult::Full(SavedData::File(_, size)) => size as i32,
+ SaveResult::Full(other) => {
+ error!("Attachment is not a file: {:?}", other);
+ return;
+ },
+ SaveResult::Partial(_, reason) => {
+ error!("Partial result: {:?}", reason);
+ return;
+ },
+ SaveResult::Error(e) => {
+ error!("Error: {:?}", e);
+ return;
+ }
+ };
+
+ let mut attachment = Attachment::new(file_name, cipher.uuid.clone(), name, size);
+ attachment.key = attachment_key.clone();
+ match attachment.save(&conn) {
+ Ok(()) => (),
+ Err(_) => error!("Failed to save attachment")
+ };
},
- SaveResult::Error(e) => {
- println!("Error: {:?}", e);
- return;
- }
- };
-
- let attachment = Attachment::new(file_name, cipher.uuid.clone(), name, size);
- match attachment.save(&conn) {
- Ok(()) => (),
- Err(_) => println!("Error: failed to save attachment")
- };
+ _ => error!("Invalid multipart name")
+ }
}).expect("Error processing multipart data");
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn)))
@@ -670,7 +751,7 @@ fn move_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbConn,
}
match cipher.save(&conn) {
Ok(()) => (),
- Err(_) => println!("Error: Failed to save cipher")
+ Err(_) => err!("Failed to save cipher")
};
ws.send_cipher_update(UpdateType::SyncCipherUpdate, &cipher, &cipher.update_users_revision(&conn));
}
@@ -708,8 +789,7 @@ fn delete_all(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn, ws
for f in Folder::find_by_user(&user.uuid, &conn) {
if f.delete(&conn).is_err() {
err!("Failed deleting folder")
- }
- else {
+ } else {
ws.send_folder_update(UpdateType::SyncFolderCreate, &f);
}
}
@@ -761,6 +841,6 @@ fn _delete_cipher_attachment_by_id(uuid: &str, attachment_id: &str, headers: &He
ws.send_cipher_update(UpdateType::SyncCipherDelete, &cipher, &cipher.update_users_revision(&conn));
Ok(())
}
- Err(_) => err!("Deleting attachement failed")
+ Err(_) => err!("Deleting attachment failed")
}
}
diff --git a/src/api/core/folders.rs b/src/api/core/folders.rs
@@ -1,11 +1,26 @@
use rocket::State;
-use rocket_contrib::{Json, Value};
-
-use db::DbConn;
-use db::models::*;
-
-use api::{JsonResult, EmptyResult, JsonUpcase, WebSocketUsers, UpdateType};
-use auth::Headers;
+use rocket_contrib::json::Json;
+use serde_json::Value;
+
+use crate::db::DbConn;
+use crate::db::models::*;
+
+use crate::api::{JsonResult, EmptyResult, JsonUpcase, WebSocketUsers, UpdateType};
+use crate::auth::Headers;
+
+use rocket::Route;
+
+pub fn routes() -> Vec<Route> {
+ routes![
+ get_folders,
+ get_folder,
+ post_folders,
+ post_folder,
+ put_folder,
+ delete_folder_post,
+ delete_folder,
+ ]
+}
#[get("/folders")]
fn get_folders(headers: Headers, conn: DbConn) -> JsonResult {
diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs
@@ -4,182 +4,69 @@ mod folders;
mod organizations;
pub(crate) mod two_factor;
-use self::accounts::*;
-use self::ciphers::*;
-use self::folders::*;
-use self::organizations::*;
-use self::two_factor::*;
-
pub fn routes() -> Vec<Route> {
- routes![
- register,
- profile,
- put_profile,
- post_profile,
- get_public_keys,
- post_keys,
- post_password,
- post_kdf,
- post_sstamp,
- post_email_token,
- post_email,
- delete_account,
- post_delete_account,
- revision_date,
- password_hint,
- prelogin,
-
- sync,
- sync_no_query,
-
- get_ciphers,
- get_cipher,
- get_cipher_admin,
- get_cipher_details,
- post_ciphers,
- put_cipher_admin,
- post_ciphers_admin,
- post_ciphers_create,
- post_ciphers_import,
- post_attachment,
- post_attachment_admin,
- post_attachment_share,
- delete_attachment_post,
- delete_attachment_post_admin,
- delete_attachment,
- delete_attachment_admin,
- post_cipher_admin,
- post_cipher_share,
- put_cipher_share,
- put_cipher_share_seleted,
- post_cipher,
- put_cipher,
- delete_cipher_post,
- delete_cipher_post_admin,
- delete_cipher,
- delete_cipher_admin,
- delete_cipher_selected,
- delete_cipher_selected_post,
- delete_all,
- move_cipher_selected,
- move_cipher_selected_put,
-
- get_folders,
- get_folder,
- post_folders,
- post_folder,
- put_folder,
- delete_folder_post,
- delete_folder,
-
- get_twofactor,
- get_recover,
- recover,
- disable_twofactor,
- disable_twofactor_put,
- generate_authenticator,
- activate_authenticator,
- activate_authenticator_put,
- generate_u2f,
- generate_u2f_challenge,
- activate_u2f,
- activate_u2f_put,
- generate_yubikey,
- activate_yubikey,
- activate_yubikey_put,
-
- get_organization,
- create_organization,
- delete_organization,
- post_delete_organization,
- leave_organization,
- get_user_collections,
- get_org_collections,
- get_org_collection_detail,
- get_collection_users,
- put_organization,
- post_organization,
- post_organization_collections,
- delete_organization_collection_user,
- post_organization_collection_delete_user,
- post_organization_collection_update,
- put_organization_collection_update,
- delete_organization_collection,
- post_organization_collection_delete,
- post_collections_update,
- post_collections_admin,
- put_collections_admin,
- get_org_details,
- get_org_users,
- send_invite,
- confirm_invite,
- get_user,
- edit_user,
- put_organization_user,
- delete_user,
- post_delete_user,
- post_reinvite_user,
- post_org_import,
-
+ let mut mod_routes = routes![
clear_device_token,
put_device_token,
get_eq_domains,
post_eq_domains,
put_eq_domains,
+ ];
+
+ let mut routes = Vec::new();
+ routes.append(&mut accounts::routes());
+ routes.append(&mut ciphers::routes());
+ routes.append(&mut folders::routes());
+ routes.append(&mut organizations::routes());
+ routes.append(&mut two_factor::routes());
+ routes.append(&mut mod_routes);
- ]
+ routes
}
///
/// Move this somewhere else
///
-
use rocket::Route;
-use rocket_contrib::{Json, Value};
+use rocket_contrib::json::Json;
+use serde_json::Value;
-use db::DbConn;
-use db::models::*;
+use crate::db::DbConn;
-use api::{JsonResult, EmptyResult, JsonUpcase};
-use auth::Headers;
+use crate::api::{EmptyResult, JsonResult, JsonUpcase};
+use crate::auth::Headers;
-#[put("/devices/identifier/<uuid>/clear-token", data = "<data>")]
-fn clear_device_token(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> EmptyResult {
- let _data: Value = data.into_inner();
-
- let device = match Device::find_by_uuid(&uuid, &conn) {
- Some(device) => device,
- None => err!("Device not found")
- };
+#[put("/devices/identifier/<uuid>/clear-token")]
+fn clear_device_token(uuid: String) -> EmptyResult {
+ // This endpoint doesn't have auth header
- if device.user_uuid != headers.user.uuid {
- err!("Device not owned by user")
- }
+ let _ = uuid;
+ // uuid is not related to deviceId
- match device.delete(&conn) {
- Ok(()) => Ok(()),
- Err(_) => err!("Failed deleting device")
- }
+ // This only clears push token
+ // https://github.com/bitwarden/core/blob/master/src/Api/Controllers/DevicesController.cs#L109
+ // https://github.com/bitwarden/core/blob/master/src/Core/Services/Implementations/DeviceService.cs#L37
+ Ok(())
}
#[put("/devices/identifier/<uuid>/token", data = "<data>")]
-fn put_device_token(uuid: String, data: Json<Value>, headers: Headers, conn: DbConn) -> JsonResult {
- let _data: Value = data.into_inner();
-
- let device = match Device::find_by_uuid(&uuid, &conn) {
- Some(device) => device,
- None => err!("Device not found")
- };
-
- if device.user_uuid != headers.user.uuid {
- err!("Device not owned by user")
- }
+fn put_device_token(uuid: String, data: JsonUpcase<Value>, headers: Headers) -> JsonResult {
+ let _data: Value = data.into_inner().data;
+ // Data has a single string value "PushToken"
+ let _ = uuid;
+ // uuid is not related to deviceId
- // TODO: What does this do?
+ // TODO: This should save the push token, but we don't have push functionality
- err!("Not implemented")
+ Ok(Json(json!({
+ "Id": headers.device.uuid,
+ "Name": headers.device.name,
+ "Type": headers.device.type_,
+ "Identifier": headers.device.uuid,
+ "CreationDate": crate::util::format_date(&headers.device.created_at),
+ })))
}
#[derive(Serialize, Deserialize, Debug)]
@@ -213,7 +100,6 @@ fn get_eq_domains(headers: Headers) -> JsonResult {
})))
}
-
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct EquivDomainData {
@@ -236,9 +122,8 @@ fn post_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: Db
match user.save(&conn) {
Ok(()) => Ok(Json(json!({}))),
- Err(_) => err!("Failed to save user")
+ Err(_) => err!("Failed to save user"),
}
-
}
#[put("/settings/domains", data = "<data>")]
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
@@ -1,14 +1,53 @@
use rocket::State;
-use rocket_contrib::{Json, Value};
-use CONFIG;
-use db::DbConn;
-use db::models::*;
+use rocket::request::Form;
+use rocket_contrib::json::Json;
+use serde_json::Value;
-use api::{PasswordData, JsonResult, EmptyResult, NumberOrString, JsonUpcase, WebSocketUsers, UpdateType};
-use auth::{Headers, AdminHeaders, OwnerHeaders};
+use crate::CONFIG;
+use crate::db::DbConn;
+use crate::db::models::*;
+
+use crate::api::{PasswordData, JsonResult, EmptyResult, NumberOrString, JsonUpcase, WebSocketUsers, UpdateType};
+use crate::auth::{Headers, AdminHeaders, OwnerHeaders};
use serde::{Deserialize, Deserializer};
+use rocket::Route;
+
+pub fn routes() -> Vec<Route> {
+ routes![
+ get_organization,
+ create_organization,
+ delete_organization,
+ post_delete_organization,
+ leave_organization,
+ get_user_collections,
+ get_org_collections,
+ get_org_collection_detail,
+ get_collection_users,
+ put_organization,
+ post_organization,
+ post_organization_collections,
+ delete_organization_collection_user,
+ post_organization_collection_delete_user,
+ post_organization_collection_update,
+ put_organization_collection_update,
+ delete_organization_collection,
+ post_organization_collection_delete,
+ get_org_details,
+ get_org_users,
+ send_invite,
+ confirm_invite,
+ get_user,
+ edit_user,
+ put_organization_user,
+ delete_user,
+ post_delete_user,
+ post_reinvite_user,
+ post_org_import,
+ ]
+}
+
#[derive(Deserialize)]
#[allow(non_snake_case)]
@@ -315,14 +354,14 @@ fn get_collection_users(org_id: String, coll_id: String, _headers: AdminHeaders,
}
#[derive(FromForm)]
-#[allow(non_snake_case)]
struct OrgIdData {
- organizationId: String
+ #[form(field = "organizationId")]
+ organization_id: String
}
-#[get("/ciphers/organization-details?<data>")]
-fn get_org_details(data: OrgIdData, headers: Headers, conn: DbConn) -> JsonResult {
- let ciphers = Cipher::find_by_org(&data.organizationId, &conn);
+#[get("/ciphers/organization-details?<data..>")]
+fn get_org_details(data: Form<OrgIdData>, headers: Headers, conn: DbConn) -> JsonResult {
+ let ciphers = Cipher::find_by_org(&data.organization_id, &conn);
let ciphers_json: Vec<Value> = ciphers.iter().map(|c| c.to_json(&headers.host, &headers.user.uuid, &conn)).collect();
Ok(Json(json!({
@@ -643,10 +682,10 @@ struct RelationsData {
Value: usize,
}
-#[post("/ciphers/import-organization?<query>", data = "<data>")]
-fn post_org_import(query: OrgIdData, data: JsonUpcase<ImportData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> EmptyResult {
+#[post("/ciphers/import-organization?<query..>", data = "<data>")]
+fn post_org_import(query: Form<OrgIdData>, data: JsonUpcase<ImportData>, headers: Headers, conn: DbConn, ws: State<WebSocketUsers>) -> EmptyResult {
let data: ImportData = data.into_inner().data;
- let org_id = query.organizationId;
+ let org_id = query.into_inner().organization_id;
let org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) {
Some(user) => user,
@@ -700,4 +739,4 @@ fn post_org_import(query: OrgIdData, data: JsonUpcase<ImportData>, headers: Head
Ok(()) => Ok(()),
Err(_) => err!("Failed to update the revision, please log out and log back in to finish import.")
}
-}
-\ No newline at end of file
+}
diff --git a/src/api/core/two_factor.rs b/src/api/core/two_factor.rs
@@ -1,16 +1,40 @@
use data_encoding::BASE32;
-use rocket_contrib::{Json, Value};
+use rocket_contrib::json::Json;
use serde_json;
+use serde_json::Value;
-use db::{
+
+use crate::db::{
models::{TwoFactor, TwoFactorType, User},
DbConn,
};
-use crypto;
-
-use api::{ApiResult, JsonResult, JsonUpcase, NumberOrString, PasswordData};
-use auth::Headers;
+use crate::crypto;
+
+use crate::api::{ApiResult, JsonResult, JsonUpcase, NumberOrString, PasswordData};
+use crate::auth::Headers;
+
+use rocket::Route;
+
+pub fn routes() -> Vec<Route> {
+ routes![
+ get_twofactor,
+ get_recover,
+ recover,
+ disable_twofactor,
+ disable_twofactor_put,
+ generate_authenticator,
+ activate_authenticator,
+ activate_authenticator_put,
+ generate_u2f,
+ generate_u2f_challenge,
+ activate_u2f,
+ activate_u2f_put,
+ generate_yubikey,
+ activate_yubikey,
+ activate_yubikey_put,
+ ]
+}
#[get("/two-factor")]
fn get_twofactor(headers: Headers, conn: DbConn) -> JsonResult {
@@ -50,7 +74,7 @@ struct RecoverTwoFactor {
fn recover(data: JsonUpcase<RecoverTwoFactor>, conn: DbConn) -> JsonResult {
let data: RecoverTwoFactor = data.into_inner().data;
- use db::models::User;
+ use crate::db::models::User;
// Get the user
let mut user = match User::find_by_mail(&data.Email, &conn) {
@@ -219,7 +243,7 @@ fn _generate_recover_code(user: &mut User, conn: &DbConn) {
let totp_recover = BASE32.encode(&crypto::get_random(vec![0u8; 20]));
user.totp_recover = Some(totp_recover);
if user.save(conn).is_err() {
- println!("Error: Failed to save the user's two factor recovery code")
+ error!("Failed to save the user's two factor recovery code")
}
}
}
@@ -228,7 +252,7 @@ use u2f::messages::{RegisterResponse, SignResponse, U2fSignRequest};
use u2f::protocol::{Challenge, U2f};
use u2f::register::Registration;
-use CONFIG;
+use crate::CONFIG;
const U2F_VERSION: &str = "U2F_V2";
@@ -376,7 +400,7 @@ fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn)
})))
}
Err(e) => {
- println!("Error: {:#?}", e);
+ error!("{:#?}", e);
err!("Error activating u2f")
}
}
@@ -480,11 +504,11 @@ pub fn validate_u2f_login(user_uuid: &str, response: &str, conn: &DbConn) -> Api
match response {
Ok(new_counter) => {
_counter = new_counter;
- println!("O {:#}", new_counter);
+ info!("O {:#}", new_counter);
return Ok(());
}
Err(e) => {
- println!("E {:#}", e);
+ info!("E {:#}", e);
break;
}
}
@@ -544,9 +568,8 @@ fn parse_yubikeys(data: &EnableYubikeyData) -> Vec<String> {
fn jsonify_yubikeys(yubikeys: Vec<String>) -> serde_json::Value {
let mut result = json!({});
- for i in 0..yubikeys.len() {
- let ref key = &yubikeys[i];
- result[format!("Key{}", i+1)] = Value::String(key.to_string());
+ for (i, key) in yubikeys.into_iter().enumerate() {
+ result[format!("Key{}", i+1)] = Value::String(key);
}
result
@@ -630,7 +653,7 @@ fn activate_yubikey(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn:
let yubikeys = parse_yubikeys(&data);
- if yubikeys.len() == 0 {
+ if yubikeys.is_empty() {
return Ok(Json(json!({
"Enabled": false,
"Object": "twoFactorU2f",
diff --git a/src/api/icons.rs b/src/api/icons.rs
@@ -7,7 +7,7 @@ use rocket::http::ContentType;
use reqwest;
-use CONFIG;
+use crate::CONFIG;
pub fn routes() -> Vec<Route> {
routes![icon]
@@ -43,7 +43,7 @@ fn get_icon (domain: &str) -> Vec<u8> {
icon
},
Err(e) => {
- println!("Error downloading icon: {:?}", e);
+ error!("Error downloading icon: {:?}", e);
get_fallback_icon()
}
}
@@ -71,7 +71,7 @@ fn get_icon_url(domain: &str) -> String {
}
fn download_icon(url: &str) -> Result<Vec<u8>, reqwest::Error> {
- println!("Downloading icon for {}...", url);
+ info!("Downloading icon for {}...", url);
let mut res = reqwest::get(url)?;
res = res.error_for_status()?;
@@ -105,7 +105,7 @@ fn get_fallback_icon() -> Vec<u8> {
icon
},
Err(e) => {
- println!("Error downloading fallback icon: {:?}", e);
+ error!("Error downloading fallback icon: {:?}", e);
vec![]
}
}
diff --git a/src/api/identity.rs b/src/api/identity.rs
@@ -1,42 +1,43 @@
-use std::collections::HashMap;
-use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+use rocket::request::LenientForm;
+use rocket::Route;
-use rocket::request::{self, Form, FormItems, FromForm, FromRequest, Request};
-use rocket::{Outcome, Route};
-
-use rocket_contrib::{Json, Value};
+use rocket_contrib::json::Json;
+use serde_json::Value;
use num_traits::FromPrimitive;
-use db::models::*;
-use db::DbConn;
+use crate::db::models::*;
+use crate::db::DbConn;
+
+use crate::util::{self, JsonMap};
-use util::{self, JsonMap};
+use crate::api::{ApiResult, EmptyResult, JsonResult};
-use api::{ApiResult, JsonResult};
+use crate::auth::ClientIp;
-use CONFIG;
+use crate::CONFIG;
pub fn routes() -> Vec<Route> {
routes![login]
}
-#[post("/connect/token", data = "<connect_data>")]
-fn login(connect_data: Form<ConnectData>, device_type: DeviceType, conn: DbConn, socket: Option<SocketAddr>) -> JsonResult {
- let data = connect_data.get();
+#[post("/connect/token", data = "<data>")]
+fn login(data: LenientForm<ConnectData>, conn: DbConn, ip: ClientIp) -> JsonResult {
+ let data: ConnectData = data.into_inner();
+ validate_data(&data)?;
match data.grant_type {
- GrantType::RefreshToken => _refresh_login(data, device_type, conn),
- GrantType::Password => _password_login(data, device_type, conn, socket),
+ GrantType::refresh_token => _refresh_login(data, conn),
+ GrantType::password => _password_login(data, conn, ip),
}
}
-fn _refresh_login(data: &ConnectData, _device_type: DeviceType, conn: DbConn) -> JsonResult {
+fn _refresh_login(data: ConnectData, conn: DbConn) -> JsonResult {
// Extract token
- let token = data.get("refresh_token");
+ let token = data.refresh_token.unwrap();
// Get device by refresh token
- let mut device = match Device::find_by_refresh_token(token, &conn) {
+ let mut device = match Device::find_by_refresh_token(&token, &conn) {
Some(device) => device,
None => err!("Invalid refresh token"),
};
@@ -47,90 +48,71 @@ fn _refresh_login(data: &ConnectData, _device_type: DeviceType, conn: DbConn) ->
let (access_token, expires_in) = device.refresh_tokens(&user, orgs);
match device.save(&conn) {
- Ok(()) => Ok(Json(json!({
- "access_token": access_token,
- "expires_in": expires_in,
- "token_type": "Bearer",
- "refresh_token": device.refresh_token,
- "Key": user.key,
- "PrivateKey": user.private_key,
- }))),
- Err(_) => err!("Failed to add device to user")
+ Ok(()) => Ok(Json(json!({
+ "access_token": access_token,
+ "expires_in": expires_in,
+ "token_type": "Bearer",
+ "refresh_token": device.refresh_token,
+ "Key": user.key,
+ "PrivateKey": user.private_key,
+ }))),
+ Err(e) => err!("Failed to add device to user", e),
}
}
-fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn, remote: Option<SocketAddr>) -> JsonResult {
- // Get the ip for error reporting
- let ip = match remote {
- Some(ip) => ip.ip(),
- None => IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
- };
-
+fn _password_login(data: ConnectData, conn: DbConn, ip: ClientIp) -> JsonResult {
// Validate scope
- let scope = data.get("scope");
+ let scope = data.scope.as_ref().unwrap();
if scope != "api offline_access" {
err!("Scope not supported")
}
// Get the user
- let username = data.get("username");
+ let username = data.username.as_ref().unwrap();
let user = match User::find_by_mail(username, &conn) {
Some(user) => user,
None => err!(format!(
"Username or password is incorrect. Try again. IP: {}. Username: {}.",
- ip, username
+ ip.ip, username
)),
};
// Check password
- let password = data.get("password");
+ let password = data.password.as_ref().unwrap();
if !user.check_valid_password(password) {
err!(format!(
"Username or password is incorrect. Try again. IP: {}. Username: {}.",
- ip, username
+ ip.ip, username
))
}
- // Let's only use the header and ignore the 'devicetype' parameter
- let device_type_num = device_type.0;
-
- let (device_id, device_name) = if data.is_device {
- (
- data.get("deviceidentifier").clone(),
- data.get("devicename").clone(),
- )
- } else {
- (format!("web-{}", user.uuid), String::from("web"))
- };
+ let device_type = util::try_parse_string(data.device_type.as_ref()).unwrap_or(0);
+ let device_id = data.device_identifier.clone().unwrap_or_else(crate::util::get_uuid);
+ let device_name = data.device_name.clone().unwrap_or("unknown_device".into());
// Find device or create new
let mut device = match Device::find_by_uuid(&device_id, &conn) {
Some(device) => {
- // Check if valid device
+ // Check if owned device, and recreate if not
if device.user_uuid != user.uuid {
- match device.delete(&conn) {
- Ok(()) => Device::new(device_id, user.uuid.clone(), device_name, device_type_num),
- Err(_) => err!("Tried to delete device not owned by user, but failed")
- }
+ info!("Device exists but is owned by another user. The old device will be discarded");
+ Device::new(device_id, user.uuid.clone(), device_name, device_type)
} else {
device
}
}
- None => {
- // Create new device
- Device::new(device_id, user.uuid.clone(), device_name, device_type_num)
- }
+ None => Device::new(device_id, user.uuid.clone(), device_name, device_type)
};
- let twofactor_token = twofactor_auth(&user.uuid, &data, &mut device, &conn)?;
+ let twofactor_token = twofactor_auth(&user.uuid, &data.clone(), &mut device, &conn)?;
// Common
let user = User::find_by_uuid(&device.user_uuid, &conn).unwrap();
let orgs = UserOrganization::find_by_user(&user.uuid, &conn);
let (access_token, expires_in) = device.refresh_tokens(&user, orgs);
- if device.save(&conn).is_err() {
- err!("Failed to add device to user")
+ if let Err(e) = device.save(&conn) {
+ err!("Failed to add device to user", e)
}
let mut result = json!({
@@ -147,6 +129,7 @@ fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn, re
result["TwoFactorToken"] = Value::String(token);
}
+ info!("User {} logged in successfully. IP: {}", username, ip.ip);
Ok(Json(result))
}
@@ -167,13 +150,10 @@ fn twofactor_auth(
return Ok(None);
}
- let provider = match util::try_parse_string(data.get_opt("twoFactorProvider")) {
- Some(provider) => provider,
- None => providers[0], // If we aren't given a two factor provider, asume the first one
- };
+ let provider = data.two_factor_provider.unwrap_or(providers[0]); // If we aren't given a two factor provider, asume the first one
- let twofactor_code = match data.get_opt("twoFactorToken") {
- Some(code) => code,
+ let twofactor_code = match data.two_factor_token {
+ Some(ref code) => code,
None => err_json!(_json_err_twofactor(&providers, user_uuid, conn)?),
};
@@ -181,8 +161,8 @@ fn twofactor_auth(
match TwoFactorType::from_i32(provider) {
Some(TwoFactorType::Remember) => {
- match &device.twofactor_remember {
- Some(remember) if remember == twofactor_code => return Ok(None), // No twofactor token needed here
+ match device.twofactor_remember {
+ Some(ref remember) if remember == twofactor_code => return Ok(None), // No twofactor token needed here
_ => err_json!(_json_err_twofactor(&providers, user_uuid, conn)?),
}
}
@@ -204,13 +184,13 @@ fn twofactor_auth(
}
Some(TwoFactorType::U2f) => {
- use api::core::two_factor;
+ use crate::api::core::two_factor;
- two_factor::validate_u2f_login(user_uuid, twofactor_code, conn)?;
+ two_factor::validate_u2f_login(user_uuid, &twofactor_code, conn)?;
}
Some(TwoFactorType::YubiKey) => {
- use api::core::two_factor;
+ use crate::api::core::two_factor;
two_factor::validate_yubikey_login(user_uuid, twofactor_code, conn)?;
}
@@ -218,7 +198,7 @@ fn twofactor_auth(
_ => err!("Invalid two factor provider"),
}
- if util::try_parse_string_or(data.get_opt("twoFactorRemember"), 0) == 1 {
+ if data.two_factor_remember.unwrap_or(0) == 1 {
Ok(Some(device.refresh_twofactor_remember()))
} else {
device.delete_twofactor_remember();
@@ -227,7 +207,7 @@ fn twofactor_auth(
}
fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> ApiResult<Value> {
- use api::core::two_factor;
+ use crate::api::core::two_factor;
let mut result = json!({
"error" : "invalid_grant",
@@ -289,93 +269,60 @@ fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> Api
Ok(result)
}
-#[derive(Clone, Copy)]
-struct DeviceType(i32);
-
-impl<'a, 'r> FromRequest<'a, 'r> for DeviceType {
- type Error = &'static str;
-
- fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
- let headers = request.headers();
- let type_opt = headers.get_one("Device-Type");
- let type_num = util::try_parse_string_or(type_opt, 0);
-
- Outcome::Success(DeviceType(type_num))
- }
-}
-
-#[derive(Debug)]
+#[derive(FromForm, Debug, Clone)]
+#[allow(non_snake_case)]
struct ConnectData {
grant_type: GrantType,
- is_device: bool,
- data: HashMap<String, String>,
-}
-#[derive(Debug, Copy, Clone)]
-enum GrantType {
- RefreshToken,
- Password,
+ // Needed for grant_type="refresh_token"
+ refresh_token: Option<String>,
+
+ // Needed for grant_type="password"
+ client_id: Option<String>, // web, cli, desktop, browser, mobile
+ password: Option<String>,
+ scope: Option<String>,
+ username: Option<String>,
+
+ #[form(field = "deviceIdentifier")]
+ device_identifier: Option<String>,
+ #[form(field = "deviceName")]
+ device_name: Option<String>,
+ #[form(field = "deviceType")]
+ device_type: Option<String>,
+
+ // Needed for two-factor auth
+ #[form(field = "twoFactorProvider")]
+ two_factor_provider: Option<i32>,
+ #[form(field = "twoFactorToken")]
+ two_factor_token: Option<String>,
+ #[form(field = "twoFactorRemember")]
+ two_factor_remember: Option<i32>,
}
-impl ConnectData {
- fn get(&self, key: &str) -> &String {
- &self.data[&key.to_lowercase()]
- }
-
- fn get_opt(&self, key: &str) -> Option<&String> {
- self.data.get(&key.to_lowercase())
- }
+#[derive(FromFormValue, Debug, Clone, Copy)]
+#[allow(non_camel_case_types)]
+enum GrantType {
+ refresh_token,
+ password,
}
-const VALUES_REFRESH: [&str; 1] = ["refresh_token"];
-const VALUES_PASSWORD: [&str; 5] = ["client_id", "grant_type", "password", "scope", "username"];
-const VALUES_DEVICE: [&str; 3] = ["deviceidentifier", "devicename", "devicetype"];
-
-impl<'f> FromForm<'f> for ConnectData {
- type Error = String;
-
- fn from_form(items: &mut FormItems<'f>, _strict: bool) -> Result<Self, Self::Error> {
- let mut data = HashMap::new();
-
- // Insert data into map
- for (key, value) in items {
- match (key.url_decode(), value.url_decode()) {
- (Ok(key), Ok(value)) => data.insert(key.to_lowercase(), value),
- _ => return Err("Error decoding key or value".to_string()),
- };
+fn validate_data(data: &ConnectData) -> EmptyResult {
+ match data.grant_type {
+ GrantType::refresh_token => {
+ _check_is_some(&data.refresh_token, "refresh_token cannot be blank")
+ }
+ GrantType::password => {
+ _check_is_some(&data.client_id, "client_id cannot be blank")?;
+ _check_is_some(&data.password, "password cannot be blank")?;
+ _check_is_some(&data.scope, "scope cannot be blank")?;
+ _check_is_some(&data.username, "username cannot be blank")
}
-
- // Validate needed values
- let (grant_type, is_device) = match data.get("grant_type").map(String::as_ref) {
- Some("refresh_token") => {
- check_values(&data, &VALUES_REFRESH)?;
- (GrantType::RefreshToken, false) // Device doesn't matter here
- }
- Some("password") => {
- check_values(&data, &VALUES_PASSWORD)?;
-
- let is_device = match data["client_id"].as_ref() {
- "browser" | "mobile" => check_values(&data, &VALUES_DEVICE)?,
- _ => false,
- };
- (GrantType::Password, is_device)
- }
- _ => return Err("Grant type not supported".to_string()),
- };
-
- Ok(ConnectData {
- grant_type,
- is_device,
- data,
- })
}
}
-fn check_values(map: &HashMap<String, String>, values: &[&str]) -> Result<bool, String> {
- for value in values {
- if !map.contains_key(*value) {
- return Err(format!("{} cannot be blank", value));
- }
+fn _check_is_some<T>(value: &Option<T>, msg: &str) -> EmptyResult {
+ if value.is_none() {
+ err!(msg)
}
- Ok(true)
+ Ok(())
}
diff --git a/src/api/mod.rs b/src/api/mod.rs
@@ -12,14 +12,15 @@ pub use self::notifications::routes as notifications_routes;
pub use self::notifications::{start_notification_server, WebSocketUsers, UpdateType};
use rocket::response::status::BadRequest;
-use rocket_contrib::Json;
+use rocket_contrib::json::Json;
+use serde_json::Value;
// Type aliases for API methods results
-type ApiResult<T> = Result<T, BadRequest<Json>>;
-type JsonResult = ApiResult<Json>;
+type ApiResult<T> = Result<T, BadRequest<Json<Value>>>;
+type JsonResult = ApiResult<Json<Value>>;
type EmptyResult = ApiResult<()>;
-use util;
+use crate::util;
type JsonUpcase<T> = Json<util::UpCase<T>>;
// Common structs representing JSON data received
diff --git a/src/api/notifications.rs b/src/api/notifications.rs
@@ -1,12 +1,12 @@
use rocket::Route;
-use rocket_contrib::Json;
+use rocket_contrib::json::Json;
use serde_json::Value as JsonValue;
-use api::JsonResult;
-use auth::Headers;
-use db::DbConn;
+use crate::api::JsonResult;
+use crate::auth::Headers;
+use crate::db::DbConn;
-use CONFIG;
+use crate::CONFIG;
pub fn routes() -> Vec<Route> {
routes![negotiate, websockets_err]
@@ -19,7 +19,7 @@ fn websockets_err() -> JsonResult {
#[post("/hub/negotiate")]
fn negotiate(_headers: Headers, _conn: DbConn) -> JsonResult {
- use crypto;
+ use crate::crypto;
use data_encoding::BASE64URL;
let conn_id = BASE64URL.encode(&crypto::get_random(vec![0u8; 16]));
@@ -52,7 +52,7 @@ use chashmap::CHashMap;
use chrono::NaiveDateTime;
use serde_json::from_str;
-use db::models::{Cipher, Folder, User};
+use crate::db::models::{Cipher, Folder, User};
use rmpv::Value;
@@ -139,7 +139,7 @@ impl Handler for WSHandler {
let _id = &query_split[1][3..];
// Validate the user
- use auth;
+ use crate::auth;
let claims = match auth::decode_jwt(access_token) {
Ok(claims) => claims,
Err(_) => {
@@ -169,7 +169,7 @@ impl Handler for WSHandler {
}
fn on_message(&mut self, msg: Message) -> ws::Result<()> {
- println!("Server got message '{}'. ", msg);
+ info!("Server got message '{}'. ", msg);
if let Message::Text(text) = msg.clone() {
let json = &text[..text.len() - 1]; // Remove last char
@@ -242,10 +242,10 @@ pub struct WebSocketUsers {
}
impl WebSocketUsers {
- fn send_update(&self, user_uuid: &String, data: Vec<u8>) -> ws::Result<()> {
+ fn send_update(&self, user_uuid: &String, data: &[u8]) -> ws::Result<()> {
if let Some(user) = self.map.get(user_uuid) {
for sender in user.iter() {
- sender.send(data.clone())?;
+ sender.send(data)?;
}
}
Ok(())
@@ -262,7 +262,7 @@ impl WebSocketUsers {
ut,
);
- self.send_update(&user.uuid.clone(), data).ok();
+ self.send_update(&user.uuid.clone(), &data).ok();
}
pub fn send_folder_update(&self, ut: UpdateType, folder: &Folder) {
@@ -275,10 +275,10 @@ impl WebSocketUsers {
ut,
);
- self.send_update(&folder.user_uuid, data).ok();
+ self.send_update(&folder.user_uuid, &data).ok();
}
- pub fn send_cipher_update(&self, ut: UpdateType, cipher: &Cipher, user_uuids: &Vec<String>) {
+ pub fn send_cipher_update(&self, ut: UpdateType, cipher: &Cipher, user_uuids: &[String]) {
let user_uuid = convert_option(cipher.user_uuid.clone());
let org_uuid = convert_option(cipher.organization_uuid.clone());
@@ -294,7 +294,7 @@ impl WebSocketUsers {
);
for uuid in user_uuids {
- self.send_update(&uuid, data.clone()).ok();
+ self.send_update(&uuid, &data).ok();
}
}
}
diff --git a/src/api/web.rs b/src/api/web.rs
@@ -6,9 +6,10 @@ use rocket::response::{self, NamedFile, Responder};
use rocket::response::content::Content;
use rocket::http::{ContentType, Status};
use rocket::Route;
-use rocket_contrib::{Json, Value};
+use rocket_contrib::json::Json;
+use serde_json::Value;
-use CONFIG;
+use crate::CONFIG;
pub fn routes() -> Vec<Route> {
if CONFIG.web_vault_enabled {
@@ -73,7 +74,7 @@ fn attachments(uuid: String, file: PathBuf) -> io::Result<NamedFile> {
#[get("/alive")]
fn alive() -> Json<String> {
- use util::format_date;
+ use crate::util::format_date;
use chrono::Utc;
Json(format_date(&Utc::now().naive_utc()))
diff --git a/src/auth.rs b/src/auth.rs
@@ -1,22 +1,21 @@
///
/// JWT Handling
///
-
-use util::read_file;
+use crate::util::read_file;
use chrono::Duration;
-use jwt;
+use jsonwebtoken::{self, Algorithm, Header};
use serde::ser::Serialize;
-use CONFIG;
+use crate::CONFIG;
-const JWT_ALGORITHM: jwt::Algorithm = jwt::Algorithm::RS256;
+const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
lazy_static! {
pub static ref DEFAULT_VALIDITY: Duration = Duration::hours(2);
pub static ref JWT_ISSUER: String = CONFIG.domain.clone();
- static ref JWT_HEADER: jwt::Header = jwt::Header::new(JWT_ALGORITHM);
+ static ref JWT_HEADER: Header = Header::new(JWT_ALGORITHM);
static ref PRIVATE_RSA_KEY: Vec<u8> = match read_file(&CONFIG.private_rsa_key) {
Ok(key) => key,
@@ -30,17 +29,17 @@ lazy_static! {
}
pub fn encode_jwt<T: Serialize>(claims: &T) -> String {
- match jwt::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) {
+ match jsonwebtoken::encode(&JWT_HEADER, claims, &PRIVATE_RSA_KEY) {
Ok(token) => token,
Err(e) => panic!("Error encoding jwt {}", e)
}
}
pub fn decode_jwt(token: &str) -> Result<JWTClaims, String> {
- let validation = jwt::Validation {
+ let validation = jsonwebtoken::Validation {
leeway: 30, // 30 seconds
validate_exp: true,
- validate_iat: true,
+ validate_iat: false, // IssuedAt is the same as NotBefore
validate_nbf: true,
aud: None,
iss: Some(JWT_ISSUER.clone()),
@@ -48,10 +47,10 @@ pub fn decode_jwt(token: &str) -> Result<JWTClaims, String> {
algorithms: vec![JWT_ALGORITHM],
};
- match jwt::decode(token, &PUBLIC_RSA_KEY, &validation) {
+ match jsonwebtoken::decode(token, &PUBLIC_RSA_KEY, &validation) {
Ok(decoded) => Ok(decoded.claims),
Err(msg) => {
- println!("Error validating jwt - {:#?}", msg);
+ error!("Error validating jwt - {:#?}", msg);
Err(msg.to_string())
}
}
@@ -76,6 +75,7 @@ pub struct JWTClaims {
pub orgowner: Vec<String>,
pub orgadmin: Vec<String>,
pub orguser: Vec<String>,
+ pub orgmanager: Vec<String>,
// user security_stamp
pub sstamp: String,
@@ -90,12 +90,11 @@ pub struct JWTClaims {
///
/// Bearer token authentication
///
-
use rocket::Outcome;
use rocket::request::{self, Request, FromRequest};
-use db::DbConn;
-use db::models::{User, Organization, UserOrganization, UserOrgType, UserOrgStatus, Device};
+use crate::db::DbConn;
+use crate::db::models::{User, Organization, UserOrganization, UserOrgType, UserOrgStatus, Device};
pub struct Headers {
pub host: String,
@@ -139,13 +138,11 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers {
// Get access_token
let access_token: &str = match request.headers().get_one("Authorization") {
- Some(a) => {
- match a.rsplit("Bearer ").next() {
- Some(split) => split,
- None => err_handler!("No access token provided")
- }
- }
- None => err_handler!("No access token provided")
+ Some(a) => match a.rsplit("Bearer ").next() {
+ Some(split) => split,
+ None => err_handler!("No access token provided"),
+ },
+ None => err_handler!("No access token provided"),
};
// Check JWT token is valid and get device and user from it
@@ -192,13 +189,12 @@ impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders {
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
match request.guard::<Headers>() {
- Outcome::Forward(f) => Outcome::Forward(f),
+ Outcome::Forward(_) => Outcome::Forward(()),
Outcome::Failure(f) => Outcome::Failure(f),
Outcome::Success(headers) => {
- // org_id is expected to be the first dynamic param
- match request.get_param::<String>(0) {
- Err(_) => err_handler!("Error getting the organization id"),
- Ok(org_id) => {
+ // org_id is expected to be the second param ("/organizations/<org_id>")
+ match request.get_param::<String>(1) {
+ Some(Ok(org_id)) => {
let conn = match request.guard::<DbConn>() {
Outcome::Success(conn) => conn,
_ => err_handler!("Error getting DB")
@@ -226,14 +222,15 @@ impl<'a, 'r> FromRequest<'a, 'r> for OrgHeaders {
device: headers.device,
user: headers.user,
org_user_type: {
- if let Some(org_usr_type) = UserOrgType::from_i32(&org_user.type_) {
+ if let Some(org_usr_type) = UserOrgType::from_i32(org_user.type_) {
org_usr_type
} else { // This should only happen if the DB is corrupted
err_handler!("Unknown user type in the database")
}
},
})
- }
+ },
+ _ => err_handler!("Error getting the organization id"),
}
}
}
@@ -252,11 +249,11 @@ impl<'a, 'r> FromRequest<'a, 'r> for AdminHeaders {
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
match request.guard::<OrgHeaders>() {
- Outcome::Forward(f) => Outcome::Forward(f),
+ Outcome::Forward(_) => Outcome::Forward(()),
Outcome::Failure(f) => Outcome::Failure(f),
Outcome::Success(headers) => {
if headers.org_user_type >= UserOrgType::Admin {
- Outcome::Success(Self{
+ Outcome::Success(Self {
host: headers.host,
device: headers.device,
user: headers.user,
@@ -281,11 +278,11 @@ impl<'a, 'r> FromRequest<'a, 'r> for OwnerHeaders {
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
match request.guard::<OrgHeaders>() {
- Outcome::Forward(f) => Outcome::Forward(f),
+ Outcome::Forward(_) => Outcome::Forward(()),
Outcome::Failure(f) => Outcome::Failure(f),
Outcome::Success(headers) => {
if headers.org_user_type == UserOrgType::Owner {
- Outcome::Success(Self{
+ Outcome::Success(Self {
host: headers.host,
device: headers.device,
user: headers.user,
@@ -296,4 +293,26 @@ impl<'a, 'r> FromRequest<'a, 'r> for OwnerHeaders {
}
}
}
-}
-\ No newline at end of file
+}
+
+///
+/// Client IP address detection
+///
+use std::net::IpAddr;
+
+pub struct ClientIp {
+ pub ip: IpAddr,
+}
+
+impl<'a, 'r> FromRequest<'a, 'r> for ClientIp {
+ type Error = ();
+
+ fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
+ let ip = match request.client_ip() {
+ Some(addr) => addr,
+ None => "0.0.0.0".parse().unwrap(),
+ };
+
+ Outcome::Success(ClientIp { ip })
+ }
+}
diff --git a/src/db/mod.rs b/src/db/mod.rs
@@ -9,7 +9,7 @@ use rocket::http::Status;
use rocket::request::{self, FromRequest};
use rocket::{Outcome, Request, State};
-use CONFIG;
+use crate::CONFIG;
/// An alias to the database connection used
type Connection = SqliteConnection;
diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs
@@ -1,7 +1,7 @@
-use serde_json::Value as JsonValue;
+use serde_json::Value;
use super::Cipher;
-use CONFIG;
+use crate::CONFIG;
#[derive(Debug, Identifiable, Queryable, Insertable, Associations)]
#[table_name = "attachments"]
@@ -12,6 +12,7 @@ pub struct Attachment {
pub cipher_uuid: String,
pub file_name: String,
pub file_size: i32,
+ pub key: Option<String>
}
/// Local methods
@@ -22,6 +23,7 @@ impl Attachment {
cipher_uuid,
file_name,
file_size,
+ key: None
}
}
@@ -29,8 +31,8 @@ impl Attachment {
format!("{}/{}/{}", CONFIG.attachments_folder, self.cipher_uuid, self.id)
}
- pub fn to_json(&self, host: &str) -> JsonValue {
- use util::get_display_size;
+ pub fn to_json(&self, host: &str) -> Value {
+ use crate::util::get_display_size;
let web_path = format!("{}/attachments/{}/{}", host, self.cipher_uuid, self.id);
let display_size = get_display_size(self.file_size);
@@ -41,6 +43,7 @@ impl Attachment {
"FileName": self.file_name,
"Size": self.file_size.to_string(),
"SizeName": display_size,
+ "Key": self.key,
"Object": "attachment"
})
}
@@ -48,8 +51,8 @@ impl Attachment {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::attachments;
+use crate::db::DbConn;
+use crate::db::schema::attachments;
/// Database methods
impl Attachment {
@@ -61,39 +64,21 @@ impl Attachment {
}
pub fn delete(self, conn: &DbConn) -> QueryResult<()> {
- use util;
- use std::{thread, time};
-
- let mut retries = 10;
-
- loop {
- match diesel::delete(
- attachments::table.filter(
- attachments::id.eq(&self.id)
- )
- ).execute(&**conn) {
- Ok(_) => break,
- Err(err) => {
- if retries < 1 {
- println!("ERROR: Failed with 10 retries");
- return Err(err)
- } else {
- retries -= 1;
- println!("Had to retry! Retries left: {}", retries);
- thread::sleep(time::Duration::from_millis(500));
- continue
- }
- }
- }
- }
-
- util::delete_file(&self.get_file_path());
+ crate::util::retry(
+ || {
+ diesel::delete(attachments::table.filter(attachments::id.eq(&self.id)))
+ .execute(&**conn)
+ },
+ 10,
+ )?;
+
+ crate::util::delete_file(&self.get_file_path());
Ok(())
}
pub fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> QueryResult<()> {
- for attachement in Attachment::find_by_cipher(&cipher_uuid, &conn) {
- attachement.delete(&conn)?;
+ for attachment in Attachment::find_by_cipher(&cipher_uuid, &conn) {
+ attachment.delete(&conn)?;
}
Ok(())
}
diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs
@@ -1,7 +1,5 @@
use chrono::{NaiveDateTime, Utc};
-use serde_json::Value as JsonValue;
-
-use uuid::Uuid;
+use serde_json::Value;
use super::{User, Organization, Attachment, FolderCipher, CollectionCipher, UserOrganization, UserOrgType, UserOrgStatus};
@@ -41,7 +39,7 @@ impl Cipher {
let now = Utc::now().naive_utc();
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
created_at: now,
updated_at: now,
@@ -63,28 +61,28 @@ impl Cipher {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::*;
+use crate::db::DbConn;
+use crate::db::schema::*;
/// Database methods
impl Cipher {
- pub fn to_json(&self, host: &str, user_uuid: &str, conn: &DbConn) -> JsonValue {
+ pub fn to_json(&self, host: &str, user_uuid: &str, conn: &DbConn) -> Value {
use serde_json;
- use util::format_date;
+ use crate::util::format_date;
use super::Attachment;
let attachments = Attachment::find_by_cipher(&self.uuid, conn);
- let attachments_json: Vec<JsonValue> = attachments.iter().map(|c| c.to_json(host)).collect();
+ let attachments_json: Vec<Value> = attachments.iter().map(|c| c.to_json(host)).collect();
- let fields_json: JsonValue = if let Some(ref fields) = self.fields {
+ let fields_json: Value = if let Some(ref fields) = self.fields {
serde_json::from_str(fields).unwrap()
- } else { JsonValue::Null };
+ } else { Value::Null };
- let password_history_json: JsonValue = if let Some(ref password_history) = self.password_history {
+ let password_history_json: Value = if let Some(ref password_history) = self.password_history {
serde_json::from_str(password_history).unwrap()
- } else { JsonValue::Null };
+ } else { Value::Null };
- let mut data_json: JsonValue = serde_json::from_str(&self.data).unwrap();
+ let mut data_json: Value = serde_json::from_str(&self.data).unwrap();
// TODO: ******* Backwards compat start **********
// To remove backwards compatibility, just remove this entire section
@@ -234,7 +232,7 @@ impl Cipher {
}
pub fn is_write_accessible_to_user(&self, user_uuid: &str, conn: &DbConn) -> bool {
- match ciphers::table
+ ciphers::table
.filter(ciphers::uuid.eq(&self.uuid))
.left_join(users_organizations::table.on(
ciphers::organization_uuid.eq(users_organizations::org_uuid.nullable()).and(
@@ -255,14 +253,11 @@ impl Cipher {
)
))
.select(ciphers::all_columns)
- .first::<Self>(&**conn).ok() {
- Some(_) => true,
- None => false
- }
+ .first::<Self>(&**conn).ok().is_some()
}
pub fn is_accessible_to_user(&self, user_uuid: &str, conn: &DbConn) -> bool {
- match ciphers::table
+ ciphers::table
.filter(ciphers::uuid.eq(&self.uuid))
.left_join(users_organizations::table.on(
ciphers::organization_uuid.eq(users_organizations::org_uuid.nullable()).and(
@@ -281,10 +276,7 @@ impl Cipher {
)
))
.select(ciphers::all_columns)
- .first::<Self>(&**conn).ok() {
- Some(_) => true,
- None => false
- }
+ .first::<Self>(&**conn).ok().is_some()
}
pub fn get_folder_uuid(&self, user_uuid: &str, conn: &DbConn) -> Option<String> {
diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs
@@ -1,6 +1,4 @@
-use serde_json::Value as JsonValue;
-
-use uuid::Uuid;
+use serde_json::Value;
use super::{Organization, UserOrganization, UserOrgType, UserOrgStatus};
@@ -18,14 +16,14 @@ pub struct Collection {
impl Collection {
pub fn new(org_uuid: String, name: String) -> Self {
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
org_uuid,
name,
}
}
- pub fn to_json(&self) -> JsonValue {
+ pub fn to_json(&self) -> Value {
json!({
"Id": self.uuid,
"OrganizationId": self.org_uuid,
@@ -37,8 +35,8 @@ impl Collection {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::*;
+use crate::db::DbConn;
+use crate::db::schema::*;
/// Database methods
impl Collection {
@@ -150,15 +148,12 @@ impl Collection {
if user_org.access_all {
true
} else {
- match users_collections::table.inner_join(collections::table)
+ users_collections::table.inner_join(collections::table)
.filter(users_collections::collection_uuid.eq(&self.uuid))
.filter(users_collections::user_uuid.eq(&user_uuid))
.filter(users_collections::read_only.eq(false))
.select(collections::all_columns)
- .first::<Self>(&**conn).ok() {
- None => false, // Read only or no access to collection
- Some(_) => true,
- }
+ .first::<Self>(&**conn).ok().is_some() // Read only or no access to collection
}
}
}
diff --git a/src/db/models/device.rs b/src/db/models/device.rs
@@ -45,7 +45,7 @@ impl Device {
pub fn refresh_twofactor_remember(&mut self) -> String {
use data_encoding::BASE64;
- use crypto;
+ use crate::crypto;
let twofactor_remember = BASE64.encode(&crypto::get_random(vec![0u8; 180]));
self.twofactor_remember = Some(twofactor_remember.clone());
@@ -62,7 +62,7 @@ impl Device {
// If there is no refresh token, we create one
if self.refresh_token.is_empty() {
use data_encoding::BASE64URL;
- use crypto;
+ use crate::crypto;
self.refresh_token = BASE64URL.encode(&crypto::get_random_64());
}
@@ -71,14 +71,14 @@ impl Device {
let time_now = Utc::now().naive_utc();
self.updated_at = time_now;
-
let orgowner: Vec<_> = orgs.iter().filter(|o| o.type_ == 0).map(|o| o.org_uuid.clone()).collect();
let orgadmin: Vec<_> = orgs.iter().filter(|o| o.type_ == 1).map(|o| o.org_uuid.clone()).collect();
let orguser: Vec<_> = orgs.iter().filter(|o| o.type_ == 2).map(|o| o.org_uuid.clone()).collect();
+ let orgmanager: Vec<_> = orgs.iter().filter(|o| o.type_ == 3).map(|o| o.org_uuid.clone()).collect();
// Create the JWT claims struct, to send to the client
- use auth::{encode_jwt, JWTClaims, DEFAULT_VALIDITY, JWT_ISSUER};
+ use crate::auth::{encode_jwt, JWTClaims, DEFAULT_VALIDITY, JWT_ISSUER};
let claims = JWTClaims {
nbf: time_now.timestamp(),
exp: (time_now + *DEFAULT_VALIDITY).timestamp(),
@@ -93,6 +93,7 @@ impl Device {
orgowner,
orgadmin,
orguser,
+ orgmanager,
sstamp: user.security_stamp.to_string(),
device: self.uuid.to_string(),
@@ -100,23 +101,29 @@ impl Device {
amr: vec!["Application".into()],
};
-
(encode_jwt(&claims), DEFAULT_VALIDITY.num_seconds())
}
}
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::devices;
+use crate::db::DbConn;
+use crate::db::schema::devices;
/// Database methods
impl Device {
pub fn save(&mut self, conn: &DbConn) -> QueryResult<()> {
self.updated_at = Utc::now().naive_utc();
- diesel::replace_into(devices::table)
- .values(&*self).execute(&**conn).and(Ok(()))
+ crate::util::retry(
+ || {
+ diesel::replace_into(devices::table)
+ .values(&*self)
+ .execute(&**conn)
+ },
+ 10,
+ )
+ .and(Ok(()))
}
pub fn delete(self, conn: &DbConn) -> QueryResult<()> {
diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs
@@ -1,7 +1,5 @@
use chrono::{NaiveDateTime, Utc};
-use serde_json::Value as JsonValue;
-
-use uuid::Uuid;
+use serde_json::Value;
use super::{User, Cipher};
@@ -33,7 +31,7 @@ impl Folder {
let now = Utc::now().naive_utc();
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
created_at: now,
updated_at: now,
@@ -42,8 +40,8 @@ impl Folder {
}
}
- pub fn to_json(&self) -> JsonValue {
- use util::format_date;
+ pub fn to_json(&self) -> Value {
+ use crate::util::format_date;
json!({
"Id": self.uuid,
@@ -65,8 +63,8 @@ impl FolderCipher {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::{folders, folders_ciphers};
+use crate::db::DbConn;
+use crate::db::schema::{folders, folders_ciphers};
/// Database methods
impl Folder {
diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs
@@ -1,7 +1,6 @@
use std::cmp::Ordering;
-use serde_json::Value as JsonValue;
+use serde_json::Value;
-use uuid::Uuid;
use super::{User, CollectionUser, Invitation};
#[derive(Debug, Identifiable, Queryable, Insertable)]
@@ -78,10 +77,10 @@ impl PartialEq<i32> for UserOrgType {
impl PartialOrd<i32> for UserOrgType {
fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
- if let Some(other) = Self::from_i32(other) {
+ if let Some(other) = Self::from_i32(*other) {
return Some(self.cmp(&other))
}
- return None
+ None
}
fn gt(&self, other: &i32) -> bool {
@@ -108,10 +107,10 @@ impl PartialEq<UserOrgType> for i32 {
impl PartialOrd<UserOrgType> for i32 {
fn partial_cmp(&self, other: &UserOrgType) -> Option<Ordering> {
- if let Some(self_type) = UserOrgType::from_i32(self) {
+ if let Some(self_type) = UserOrgType::from_i32(*self) {
return Some(self_type.cmp(other))
}
- return None
+ None
}
fn lt(&self, other: &UserOrgType) -> bool {
@@ -141,7 +140,7 @@ impl UserOrgType {
}
}
- pub fn from_i32(i: &i32) -> Option<Self> {
+ pub fn from_i32(i: i32) -> Option<Self> {
match i {
0 => Some(UserOrgType::Owner),
1 => Some(UserOrgType::Admin),
@@ -159,7 +158,7 @@ impl Organization {
pub fn new(name: String, billing_email: String) -> Self {
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
name,
billing_email,
@@ -174,7 +173,7 @@ impl Organization {
}
}
- pub fn to_json(&self) -> JsonValue {
+ pub fn to_json(&self) -> Value {
json!({
"Id": self.uuid,
"Name": self.name,
@@ -206,7 +205,7 @@ impl Organization {
impl UserOrganization {
pub fn new(user_uuid: String, org_uuid: String) -> Self {
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
user_uuid,
org_uuid,
@@ -236,8 +235,8 @@ impl UserOrganization {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::{organizations, users_organizations, users_collections, ciphers_collections};
+use crate::db::DbConn;
+use crate::db::schema::{organizations, users_organizations, users_collections, ciphers_collections};
/// Database methods
impl Organization {
@@ -285,7 +284,7 @@ impl Organization {
}
impl UserOrganization {
- pub fn to_json(&self, conn: &DbConn) -> JsonValue {
+ pub fn to_json(&self, conn: &DbConn) -> Value {
let org = Organization::find_by_uuid(&self.org_uuid, conn).unwrap();
json!({
@@ -313,7 +312,7 @@ impl UserOrganization {
})
}
- pub fn to_json_user_details(&self, conn: &DbConn) -> JsonValue {
+ pub fn to_json_user_details(&self, conn: &DbConn) -> Value {
let user = User::find_by_uuid(&self.user_uuid, conn).unwrap();
json!({
@@ -330,7 +329,7 @@ impl UserOrganization {
})
}
- pub fn to_json_collection_user_details(&self, read_only: bool, conn: &DbConn) -> JsonValue {
+ pub fn to_json_collection_user_details(&self, read_only: bool, conn: &DbConn) -> Value {
let user = User::find_by_uuid(&self.user_uuid, conn).unwrap();
json!({
@@ -345,7 +344,7 @@ impl UserOrganization {
})
}
- pub fn to_json_details(&self, conn: &DbConn) -> JsonValue {
+ pub fn to_json_details(&self, conn: &DbConn) -> Value {
let coll_uuids = if self.access_all {
vec![] // If we have complete access, no need to fill the array
} else {
diff --git a/src/db/models/two_factor.rs b/src/db/models/two_factor.rs
@@ -1,6 +1,4 @@
-use serde_json::Value as JsonValue;
-
-use uuid::Uuid;
+use serde_json::Value;
use super::User;
@@ -36,7 +34,7 @@ pub enum TwoFactorType {
impl TwoFactor {
pub fn new(user_uuid: String, type_: TwoFactorType, data: String) -> Self {
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
user_uuid,
type_: type_ as i32,
enabled: true,
@@ -59,7 +57,7 @@ impl TwoFactor {
generated == totp_code
}
- pub fn to_json(&self) -> JsonValue {
+ pub fn to_json(&self) -> Value {
json!({
"Enabled": self.enabled,
"Key": "", // This key and value vary
@@ -67,7 +65,7 @@ impl TwoFactor {
})
}
- pub fn to_json_list(&self) -> JsonValue {
+ pub fn to_json_list(&self) -> Value {
json!({
"Enabled": self.enabled,
"Type": self.type_,
@@ -78,8 +76,8 @@ impl TwoFactor {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::twofactor;
+use crate::db::DbConn;
+use crate::db::schema::twofactor;
/// Database methods
impl TwoFactor {
diff --git a/src/db/models/user.rs b/src/db/models/user.rs
@@ -1,10 +1,8 @@
use chrono::{NaiveDateTime, Utc};
-use serde_json::Value as JsonValue;
+use serde_json::Value;
-use uuid::Uuid;
-
-use crypto;
-use CONFIG;
+use crate::crypto;
+use crate::CONFIG;
#[derive(Debug, Identifiable, Queryable, Insertable)]
@@ -50,7 +48,7 @@ impl User {
let email = mail.to_lowercase();
Self {
- uuid: Uuid::new_v4().to_string(),
+ uuid: crate::util::get_uuid(),
created_at: now,
updated_at: now,
name: email.clone(),
@@ -61,7 +59,7 @@ impl User {
salt: crypto::get_random_64(),
password_iterations: CONFIG.password_iterations,
- security_stamp: Uuid::new_v4().to_string(),
+ security_stamp: crate::util::get_uuid(),
password_hint: None,
private_key: None,
@@ -97,11 +95,10 @@ impl User {
self.password_hash = crypto::hash_password(password.as_bytes(),
&self.salt,
self.password_iterations as u32);
- self.reset_security_stamp();
}
pub fn reset_security_stamp(&mut self) {
- self.security_stamp = Uuid::new_v4().to_string();
+ self.security_stamp = crate::util::get_uuid();
}
pub fn is_server_admin(&self) -> bool {
@@ -114,20 +111,20 @@ impl User {
use diesel;
use diesel::prelude::*;
-use db::DbConn;
-use db::schema::{users, invitations};
+use crate::db::DbConn;
+use crate::db::schema::{users, invitations};
use super::{Cipher, Folder, Device, UserOrganization, UserOrgType};
/// Database methods
impl User {
- pub fn to_json(&self, conn: &DbConn) -> JsonValue {
+ pub fn to_json(&self, conn: &DbConn) -> Value {
use super::{UserOrganization, UserOrgType, UserOrgStatus, TwoFactor};
let mut orgs = UserOrganization::find_by_user(&self.uuid, conn);
if self.is_server_admin() {
orgs.push(UserOrganization::new_virtual(self.uuid.clone(), UserOrgType::Owner, UserOrgStatus::Confirmed));
}
- let orgs_json: Vec<JsonValue> = orgs.iter().map(|c| c.to_json(&conn)).collect();
+ let orgs_json: Vec<Value> = orgs.iter().map(|c| c.to_json(&conn)).collect();
let twofactor_enabled = !TwoFactor::find_by_user(&self.uuid, conn).is_empty();
json!({
@@ -181,7 +178,7 @@ impl User {
pub fn update_uuid_revision(uuid: &str, conn: &DbConn) {
if let Some(mut user) = User::find_by_uuid(&uuid, conn) {
if user.update_revision(conn).is_err(){
- println!("Warning: Failed to update revision for {}", user.email);
+ warn!("Failed to update revision for {}", user.email);
};
};
}
diff --git a/src/db/schema.rs b/src/db/schema.rs
@@ -4,6 +4,7 @@ table! {
cipher_uuid -> Text,
file_name -> Text,
file_size -> Integer,
+ key -> Nullable<Text>,
}
}
diff --git a/src/mail.rs b/src/mail.rs
@@ -4,7 +4,7 @@ use lettre::smtp::ConnectionReuseParameters;
use lettre::smtp::authentication::Credentials;
use lettre_email::EmailBuilder;
-use MailConfig;
+use crate::MailConfig;
fn mailer(config: &MailConfig) -> SmtpTransport {
let client_security = if config.smtp_ssl {
diff --git a/src/main.rs b/src/main.rs
@@ -1,41 +1,15 @@
-#![feature(plugin, custom_derive, vec_remove_item, try_trait)]
-#![plugin(rocket_codegen)]
-#![recursion_limit="128"]
+#![feature(proc_macro_hygiene, decl_macro, vec_remove_item, try_trait)]
+#![recursion_limit = "128"]
#![allow(proc_macro_derive_resolution_fallback)] // TODO: Remove this when diesel update fixes warnings
-extern crate rocket;
-extern crate rocket_contrib;
-extern crate reqwest;
-extern crate multipart;
-extern crate ws;
-extern crate rmpv;
-extern crate chashmap;
-extern crate serde;
-#[macro_use]
-extern crate serde_derive;
-#[macro_use]
-extern crate serde_json;
-#[macro_use]
-extern crate diesel;
-#[macro_use]
-extern crate diesel_migrations;
-extern crate ring;
-extern crate uuid;
-extern crate chrono;
-extern crate oath;
-extern crate data_encoding;
-extern crate jsonwebtoken as jwt;
-extern crate u2f;
-extern crate yubico;
-extern crate dotenv;
-#[macro_use]
-extern crate lazy_static;
-#[macro_use]
-extern crate num_derive;
-extern crate num_traits;
-extern crate lettre;
-extern crate lettre_email;
-extern crate native_tls;
-extern crate byteorder;
+
+#[macro_use] extern crate rocket;
+#[macro_use] extern crate serde_derive;
+#[macro_use] extern crate serde_json;
+#[macro_use] extern crate log;
+#[macro_use] extern crate diesel;
+#[macro_use] extern crate diesel_migrations;
+#[macro_use] extern crate lazy_static;
+#[macro_use] extern crate num_derive;
use std::{path::Path, process::{exit, Command}};
use rocket::Rocket;
@@ -50,6 +24,9 @@ mod auth;
mod mail;
fn init_rocket() -> Rocket {
+
+ // TODO: TO HIDE MOUNTING LOG, call ignite, set logging to disabled, call all the mounts, and then enable it again
+
rocket::ignite()
.mount("/", api::web_routes())
.mount("/api", api::core_routes())
@@ -69,7 +46,7 @@ mod migrations {
pub fn run_migrations() {
// Make sure the database is up to date (create if it doesn't exist, or run the migrations)
- let connection = ::db::get_connection().expect("Can't conect to DB");
+ let connection = crate::db::get_connection().expect("Can't conect to DB");
use std::io::stdout;
embedded_migrations::run_with_output(&connection, &mut stdout()).expect("Can't run migrations");
@@ -77,6 +54,10 @@ mod migrations {
}
fn main() {
+ if CONFIG.extended_logging {
+ init_logging().ok();
+ }
+
check_db();
check_rsa_keys();
check_web_vault();
@@ -85,13 +66,61 @@ fn main() {
init_rocket().launch();
}
+fn init_logging() -> Result<(), fern::InitError> {
+ let mut logger = fern::Dispatch::new()
+ .format(|out, message, record| {
+ out.finish(format_args!(
+ "{}[{}][{}] {}",
+ chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
+ record.target(),
+ record.level(),
+ message
+ ))
+ })
+ .level(log::LevelFilter::Debug)
+ .level_for("hyper", log::LevelFilter::Warn)
+ .level_for("ws", log::LevelFilter::Info)
+ .level_for("multipart", log::LevelFilter::Info)
+ .chain(std::io::stdout());
+
+ if let Some(log_file) = CONFIG.log_file.as_ref() {
+ logger = logger.chain(fern::log_file(log_file)?);
+ }
+
+ logger = chain_syslog(logger);
+ logger.apply()?;
+
+ Ok(())
+}
+
+#[cfg(not(feature = "enable_syslog"))]
+fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch { logger }
+
+#[cfg(feature = "enable_syslog")]
+fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch {
+ let syslog_fmt = syslog::Formatter3164 {
+ facility: syslog::Facility::LOG_USER,
+ hostname: None,
+ process: "bitwarden_rs".into(),
+ pid: 0,
+ };
+
+ match syslog::unix(syslog_fmt) {
+ Ok(sl) => logger.chain(sl),
+ Err(e) => {
+ error!("Unable to connect to syslog: {:?}", e);
+ logger
+ }
+ }
+}
+
fn check_db() {
let path = Path::new(&CONFIG.database_url);
if let Some(parent) = path.parent() {
use std::fs;
if fs::create_dir_all(parent).is_err() {
- println!("Error creating database directory");
+ error!("Error creating database directory");
exit(1);
}
}
@@ -106,16 +135,16 @@ fn check_rsa_keys() {
// If the RSA keys don't exist, try to create them
if !util::file_exists(&CONFIG.private_rsa_key)
|| !util::file_exists(&CONFIG.public_rsa_key) {
- println!("JWT keys don't exist, checking if OpenSSL is available...");
+ info!("JWT keys don't exist, checking if OpenSSL is available...");
Command::new("openssl")
.arg("version")
.output().unwrap_or_else(|_| {
- println!("Can't create keys because OpenSSL is not available, make sure it's installed and available on the PATH");
+ info!("Can't create keys because OpenSSL is not available, make sure it's installed and available on the PATH");
exit(1);
});
- println!("OpenSSL detected, creating keys...");
+ info!("OpenSSL detected, creating keys...");
let mut success = Command::new("openssl").arg("genrsa")
.arg("-out").arg(&CONFIG.private_rsa_key_pem)
@@ -139,9 +168,9 @@ fn check_rsa_keys() {
.status.success();
if success {
- println!("Keys created correctly.");
+ info!("Keys created correctly.");
} else {
- println!("Error creating keys, exiting...");
+ error!("Error creating keys, exiting...");
exit(1);
}
}
@@ -155,7 +184,7 @@ fn check_web_vault() {
let index_path = Path::new(&CONFIG.web_vault_folder).join("index.html");
if !index_path.exists() {
- println!("Web vault is not found. Please follow the steps in the README to install it");
+ error!("Web vault is not found. Please follow the steps in the README to install it");
exit(1);
}
}
@@ -177,7 +206,7 @@ pub struct MailConfig {
impl MailConfig {
fn load() -> Option<Self> {
- use util::{get_env, get_env_or};
+ use crate::util::{get_env, get_env_or};
// When SMTP_HOST is absent, we assume the user does not want to enable it.
let smtp_host = match get_env("SMTP_HOST") {
@@ -186,7 +215,7 @@ impl MailConfig {
};
let smtp_from = get_env("SMTP_FROM").unwrap_or_else(|| {
- println!("Please specify SMTP_FROM to enable SMTP support.");
+ error!("Please specify SMTP_FROM to enable SMTP support.");
exit(1);
});
@@ -202,7 +231,7 @@ impl MailConfig {
let smtp_username = get_env("SMTP_USERNAME");
let smtp_password = get_env("SMTP_PASSWORD").or_else(|| {
if smtp_username.as_ref().is_some() {
- println!("SMTP_PASSWORD is mandatory when specifying SMTP_USERNAME.");
+ error!("SMTP_PASSWORD is mandatory when specifying SMTP_USERNAME.");
exit(1);
} else {
None
@@ -236,6 +265,9 @@ pub struct Config {
websocket_enabled: bool,
websocket_url: String,
+ extended_logging: bool,
+ log_file: Option<String>,
+
local_icon_extractor: bool,
signups_allowed: bool,
invitations_allowed: bool,
@@ -256,7 +288,7 @@ pub struct Config {
impl Config {
fn load() -> Self {
- use util::{get_env, get_env_or};
+ use crate::util::{get_env, get_env_or};
dotenv::dotenv().ok();
let df = get_env_or("DATA_FOLDER", "data".to_string());
@@ -281,6 +313,9 @@ impl Config {
websocket_enabled: get_env_or("WEBSOCKET_ENABLED", false),
websocket_url: format!("{}:{}", get_env_or("WEBSOCKET_ADDRESS", "0.0.0.0".to_string()), get_env_or("WEBSOCKET_PORT", 3012)),
+
+ extended_logging: get_env_or("EXTENDED_LOGGING", true),
+ log_file: get_env("LOG_FILE"),
local_icon_extractor: get_env_or("LOCAL_ICON_EXTRACTOR", false),
signups_allowed: get_env_or("SIGNUPS_ALLOWED", true),
diff --git a/src/util.rs b/src/util.rs
@@ -2,36 +2,46 @@
/// Macros
///
#[macro_export]
-macro_rules! err {
- ($err:expr, $msg:expr) => {{
- println!("ERROR: {}", $msg);
+macro_rules! _err_object {
+ ($msg:expr) => {{
err_json!(json!({
- "error": $err,
- "error_description": $err,
- "ErrorModel": {
- "Message": $msg,
- "ValidationErrors": null,
- "ExceptionMessage": null,
- "ExceptionStackTrace": null,
- "InnerExceptionMessage": null,
- "Object": "error"
- }}))
+ "Message": "",
+ "error": "",
+ "error_description": "",
+ "ValidationErrors": {"": [ $msg ]},
+ "ErrorModel": {
+ "Message": $msg,
+ "Object": "error"
+ },
+ "Object": "error"
+ }))
+ }};
+}
+
+#[macro_export]
+macro_rules! err {
+ ($msg:expr) => {{
+ error!("{}", $msg);
+ _err_object!($msg)
}};
- ($msg:expr) => { err!("unknown_error", $msg) }
+ ($usr_msg:expr, $log_value:expr) => {{
+ error!("{}: {:#?}", $usr_msg, $log_value);
+ _err_object!($usr_msg)
+ }}
}
#[macro_export]
macro_rules! err_json {
($expr:expr) => {{
- return Err($crate::rocket::response::status::BadRequest(Some($crate::rocket_contrib::Json($expr))));
+ return Err(rocket::response::status::BadRequest(Some(rocket_contrib::json::Json($expr))));
}}
}
#[macro_export]
macro_rules! err_handler {
($expr:expr) => {{
- println!("ERROR: {}", $expr);
- return $crate::rocket::Outcome::Failure(($crate::rocket::http::Status::Unauthorized, $expr));
+ error!("{}", $expr);
+ return rocket::Outcome::Failure((rocket::http::Status::Unauthorized, $expr));
}}
}
@@ -92,6 +102,10 @@ pub fn get_display_size(size: i32) -> String {
format!("{} {}", size, UNITS[unit_counter])
}
+pub fn get_uuid() -> String {
+ uuid::Uuid::new_v4().to_string()
+}
+
///
/// String util methods
@@ -238,6 +252,33 @@ fn upcase_value(value: &Value) -> Value {
fn _process_key(key: &str) -> String {
match key.to_lowercase().as_ref() {
"ssn" => "SSN".into(),
- _ => self::upcase_first(key)
+ _ => self::upcase_first(key),
+ }
+}
+
+//
+// Retry methods
+//
+
+pub fn retry<F, T, E>(func: F, max_tries: i32) -> Result<T, E>
+where
+ F: Fn() -> Result<T, E>,
+{
+ use std::{thread::sleep, time::Duration};
+ let mut tries = 0;
+
+ loop {
+ match func() {
+ ok @ Ok(_) => return ok,
+ err @ Err(_) => {
+ tries += 1;
+
+ if tries >= max_tries {
+ return err;
+ }
+
+ sleep(Duration::from_millis(500));
+ }
+ }
}
}