diff options
author | Daniel GarcĂa <[email protected]> | 2018-09-13 15:39:28 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2018-09-13 15:39:28 +0200 |
commit | fdbd73c716a435970d77ecfe64357ec1745753ac (patch) | |
tree | 26e5e59a87fcbdd0805ba7075eebf5c10bf05ff9 | |
parent | af69606bea7afb533ad2b46e645d85cb74f88f84 (diff) | |
parent | f397f0cbd0a5d32b78c6e0f139acef598e737ad6 (diff) | |
download | vaultwarden-fdbd73c716a435970d77ecfe64357ec1745753ac.tar.gz vaultwarden-fdbd73c716a435970d77ecfe64357ec1745753ac.zip |
Merge branch 'master' into master
33 files changed, 1343 insertions, 579 deletions
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..c37ede59 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +# Copied from Rocket's .travis.yml +language: rust +sudo: required # so we get a VM with higher specs +dist: trusty # so we get a VM with higher specs +cache: cargo +rust: +- nightly @@ -17,28 +17,29 @@ cargo build --release When run, the server is accessible in [http://localhost:80](http://localhost:80). ### Install the web-vault -Download the latest official release from the [releases page](https://github.com/bitwarden/web/releases) and extract it. - -Modify `web-vault/settings.Production.json` to look like this: -```json -{ - "appSettings": { - "apiUri": "/api", - "identityUri": "/identity", - "iconsUri": "/icons", - "stripeKey": "", - "braintreeKey": "" - } -} +Clone the git repository at [bitwarden/web](https://github.com/bitwarden/web) and checkout the latest release tag (e.g. v2.1.1): +```sh +# clone the repository +git clone https://github.com/bitwarden/web.git web-vault +cd web-vault +# switch to the latest tag +git checkout "$(git tag | tail -n1)" +``` + +Apply the patch file from `docker/set-vault-baseurl.patch`: +```sh +# In the Vault repository directory +git apply /path/to/bitwarden_rs/docker/set-vault-baseurl.patch ``` -Then, run the following from the `web-vault` directory: +Then, build the Vault: ```sh +npm run sub:init npm install -npx gulp dist:selfHosted +npm run dist ``` -Finally copy the contents of the `web-vault/dist` folder into the `bitwarden_rs/web-vault` folder. +Finally copy the contents of the `build` folder into the `bitwarden_rs/web-vault` folder. # Configuration The available configuration options are documented in the default `.env` file, and they can be modified by uncommenting the desired options in that file or by setting their respective environment variables. Look at the README file for the main configuration options available. @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "ascii" -version = "0.7.1" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -34,7 +34,7 @@ name = "base64" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -42,7 +42,7 @@ name = "base64" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -51,7 +51,7 @@ name = "base64" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -62,44 +62,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitwarden_rs" -version = "0.10.0" +version = "1.0.0" dependencies = [ - "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.3.2 (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", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libsqlite3-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "multipart 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsqlite3-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "multipart 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "oath 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket_codegen 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket_contrib 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket_codegen 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket_contrib 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "u2f 0.1.2 (git+https://github.com/wisespace-io/u2f-rs?rev=193de35093a44)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "buf_redux" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (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.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -114,40 +115,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "chrono" -version = "0.2.25" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "chrono" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -182,7 +174,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -190,7 +182,7 @@ name = "core-foundation-sys" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -225,9 +217,9 @@ version = "0.3.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)", - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.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.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -239,9 +231,9 @@ version = "0.4.3" 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.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.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)", ] @@ -251,7 +243,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -259,7 +251,7 @@ name = "crossbeam-utils" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -281,10 +273,10 @@ name = "diesel" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_derives 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsqlite3-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libsqlite3-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -329,9 +321,9 @@ name = "dotenv" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -398,10 +390,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.7.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -411,20 +403,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "failure" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -450,7 +443,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -531,21 +524,20 @@ version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -563,7 +555,7 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -580,7 +572,7 @@ name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -590,7 +582,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -601,7 +593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -614,7 +606,7 @@ name = "isatty" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (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.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -629,12 +621,12 @@ name = "jsonwebtoken" version = "4.0.1" dependencies = [ "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.5 (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.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -659,8 +651,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "lazycell" @@ -669,7 +664,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.42" +version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -678,18 +673,18 @@ version = "0.1.16" 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.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libsqlite3-sys" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -697,36 +692,36 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "matches" -version = "0.1.6" +name = "mach" +version = "0.2.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)", +] [[package]] -name = "memchr" -version = "1.0.2" +name = "matches" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -762,7 +757,7 @@ dependencies = [ [[package]] name = "mime" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -770,7 +765,7 @@ dependencies = [ [[package]] name = "mime_guess" -version = "1.8.5" +version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -781,10 +776,10 @@ dependencies = [ [[package]] name = "mime_guess" -version = "2.0.0-alpha.5" +version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -800,11 +795,11 @@ dependencies = [ "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 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (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)", - "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -826,22 +821,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "multipart" -version = "0.14.2" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.13 (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.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (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)", "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (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)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -860,7 +855,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -873,8 +868,8 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -885,7 +880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "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)", @@ -903,24 +898,14 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "num" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "num-derive" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -932,15 +917,6 @@ dependencies = [ ] [[package]] -name = "num-iter" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "num-traits" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -950,7 +926,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -972,20 +948,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (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.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.33" +version = "0.9.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -995,12 +971,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pear" -version = "0.0.18" +version = "0.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pear_codegen" -version = "0.0.18" +version = "0.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1035,7 +1011,7 @@ version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1043,13 +1019,13 @@ name = "phf_shared" version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pkg-config" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1070,7 +1046,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.6" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1096,10 +1072,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1108,27 +1084,17 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -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.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.4.2" +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.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1137,19 +1103,18 @@ name = "rayon" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.4.0" +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.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.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)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1165,19 +1130,19 @@ dependencies = [ "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.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.5 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.2 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1191,7 +1156,7 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1215,21 +1180,21 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (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.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1244,14 +1209,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.54 (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.42 (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)", ] [[package]] name = "rocket" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1263,10 +1228,10 @@ dependencies = [ "memchr 2.0.1 (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.18 (registry+https://github.com/rust-lang/crates.io-index)", - "pear_codegen 0.0.18 (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.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (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.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1277,24 +1242,24 @@ dependencies = [ [[package]] name = "rocket_codegen" -version = "0.3.14" +version = "0.3.16" 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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rocket_contrib" -version = "0.3.14" +version = "0.3.16" 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.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1321,16 +1286,26 @@ dependencies = [ ] [[package]] +name = "ryu" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "safemem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "schannel" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1359,7 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1369,42 +1344,42 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.22" +version = "1.0.26" 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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_urlencoded" -version = "0.5.2" +version = "0.5.3" 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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1434,28 +1409,31 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slab" -version = "0.3.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "slab" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallvec" -version = "0.2.1" +name = "slice-deque" +version = "0.1.11" 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.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "smallvec" -version = "0.6.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "state" @@ -1484,11 +1462,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.14.4" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1502,34 +1480,30 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.6.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (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 = "take" -version = "0.1.0" -source = "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" dependencies = [ - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1537,22 +1511,22 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.42 (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.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny_http" -version = "0.5.9" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", + "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1562,13 +1536,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1577,7 +1551,7 @@ name = "tokio-codec" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1587,22 +1561,22 @@ name = "tokio-core" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1610,7 +1584,7 @@ dependencies = [ [[package]] name = "tokio-fs" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1623,38 +1597,21 @@ name = "tokio-io" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-proto" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (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.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1668,15 +1625,15 @@ dependencies = [ [[package]] name = "tokio-tcp" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1686,19 +1643,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (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.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1717,13 +1674,13 @@ name = "tokio-udp" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1731,7 +1688,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1776,13 +1733,13 @@ version = "0.1.2" source = "git+https://github.com/wisespace-io/u2f-rs?rev=193de35093a44#193de35093a44576edba6cc94d9b54f2a1cbdcd1" dependencies = [ "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.5 (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.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (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)", @@ -1814,7 +1771,7 @@ name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1855,21 +1812,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "url" -version = "0.2.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1880,25 +1827,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uuid" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "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)", -] - -[[package]] -name = "uuid" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "vcpkg" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1917,7 +1855,7 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1997,21 +1935,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" "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 ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" +"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" +"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 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.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" -"checksum bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd32989a66957d3f0cba6588f15d4281a733f4e9ffc43fcd2385f57d3bf99ff" -"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" -"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" -"checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" -"checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37" +"checksum byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8389c509ec62b9fe8eca58c502a0acaf017737355615243496cde4994f8fa4f9" +"checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8" +"checksum cc 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc738b39aea615873af94099619ed6915a82575880ed5cdfbf17b63307f1b14" +"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" +"checksum chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e48d85528df61dc964aa43c5f6ca681a19cfa74939b2348d204bd08a981f2fb0" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "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" @@ -2040,10 +1977,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d" +"checksum encoding_rs 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2a91912d6f37c6a8fef8a2316a862542d036f13c923ad518b5aca7bcaac7544c" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" -"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" +"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" +"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "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" @@ -2059,7 +1996,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" "checksum hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)" = "34a590ca09d341e94cddf8e5af0bbccde205d5fbc2fa3c09dd67c7f85cea59d7" "checksum hyper-sync-rustls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6df6f419a9f116cc93b5f39a5ded1161e088a2c8424c8fcd1d4049193424a4" -"checksum hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a5aa51f6ae9842239b0fac14af5f22123b8432b4cc774a44ff059fcba0f675ca" +"checksum hyper-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb1bd5e518d3065840ab315dbbf44e4420e5f7d80e2cb93fa6ffffc50522378" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "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" @@ -2068,118 +2005,114 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" +"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" -"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum libflate 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "7d4b4c7aff5bac19b956f693d0ea0eade8066deb092186ae954fa6ba14daab98" -"checksum libsqlite3-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9eb7b8e152b6a01be6a4a2917248381875758250dc3df5d46caf9250341dda" +"checksum libsqlite3-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d3711dfd91a1081d2458ad2d06ea30a8755256e74038be2ad927d94e1c955ca8" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" -"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" +"checksum mach 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "977262a11cfd76b94da10b8898cea6e9ac391301ab74741e6da6bee13d7df46d" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "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" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mime 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fe51c8699d2dc522bf8c1ebe26ea2193d151fb54bcdfd7d0318750c189994cd9" -"checksum mime_guess 1.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7287ba93031813826d8974566e54eb5e49d4473752f7df21c610dab289aee8cb" -"checksum mime_guess 2.0.0-alpha.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a78b5e2283080d5a8ba68216171b4fe34f6ccdd909bb29be16ce8a9a831341" +"checksum mime 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4b082692d3f6cf41b453af73839ce3dfc212c4411cbb2441dff80a716e38bd79" +"checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" +"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum mio 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4fcfcb32d63961fb6f367bfd5d21e4600b92cd310f71f9dca25acae196eb1560" "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.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1720cbd59d1cbcc184b66f2f74a3287caf524764eee5a8fbb3f5f0e469cd5c00" +"checksum multipart 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2745c8c82bc18e8847772ea04bb20d18464e120445a4e3f04771c5cfa24a3e" "checksum mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb004e419334fc9172d0a5ff91c0770bdd6239091b0b343eb5926101f0a7d13" "checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" "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 nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum oath 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6405dc6afe8219020d535f9ad888a12b191bbc8ce1c55f7ee663bde5be80ca" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" -"checksum openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)" = "d8abc04833dcedef24221a91852931df2f63e3369ae003134e70aff3645775cc" +"checksum openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)" = "912f301a749394e1025d9dcddef6106ddee9252620e6d0a0e5f8d0681de9b129" "checksum ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b81cf3b8cb96aa0e73bbedfcdc9708d09fec2854ba8d474be4e6f666d7379e8b" -"checksum pear 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "e868f6a0ac6ea21cbc8bcead234c875209523cc50dddc12b082c09c06a84f85a" -"checksum pear_codegen 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "758ab26a919053f465d887a454f93c39735c615bc36b5598405f557cc033ae88" +"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 percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" "checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" -"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" +"checksum pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "104630aa1c83213cbc76db0703630fcb0421dac3585063be4ce9a8a2feeaa745" "checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" +"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" +"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9078ca6a8a5568ed142083bb2f7dc9295b69d16f867ddcc9849e51b17d8db46" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a" -"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" +"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c93d55961981ba9226a213b385216f83ab43bd6ac53ab16b2eeb47e337cf4e" +"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05b06a75f5217880fc5e905952a42750bf44787e56a6c6d6852ed0992f5e1d54" +"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2abe46f8e00792693a2488e296c593d1f4ea39bb1178cfce081d6793657575e4" +"checksum reqwest 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "738769ec83daf6c1929dc9dae7d69ed3779b55ae5c356e989dcd3aa677d8486e" "checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724" -"checksum rocket 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "798935129effaaf50a4647dbd96bf48cedb3d06c16ab645405d9f02fb90a29d0" -"checksum rocket_codegen 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dca5401b057885267f9b0d81138b7f0b926549261b5cc429ee5535166c47b8e8" -"checksum rocket_contrib 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f04b11a285fb5b0ce426241468aa0494f0b5ca981bda5198facd0106d8edd731" +"checksum rocket 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc32be1d093e7b2f9718983318c6bf5a14f43d7ea01a0b5143c3450c90725b9" +"checksum rocket_codegen 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc94e7781a8bc502f3614521ae94b562f209c7537671cb6169cbbe9dbcc6c5e" +"checksum rocket_contrib 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "c1bae00c367de4599157febc585431c7c647c5f0ffa8fa0e9e875edbbb0bd929" "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 rustls 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17727f4b991294da2c84d75a43c003151ff58072212768800f66c56ee46dca43" +"checksum ryu 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c066b8e2923f05d4718a06d2622f189ff362bc642bfade6c6629f0440f3827" "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 schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1fabf2a7b6483a141426e1afd09ad543520a77ac49bd03c286e7696ccfd77f" "checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" "checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" -"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" -"checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" -"checksum serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "84b8035cabe9b35878adec8ac5fe03d5f6bc97ff6edd7ccb96b44c1276ba390e" -"checksum serde_urlencoded 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e703cef904312097cfceab9ce131ff6bbe09e8c964a0703345a5f49238757bc1" +"checksum serde 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)" = "f218becd0d51dd24297ef804cb9b2de179dcdc2a3ddf8a73b04b4d595d9e6338" +"checksum serde_derive 1.0.74 (registry+https://github.com/rust-lang/crates.io-index)" = "47e3375b02728fa6f8c53cb8c1ad3dea7689e12793b6af399ad1e0e202f91c18" +"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" +"checksum serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aaed41d9fb1e2f587201b863356590c90c1157495d811430a0c0325fe8169650" "checksum sha-1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8347606816471548cd60f0abd5ef0d513a81f5202dbdab9c09f17a15b5248484" "checksum sha2 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "84920f9ac881e94e33ec89e1b3dcd36040523a308a92548e01217ce35d8cf6a8" -"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" -"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "312a7df010092e73d6bbaf141957e868d4f30efd2bfd9bb1028ad91abec58514" +"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.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d9a5f495de574fc059720e2d7b865676d3812aac26d51f0542a0ef8580a1f2ca" +"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" "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.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" -"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" +"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f4d55c9a213880d1f0c89ded183f209c6e45b912ca6c7df6f93c163773572e1" +"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63" "checksum tokio 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee337e5f4e501fc32966fec6fe0ca0cc1c237b0b1b14a335f8bfe3c5f06e286" "checksum tokio-codec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "881e9645b81c2ce95fcb799ded2c29ffb9f25ef5bef909089a420e5961dd8ccb" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" -"checksum tokio-fs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40697ecbea5660df15b15d50a077386477d2f6a35002adf01ce76ff9dd9dce48" +"checksum tokio-executor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "424f0c87ecd66b863045d84e384cb7ce0ae384d8b065b9f0363d29c0d1b30b2f" +"checksum tokio-fs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5cbe4ca6e71cb0b62a66e4e6f53a8c06a6eefe46cc5f665ad6f274c9906f135" "checksum tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a5c9635ee806f26d302b8baa1e145689a280d8f5aa8d0552e7344808da54cc21" -"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" -"checksum tokio-reactor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e00ec63bbec2c97ce1178cb0587b2c438b2f6b09d3ee54a33c45a9cf0d530810" +"checksum tokio-reactor 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8703a5762ff6913510dc64272c714c4389ffd8c4b3cf602879b8bd14ff06b604" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" +"checksum tokio-tcp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4c329b47f071eb8a746040465fa751bd95e4716e98daef6a9b4e434c17d565" "checksum tokio-threadpool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "24ab84f574027b0e875378f31575cf175360891919e93a3490f07e76e00e4efb" -"checksum tokio-timer 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "028b94314065b90f026a21826cffd62a4e40a92cda3e5c069cc7b02e5945f5e9" +"checksum tokio-timer 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1c76b4e97a4f61030edff8bd272364e4f731b9f54c7307eb4eb733c3926eb96a" "checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913" "checksum tokio-udp 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43eb534af6e8f37d43ab1b612660df14755c42bd003c5f8d2475ee78cc4600c0" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" @@ -2200,12 +2133,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "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 url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" -"checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" -"checksum vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cbe533e138811704c0e3cbde65a818b35d3240409b4346256c5ede403e082474" +"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum want 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a05d9d966753fa4b5c8db73fcab5eed4549cfe0e1e4e66911e5564a0085c35d1" @@ -1,31 +1,31 @@ [package] name = "bitwarden_rs" -version = "0.12.0" +version = "1.0.0" authors = ["Daniel GarcĂa <[email protected]>"] [dependencies] # Web framework for nightly with a focus on ease-of-use, expressibility, and speed. -rocket = { version = "0.3.14", features = ["tls"] } -rocket_codegen = "0.3.14" -rocket_contrib = "0.3.14" +rocket = { version = "0.3.16", features = ["tls"] } +rocket_codegen = "0.3.16" +rocket_contrib = "0.3.16" # HTTP client -reqwest = "0.8.6" +reqwest = "0.8.8" # multipart/form-data support -multipart = "0.14.2" +multipart = "0.15.2" # A generic serialization/deserialization framework -serde = "1.0.70" -serde_derive = "1.0.70" -serde_json = "1.0.22" +serde = "1.0.74" +serde_derive = "1.0.74" +serde_json = "1.0.26" # A safe, extensible ORM and Query builder diesel = { version = "1.3.2", features = ["sqlite", "chrono", "r2d2"] } diesel_migrations = { version = "1.3.0", features = ["sqlite"] } # Bundled SQLite -libsqlite3-sys = { version = "0.9.1", features = ["bundled"] } +libsqlite3-sys = { version = "0.9.3", features = ["bundled"] } # Crypto library ring = { version = "= 0.11.0", features = ["rsa_signing"] } @@ -34,7 +34,7 @@ ring = { version = "= 0.11.0", features = ["rsa_signing"] } uuid = { version = "0.6.5", features = ["v4"] } # Date and time library for Rust -chrono = "0.4.4" +chrono = "0.4.5" # TOTP library oath = "0.10.2" @@ -52,7 +52,7 @@ u2f = "0.1.2" dotenv = { version = "0.13.0", default-features = false } # Lazy static macro -lazy_static = "1.0.1" +lazy_static = "1.1.0" # Numerical libraries num-traits = "0.2.5" @@ -68,4 +68,4 @@ fast_chemail = "0.9.5" jsonwebtoken = { path = "libs/jsonwebtoken" } # 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' }
\ No newline at end of file +u2f = { git = 'https://github.com/wisespace-io/u2f-rs', rev = '193de35093a44' } @@ -2,31 +2,27 @@ # https://docs.docker.com/develop/develop-images/multistage-build/ # https://whitfin.io/speeding-up-rust-docker-builds/ ####################### VAULT BUILD IMAGE ####################### -FROM node:9-alpine as vault +FROM node:8-alpine as vault -ENV VAULT_VERSION "1.27.0" -ENV URL "https://github.com/bitwarden/web/archive/v${VAULT_VERSION}.tar.gz" +ENV VAULT_VERSION "v2.2.0" + +ENV URL "https://github.com/bitwarden/web.git" RUN apk add --update-cache --upgrade \ curl \ git \ - tar \ - && npm install -g \ - gulp-cli \ - gulp - -RUN mkdir /web-build \ - && cd /web-build \ - && curl -L "${URL}" | tar -xvz --strip-components=1 + tar +RUN git clone -b $VAULT_VERSION --depth 1 $URL web-build WORKDIR /web-build -COPY /docker/settings.Production.json /web-build/ +COPY /docker/set-vault-baseurl.patch /web-build/ +RUN git apply set-vault-baseurl.patch + +RUN npm run sub:init && npm install -RUN git config --global url."https://github.com/".insteadOf ssh://[email protected]/ \ - && npm install \ - && gulp dist:selfHosted \ - && mv dist /web-vault +RUN npm run dist \ + && mv build /web-vault ########################## BUILD IMAGE ########################## # We need to use the Rust build image, because diff --git a/Dockerfile.alpine b/Dockerfile.alpine new file mode 100644 index 00000000..3a8b4b1d --- /dev/null +++ b/Dockerfile.alpine @@ -0,0 +1,80 @@ +# Using multistage build: +# 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 + +ENV VAULT_VERSION "v2.2.0" + +ENV URL "https://github.com/bitwarden/web.git" + +RUN apk add --update-cache --upgrade \ + curl \ + git \ + tar + +RUN git clone -b $VAULT_VERSION --depth 1 $URL web-build +WORKDIR /web-build + +COPY /docker/set-vault-baseurl.patch /web-build/ +RUN git apply set-vault-baseurl.patch + +RUN npm run sub:init && npm install + +RUN npm run dist \ + && mv build /web-vault + +########################## BUILD IMAGE ########################## +# Musl build image for statically compiled binary +FROM clux/muslrust:nightly-2018-08-24 as build + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo init --bin + +# Copies over *only* your manifests and vendored dependencies +COPY ./Cargo.* ./ +COPY ./libs ./libs +COPY ./rust-toolchain ./rust-toolchain + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN cargo build --release +RUN find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Builds again, this time it'll just be +# your actual source files being built +RUN cargo build --release + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM alpine:3.8 + +ENV ROCKET_ENV "staging" +ENV ROCKET_WORKERS=10 +ENV SSL_CERT_DIR=/etc/ssl/certs + +# Install needed libraries +RUN apk add \ + openssl\ + ca-certificates \ + && rm /var/cache/apk/* + +RUN mkdir /data +VOLUME /data +EXPOSE 80 + +# Copies the files from the context (env file and web-vault) +# and the binary from the "build" stage to the current stage +COPY .env . +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /volume/target/x86_64-unknown-linux-musl/release/bitwarden_rs . + +# Configures the startup! +CMD ./bitwarden_rs diff --git a/Dockerfile.armv7 b/Dockerfile.armv7 new file mode 100644 index 00000000..7cf6508d --- /dev/null +++ b/Dockerfile.armv7 @@ -0,0 +1,113 @@ +# Using multistage build: +# 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 + +ENV VAULT_VERSION "v2.2.0" + +ENV URL "https://github.com/bitwarden/web.git" + +RUN apk add --update-cache --upgrade \ + curl \ + git \ + tar + +RUN git clone -b $VAULT_VERSION --depth 1 $URL web-build +WORKDIR /web-build + +COPY /docker/set-vault-baseurl.patch /web-build/ +RUN git apply set-vault-baseurl.patch + +RUN npm run sub:init && npm install + +RUN npm run dist \ + && mv build /web-vault + +########################## BUILD IMAGE ########################## +# We need to use the Rust build image, because +# we need the Rust compiler and Cargo tooling +FROM rust as build + +RUN apt-get update \ + && apt-get install -y \ + gcc-arm-linux-gnueabihf \ + && mkdir -p ~/.cargo \ + && echo '[target.armv7-unknown-linux-gnueabihf]' >> ~/.cargo/config \ + && echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config + +ENV CARGO_HOME "/root/.cargo" +ENV USER "root" + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin app +WORKDIR /app + +# Copies over *only* your manifests and vendored dependencies +COPY ./Cargo.* ./ +COPY ./libs ./libs +COPY ./rust-toolchain ./rust-toolchain + +# Prepare openssl armhf libs +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ + /etc/apt/sources.list.d/deb-src.list \ + && dpkg --add-architecture armhf \ + && apt-get update \ + && apt-get install -y \ + libssl-dev:armhf \ + libc6-dev:armhf + +ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf" +ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabihf" + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +COPY . . +RUN rustup target add armv7-unknown-linux-gnueabihf +RUN cargo build --release --target=armv7-unknown-linux-gnueabihf -v +RUN find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Builds again, this time it'll just be +# your actual source files being built +RUN cargo build --release --target=armv7-unknown-linux-gnueabihf -v + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM resin/armv7hf-debian:stretch + +ENV ROCKET_ENV "staging" +ENV ROCKET_WORKERS=10 + +RUN [ "cross-build-start" ] + +# Install needed libraries +RUN apt-get update && apt-get install -y\ + openssl\ + ca-certificates\ + --no-install-recommends\ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir /data + +RUN [ "cross-build-end" ] + +VOLUME /data +EXPOSE 80 + +# Copies the files from the context (env file and web-vault) +# and the binary from the "build" stage to the current stage +COPY .env . +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/armv7-unknown-linux-gnueabihf/release/bitwarden_rs . + +# Configures the startup! +CMD ./bitwarden_rs
\ No newline at end of file @@ -1,9 +1,19 @@ -This is Bitwarden server API implementation written in rust compatible with [upstream Bitwarden clients](https://bitwarden.com/#download)*, ideal for self-hosted deployment where running official resource-heavy service might not be ideal. +### This is a Bitwarden server API implementation written in Rust compatible with [upstream Bitwarden clients](https://bitwarden.com/#download)*, perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. + +--- + +[![Travis Build Status](https://travis-ci.org/dani-garcia/bitwarden_rs.svg?branch=master)](https://travis-ci.org/dani-garcia/bitwarden_rs) +[![Dependency Status](https://deps.rs/repo/github/dani-garcia/bitwarden_rs/status.svg)](https://deps.rs/repo/github/dani-garcia/bitwarden_rs) +[![GitHub Release](https://img.shields.io/github/release/dani-garcia/bitwarden_rs.svg)](https://github.com/dani-garcia/bitwarden_rs/releases/latest) +[![GPL-3.0 Licensed](https://img.shields.io/github/license/dani-garcia/bitwarden_rs.svg)](https://github.com/dani-garcia/bitwarden_rs/blob/master/LICENSE.txt) +[![Matrix Chat](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#bitwarden_rs:matrix.org) Image is based on [Rust implementation of Bitwarden API](https://github.com/dani-garcia/bitwarden_rs). _*Note, that this project is not associated with the [Bitwarden](https://bitwarden.com/) project nor 8bit Solutions LLC._ +--- + **Table of contents** - [Features](#features) @@ -13,6 +23,7 @@ _*Note, that this project is not associated with the [Bitwarden](https://bitward - [Updating the bitwarden image](#updating-the-bitwarden-image) - [Configuring bitwarden service](#configuring-bitwarden-service) - [Disable registration of new users](#disable-registration-of-new-users) + - [Disable invitations](#disable-invitations) - [Enabling HTTPS](#enabling-https) - [Enabling U2F authentication](#enabling-u2f-authentication) - [Changing persistent data location](#changing-persistent-data-location) @@ -24,6 +35,7 @@ _*Note, that this project is not associated with the [Bitwarden](https://bitward - [Changing the number of workers](#changing-the-number-of-workers) - [SMTP configuration](#smtp-configuration) - [Password hint display](#password-hint-display) + - [Disabling or overriding the Vault interface hosting](#disabling-or-overriding-the-vault-interface-hosting) - [Other configuration](#other-configuration) - [Building your own image](#building-your-own-image) - [Building binary](#building-binary) @@ -35,6 +47,11 @@ _*Note, that this project is not associated with the [Bitwarden](https://bitward - [3. the key files](#3-the-key-files) - [4. Icon Cache](#4-icon-cache) - [Running the server with non-root user](#running-the-server-with-non-root-user) +- [Differences from upstream API implementation](#differences-from-upstream-api-implementation) + - [Changing user email](#changing-user-email) + - [Creating organization](#creating-organization) + - [Inviting users into organization](#inviting-users-into-organization) + - [Running on unencrypted connection](#running-on-unencrypted-connection) - [Get in touch](#get-in-touch) ## Features @@ -122,6 +139,20 @@ docker run -d --name bitwarden \ -p 80:80 \ mprasil/bitwarden:latest ``` +Note: While users can't register on their own, they can still be invited by already registered users. Read bellow if you also want to disable that. + +### Disable invitations + +Even when registration is disabled, organization administrators or owners can invite users to join organization. This won't send email invitation to the users, but after they are invited, they can register with the invited email even if `SIGNUPS_ALLOWED` is actually set to `false`. You can disable this functionality completely by setting `INVITATIONS_ALLOWED` env variable to `false`: + +```sh +docker run -d --name bitwarden \ + -e SIGNUPS_ALLOWED=false \ + -e INVITATIONS_ALLOWED=false \ + -v /bw-data/:/data/ \ + -p 80:80 \ + mprasil/bitwarden:latest +``` ### Enabling HTTPS To enable HTTPS, you need to configure the `ROCKET_TLS`. @@ -136,10 +167,9 @@ Where: ```sh docker run -d --name bitwarden \ - -e ROCKET_TLS={certs='"/ssl/certs.pem",key="/ssl/key.pem"}' \ + -e ROCKET_TLS='{certs="/ssl/certs.pem",key="/ssl/key.pem"}' \ -v /ssl/keys/:/ssl/ \ -v /bw-data/:/data/ \ - -v /icon_cache/ \ -p 443:80 \ mprasil/bitwarden:latest ``` @@ -265,7 +295,7 @@ docker run -d --name bitwarden \ -p 80:80 \ mprasil/bitwarden:latest ``` - + When `SMTP_SSL` is set to `true`(this is the default), only TLSv1.1 and TLSv1.2 protocols will be accepted and `SMTP_PORT` will default to `587`. If set to `false`, `SMTP_PORT` will default to `25` and the connection won't be encrypted. This can be very insecure, use this setting only if you know what you're doing. ### Password hint display @@ -280,6 +310,29 @@ docker run -d --name bitwarden \ mprasil/bitwarden:latest ``` +### Disabling or overriding the Vault interface hosting + +As a convenience bitwarden_rs image will also host static files for Vault web interface. You can disable this static file hosting completely by setting the WEB_VAULT_ENABLED variable. + +```sh +docker run -d --name bitwarden \ + -e WEB_VAULT_ENABLED=false \ + -v /bw-data/:/data/ \ + -p 80:80 \ + mprasil/bitwarden:latest +``` +Alternatively you can override the Vault files and provide your own static files to host. You can do that by mounting a path with your files over the `/web-vault` directory in the container. Just make sure the directory contains at least `index.html` file. + +```sh +docker run -d --name bitwarden \ + -v /path/to/static/files_directory:/web-vault \ + -v /bw-data/:/data/ \ + -p 80:80 \ + mprasil/bitwarden:latest +``` + +Note that you can also change the path where bitwarden_rs looks for static files by providing the `WEB_VAULT_FOLDER` environment variable with the path. + ### Other configuration Though this is unlikely to be required in small deployment, you can fine-tune some other settings like number of workers using environment variables that are processed by [Rocket](https://rocket.rs), please see details in [documentation](https://rocket.rs/guide/configuration/#environment-variables). @@ -345,6 +398,27 @@ docker run -d --name bitwarden \ -p 80:8080 \ mprasil/bitwarden:latest ``` + +## Differences from upstream API implementation + +### Changing user email + +Because we don't have any SMTP functionality at the moment, there's no way to deliver the verification token when you try to change the email. User just needs to enter any random token to continue and the change will be applied. + +### Creating organization + +We use upstream Vault interface directly without any (significant) changes, this is why user is presented with paid options when creating organization. To create an organization, just use the free option, none of the limits apply when using bitwarden_rs as back-end API and after the organization is created it should behave like Enterprise organization. + +### Inviting users into organization + +If you have [invitations disabled](#disable-invitations), the users must already be registered on your server to invite them. The invited users won't get the invitation email, instead they will appear in the interface as if they already accepted the invitation. (if the user has already registered) Organization admin then just needs to confirm them to be proper Organization members and to give them access to the shared secrets. + +### Running on unencrypted connection + +It is strongly recommended to run bitwarden_rs service over HTTPS. However the server itself while [supporting it](#enabling-https) does not strictly require such setup. This makes it a bit easier to spin up the service in cases where you can generally trust the connection (internal and secure network, access over VPN,..) or when you want to put the service behind HTTP proxy, that will do the encryption on the proxy end. + +Running over HTTP is still reasonably secure provided you use really strong master password and that you avoid using web Vault over connection that is vulnerable to MITM attacks where attacker could inject javascript into your interface. However some forms of 2FA might not work in this setup and [Vault doesn't work in this configuration in Chrome](https://github.com/bitwarden/web/issues/254). + ## Get in touch To ask an question, [raising an issue](https://github.com/dani-garcia/bitwarden_rs/issues/new) is fine, also please report any bugs spotted here. diff --git a/docker/set-vault-baseurl.patch b/docker/set-vault-baseurl.patch new file mode 100644 index 00000000..5e872023 --- /dev/null +++ b/docker/set-vault-baseurl.patch @@ -0,0 +1,28 @@ +--- a/src/app/services/services.module.ts ++++ b/src/app/services/services.module.ts +@@ -120,20 +120,17 @@ const notificationsService = new NotificationsService(userService, syncService, + const environmentService = new EnvironmentService(apiService, storageService, notificationsService); + const auditService = new AuditService(cryptoFunctionService, apiService); + +-const analytics = new Analytics(window, () => platformUtilsService.isDev() || platformUtilsService.isSelfHost(), ++const analytics = new Analytics(window, () => platformUtilsService.isDev() || platformUtilsService.isSelfHost() || true, + platformUtilsService, storageService, appIdService); + containerService.attachToWindow(window); + + export function initFactory(): Function { + return async () => { + await (storageService as HtmlStorageService).init(); +- const isDev = platformUtilsService.isDev(); +- if (!isDev && platformUtilsService.isSelfHost()) { +- environmentService.baseUrl = window.location.origin; +- } else { +- environmentService.notificationsUrl = isDev ? 'http://localhost:61840' : +- 'https://notifications.bitwarden.com'; // window.location.origin + '/notifications'; +- } ++ const isDev = false; ++ environmentService.baseUrl = window.location.origin; ++ environmentService.notificationsUrl = window.location.origin + '/notifications'; ++ + await apiService.setUrls({ + base: isDev ? null : window.location.origin, + api: isDev ? 'http://localhost:4000' : null, diff --git a/docker/settings.Production.json b/docker/settings.Production.json deleted file mode 100644 index a3e5e911..00000000 --- a/docker/settings.Production.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "appSettings": { - "apiUri": "/api", - "identityUri": "/identity", - "iconsUri": "/icons", - "stripeKey": "", - "braintreeKey": "" - } -} diff --git a/migrations/2018-08-27-172114_update_ciphers/down.sql b/migrations/2018-08-27-172114_update_ciphers/down.sql new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/migrations/2018-08-27-172114_update_ciphers/down.sql diff --git a/migrations/2018-08-27-172114_update_ciphers/up.sql b/migrations/2018-08-27-172114_update_ciphers/up.sql new file mode 100644 index 00000000..624efd66 --- /dev/null +++ b/migrations/2018-08-27-172114_update_ciphers/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE ciphers + ADD COLUMN + password_history TEXT;
\ No newline at end of file diff --git a/migrations/2018-09-10-111213_add_invites/down.sql b/migrations/2018-09-10-111213_add_invites/down.sql new file mode 100644 index 00000000..af3776cf --- /dev/null +++ b/migrations/2018-09-10-111213_add_invites/down.sql @@ -0,0 +1 @@ +DROP TABLE invitations;
\ No newline at end of file diff --git a/migrations/2018-09-10-111213_add_invites/up.sql b/migrations/2018-09-10-111213_add_invites/up.sql new file mode 100644 index 00000000..b42e9a2a --- /dev/null +++ b/migrations/2018-09-10-111213_add_invites/up.sql @@ -0,0 +1,3 @@ +CREATE TABLE invitations ( + email TEXT NOT NULL PRIMARY KEY +);
\ No newline at end of file diff --git a/rust-toolchain b/rust-toolchain index 1f5db4bc..87a70769 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2018-06-26 +nightly-2018-08-24 diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index 2f66b200..3e545773 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -32,15 +32,34 @@ struct KeysData { fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult { let data: RegisterData = data.into_inner().data; - if !CONFIG.signups_allowed { - err!("Signups not allowed") - } - if User::find_by_mail(&data.Email, &conn).is_some() { - err!("Email already exists") - } + let mut user = match User::find_by_mail(&data.Email, &conn) { + Some(mut 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; + user_org.save(&conn); + }; + user + } else { + if CONFIG.signups_allowed { + err!("Account with this email already exists") + } else { + err!("Registration not allowed") + } + } + }, + None => { + if CONFIG.signups_allowed || Invitation::take(&data.Email, &conn) { + User::new(data.Email) + } else { + err!("Registration not allowed") + } + } + }; - let mut user = User::new(data.Email, data.Key, data.MasterPasswordHash); + user.set_password(&data.MasterPasswordHash); + user.key = data.Key; // Add extra fields if present if let Some(name) = data.Name { @@ -75,6 +94,11 @@ struct ProfileData { Name: String, } +#[put("/accounts/profile", data = "<data>")] +fn put_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult { + post_profile(data, headers, conn) +} + #[post("/accounts/profile", data = "<data>")] fn post_profile(data: JsonUpcase<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult { let data: ProfileData = data.into_inner().data; @@ -249,7 +273,7 @@ fn delete_account(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn #[get("/accounts/revision-date")] fn revision_date(headers: Headers) -> String { - let revision_date = headers.user.updated_at.timestamp(); + let revision_date = headers.user.updated_at.timestamp_millis(); revision_date.to_string() } @@ -264,7 +288,7 @@ fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResul let data: PasswordHintData = data.into_inner().data; if !is_valid_email(&data.Email) { - return err!("This email address is not valid..."); + err!("This email address is not valid..."); } let user = User::find_by_mail(&data.Email, &conn); @@ -287,3 +311,31 @@ fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResul Ok(()) } + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct PreloginData { + Email: String, +} + +#[post("/accounts/prelogin", data = "<data>")] +fn prelogin(data: JsonUpcase<PreloginData>, conn: DbConn) -> JsonResult { + let data: PreloginData = data.into_inner().data; + + match User::find_by_mail(&data.Email, &conn) { + Some(user) => { + let kdf_type = 0; // PBKDF2: 0 + + let _server_iter = user.password_iterations; + let client_iter = 5000; // TODO: Make iterations user configurable + + + Ok(Json(json!({ + "Kdf": kdf_type, + "KdfIterations": client_iter + }))) + }, + None => err!("Invalid user"), + } +} + diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index ec1227bf..b0bf574a 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -86,7 +86,9 @@ fn get_cipher_details(uuid: String, headers: Headers, conn: DbConn) -> JsonResul #[derive(Deserialize, Debug)] #[allow(non_snake_case)] -struct CipherData { +pub struct CipherData { + // Id is optional as it is included only in bulk share + 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 @@ -98,8 +100,8 @@ struct CipherData { Card = 3, Identity = 4 */ - Type: i32, // TODO: Change this to NumberOrString - Name: String, + pub Type: i32, // TODO: Change this to NumberOrString + pub Name: String, Notes: Option<String>, Fields: Option<Value>, @@ -110,6 +112,8 @@ struct CipherData { Identity: Option<Value>, Favorite: Option<bool>, + + PasswordHistory: Option<Value>, } #[post("/ciphers/admin", data = "<data>")] @@ -123,26 +127,26 @@ fn post_ciphers(data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn) -> let data: CipherData = data.into_inner().data; let mut cipher = Cipher::new(data.Type, data.Name.clone()); - update_cipher_from_data(&mut cipher, data, &headers, true, &conn)?; + update_cipher_from_data(&mut cipher, data, &headers, false, &conn)?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn))) } -fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Headers, is_new_or_shared: bool, conn: &DbConn) -> EmptyResult { - if is_new_or_shared { - if let Some(org_id) = data.OrganizationId { - match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { - None => err!("You don't have permission to add item to organization"), - Some(org_user) => if org_user.has_full_access() { - cipher.organization_uuid = Some(org_id); - cipher.user_uuid = None; - } else { - err!("You don't have permission to add cipher directly to organization") - } +pub fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Headers, shared_to_collection: bool, conn: &DbConn) -> EmptyResult { + if let Some(org_id) = data.OrganizationId { + match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { + None => err!("You don't have permission to add item to organization"), + Some(org_user) => if shared_to_collection + || org_user.has_full_access() + || cipher.is_write_accessible_to_user(&headers.user.uuid, &conn) { + cipher.organization_uuid = Some(org_id); + cipher.user_uuid = None; + } else { + err!("You don't have permission to add cipher directly to organization") } - } else { - cipher.user_uuid = Some(headers.user.uuid.clone()); } + } else { + cipher.user_uuid = Some(headers.user.uuid.clone()); } if let Some(ref folder_id) = data.FolderId { @@ -175,6 +179,7 @@ fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Head type_data["Name"] = Value::String(data.Name.clone()); type_data["Notes"] = data.Notes.clone().map(Value::String).unwrap_or(Value::Null); type_data["Fields"] = data.Fields.clone().unwrap_or(Value::Null); + type_data["PasswordHistory"] = data.PasswordHistory.clone().unwrap_or(Value::Null); // TODO: ******* Backwards compat end ********** cipher.favorite = data.Favorite.unwrap_or(false); @@ -182,6 +187,7 @@ fn update_cipher_from_data(cipher: &mut Cipher, data: CipherData, headers: &Head cipher.notes = data.Notes; cipher.fields = data.Fields.map(|f| f.to_string()); cipher.data = type_data.to_string(); + cipher.password_history = data.PasswordHistory.map(|f| f.to_string()); cipher.save(&conn); @@ -237,17 +243,26 @@ fn post_ciphers_import(data: JsonUpcase<ImportData>, headers: Headers, conn: DbC .map(|i| folders[*i].uuid.clone()); let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone()); - update_cipher_from_data(&mut cipher, cipher_data, &headers, true, &conn)?; + update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &conn)?; cipher.move_to_folder(folder_uuid, &headers.user.uuid.clone(), &conn).ok(); } - Ok(()) + let mut user = headers.user; + match user.update_revision(&conn) { + Ok(()) => Ok(()), + Err(_) => err!("Failed to update the revision, please log out and log back in to finish import.") + } +} + + +#[put("/ciphers/<uuid>/admin", data = "<data>")] +fn put_cipher_admin(uuid: String, data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn) -> JsonResult { + put_cipher(uuid, data, headers, conn) } #[post("/ciphers/<uuid>/admin", data = "<data>")] fn post_cipher_admin(uuid: String, data: JsonUpcase<CipherData>, headers: Headers, conn: DbConn) -> JsonResult { - // TODO: Implement this correctly post_cipher(uuid, data, headers, conn) } @@ -285,6 +300,11 @@ fn post_collections_update(uuid: String, data: JsonUpcase<CollectionsAdminData>, post_collections_admin(uuid, data, headers, conn) } +#[put("/ciphers/<uuid>/collections-admin", data = "<data>")] +fn put_collections_admin(uuid: String, data: JsonUpcase<CollectionsAdminData>, headers: Headers, conn: DbConn) -> EmptyResult { + post_collections_admin(uuid, data, headers, conn) +} + #[post("/ciphers/<uuid>/collections-admin", data = "<data>")] fn post_collections_admin(uuid: String, data: JsonUpcase<CollectionsAdminData>, headers: Headers, conn: DbConn) -> EmptyResult { let data: CollectionsAdminData = data.into_inner().data; @@ -332,6 +352,65 @@ struct ShareCipherData { fn post_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn) -> JsonResult { let data: ShareCipherData = data.into_inner().data; + share_cipher_by_uuid(&uuid, data, &headers, &conn) +} + +#[put("/ciphers/<uuid>/share", data = "<data>")] +fn put_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: Headers, conn: DbConn) -> JsonResult { + let data: ShareCipherData = data.into_inner().data; + + share_cipher_by_uuid(&uuid, data, &headers, &conn) +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct ShareSelectedCipherData { + Ciphers: Vec<CipherData>, + CollectionIds: Vec<String> +} + +#[put("/ciphers/share", data = "<data>")] +fn put_cipher_share_seleted(data: JsonUpcase<ShareSelectedCipherData>, headers: Headers, conn: DbConn) -> EmptyResult { + let mut data: ShareSelectedCipherData = data.into_inner().data; + let mut cipher_ids: Vec<String> = Vec::new(); + + if data.Ciphers.len() == 0 { + err!("You must select at least one cipher.") + } + + if data.CollectionIds.len() == 0 { + err!("You must select at least one collection.") + } + + for cipher in data.Ciphers.iter() { + match cipher.Id { + Some(ref id) => cipher_ids.push(id.to_string()), + None => err!("Request missing ids field") + }; + } + + let attachments = Attachment::find_by_ciphers(cipher_ids, &conn); + + if attachments.len() > 0 { + err!("Ciphers should not have any attachments.") + } + + while let Some(cipher) = data.Ciphers.pop() { + let mut shared_cipher_data = ShareCipherData { + Cipher: cipher, + CollectionIds: data.CollectionIds.clone() + }; + + match shared_cipher_data.Cipher.Id.take() { + Some(id) => share_cipher_by_uuid(&id, shared_cipher_data , &headers, &conn)?, + None => err!("Request missing ids field") + }; + } + + Ok(()) +} + +fn share_cipher_by_uuid(uuid: &str, data: ShareCipherData, headers: &Headers, conn: &DbConn) -> JsonResult { let mut cipher = match Cipher::find_by_uuid(&uuid, &conn) { Some(cipher) => { if cipher.is_write_accessible_to_user(&headers.user.uuid, &conn) { @@ -343,22 +422,28 @@ fn post_cipher_share(uuid: String, data: JsonUpcase<ShareCipherData>, headers: H None => err!("Cipher doesn't exist") }; - match data.Cipher.OrganizationId { + match data.Cipher.OrganizationId.clone() { None => err!("Organization id not provided"), - Some(_) => { - update_cipher_from_data(&mut cipher, data.Cipher, &headers, true, &conn)?; + Some(organization_uuid) => { + let mut shared_to_collection = false; for uuid in &data.CollectionIds { match Collection::find_by_uuid(uuid, &conn) { None => err!("Invalid collection ID provided"), Some(collection) => { if collection.is_writable_by_user(&headers.user.uuid, &conn) { - CollectionCipher::save(&cipher.uuid.clone(), &collection.uuid, &conn); + if collection.org_uuid == organization_uuid { + CollectionCipher::save(&cipher.uuid.clone(), &collection.uuid, &conn); + shared_to_collection = true; + } else { + err!("Collection does not belong to organization") + } } else { err!("No rights to modify the collection") } } } } + update_cipher_from_data(&mut cipher, data.Cipher, &headers, shared_to_collection, &conn)?; Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn))) } @@ -409,7 +494,10 @@ fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers }; let attachment = Attachment::new(file_name, cipher.uuid.clone(), name, size); - attachment.save(&conn); + match attachment.save(&conn) { + Ok(()) => (), + Err(_) => println!("Error: failed to save attachment") + }; }).expect("Error processing multipart data"); Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn))) @@ -441,6 +529,11 @@ fn delete_attachment(uuid: String, attachment_id: String, headers: Headers, conn _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &conn) } +#[delete("/ciphers/<uuid>/attachment/<attachment_id>/admin")] +fn delete_attachment_admin(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> EmptyResult { + _delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &conn) +} + #[post("/ciphers/<uuid>/delete")] fn delete_cipher_post(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { _delete_cipher_by_uuid(&uuid, &headers, &conn) @@ -456,13 +549,18 @@ fn delete_cipher(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { _delete_cipher_by_uuid(&uuid, &headers, &conn) } -#[post("/ciphers/delete", data = "<data>")] +#[delete("/ciphers/<uuid>/admin")] +fn delete_cipher_admin(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult { + _delete_cipher_by_uuid(&uuid, &headers, &conn) +} + +#[delete("/ciphers", data = "<data>")] fn delete_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) -> EmptyResult { let data: Value = data.into_inner().data; let uuids = match data.get("Ids") { Some(ids) => match ids.as_array() { - Some(ids) => ids.iter().filter_map(|uuid| { uuid.as_str() }), + Some(ids) => ids.iter().filter_map(Value::as_str), None => err!("Posted ids field is not an array") }, None => err!("Request missing ids field") @@ -477,6 +575,11 @@ fn delete_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbCon Ok(()) } +#[post("/ciphers/delete", data = "<data>")] +fn delete_cipher_selected_post(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) -> EmptyResult { + delete_cipher_selected(data, headers, conn) +} + #[post("/ciphers/move", data = "<data>")] fn move_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) -> EmptyResult { let data = data.into_inner().data; @@ -503,7 +606,7 @@ fn move_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) let uuids = match data.get("Ids") { Some(ids) => match ids.as_array() { - Some(ids) => ids.iter().filter_map(|uuid| { uuid.as_str() }), + Some(ids) => ids.iter().filter_map(Value::as_str), None => err!("Posted ids field is not an array") }, None => err!("Request missing ids field") @@ -529,6 +632,11 @@ fn move_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) Ok(()) } +#[put("/ciphers/move", data = "<data>")] +fn move_cipher_selected_put(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) -> EmptyResult { + move_cipher_selected(data, headers, conn) +} + #[post("/ciphers/purge", data = "<data>")] fn delete_all(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> EmptyResult { let data: PasswordData = data.into_inner().data; @@ -551,7 +659,7 @@ fn delete_all(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> for f in Folder::find_by_user(&user.uuid, &conn) { if f.delete(&conn).is_err() { err!("Failed deleting folder") - } + } } Ok(()) diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index 5ce63062..31e4d601 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -14,6 +14,7 @@ pub fn routes() -> Vec<Route> { routes![ register, profile, + put_profile, post_profile, get_public_keys, post_keys, @@ -24,6 +25,7 @@ pub fn routes() -> Vec<Route> { delete_account, revision_date, password_hint, + prelogin, sync, @@ -32,6 +34,7 @@ pub fn routes() -> Vec<Route> { get_cipher_admin, get_cipher_details, post_ciphers, + put_cipher_admin, post_ciphers_admin, post_ciphers_import, post_attachment, @@ -40,16 +43,22 @@ pub fn routes() -> Vec<Route> { 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, @@ -63,33 +72,45 @@ pub fn routes() -> Vec<Route> { get_recover, recover, disable_twofactor, + disable_twofactor_put, generate_authenticator, activate_authenticator, + activate_authenticator_put, generate_u2f, activate_u2f, + activate_u2f_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_org_import, clear_device_token, put_device_token, diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 8c87a1dd..4d47eab7 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -1,13 +1,13 @@ -#![allow(unused_imports)] - use rocket_contrib::{Json, Value}; - +use CONFIG; use db::DbConn; use db::models::*; use api::{PasswordData, JsonResult, EmptyResult, NumberOrString, JsonUpcase}; use auth::{Headers, AdminHeaders, OwnerHeaders}; +use serde::{Deserialize, Deserializer}; + #[derive(Deserialize)] #[allow(non_snake_case)] @@ -17,7 +17,7 @@ struct OrgData { Key: String, Name: String, #[serde(rename = "PlanType")] - _PlanType: String, // Ignored, always use the same plan + _PlanType: NumberOrString, // Ignored, always use the same plan } #[derive(Deserialize, Debug)] @@ -55,7 +55,7 @@ fn create_organization(headers: Headers, data: JsonUpcase<OrgData>, conn: DbConn Ok(Json(org.to_json())) } -#[post("/organizations/<org_id>/delete", data = "<data>")] +#[delete("/organizations/<org_id>", data = "<data>")] fn delete_organization(org_id: String, data: JsonUpcase<PasswordData>, headers: OwnerHeaders, conn: DbConn) -> EmptyResult { let data: PasswordData = data.into_inner().data; let password_hash = data.MasterPasswordHash; @@ -73,6 +73,11 @@ fn delete_organization(org_id: String, data: JsonUpcase<PasswordData>, headers: } } +#[post("/organizations/<org_id>/delete", data = "<data>")] +fn post_delete_organization(org_id: String, data: JsonUpcase<PasswordData>, headers: OwnerHeaders, conn: DbConn) -> EmptyResult { + delete_organization(org_id, data, headers, conn) +} + #[post("/organizations/<org_id>/leave")] fn leave_organization(org_id: String, headers: Headers, conn: DbConn) -> EmptyResult { match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { @@ -104,6 +109,11 @@ fn get_organization(org_id: String, _headers: OwnerHeaders, conn: DbConn) -> Jso } } +#[put("/organizations/<org_id>", data = "<data>")] +fn put_organization(org_id: String, headers: OwnerHeaders, data: JsonUpcase<OrganizationUpdateData>, conn: DbConn) -> JsonResult { + post_organization(org_id, headers, data, conn) +} + #[post("/organizations/<org_id>", data = "<data>")] fn post_organization(org_id: String, _headers: OwnerHeaders, data: JsonUpcase<OrganizationUpdateData>, conn: DbConn) -> JsonResult { let data: OrganizationUpdateData = data.into_inner().data; @@ -128,9 +138,8 @@ fn get_user_collections(headers: Headers, conn: DbConn) -> JsonResult { "Data": Collection::find_by_user_uuid(&headers.user.uuid, &conn) .iter() - .map(|collection| { - collection.to_json() - }).collect::<Value>(), + .map(Collection::to_json) + .collect::<Value>(), "Object": "list" }))) } @@ -141,9 +150,8 @@ fn get_org_collections(org_id: String, _headers: AdminHeaders, conn: DbConn) -> "Data": Collection::find_by_organization(&org_id, &conn) .iter() - .map(|collection| { - collection.to_json() - }).collect::<Value>(), + .map(Collection::to_json) + .collect::<Value>(), "Object": "list" }))) } @@ -164,6 +172,11 @@ fn post_organization_collections(org_id: String, _headers: AdminHeaders, data: J Ok(Json(collection.to_json())) } +#[put("/organizations/<org_id>/collections/<col_id>", data = "<data>")] +fn put_organization_collection_update(org_id: String, col_id: String, headers: AdminHeaders, data: JsonUpcase<NewCollectionData>, conn: DbConn) -> JsonResult { + post_organization_collection_update(org_id, col_id, headers, data, conn) +} + #[post("/organizations/<org_id>/collections/<col_id>", data = "<data>")] fn post_organization_collection_update(org_id: String, col_id: String, _headers: AdminHeaders, data: JsonUpcase<NewCollectionData>, conn: DbConn) -> JsonResult { let data: NewCollectionData = data.into_inner().data; @@ -188,8 +201,9 @@ fn post_organization_collection_update(org_id: String, col_id: String, _headers: Ok(Json(collection.to_json())) } -#[post("/organizations/<org_id>/collections/<col_id>/delete-user/<org_user_id>")] -fn post_organization_collection_delete_user(org_id: String, col_id: String, org_user_id: String, _headers: AdminHeaders, conn: DbConn) -> EmptyResult { + +#[delete("/organizations/<org_id>/collections/<col_id>/user/<org_user_id>")] +fn delete_organization_collection_user(org_id: String, col_id: String, org_user_id: String, _headers: AdminHeaders, conn: DbConn) -> EmptyResult { let collection = match Collection::find_by_uuid(&col_id, &conn) { None => err!("Collection not found"), Some(collection) => if collection.org_uuid == org_id { @@ -199,7 +213,7 @@ fn post_organization_collection_delete_user(org_id: String, col_id: String, org_ } }; - match UserOrganization::find_by_uuid(&org_user_id, &conn) { + match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &conn) { None => err!("User not found in organization"), Some(user_org) => { match CollectionUser::find_by_collection_and_user(&collection.uuid, &user_org.user_uuid, &conn) { @@ -215,17 +229,13 @@ fn post_organization_collection_delete_user(org_id: String, col_id: String, org_ } } -#[derive(Deserialize, Debug)] -#[allow(non_snake_case)] -struct DeleteCollectionData { - Id: String, - OrgId: String, +#[post("/organizations/<org_id>/collections/<col_id>/delete-user/<org_user_id>")] +fn post_organization_collection_delete_user(org_id: String, col_id: String, org_user_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult { + delete_organization_collection_user(org_id, col_id, org_user_id, headers, conn) } -#[post("/organizations/<org_id>/collections/<col_id>/delete", data = "<data>")] -fn post_organization_collection_delete(org_id: String, col_id: String, _headers: AdminHeaders, data: JsonUpcase<DeleteCollectionData>, conn: DbConn) -> EmptyResult { - let _data: DeleteCollectionData = data.into_inner().data; - +#[delete("/organizations/<org_id>/collections/<col_id>")] +fn delete_organization_collection(org_id: String, col_id: String, _headers: AdminHeaders, conn: DbConn) -> EmptyResult { match Collection::find_by_uuid(&col_id, &conn) { None => err!("Collection not found"), Some(collection) => if collection.org_uuid == org_id { @@ -239,6 +249,18 @@ fn post_organization_collection_delete(org_id: String, col_id: String, _headers: } } +#[derive(Deserialize, Debug)] +#[allow(non_snake_case)] +struct DeleteCollectionData { + Id: String, + OrgId: String, +} + +#[post("/organizations/<org_id>/collections/<col_id>/delete", data = "<_data>")] +fn post_organization_collection_delete(org_id: String, col_id: String, headers: AdminHeaders, _data: JsonUpcase<DeleteCollectionData>, conn: DbConn) -> EmptyResult { + delete_organization_collection(org_id, col_id, headers, conn) +} + #[get("/organizations/<org_id>/collections/<coll_id>/details")] fn get_org_collection_detail(org_id: String, coll_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult { match Collection::find_by_uuid_and_user(&coll_id, &headers.user.uuid, &conn) { @@ -308,6 +330,14 @@ fn get_org_users(org_id: String, headers: AdminHeaders, conn: DbConn) -> JsonRes }))) } +fn deserialize_collections<'de, D>(deserializer: D) -> Result<Vec<CollectionData>, D::Error> +where + D: Deserializer<'de>, +{ + // Deserialize null to empty Vec + Deserialize::deserialize(deserializer).or(Ok(vec![])) +} + #[derive(Deserialize)] #[allow(non_snake_case)] struct CollectionData { @@ -320,6 +350,7 @@ struct CollectionData { struct InviteData { Emails: Vec<String>, Type: NumberOrString, + #[serde(deserialize_with = "deserialize_collections")] Collections: Vec<CollectionData>, AccessAll: Option<bool>, } @@ -338,54 +369,70 @@ fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: AdminHeade err!("Only Owners can invite Admins or Owners") } - for user_opt in data.Emails.iter().map(|email| User::find_by_mail(email, &conn)) { - match user_opt { - None => err!("User email does not exist"), - Some(user) => { - if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &conn).is_some() { - err!("User already in organization") + for email in data.Emails.iter() { + let mut user_org_status = UserOrgStatus::Accepted as i32; + let user = match User::find_by_mail(&email, &conn) { + None => if CONFIG.invitations_allowed { // Invite user if that's enabled + let mut invitation = Invitation::new(email.clone()); + match invitation.save(&conn) { + Ok(()) => { + let mut user = User::new(email.clone()); + if user.save(&conn) { + user_org_status = UserOrgStatus::Invited as i32; + user + } else { + err!("Failed to create placeholder for invited user") + } + } + Err(_) => err!(format!("Failed to invite: {}", email)) } + + } else { + err!(format!("User email does not exist: {}", email)) + }, + Some(user) => if UserOrganization::find_by_user_and_org(&user.uuid, &org_id, &conn).is_some() { + err!(format!("User already in organization: {}", email)) + } else { + user + } - let mut new_user = UserOrganization::new(user.uuid.clone(), org_id.clone()); - let access_all = data.AccessAll.unwrap_or(false); - new_user.access_all = access_all; - new_user.type_ = new_type; - - // If no accessAll, add the collections received - if !access_all { - for col in &data.Collections { - match Collection::find_by_uuid_and_org(&col.Id, &org_id, &conn) { - None => err!("Collection not found in Organization"), - Some(collection) => { - if CollectionUser::save(&user.uuid, &collection.uuid, col.ReadOnly, &conn).is_err() { - err!("Failed saving collection access for user") - } - } + }; + + let mut new_user = UserOrganization::new(user.uuid.clone(), org_id.clone()); + let access_all = data.AccessAll.unwrap_or(false); + new_user.access_all = access_all; + new_user.type_ = new_type; + new_user.status = user_org_status; + + // If no accessAll, add the collections received + if !access_all { + for col in &data.Collections { + match Collection::find_by_uuid_and_org(&col.Id, &org_id, &conn) { + None => err!("Collection not found in Organization"), + Some(collection) => { + if CollectionUser::save(&user.uuid, &collection.uuid, col.ReadOnly, &conn).is_err() { + err!("Failed saving collection access for user") } } } - - new_user.save(&conn); } } + + new_user.save(&conn); } Ok(()) } -#[post("/organizations/<org_id>/users/<user_id>/confirm", data = "<data>")] -fn confirm_invite(org_id: String, user_id: String, data: JsonUpcase<Value>, headers: AdminHeaders, conn: DbConn) -> EmptyResult { +#[post("/organizations/<org_id>/users/<org_user_id>/confirm", data = "<data>")] +fn confirm_invite(org_id: String, org_user_id: String, data: JsonUpcase<Value>, headers: AdminHeaders, conn: DbConn) -> EmptyResult { let data = data.into_inner().data; - let mut user_to_confirm = match UserOrganization::find_by_uuid(&user_id, &conn) { + let mut user_to_confirm = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &conn) { Some(user) => user, - None => err!("Failed to find user membership") + None => err!("The specified user isn't a member of the organization") }; - if user_to_confirm.org_uuid != org_id { - err!("The specified user isn't a member of the organization") - } - if user_to_confirm.type_ != UserOrgType::User as i32 && headers.org_user_type != UserOrgType::Owner as i32 { err!("Only Owners can confirm Admins or Owners") @@ -406,17 +453,13 @@ fn confirm_invite(org_id: String, user_id: String, data: JsonUpcase<Value>, head Ok(()) } -#[get("/organizations/<org_id>/users/<user_id>")] -fn get_user(org_id: String, user_id: String, _headers: AdminHeaders, conn: DbConn) -> JsonResult { - let user = match UserOrganization::find_by_uuid(&user_id, &conn) { +#[get("/organizations/<org_id>/users/<org_user_id>")] +fn get_user(org_id: String, org_user_id: String, _headers: AdminHeaders, conn: DbConn) -> JsonResult { + let user = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &conn) { Some(user) => user, - None => err!("Failed to find user membership") + None => err!("The specified user isn't a member of the organization") }; - if user.org_uuid != org_id { - err!("The specified user isn't a member of the organization") - } - Ok(Json(user.to_json_details(&conn))) } @@ -424,12 +467,18 @@ fn get_user(org_id: String, user_id: String, _headers: AdminHeaders, conn: DbCon #[allow(non_snake_case)] struct EditUserData { Type: NumberOrString, + #[serde(deserialize_with = "deserialize_collections")] Collections: Vec<CollectionData>, AccessAll: bool, } -#[post("/organizations/<org_id>/users/<user_id>", data = "<data>", rank = 1)] -fn edit_user(org_id: String, user_id: String, data: JsonUpcase<EditUserData>, headers: AdminHeaders, conn: DbConn) -> EmptyResult { +#[put("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)] +fn put_organization_user(org_id: String, org_user_id: String, data: JsonUpcase<EditUserData>, headers: AdminHeaders, conn: DbConn) -> EmptyResult { + edit_user(org_id, org_user_id, data, headers, conn) +} + +#[post("/organizations/<org_id>/users/<org_user_id>", data = "<data>", rank = 1)] +fn edit_user(org_id: String, org_user_id: String, data: JsonUpcase<EditUserData>, headers: AdminHeaders, conn: DbConn) -> EmptyResult { let data: EditUserData = data.into_inner().data; let new_type = match UserOrgType::from_str(&data.Type.into_string()) { @@ -437,19 +486,22 @@ fn edit_user(org_id: String, user_id: String, data: JsonUpcase<EditUserData>, he None => err!("Invalid type") }; - let mut user_to_edit = match UserOrganization::find_by_uuid(&user_id, &conn) { + let mut user_to_edit = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &conn) { Some(user) => user, None => err!("The specified user isn't member of the organization") }; - if new_type != UserOrgType::User as i32 && + if new_type != user_to_edit.type_ as i32 && ( + user_to_edit.type_ <= UserOrgType::Admin as i32 || + new_type <= UserOrgType::Admin as i32 + ) && headers.org_user_type != UserOrgType::Owner as i32 { - err!("Only Owners can grant Admin or Owner type") + err!("Only Owners can grant and remove Admin or Owner privileges") } - if user_to_edit.type_ != UserOrgType::User as i32 && + if user_to_edit.type_ == UserOrgType::Owner as i32 && headers.org_user_type != UserOrgType::Owner as i32 { - err!("Only Owners can edit Admin or Owner") + err!("Only Owners can edit Owner users") } if user_to_edit.type_ == UserOrgType::Owner as i32 && @@ -494,9 +546,9 @@ fn edit_user(org_id: String, user_id: String, data: JsonUpcase<EditUserData>, he Ok(()) } -#[post("/organizations/<org_id>/users/<user_id>/delete")] -fn delete_user(org_id: String, user_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult { - let user_to_delete = match UserOrganization::find_by_uuid(&user_id, &conn) { +#[delete("/organizations/<org_id>/users/<org_user_id>")] +fn delete_user(org_id: String, org_user_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult { + let user_to_delete = match UserOrganization::find_by_uuid_and_org(&org_user_id, &org_id, &conn) { Some(user) => user, None => err!("User to delete isn't member of the organization") }; @@ -521,4 +573,78 @@ fn delete_user(org_id: String, user_id: String, headers: AdminHeaders, conn: DbC Ok(()) => Ok(()), Err(_) => err!("Failed deleting user from organization") } +} + +#[post("/organizations/<org_id>/users/<org_user_id>/delete")] +fn post_delete_user(org_id: String, org_user_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult { + delete_user(org_id, org_user_id, headers, conn) +} + +use super::ciphers::CipherData; +use super::ciphers::update_cipher_from_data; + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct ImportData { + Ciphers: Vec<CipherData>, + Collections: Vec<NewCollectionData>, + CollectionRelationships: Vec<RelationsData>, +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct RelationsData { + // Cipher index + Key: usize, + // Collection index + Value: usize, +} + +#[post("/ciphers/import-organization?<query>", data = "<data>")] +fn post_org_import(query: OrgIdData, data: JsonUpcase<ImportData>, headers: Headers, conn: DbConn) -> EmptyResult { + let data: ImportData = data.into_inner().data; + let org_id = query.organizationId; + + let org_user = match UserOrganization::find_by_user_and_org(&headers.user.uuid, &org_id, &conn) { + Some(user) => user, + None => err!("User is not part of the organization") + }; + + if org_user.type_ > UserOrgType::Admin as i32 { + err!("Only admins or owners can import into an organization") + } + + // Read and create the collections + let collections: Vec<_> = data.Collections.into_iter().map(|coll| { + let mut collection = Collection::new(org_id.clone(), coll.Name); + collection.save(&conn); + collection + }).collect(); + + // Read the relations between collections and ciphers + let mut relations = Vec::new(); + for relation in data.CollectionRelationships { + relations.push((relation.Key, relation.Value)); + } + + // Read and create the ciphers + let ciphers: Vec<_> = data.Ciphers.into_iter().map(|cipher_data| { + let mut cipher = Cipher::new(cipher_data.Type, cipher_data.Name.clone()); + update_cipher_from_data(&mut cipher, cipher_data, &headers, false, &conn).ok(); + cipher + }).collect(); + + // Assign the collections + for (cipher_index, coll_index) in relations { + let cipher_id = &ciphers[cipher_index].uuid; + let coll_id = &collections[coll_index].uuid; + + CollectionCipher::save(cipher_id, coll_id, &conn); + } + + let mut user = headers.user; + match user.update_revision(&conn) { + 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 index 420362a5..875dec28 100644 --- a/src/api/core/two_factor.rs +++ b/src/api/core/two_factor.rs @@ -112,6 +112,15 @@ fn disable_twofactor( }))) } +#[put("/two-factor/disable", data = "<data>")] +fn disable_twofactor_put( + data: JsonUpcase<DisableTwoFactorData>, + headers: Headers, + conn: DbConn, +) -> JsonResult { + disable_twofactor(data, headers, conn) +} + #[post("/two-factor/get-authenticator", data = "<data>")] fn generate_authenticator( data: JsonUpcase<PasswordData>, @@ -194,6 +203,15 @@ fn activate_authenticator( }))) } +#[put("/two-factor/authenticator", data = "<data>")] +fn activate_authenticator_put( + data: JsonUpcase<EnableAuthenticatorData>, + headers: Headers, + conn: DbConn, +) -> JsonResult { + activate_authenticator(data, headers, conn) +} + fn _generate_recover_code(user: &mut User, conn: &DbConn) { if user.totp_recover.is_none() { let totp_recover = BASE32.encode(&crypto::get_random(vec![0u8; 20])); @@ -356,6 +374,11 @@ fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn) } } +#[put("/two-factor/u2f", data = "<data>")] +fn activate_u2f_put(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn) -> JsonResult { + activate_u2f(data,headers, conn) +} + fn _create_u2f_challenge(user_uuid: &str, type_: TwoFactorType, conn: &DbConn) -> Challenge { let challenge = U2F.generate_challenge().unwrap(); diff --git a/src/api/identity.rs b/src/api/identity.rs index fb6120ef..e1994c00 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use rocket::request::{self, Form, FormItems, FromForm, FromRequest, Request}; use rocket::{Outcome, Route}; @@ -21,12 +22,12 @@ pub fn routes() -> Vec<Route> { } #[post("/connect/token", data = "<connect_data>")] -fn login(connect_data: Form<ConnectData>, device_type: DeviceType, conn: DbConn) -> JsonResult { +fn login(connect_data: Form<ConnectData>, device_type: DeviceType, conn: DbConn, socket: Option<SocketAddr>) -> JsonResult { let data = connect_data.get(); match data.grant_type { GrantType::RefreshToken => _refresh_login(data, device_type, conn), - GrantType::Password => _password_login(data, device_type, conn), + GrantType::Password => _password_login(data, device_type, conn, socket), } } @@ -57,7 +58,13 @@ fn _refresh_login(data: &ConnectData, _device_type: DeviceType, conn: DbConn) -> }))) } -fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> JsonResult { +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)), + }; + // Validate scope let scope = data.get("scope"); if scope != "api offline_access" { @@ -68,13 +75,19 @@ fn _password_login(data: &ConnectData, device_type: DeviceType, conn: DbConn) -> let username = data.get("username"); let user = match User::find_by_mail(username, &conn) { Some(user) => user, - None => err!("Username or password is incorrect. Try again."), + None => err!(format!( + "Username or password is incorrect. Try again. IP: {}. Username: {}.", + ip, username + )), }; // Check password let password = data.get("password"); if !user.check_valid_password(password) { - err!("Username or password is incorrect. Try again.") + err!(format!( + "Username or password is incorrect. Try again. IP: {}. Username: {}.", + ip, username + )) } // Let's only use the header and ignore the 'devicetype' parameter diff --git a/src/api/mod.rs b/src/api/mod.rs index 15f6778c..d651497b 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -2,11 +2,13 @@ pub(crate) mod core; mod icons; mod identity; mod web; +mod notifications; pub use self::core::routes as core_routes; pub use self::icons::routes as icons_routes; pub use self::identity::routes as identity_routes; pub use self::web::routes as web_routes; +pub use self::notifications::routes as notifications_routes; use rocket::response::status::BadRequest; use rocket_contrib::Json; diff --git a/src/api/notifications.rs b/src/api/notifications.rs new file mode 100644 index 00000000..f24fade6 --- /dev/null +++ b/src/api/notifications.rs @@ -0,0 +1,31 @@ +use rocket::Route; +use rocket_contrib::Json; + +use db::DbConn; +use api::JsonResult; +use auth::Headers; + +pub fn routes() -> Vec<Route> { + routes![negotiate] +} + +#[post("/hub/negotiate")] +fn negotiate(_headers: Headers, _conn: DbConn) -> JsonResult { + use data_encoding::BASE64URL; + use crypto; + + // Store this in db? + let conn_id = BASE64URL.encode(&crypto::get_random(vec![0u8; 16])); + + // TODO: Implement transports + // Rocket WS support: https://github.com/SergioBenitez/Rocket/issues/90 + // Rocket SSE support: https://github.com/SergioBenitez/Rocket/issues/33 + Ok(Json(json!({ + "connectionId": conn_id, + "availableTransports":[ + // {"transport":"WebSockets", "transferFormats":["Text","Binary"]}, + // {"transport":"ServerSentEvents", "transferFormats":["Text"]}, + // {"transport":"LongPolling", "transferFormats":["Text","Binary"]} + ] + }))) +}
\ No newline at end of file diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs index 1f5e29a7..9c8eeefd 100644 --- a/src/db/models/attachment.rs +++ b/src/db/models/attachment.rs @@ -53,13 +53,11 @@ use db::schema::attachments; /// Database methods impl Attachment { - pub fn save(&self, conn: &DbConn) -> bool { - match diesel::replace_into(attachments::table) + pub fn save(&self, conn: &DbConn) -> QueryResult<()> { + diesel::replace_into(attachments::table) .values(self) - .execute(&**conn) { - Ok(1) => true, // One row inserted - _ => false, - } + .execute(&**conn) + .and(Ok(())) } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { @@ -67,7 +65,7 @@ impl Attachment { use std::{thread, time}; let mut retries = 10; - + loop { match diesel::delete( attachments::table.filter( @@ -111,4 +109,10 @@ impl Attachment { .filter(attachments::cipher_uuid.eq(cipher_uuid)) .load::<Self>(&**conn).expect("Error loading attachments") } + + pub fn find_by_ciphers(cipher_uuids: Vec<String>, conn: &DbConn) -> Vec<Self> { + attachments::table + .filter(attachments::cipher_uuid.eq_any(cipher_uuids)) + .load::<Self>(&**conn).expect("Error loading attachments") + } } diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index 899e5dda..917a76ea 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -3,7 +3,7 @@ use serde_json::Value as JsonValue; use uuid::Uuid; -use super::{User, Organization, Attachment, FolderCipher, CollectionCipher, UserOrgType, UserOrgStatus}; +use super::{User, Organization, Attachment, FolderCipher, CollectionCipher, UserOrganization, UserOrgType, UserOrgStatus}; #[derive(Debug, Identifiable, Queryable, Insertable, Associations)] #[table_name = "ciphers"] @@ -32,6 +32,7 @@ pub struct Cipher { pub data: String, pub favorite: bool, + pub password_history: Option<String>, } /// Local methods @@ -55,6 +56,7 @@ impl Cipher { fields: None, data: String::new(), + password_history: None, } } } @@ -77,6 +79,10 @@ impl Cipher { let fields_json: JsonValue = if let Some(ref fields) = self.fields { serde_json::from_str(fields).unwrap() } else { JsonValue::Null }; + + let password_history_json: JsonValue = if let Some(ref password_history) = self.password_history { + serde_json::from_str(password_history).unwrap() + } else { JsonValue::Null }; let mut data_json: JsonValue = serde_json::from_str(&self.data).unwrap(); @@ -108,6 +114,8 @@ impl Cipher { "Object": "cipher", "Edit": true, + + "PasswordHistory": password_history_json, }); let key = match self.type_ { @@ -122,7 +130,23 @@ impl Cipher { json_object } + pub fn update_users_revision(&self, conn: &DbConn) { + match self.user_uuid { + Some(ref user_uuid) => User::update_uuid_revision(&user_uuid, conn), + None => { // Belongs to Organization, need to update affected users + if let Some(ref org_uuid) = self.organization_uuid { + UserOrganization::find_by_cipher_and_org(&self.uuid, &org_uuid, conn) + .iter() + .for_each(|user_org| { + User::update_uuid_revision(&user_org.user_uuid, conn) + }); + } + } + }; + } + pub fn save(&mut self, conn: &DbConn) -> bool { + self.update_users_revision(conn); self.updated_at = Utc::now().naive_utc(); match diesel::replace_into(ciphers::table) @@ -134,6 +158,8 @@ impl Cipher { } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + self.update_users_revision(conn); + FolderCipher::delete_all_by_cipher(&self.uuid, &conn)?; CollectionCipher::delete_all_by_cipher(&self.uuid, &conn)?; Attachment::delete_all_by_cipher(&self.uuid, &conn)?; @@ -157,6 +183,7 @@ impl Cipher { None => { match folder_uuid { Some(new_folder) => { + self.update_users_revision(conn); let folder_cipher = FolderCipher::new(&new_folder, &self.uuid); folder_cipher.save(&conn).or(Err("Couldn't save folder setting")) }, @@ -169,6 +196,7 @@ impl Cipher { if current_folder == new_folder { Ok(()) //nothing to do } else { + self.update_users_revision(conn); match FolderCipher::find_by_folder_and_cipher(¤t_folder, &self.uuid, &conn) { Some(current_folder) => { current_folder.delete(&conn).or(Err("Failed removing old folder mapping")) @@ -181,6 +209,7 @@ impl Cipher { } }, None => { + self.update_users_revision(conn); match FolderCipher::find_by_folder_and_cipher(¤t_folder, &self.uuid, &conn) { Some(current_folder) => { current_folder.delete(&conn).or(Err("Failed removing old folder mapping")) diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs index fa16ec28..2bf116c5 100644 --- a/src/db/models/collection.rs +++ b/src/db/models/collection.rs @@ -185,6 +185,8 @@ impl CollectionUser { } pub fn save(user_uuid: &str, collection_uuid: &str, read_only:bool, conn: &DbConn) -> QueryResult<()> { + User::update_uuid_revision(&user_uuid, conn); + diesel::replace_into(users_collections::table) .values(( users_collections::user_uuid.eq(user_uuid), @@ -194,6 +196,8 @@ impl CollectionUser { } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + User::update_uuid_revision(&self.user_uuid, conn); + diesel::delete(users_collections::table .filter(users_collections::user_uuid.eq(&self.user_uuid)) .filter(users_collections::collection_uuid.eq(&self.collection_uuid))) @@ -216,12 +220,20 @@ impl CollectionUser { } pub fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> QueryResult<()> { + CollectionUser::find_by_collection(&collection_uuid, conn) + .iter() + .for_each(|collection| { + User::update_uuid_revision(&collection.user_uuid, conn) + }); + diesel::delete(users_collections::table .filter(users_collections::collection_uuid.eq(collection_uuid)) ).execute(&**conn).and(Ok(())) } pub fn delete_all_by_user(user_uuid: &str, conn: &DbConn) -> QueryResult<()> { + User::update_uuid_revision(&user_uuid, conn); + diesel::delete(users_collections::table .filter(users_collections::user_uuid.eq(user_uuid)) ).execute(&**conn).and(Ok(())) diff --git a/src/db/models/folder.rs b/src/db/models/folder.rs index d9b90bf0..701a7da9 100644 --- a/src/db/models/folder.rs +++ b/src/db/models/folder.rs @@ -71,6 +71,7 @@ use db::schema::{folders, folders_ciphers}; /// Database methods impl Folder { pub fn save(&mut self, conn: &DbConn) -> bool { + User::update_uuid_revision(&self.user_uuid, conn); self.updated_at = Utc::now().naive_utc(); match diesel::replace_into(folders::table) @@ -82,6 +83,7 @@ impl Folder { } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + User::update_uuid_revision(&self.user_uuid, conn); FolderCipher::delete_all_by_folder(&self.uuid, &conn)?; diesel::delete( diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs index 7032a391..1f8d10a8 100644 --- a/src/db/models/mod.rs +++ b/src/db/models/mod.rs @@ -12,7 +12,7 @@ pub use self::attachment::Attachment; pub use self::cipher::Cipher; pub use self::device::Device; pub use self::folder::{Folder, FolderCipher}; -pub use self::user::User; +pub use self::user::{User, Invitation}; pub use self::organization::Organization; pub use self::organization::{UserOrganization, UserOrgStatus, UserOrgType}; pub use self::collection::{Collection, CollectionUser, CollectionCipher}; diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs index 4bb55912..a2d9f5c7 100644 --- a/src/db/models/organization.rs +++ b/src/db/models/organization.rs @@ -1,6 +1,7 @@ use serde_json::Value as JsonValue; use uuid::Uuid; +use super::{User, CollectionUser}; #[derive(Debug, Identifiable, Queryable, Insertable)] #[table_name = "organizations"] @@ -26,7 +27,7 @@ pub struct UserOrganization { } pub enum UserOrgStatus { - _Invited = 0, // Unused, users are accepted automatically + Invited = 0, Accepted = 1, Confirmed = 2, } @@ -108,12 +109,17 @@ impl UserOrganization { use diesel; use diesel::prelude::*; use db::DbConn; -use db::schema::organizations; -use db::schema::users_organizations; +use db::schema::{organizations, users_organizations, users_collections, ciphers_collections}; /// Database methods impl Organization { pub fn save(&mut self, conn: &DbConn) -> bool { + UserOrganization::find_by_org(&self.uuid, conn) + .iter() + .for_each(|user_org| { + User::update_uuid_revision(&user_org.user_uuid, conn); + }); + match diesel::replace_into(organizations::table) .values(&*self) .execute(&**conn) { @@ -172,7 +178,6 @@ impl UserOrganization { } pub fn to_json_user_details(&self, conn: &DbConn) -> JsonValue { - use super::User; let user = User::find_by_uuid(&self.user_uuid, conn).unwrap(); json!({ @@ -190,7 +195,6 @@ impl UserOrganization { } pub fn to_json_collection_user_details(&self, read_only: &bool, conn: &DbConn) -> JsonValue { - use super::User; let user = User::find_by_uuid(&self.user_uuid, conn).unwrap(); json!({ @@ -209,7 +213,6 @@ impl UserOrganization { let coll_uuids = if self.access_all { vec![] // If we have complete access, no need to fill the array } else { - use super::CollectionUser; let collections = CollectionUser::find_by_organization_and_user_uuid(&self.org_uuid, &self.user_uuid, conn); collections.iter().map(|c| json!({"Id": c.collection_uuid, "ReadOnly": c.read_only})).collect() }; @@ -228,6 +231,8 @@ impl UserOrganization { } pub fn save(&mut self, conn: &DbConn) -> bool { + User::update_uuid_revision(&self.user_uuid, conn); + match diesel::replace_into(users_organizations::table) .values(&*self) .execute(&**conn) { @@ -237,7 +242,7 @@ impl UserOrganization { } pub fn delete(self, conn: &DbConn) -> QueryResult<()> { - use super::CollectionUser; + User::update_uuid_revision(&self.user_uuid, conn); CollectionUser::delete_all_by_user(&self.user_uuid, &conn)?; @@ -265,6 +270,13 @@ impl UserOrganization { .first::<Self>(&**conn).ok() } + pub fn find_by_uuid_and_org(uuid: &str, org_uuid: &str, conn: &DbConn) -> Option<Self> { + users_organizations::table + .filter(users_organizations::uuid.eq(uuid)) + .filter(users_organizations::org_uuid.eq(org_uuid)) + .first::<Self>(&**conn).ok() + } + pub fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> { users_organizations::table .filter(users_organizations::user_uuid.eq(user_uuid)) @@ -272,6 +284,13 @@ impl UserOrganization { .load::<Self>(&**conn).unwrap_or(vec![]) } + pub fn find_invited_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> { + users_organizations::table + .filter(users_organizations::user_uuid.eq(user_uuid)) + .filter(users_organizations::status.eq(UserOrgStatus::Invited as i32)) + .load::<Self>(&**conn).unwrap_or(vec![]) + } + pub fn find_by_org(org_uuid: &str, conn: &DbConn) -> Vec<Self> { users_organizations::table .filter(users_organizations::org_uuid.eq(org_uuid)) @@ -291,6 +310,26 @@ impl UserOrganization { .filter(users_organizations::org_uuid.eq(org_uuid)) .first::<Self>(&**conn).ok() } + + pub fn find_by_cipher_and_org(cipher_uuid: &str, org_uuid: &str, conn: &DbConn) -> Vec<Self> { + users_organizations::table + .filter(users_organizations::org_uuid.eq(org_uuid)) + .left_join(users_collections::table.on( + users_collections::user_uuid.eq(users_organizations::user_uuid) + )) + .left_join(ciphers_collections::table.on( + ciphers_collections::collection_uuid.eq(users_collections::collection_uuid).and( + ciphers_collections::cipher_uuid.eq(&cipher_uuid) + ) + )) + .filter( + users_organizations::access_all.eq(true).or( // AccessAll.. + ciphers_collections::cipher_uuid.eq(&cipher_uuid) // ..or access to collection with cipher + ) + ) + .select(users_organizations::all_columns) + .load::<Self>(&**conn).expect("Error loading user organizations") + } } diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 2c30c52d..0d958b5e 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -39,13 +39,12 @@ pub struct User { /// Local methods impl User { - pub fn new(mail: String, key: String, password: String) -> Self { + pub fn new(mail: String) -> Self { let now = Utc::now().naive_utc(); let email = mail.to_lowercase(); let iterations = CONFIG.password_iterations; let salt = crypto::get_random_64(); - let password_hash = crypto::hash_password(password.as_bytes(), &salt, iterations as u32); Self { uuid: Uuid::new_v4().to_string(), @@ -53,9 +52,9 @@ impl User { updated_at: now, name: email.clone(), email, - key, + key: String::new(), - password_hash, + password_hash: Vec::new(), salt, password_iterations: iterations, @@ -103,7 +102,7 @@ impl User { use diesel; use diesel::prelude::*; use db::DbConn; -use db::schema::users; +use db::schema::{users, invitations}; /// Database methods impl User { @@ -154,6 +153,25 @@ 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); + }; + }; + } + + pub fn update_revision(&mut self, conn: &DbConn) -> QueryResult<()> { + self.updated_at = Utc::now().naive_utc(); + diesel::update( + users::table.filter( + users::uuid.eq(&self.uuid) + ) + ) + .set(users::updated_at.eq(&self.updated_at)) + .execute(&**conn).and(Ok(())) + } + pub fn find_by_mail(mail: &str, conn: &DbConn) -> Option<Self> { let lower_mail = mail.to_lowercase(); users::table @@ -167,3 +185,47 @@ impl User { .first::<Self>(&**conn).ok() } } + +#[derive(Debug, Identifiable, Queryable, Insertable)] +#[table_name = "invitations"] +#[primary_key(email)] +pub struct Invitation { + pub email: String, +} + +impl Invitation { + pub fn new(email: String) -> Self { + Self { + email + } + } + + pub fn save(&mut self, conn: &DbConn) -> QueryResult<()> { + diesel::replace_into(invitations::table) + .values(&*self) + .execute(&**conn) + .and(Ok(())) + } + + pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + diesel::delete(invitations::table.filter( + invitations::email.eq(self.email))) + .execute(&**conn) + .and(Ok(())) + } + + pub fn find_by_mail(mail: &str, conn: &DbConn) -> Option<Self> { + let lower_mail = mail.to_lowercase(); + invitations::table + .filter(invitations::email.eq(lower_mail)) + .first::<Self>(&**conn).ok() + } + + pub fn take(mail: &str, conn: &DbConn) -> bool { + CONFIG.invitations_allowed && + match Self::find_by_mail(mail, &conn) { + Some(invitation) => invitation.delete(&conn).is_ok(), + None => false + } + } +}
\ No newline at end of file diff --git a/src/db/schema.rs b/src/db/schema.rs index f39701b1..457b84c2 100644 --- a/src/db/schema.rs +++ b/src/db/schema.rs @@ -21,6 +21,7 @@ table! { fields -> Nullable<Text>, data -> Text, favorite -> Bool, + password_history -> Nullable<Text>, } } @@ -113,6 +114,12 @@ table! { } table! { + invitations (email) { + email -> Text, + } +} + +table! { users_collections (user_uuid, collection_uuid) { user_uuid -> Text, collection_uuid -> Text, diff --git a/src/main.rs b/src/main.rs index 5fbefb0b..c794d95b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![feature(plugin, custom_derive)] #![plugin(rocket_codegen)] +#![allow(proc_macro_derive_resolution_fallback)] // TODO: Remove this when diesel update fixes warnings extern crate rocket; extern crate rocket_contrib; extern crate reqwest; @@ -49,6 +50,7 @@ fn init_rocket() -> Rocket { .mount("/api", api::core_routes()) .mount("/identity", api::identity_routes()) .mount("/icons", api::icons_routes()) + .mount("/notifications", api::notifications_routes()) .manage(db::init_pool()) } @@ -224,6 +226,7 @@ pub struct Config { local_icon_extractor: bool, signups_allowed: bool, + invitations_allowed: bool, password_iterations: i32, show_password_hint: bool, @@ -256,6 +259,7 @@ impl Config { local_icon_extractor: util::parse_option_string(env::var("LOCAL_ICON_EXTRACTOR").ok()).unwrap_or(false), signups_allowed: util::parse_option_string(env::var("SIGNUPS_ALLOWED").ok()).unwrap_or(true), + invitations_allowed: util::parse_option_string(env::var("INVITATIONS_ALLOWED").ok()).unwrap_or(true), password_iterations: util::parse_option_string(env::var("PASSWORD_ITERATIONS").ok()).unwrap_or(100_000), show_password_hint: util::parse_option_string(env::var("SHOW_PASSWORD_HINT").ok()).unwrap_or(true), diff --git a/src/util.rs b/src/util.rs index 4a186809..c5bade68 100644 --- a/src/util.rs +++ b/src/util.rs @@ -3,19 +3,20 @@ /// #[macro_export] macro_rules! err { - ($err:expr, $err_desc:expr, $msg:expr) => {{ + ($err:expr, $msg:expr) => {{ println!("ERROR: {}", $msg); err_json!(json!({ - "error": $err, - "error_description": $err_desc, - "ErrorModel": { - "Message": $msg, - "ValidationErrors": null, - "Object": "error" - } + "Message": $err, + "ValidationErrors": { + "": [$msg,], + }, + "ExceptionMessage": null, + "ExceptionStackTrace": null, + "InnerExceptionMessage": null, + "Object": "error", })) }}; - ($msg:expr) => { err!("default_error", "default_error_description", $msg) } + ($msg:expr) => { err!("The model state is invalid", $msg) } } #[macro_export] |