Compare commits

..

80 Commits

Author SHA1 Message Date
Daniel García
1c57c9d8e0 Merge pull request #148 from mprasil/beta
Merge Beta to master
2018-08-21 22:41:50 +02:00
Daniel García
bd20d8724b Merge pull request #147 from mprasil/master
Bump version to 0.13.0 - latest Vault v1
2018-08-21 22:32:54 +02:00
Miroslav Prasil
69a18255c6 Bump up version to 1.0.0 2018-08-21 21:21:54 +01:00
Miroslav Prasil
c40baf5e17 Merge branch 'master' into beta 2018-08-21 21:17:12 +01:00
Miroslav Prasil
df041108f6 Bump version to 0.13.0 - latest Vault v1 2018-08-21 21:13:56 +01:00
Daniel García
ee10d278a7 Merge pull request #146 from mprasil/cipher_folder_revision
Update affected users revision on cipher and folder change
2018-08-21 21:44:33 +02:00
Miroslav Prasil
2b2401be19 Update affected users revision on cipher and folder change 2018-08-21 17:32:00 +01:00
Daniel García
4f58d07c83 Merge pull request #145 from mprasil/org_user_revision
Organization update improvements
2018-08-21 16:27:19 +02:00
Miroslav Prasil
9eea0151ba Update user revision timestamp on Organization changes 2018-08-21 13:26:22 +01:00
Miroslav Prasil
40d09ddd2a Add PUT alias for Organization updates 2018-08-21 13:25:52 +01:00
Daniel García
d332e87655 Merge pull request #144 from mprasil/collection_revision
Update affected users revision when there are collection changes
2018-08-21 13:47:19 +02:00
Daniel García
0fa48a749f Merge pull request #143 from mprasil/update_revision_fix
Actually update the revision date for user struct, not just in DB
2018-08-21 13:46:05 +02:00
Miroslav Prasil
a5ef8aef0f Update affected users revision when there are collection changes 2018-08-21 12:20:55 +01:00
Miroslav Prasil
4fb09c5b4d Actually update the revision date for user struct, not just in DB 2018-08-21 10:36:04 +01:00
Daniel García
6fdeeb56ce Merge pull request #140 from mprasil/error_format
Update the error format to show message in new Vault
2018-08-16 00:52:46 +02:00
Daniel García
b002d34cd4 Merge pull request #139 from mprasil/edit_shared_fix
Add PUT alias for editing cipher
2018-08-15 23:02:59 +02:00
Daniel García
e46fc62b78 Merge pull request #141 from mprasil/profile_update
Add PUT alias for profile update
2018-08-15 23:02:34 +02:00
Miroslav Prasil
12a2dc0901 Add PUT alias for profile update 2018-08-15 16:10:40 +01:00
Miroslav Prasil
b3f3fd81ac Update theerror format to show message in new Vault 2018-08-15 15:50:07 +01:00
Miroslav Prasil
f2fec345ec Add PUT alias for editing cipher 2018-08-15 14:27:37 +01:00
Daniel García
b6312340b6 Merge pull request #138 from mprasil/readme_updates
Cleaned up HTTPS example
2018-08-15 15:12:01 +02:00
Daniel García
3d1fc0f2e8 Merge pull request #136 from mprasil/disable_analytics
Remove analytics from Vault
2018-08-15 15:11:45 +02:00
Miroslav Prasil
80bad9f66d Cleaned up HTTPS example 2018-08-15 11:18:34 +01:00
Miroslav Prasil
5ecafb157d Disable analytics via patch to Vault 2018-08-14 21:48:56 +01:00
Daniel García
f1ade62638 Merge pull request #135 from mprasil/empty_collection
Deserialize "null" to empty Vec for Collections
2018-08-14 16:43:03 +02:00
Miroslav Prasil
00b882935f Deserialize "null" to empty Vec for Collections 2018-08-14 11:06:42 +01:00
Daniel García
eb5641b863 Merge pull request #134 from mprasil/put_collections_admin
Add aliases for PUTs and DELETEs on collections, organizations and org users
2018-08-13 20:16:34 +02:00
Miroslav Prasil
0dfd9c7670 Add couple more aliases for PUTs and DELETEs 2018-08-13 16:45:30 +01:00
Miroslav Prasil
6ede1743ac add alias for PUT collections-admin 2018-08-13 16:00:10 +01:00
Daniel García
d3f357b708 Implemented PUT for u2f registration 2018-08-13 15:26:01 +02:00
Daniel García
5a55dd1d4b Merge pull request #133 from mprasil/document_differences
Extend documentation
2018-08-13 14:38:54 +02:00
Daniel García
16056626b0 Merge pull request #131 from mprasil/revision_date
Implement update_revision trigger
2018-08-13 14:38:30 +02:00
Miroslav Prasil
626a3c93ba Revert "Merge branch 'beta' of https://github.com/krankur/bitwarden_rs into beta"
This reverts commit 3fd3d8d5e9.
2018-08-13 12:35:41 +01:00
Miroslav Prasil
c0f554311b Extend documentation 2018-08-13 12:01:52 +01:00
Miroslav Prasil
3f5a99916a Implement update_revision trigger 2018-08-13 10:58:39 +01:00
Miroslav Prasil
b5a057f063 Merge branch 'master' into beta 2018-08-10 21:43:16 +01:00
Daniel García
e7e0717f5b Merge pull request #129 from krankur/beta
Implemented PUT for /two-factor/authenticator and /two-factor/disable #124
2018-08-10 22:20:44 +02:00
Kumar Ankur
3fd3d8d5e9 Merge branch 'beta' of https://github.com/krankur/bitwarden_rs into beta 2018-08-10 23:49:34 +05:30
Kumar Ankur
7b2de40beb Merge branch 'beta' of https://github.com/krankur/bitwarden_rs into beta 2018-08-10 23:26:55 +05:30
Kumar Ankur
5f6d721c09 Implemented PUT for /two-factor/authenticator and /two-factor/disable 2018-08-10 23:20:19 +05:30
Kumar Ankur
ddda86b90d Implemented bulk cipher share (share selected) #100 2018-08-10 23:20:19 +05:30
Daniel García
c6256e1455 Merge pull request #128 from mprasil/revision_date
Return revision date in miliseconds (fixes #127)
2018-08-10 19:40:56 +02:00
Daniel García
0cd3053fcb Merge pull request #125 from stammw/master
Make password hints available in the error message #85
2018-08-10 19:40:31 +02:00
Miroslav Prasil
58c1545707 Return revision date in miliseconds (fixes #127) 2018-08-10 17:18:59 +01:00
Jean-Christophe BEGUE
d3b4b10d18 Add a explaination to the password hint message #85 2018-08-10 16:59:23 +02:00
Jean-Christophe BEGUE
c031ae9f2f Make password hints available in the error message #85 2018-08-10 15:52:06 +02:00
Daniel García
672e3273cd Merge pull request #123 from mprasil/beta_patch
Fix patch file for v2.1.1
2018-08-09 16:40:29 +02:00
Miroslav Prasil
039860f87e Fix patch file for v2.1.1 2018-08-09 13:38:40 +01:00
Daniel García
9511456ded Merge pull request #116 from krankur/beta
Implemented bulk cipher share (share selected) #100
2018-08-09 01:44:16 +02:00
Daniel García
04b198a7e2 Merge pull request #120 from mprasil/vault_2.1.1
Update vault to latest version
2018-08-09 01:43:22 +02:00
Miroslav Prasil
73a1abed10 Update vault to latest version 2018-08-08 23:15:01 +02:00
Kumar Ankur
fb7b1c8c18 Implemented bulk cipher share (share selected) #100 2018-08-06 03:29:44 +05:30
Daniel García
8ffa7ebb6a Merge pull request #115 from krankur/beta
Implmeneted DELETE on 'api/ciphers' to delete selected ciphers (#98)
2018-08-03 16:29:23 +02:00
Kumar Ankur
aac1304b46 clean up 2018-08-03 19:31:01 +05:30
Kumar Ankur
7dfc759691 Implmeneted DELETE on 'api/ciphers' to delete selected ciphers (#98) 2018-08-03 19:23:38 +05:30
Daniel García
54afe0671e Merge pull request #111 from krankur/beta
Implemented PUT for single cipher sharing (#97)
2018-08-01 21:12:48 +02:00
Kumar Ankur
74e2ca81ae Implemented PUT for single cipher sharing (#97) 2018-08-02 00:07:14 +05:30
Daniel García
d6fadb52ff Merge pull request #109 from mprasil/beta_merge
Merge changes from master to beta
2018-08-01 12:57:32 +02:00
Miroslav Prasil
b163aeb8ca Merge changes in master to beta branch (concurrency fixes) 2018-08-01 11:37:42 +01:00
Daniel García
fcb479a457 Merge pull request #108 from krankur/beta
Implementing PUT for 'api/ciphers/move' (#99)
2018-08-01 11:49:14 +02:00
Kumar Ankur
0e095a9fa4 change to reuse the logic for POST in PUT as well 2018-08-01 13:50:52 +05:30
Kumar Ankur
2f6aa3c363 Reverting removal of 'api/ciphers/move' POST as it is required for backward compatibility 2018-08-01 11:21:05 +05:30
Kumar Ankur
fcc485384f clean up 2018-08-01 04:12:46 +05:30
Kumar Ankur
91a2319325 Implementing PUT for ciphers/move (#99) 2018-08-01 03:58:47 +05:30
Daniel García
56b3afa77c Merge pull request #107 from shauder/bug/attachments_for_orgs
Bug/attachments for orgs
2018-07-31 20:08:05 +02:00
Shane A. Faulkner
d335f45e34 Bump version to 0.12.0 2018-07-31 12:07:03 -05:00
Shane A. Faulkner
34d2648509 Merge pull request #3 from shauder/master
Sync working branch with changes in master upstream
2018-07-31 12:05:52 -05:00
Shane A. Faulkner
f39c4fe2f4 Merge pull request #2 from dani-garcia/master
Sync local fork with upstream
2018-07-31 12:03:39 -05:00
Shane A. Faulkner
01875c395b Merge pull request #1 from mprasil/concurrency_fix
WAL journal mode and delete retry added
2018-07-31 11:39:45 -05:00
Miroslav Prasil
2872f40d13 WAL journal mode and delete retry added 2018-07-31 16:43:43 +01:00
Daniel García
07a30c8334 Merge pull request #106 from mprasil/beta_stable
Use stable release of v2.0.0
2018-07-30 15:43:41 +02:00
Miroslav Prasil
ceb3d0314d Use stable release of v2.0.0 2018-07-27 10:01:33 +01:00
mprasil
d7df545078 Merge pull request #104 from jcgruenhage/patch-1
Update matrix.to link in the README
2018-07-26 22:52:12 +01:00
Jan Christian Grünhage
d073f06652 Update matrix.to link in the README
Using the room ID instead of an alias isn't supposed to be working for joining rooms, and doesn't work when joining over federation. It only works when your server is already participating in the room.
2018-07-26 22:42:02 +01:00
Daniel García
3726da9c14 Merge pull request #103 from mprasil/https_doc_fix
Fixed the documentation for https (resolves #101)
2018-07-24 15:28:23 +02:00
Miroslav Prasil
51450a0df9 Fixed the documentation for https (resolves #101) 2018-07-24 12:32:41 +01:00
Daniel García
659f677897 Add missing slash, to put it like it was at first 2018-07-21 18:50:54 +02:00
Daniel García
a291dea16f Updated dependencies and Docker image to new web-vault 2018-07-21 17:27:00 +02:00
Shane A. Faulkner
98bae4a0a1 Cleanup and working with 2 or less attachments 2018-07-18 15:35:45 -05:00
Shane A. Faulkner
31349a47d3 Very dirty addition of missing api's 2018-07-14 01:09:20 -05:00
21 changed files with 611 additions and 250 deletions

3
.env
View File

@@ -27,6 +27,9 @@
## The change only applies when the password is changed
# PASSWORD_ITERATIONS=100000
## Whether password hint should be sent into the error response when the client request it
# SHOW_PASSWORD_HINT=true
## Domain settings
## The domain must match the address from where you access the server
## Unless you are using U2F, or having problems with attachments not downloading, there is no need to change this

266
Cargo.lock generated
View File

@@ -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]]
@@ -67,7 +67,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitwarden_rs"
version = "0.10.0"
version = "0.11.0"
dependencies = [
"chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -75,31 +75,32 @@ dependencies = [
"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)",
"lazy_static 1.0.2 (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)",
"multipart 0.15.0 (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)",
"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)",
"rocket 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_codegen 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_contrib 0.3.15 (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_json 1.0.24 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -136,15 +137,6 @@ name = "cfg-if"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.2.25"
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"
@@ -227,7 +219,7 @@ 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)",
"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.0.2 (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)",
@@ -241,7 +233,7 @@ 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)",
"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.0.2 (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)",
]
@@ -330,8 +322,8 @@ 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)",
"lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -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.7 (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)",
]
@@ -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)",
@@ -634,7 +626,7 @@ dependencies = [
"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_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -659,7 +651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -688,7 +680,7 @@ version = "0.9.1"
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)",
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -709,18 +701,18 @@ dependencies = [
]
[[package]]
name = "matches"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "1.0.2"
name = "mach"
version = "0.2.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)",
]
[[package]]
name = "matches"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.0.1"
@@ -770,7 +762,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,7 +773,7 @@ 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)",
@@ -826,22 +818,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "multipart"
version = "0.14.2"
version = "0.15.0"
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)",
"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.2 (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)",
]
@@ -885,7 +877,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.0.2 (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)",
@@ -902,23 +894,13 @@ name = "nodrop"
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)",
"proc-macro2 0.4.8 (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)",
]
@@ -931,15 +913,6 @@ dependencies = [
"num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[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"
@@ -972,7 +945,7 @@ 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)",
"lazy_static 1.0.2 (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)",
]
@@ -984,7 +957,7 @@ 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)",
"pkg-config 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -995,12 +968,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pear"
version = "0.0.18"
version = "0.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pear_codegen"
version = "0.0.18"
version = "0.0.19"
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)",
@@ -1049,7 +1022,7 @@ dependencies = [
[[package]]
name = "pkg-config"
version = "0.3.11"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -1070,7 +1043,7 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "0.4.6"
version = "0.4.8"
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)",
@@ -1099,7 +1072,7 @@ name = "quote"
version = "0.6.3"
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1137,19 +1110,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)",
"lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.42 (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]]
@@ -1171,12 +1143,12 @@ dependencies = [
[[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)",
"regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.5 (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 +1163,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)",
@@ -1225,10 +1197,10 @@ dependencies = [
"hyper-tls 0.1.3 (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)",
"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_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.2 (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)",
@@ -1251,7 +1223,7 @@ dependencies = [
[[package]]
name = "rocket"
version = "0.3.14"
version = "0.3.15"
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 +1235,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.19 (registry+https://github.com/rust-lang/crates.io-index)",
"pear_codegen 0.0.19 (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.3 (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 +1249,24 @@ dependencies = [
[[package]]
name = "rocket_codegen"
version = "0.3.14"
version = "0.3.15"
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.15 (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.15"
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.15 (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_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1325,12 +1297,17 @@ 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.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1382,14 +1359,14 @@ name = "serde_derive"
version = "1.0.70"
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.8 (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)",
]
[[package]]
name = "serde_json"
version = "1.0.22"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1447,6 +1424,16 @@ name = "slab"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "slice-deque"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
"mach 0.2.0 (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.2.1"
@@ -1454,8 +1441,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.6.2"
version = "0.6.3"
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"
@@ -1487,7 +1477,7 @@ name = "syn"
version = "0.14.4"
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1528,7 +1518,7 @@ name = "thread_local"
version = "0.3.5"
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.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1544,15 +1534,15 @@ dependencies = [
[[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.4 (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.3 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1782,7 +1772,7 @@ dependencies = [
"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_json 1.0.24 (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 +1804,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.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1853,23 +1843,13 @@ name = "untrusted"
version = "0.5.1"
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.7 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1878,15 +1858,6 @@ name = "utf8-ranges"
version = "1.0.0"
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"
@@ -1997,20 +1968,19 @@ 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 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 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"
@@ -2068,53 +2038,51 @@ 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.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3"
"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 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 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 mach 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b549fa8738e27dcf6c8c5d6d35211e786aa02715a22b60c33b9488fdd634a90b"
"checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a"
"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_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.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c934f2af2afbe9277d5be4c46599116e6dd93339871504c578318eeef725aa64"
"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 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.19 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc18e7bc730525f5bcc1069487631a94e5d7389c7f7e63c081cda5c3542ea3e"
"checksum pear_codegen 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ac78ce520b1274885d8415a02ae3f1bb06038e0f6862f105aa97060c6a10fd99"
"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.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6a52e4dbc8354505ee07e484ab07127e06d87ca6fa7f0a516a2b294e5ad5ad16"
"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.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c65b1ea15bb859d922cade2d1765b4b88beac339cbfad545ef2d2ef8c8215ee6"
"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"
@@ -2123,23 +2091,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"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 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 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.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c9010c81b707444fe8de4f83380e6e18bbc2825aac2da797d5553ce3d5b3e702"
"checksum rocket_codegen 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0109d1692a1a05c267ed1eef94ff018bd360e0b6487c8678da4ebbbdbf02cef7"
"checksum rocket_contrib 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f5eaf6d3324a58b1d961b92fd1ff19c37074c603b8a095daa372089f644f4"
"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 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"
@@ -2148,15 +2117,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"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_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2"
"checksum serde_urlencoded 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e703cef904312097cfceab9ce131ff6bbe09e8c964a0703345a5f49238757bc1"
"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 slice-deque 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "84f8bc1bafa053290fdd4f40eefa15914cb16cf8bee9793312e4389114d15645"
"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 smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
"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"
@@ -2167,7 +2137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"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 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"
@@ -2200,10 +2170,8 @@ 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 version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051"

View File

@@ -1,24 +1,24 @@
[package]
name = "bitwarden_rs"
version = "0.11.0"
version = "1.0.0"
authors = ["Daniel García <dani-garcia@users.noreply.github.com>"]
[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.15", features = ["tls"] }
rocket_codegen = "0.3.15"
rocket_contrib = "0.3.15"
# HTTP client
reqwest = "0.8.6"
# multipart/form-data support
multipart = "0.14.2"
multipart = "0.15.0"
# A generic serialization/deserialization framework
serde = "1.0.70"
serde_derive = "1.0.70"
serde_json = "1.0.22"
serde_json = "1.0.24"
# A safe, extensible ORM and Query builder
diesel = { version = "1.3.2", features = ["sqlite", "chrono", "r2d2"] }
@@ -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.0.2"
# Numerical libraries
num-traits = "0.2.5"

View File

@@ -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.1.1"
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 git config --global url."https://github.com/".insteadOf ssh://git@github.com/ \
&& npm install \
&& gulp dist:selfHosted \
&& mv dist /web-vault
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

View File

@@ -22,6 +22,7 @@ _*Note, that this project is not associated with the [Bitwarden](https://bitward
- [icons cache](#icons-cache)
- [Changing the API request size limit](#changing-the-api-request-size-limit)
- [Changing the number of workers](#changing-the-number-of-workers)
- [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)
@@ -33,6 +34,10 @@ _*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)
- [Get in touch](#get-in-touch)
## Features
@@ -134,11 +139,10 @@ 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:443 \
-p 443:80 \
mprasil/bitwarden:latest
```
Note that you need to mount ssl files and you need to forward appropriate port.
@@ -248,6 +252,30 @@ 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).
@@ -313,8 +341,23 @@ 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
The users must already be registered on your server to invite them, because we can't send the invitation via email. The invited users won't get the invitation email, instead they will appear in the interface as if they already accepted the invitation. Organization admin then just needs to confirm them to be proper Organization members and to give them access to the shared secrets.
## 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.
If you prefer to chat, we're usually hanging around at [#bitwarden_rs:matrix.org](https://matrix.to/#/!cASGtOHlSftdScFNMs:matrix.org) room on Matrix. Feel free to join us!
If you prefer to chat, we're usually hanging around at [#bitwarden_rs:matrix.org](https://matrix.to/#/#bitwarden_rs:matrix.org) room on Matrix. Feel free to join us!

View File

@@ -0,0 +1,23 @@
--- a/src/app/services/services.module.ts
+++ b/src/app/services/services.module.ts
@@ -116,17 +116,15 @@ const exportService = new ExportService(folderService, cipherService, apiService
const importService = new ImportService(cipherService, folderService, apiService, i18nService, collectionService);
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;
- }
+ const isDev = false;
+ environmentService.baseUrl = window.location.origin;
await apiService.setUrls({
base: isDev ? null : window.location.origin,
api: isDev ? 'http://localhost:4000' : null,

View File

@@ -1,9 +0,0 @@
{
"appSettings": {
"apiUri": "/api",
"identityUri": "/identity",
"iconsUri": "/icons",
"stripeKey": "",
"braintreeKey": ""
}
}

View File

@@ -1 +1 @@
nightly-2018-06-26
nightly-2018-07-18

View File

@@ -73,6 +73,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;
@@ -244,6 +249,29 @@ 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()
}
#[derive(Deserialize)]
#[allow(non_snake_case)]
struct PasswordHintData {
Email: String,
}
#[post("/accounts/password-hint", data = "<data>")]
fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResult {
let data: PasswordHintData = data.into_inner().data;
if !CONFIG.show_password_hint {
return Ok(())
}
match User::find_by_mail(&data.Email, &conn) {
Some(user) => {
let hint = user.password_hint.to_owned().unwrap_or_default();
err!(format!("Your password hint is: {}", hint))
},
None => Ok(()),
}
}

View File

@@ -87,6 +87,8 @@ fn get_cipher_details(uuid: String, headers: Headers, conn: DbConn) -> JsonResul
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
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
@@ -242,12 +244,21 @@ fn post_ciphers_import(data: JsonUpcase<ImportData>, headers: Headers, conn: DbC
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 +296,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 +348,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) {
@@ -415,6 +490,22 @@ fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers
Ok(Json(cipher.to_json(&headers.host, &headers.user.uuid, &conn)))
}
#[post("/ciphers/<uuid>/attachment-admin", format = "multipart/form-data", data = "<data>")]
fn post_attachment_admin(uuid: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> JsonResult {
post_attachment(uuid, data, content_type, headers, conn)
}
#[post("/ciphers/<uuid>/attachment/<attachment_id>/share", format = "multipart/form-data", data = "<data>")]
fn post_attachment_share(uuid: String, attachment_id: String, data: Data, content_type: &ContentType, headers: Headers, conn: DbConn) -> JsonResult {
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &conn)?;
post_attachment(uuid, data, content_type, headers, conn)
}
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete-admin")]
fn delete_attachment_post_admin(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> EmptyResult {
delete_attachment(uuid, attachment_id, headers, conn)
}
#[post("/ciphers/<uuid>/attachment/<attachment_id>/delete")]
fn delete_attachment_post(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> EmptyResult {
delete_attachment(uuid, attachment_id, headers, conn)
@@ -422,29 +513,7 @@ fn delete_attachment_post(uuid: String, attachment_id: String, headers: Headers,
#[delete("/ciphers/<uuid>/attachment/<attachment_id>")]
fn delete_attachment(uuid: String, attachment_id: String, headers: Headers, conn: DbConn) -> EmptyResult {
let attachment = match Attachment::find_by_id(&attachment_id, &conn) {
Some(attachment) => attachment,
None => err!("Attachment doesn't exist")
};
if attachment.cipher_uuid != uuid {
err!("Attachment from other cipher")
}
let cipher = match Cipher::find_by_uuid(&uuid, &conn) {
Some(cipher) => cipher,
None => err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, &conn) {
err!("Cipher cannot be deleted by user")
}
// Delete attachment
match attachment.delete(&conn) {
Ok(()) => Ok(()),
Err(_) => err!("Deleting attachement failed")
}
_delete_cipher_attachment_by_id(&uuid, &attachment_id, &headers, &conn)
}
#[post("/ciphers/<uuid>/delete")]
@@ -462,7 +531,7 @@ fn delete_cipher(uuid: String, headers: Headers, conn: DbConn) -> EmptyResult {
_delete_cipher_by_uuid(&uuid, &headers, &conn)
}
#[post("/ciphers/delete", data = "<data>")]
#[delete("/ciphers", data = "<data>")]
fn delete_cipher_selected(data: JsonUpcase<Value>, headers: Headers, conn: DbConn) -> EmptyResult {
let data: Value = data.into_inner().data;
@@ -483,6 +552,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;
@@ -535,6 +609,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;
@@ -578,3 +657,29 @@ fn _delete_cipher_by_uuid(uuid: &str, headers: &Headers, conn: &DbConn) -> Empty
Err(_) => err!("Failed deleting cipher")
}
}
fn _delete_cipher_attachment_by_id(uuid: &str, attachment_id: &str, headers: &Headers, conn: &DbConn) -> EmptyResult {
let attachment = match Attachment::find_by_id(&attachment_id, &conn) {
Some(attachment) => attachment,
None => err!("Attachment doesn't exist")
};
if attachment.cipher_uuid != uuid {
err!("Attachment from other cipher")
}
let cipher = match Cipher::find_by_uuid(&uuid, &conn) {
Some(cipher) => cipher,
None => err!("Cipher doesn't exist")
};
if !cipher.is_write_accessible_to_user(&headers.user.uuid, &conn) {
err!("Cipher cannot be deleted by user")
}
// Delete attachment
match attachment.delete(&conn) {
Ok(()) => Ok(()),
Err(_) => err!("Deleting attachement failed")
}
}

View File

@@ -14,6 +14,7 @@ pub fn routes() -> Vec<Route> {
routes![
register,
profile,
put_profile,
post_profile,
get_public_keys,
post_keys,
@@ -23,6 +24,7 @@ pub fn routes() -> Vec<Route> {
post_email,
delete_account,
revision_date,
password_hint,
sync,
@@ -31,21 +33,29 @@ pub fn routes() -> Vec<Route> {
get_cipher_admin,
get_cipher_details,
post_ciphers,
put_cipher_admin,
post_ciphers_admin,
post_ciphers_import,
post_attachment,
post_attachment_admin,
post_attachment_share,
delete_attachment_post,
delete_attachment_post_admin,
delete_attachment,
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_selected,
delete_cipher_selected_post,
delete_all,
move_cipher_selected,
move_cipher_selected_put,
get_folders,
get_folder,
@@ -59,33 +69,44 @@ 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,
clear_device_token,
put_device_token,

View File

@@ -8,6 +8,8 @@ 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 +19,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 +57,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 +75,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 +111,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;
@@ -164,6 +176,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 +205,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 {
@@ -215,17 +233,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 +253,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 +334,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 +354,7 @@ struct CollectionData {
struct InviteData {
Emails: Vec<String>,
Type: NumberOrString,
#[serde(deserialize_with = "deserialize_collections")]
Collections: Vec<CollectionData>,
AccessAll: Option<bool>,
}
@@ -424,10 +459,16 @@ 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,
}
#[put("/organizations/<org_id>/users/<user_id>", data = "<data>", rank = 1)]
fn put_organization_user(org_id: String, user_id: String, data: JsonUpcase<EditUserData>, headers: AdminHeaders, conn: DbConn) -> EmptyResult {
edit_user(org_id, user_id, data, headers, conn)
}
#[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 {
let data: EditUserData = data.into_inner().data;
@@ -494,7 +535,7 @@ fn edit_user(org_id: String, user_id: String, data: JsonUpcase<EditUserData>, he
Ok(())
}
#[post("/organizations/<org_id>/users/<user_id>/delete")]
#[delete("/organizations/<org_id>/users/<user_id>")]
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) {
Some(user) => user,
@@ -522,3 +563,8 @@ fn delete_user(org_id: String, user_id: String, headers: AdminHeaders, conn: DbC
Err(_) => err!("Failed deleting user from organization")
}
}
#[post("/organizations/<org_id>/users/<user_id>/delete")]
fn post_delete_user(org_id: String, user_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult {
delete_user(org_id, user_id, headers, conn)
}

View File

@@ -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();

View File

@@ -64,14 +64,33 @@ impl Attachment {
pub fn delete(self, conn: &DbConn) -> QueryResult<()> {
use util;
use std::{thread, time};
let mut retries = 10;
loop {
match diesel::delete(
attachments::table.filter(
attachments::id.eq(&self.id)
)
).execute(&**conn) {
Ok(_) => break,
Err(err) => {
if retries < 1 {
println!("ERROR: Failed with 10 retries");
return Err(err)
} else {
retries = retries - 1;
println!("Had to retry! Retries left: {}", retries);
thread::sleep(time::Duration::from_millis(500));
continue
}
}
}
}
util::delete_file(&self.get_file_path());
diesel::delete(
attachments::table.filter(
attachments::id.eq(self.id)
)
).execute(&**conn).and(Ok(()))
Ok(())
}
pub fn delete_all_by_cipher(cipher_uuid: &str, conn: &DbConn) -> QueryResult<()> {
@@ -92,4 +111,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")
}
}

View File

@@ -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"]
@@ -122,7 +122,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 +150,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 +175,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 +188,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(&current_folder, &self.uuid, &conn) {
Some(current_folder) => {
current_folder.delete(&conn).or(Err("Failed removing old folder mapping"))
@@ -181,6 +201,7 @@ impl Cipher {
}
},
None => {
self.update_users_revision(conn);
match FolderCipher::find_by_folder_and_cipher(&current_folder, &self.uuid, &conn) {
Some(current_folder) => {
current_folder.delete(&conn).or(Err("Failed removing old folder mapping"))

View File

@@ -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(()))

View File

@@ -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(

View File

@@ -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"]
@@ -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)?;
@@ -291,6 +296,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")
}
}

View File

@@ -154,6 +154,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

View File

@@ -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;
@@ -83,6 +84,11 @@ fn check_db() {
exit(1);
}
}
// Turn on WAL in SQLite
use diesel::RunQueryDsl;
let connection = db::get_connection().expect("Can't conect to DB");
diesel::sql_query("PRAGMA journal_mode=wal").execute(&connection).expect("Failed to turn on WAL");
}
fn check_rsa_keys() {
@@ -164,6 +170,7 @@ pub struct Config {
local_icon_extractor: bool,
signups_allowed: bool,
password_iterations: i32,
show_password_hint: bool,
domain: String,
domain_set: bool,
}
@@ -192,6 +199,8 @@ 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),
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),
domain_set: domain.is_ok(),
domain: domain.unwrap_or("http://localhost".into()),
}

View File

@@ -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]