commit a1dc47b82646d3b2ba8092c5cca7af2d04c68735
parent 86de0ca17b87bc8c1ab40eae0f5d5d7caa70487d
Author: Daniel GarcĂa <dani-garcia@users.noreply.github.com>
Date: Fri, 25 Jan 2019 18:23:51 +0100
Change config to thread-safe system, needed for a future config panel.
Improved some two factor methods.
Diffstat:
19 files changed, 453 insertions(+), 390 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -95,7 +95,7 @@ dependencies = [
[[package]]
name = "base64"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -119,7 +119,7 @@ dependencies = [
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "diesel 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dotenv 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -135,6 +135,7 @@ dependencies = [
"num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"oath 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rmpv 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -427,7 +428,7 @@ dependencies = [
[[package]]
name = "diesel"
-version = "1.4.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -739,7 +740,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "h2"
-version = "0.1.15"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -833,13 +834,13 @@ dependencies = [
[[package]]
name = "hyper"
-version = "0.12.22"
+version = "0.12.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "h2 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -875,7 +876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.12.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1108,7 +1109,7 @@ name = "migrations_internals"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "diesel 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1454,6 +1455,26 @@ dependencies = [
]
[[package]]
+name = "paste"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "paste-impl"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "pear"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1566,6 +1587,16 @@ dependencies = [
]
[[package]]
+name = "proc-macro-hack"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "proc-macro2"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1608,7 +1639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1633,7 +1664,7 @@ dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1648,7 +1679,7 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1656,12 +1687,20 @@ name = "rand_core"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
-version = "0.3.0"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -1669,7 +1708,7 @@ name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1677,7 +1716,7 @@ name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1688,7 +1727,7 @@ dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1698,7 +1737,7 @@ name = "rand_pcg"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1707,7 +1746,7 @@ name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1715,7 +1754,7 @@ name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1756,12 +1795,12 @@ name = "reqwest"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "hyper 0.12.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1814,7 +1853,7 @@ name = "rocket"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2640,7 +2679,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"block-modes 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2666,7 +2705,7 @@ dependencies = [
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
-"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
+"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
@@ -2704,7 +2743,7 @@ dependencies = [
"checksum devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3"
"checksum devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7"
"checksum devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487"
-"checksum diesel 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "66d7d3a2f8a24763a1a52b5324737b4d24141bb294440ed9094db60bd6cd29ee"
+"checksum diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a2469cbcf1dfb9446e491cac4c493c2554133f87f7d041e892ac82e5cd36e863"
"checksum diesel_derives 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62a27666098617d52c487a41f70de23d44a1dc1f3aa5877ceba2790fb1f1cab4"
"checksum diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c"
"checksum digest 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a68d759d7a66a4f63d5bd2a2b14ad7e8cf93fe8c9be227031cd4e72ab0e9ee8"
@@ -2742,7 +2781,7 @@ dependencies = [
"checksum generic-array 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe043cf9b85297937897087de81f590361686e1ac2d4d471b45435de5dfb6a6"
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
"checksum groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57"
-"checksum h2 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "30e0b8e55b4d7ffedade2b9605851f8e85f5010663e7ad170ef3c0f0681bc43f"
+"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e"
"checksum handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d82e5750d8027a97b9640e3fefa66bbaf852a35228e1c90790efd13c4b09c166"
"checksum hmac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb5aa9647ba4711e9d6968dc1c810cd23989ed435443ca962e1bf6d8b8b83ff"
"checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771"
@@ -2750,7 +2789,7 @@ dependencies = [
"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5"
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
"checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c"
-"checksum hyper 0.12.22 (registry+https://github.com/rust-lang/crates.io-index)" = "622db8120387cf64e3159e57343233b5a37253176fcda7f8a7e48f5a9c4c98fd"
+"checksum hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)" = "860faf61a9957c9cb0e23e69f1c8290e92f6eb660fcdd1f2d6777043a2ae1a46"
"checksum hyper-sync-rustls 0.3.0-rc.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d1a443a90413a118ac6739e024f6a5180aa3b3f43f7de65f9d388a961cff19b"
"checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
@@ -2812,6 +2851,8 @@ dependencies = [
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
+"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d"
+"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a"
"checksum pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c26d2b92e47063ffce70d3e3b1bd097af121a9e0db07ca38a6cc1cf0cc85ff25"
"checksum pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
@@ -2825,6 +2866,7 @@ dependencies = [
"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0"
+"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66"
"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978"
"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"
@@ -2835,7 +2877,8 @@ dependencies = [
"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
-"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
+"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca"
diff --git a/Cargo.toml b/Cargo.toml
@@ -95,6 +95,9 @@ native-tls = "0.2.2"
# Template library
handlebars = "1.1.0"
+# Macro ident-combining library
+paste = "0.1.4"
+
[patch.crates-io]
# Add support for Timestamp type
rmp = { git = 'https://github.com/dani-garcia/msgpack-rust' }
diff --git a/src/api/admin.rs b/src/api/admin.rs
@@ -1,4 +1,3 @@
-use rocket_contrib::json::Json;
use serde_json::Value;
use rocket::http::{Cookie, Cookies, SameSite};
@@ -6,7 +5,7 @@ use rocket::request::{self, FlashMessage, Form, FromRequest, Request};
use rocket::response::{content::Html, Flash, Redirect};
use rocket::{Outcome, Route};
-use crate::api::{JsonResult, JsonUpcase};
+use crate::api::{ApiResult, EmptyResult, JsonUpcase};
use crate::auth::{decode_admin, encode_jwt, generate_admin_claims, ClientIp};
use crate::db::{models::*, DbConn};
use crate::error::Error;
@@ -14,7 +13,7 @@ use crate::mail;
use crate::CONFIG;
pub fn routes() -> Vec<Route> {
- if CONFIG.admin_token.is_none() {
+ if CONFIG.admin_token().is_none() {
return Vec::new();
}
@@ -54,7 +53,7 @@ impl AdminTemplateData {
}
#[get("/", rank = 2)]
-fn admin_login(flash: Option<FlashMessage>) -> Result<Html<String>, Error> {
+fn admin_login(flash: Option<FlashMessage>) -> ApiResult<Html<String>> {
// If there is an error, show it
let msg = flash.map(|msg| format!("{}: {}", msg.name(), msg.msg()));
@@ -97,14 +96,14 @@ fn post_admin_login(data: Form<LoginForm>, mut cookies: Cookies, ip: ClientIp) -
}
fn _validate_token(token: &str) -> bool {
- match CONFIG.admin_token.as_ref() {
+ match CONFIG.admin_token().as_ref() {
None => false,
Some(t) => t == token,
}
}
#[get("/", rank = 1)]
-fn admin_page(_token: AdminToken, conn: DbConn) -> Result<Html<String>, Error> {
+fn admin_page(_token: AdminToken, conn: DbConn) -> ApiResult<Html<String>> {
let users = User::get_all(&conn);
let users_json: Vec<Value> = users.iter().map(|u| u.to_json(&conn)).collect();
@@ -119,39 +118,36 @@ struct InviteData {
}
#[post("/invite", data = "<data>")]
-fn invite_user(data: JsonUpcase<InviteData>, _token: AdminToken, conn: DbConn) -> JsonResult {
+fn invite_user(data: JsonUpcase<InviteData>, _token: AdminToken, conn: DbConn) -> EmptyResult {
let data: InviteData = data.into_inner().data;
let email = data.Email.clone();
if User::find_by_mail(&data.Email, &conn).is_some() {
err!("User already exists")
}
- if !CONFIG.invitations_allowed {
+ if !CONFIG.invitations_allowed() {
err!("Invitations are not allowed")
}
- if let Some(ref mail_config) = CONFIG.mail {
+ if let Some(ref mail_config) = CONFIG.mail() {
let mut user = User::new(email);
user.save(&conn)?;
let org_name = "bitwarden_rs";
- mail::send_invite(&user.email, &user.uuid, None, None, &org_name, None, mail_config)?;
+ mail::send_invite(&user.email, &user.uuid, None, None, &org_name, None, mail_config)
} else {
let mut invitation = Invitation::new(data.Email);
- invitation.save(&conn)?;
+ invitation.save(&conn)
}
-
- Ok(Json(json!({})))
}
#[post("/users/<uuid>/delete")]
-fn delete_user(uuid: String, _token: AdminToken, conn: DbConn) -> JsonResult {
+fn delete_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult {
let user = match User::find_by_uuid(&uuid, &conn) {
Some(user) => user,
None => err!("User doesn't exist"),
};
- user.delete(&conn)?;
- Ok(Json(json!({})))
+ user.delete(&conn)
}
pub struct AdminToken {}
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs
@@ -79,14 +79,14 @@ fn register(data: JsonUpcase<RegisterData>, conn: DbConn) -> EmptyResult {
}
user
- } else if CONFIG.signups_allowed {
+ } else if CONFIG.signups_allowed() {
err!("Account with this email already exists")
} else {
err!("Registration not allowed")
}
}
None => {
- if CONFIG.signups_allowed || Invitation::take(&data.Email, &conn) {
+ if CONFIG.signups_allowed() || Invitation::take(&data.Email, &conn) {
User::new(data.Email.clone())
} else {
err!("Registration not allowed")
@@ -419,9 +419,9 @@ fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResul
None => return Ok(()),
};
- if let Some(ref mail_config) = CONFIG.mail {
+ if let Some(ref mail_config) = CONFIG.mail() {
mail::send_password_hint(&data.Email, hint, mail_config)?;
- } else if CONFIG.show_password_hint {
+ } else if CONFIG.show_password_hint() {
if let Some(hint) = hint {
err!(format!("Your password hint is: {}", &hint));
} else {
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
@@ -302,7 +302,7 @@ pub fn update_cipher_from_data(
cipher.fields = data.Fields.map(|f| f.to_string());
cipher.data = type_data.to_string();
cipher.password_history = data.PasswordHistory.map(|f| f.to_string());
-
+
cipher.save(&conn)?;
cipher.move_to_folder(data.FolderId, &headers.user.uuid, &conn)?;
@@ -651,7 +651,7 @@ fn post_attachment(uuid: String, data: Data, content_type: &ContentType, headers
let boundary_pair = params.next().expect("No boundary provided");
let boundary = boundary_pair.1;
- let base_path = Path::new(&CONFIG.attachments_folder).join(&cipher.uuid);
+ let base_path = Path::new(&CONFIG.attachments_folder()).join(&cipher.uuid);
let mut attachment_key = None;
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
@@ -486,17 +486,17 @@ fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: AdminHeade
}
for email in data.Emails.iter() {
- let mut user_org_status = match CONFIG.mail {
+ let mut user_org_status = match CONFIG.mail() {
Some(_) => UserOrgStatus::Invited as i32,
None => UserOrgStatus::Accepted as i32, // Automatically mark user as accepted if no email invites
};
let user = match User::find_by_mail(&email, &conn) {
None => {
- if !CONFIG.invitations_allowed {
+ if !CONFIG.invitations_allowed() {
err!(format!("User email does not exist: {}", email))
}
- if CONFIG.mail.is_none() {
+ if CONFIG.mail().is_none() {
let mut invitation = Invitation::new(email.clone());
invitation.save(&conn)?;
}
@@ -535,7 +535,7 @@ fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: AdminHeade
new_user.save(&conn)?;
- if let Some(ref mail_config) = CONFIG.mail {
+ if let Some(ref mail_config) = CONFIG.mail() {
let org_name = match Organization::find_by_uuid(&org_id, &conn) {
Some(org) => org.name,
None => err!("Error looking up organization"),
@@ -558,11 +558,11 @@ fn send_invite(org_id: String, data: JsonUpcase<InviteData>, headers: AdminHeade
#[post("/organizations/<org_id>/users/<user_org>/reinvite")]
fn reinvite_user(org_id: String, user_org: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult {
- if !CONFIG.invitations_allowed {
+ if !CONFIG.invitations_allowed() {
err!("Invitations are not allowed.")
}
- if CONFIG.mail.is_none() {
+ if CONFIG.mail().is_none() {
err!("SMTP is not configured.")
}
@@ -585,7 +585,7 @@ fn reinvite_user(org_id: String, user_org: String, headers: AdminHeaders, conn:
None => err!("Error looking up organization."),
};
- if let Some(ref mail_config) = CONFIG.mail {
+ if let Some(ref mail_config) = CONFIG.mail() {
mail::send_invite(
&user.email,
&user.uuid,
@@ -637,7 +637,7 @@ fn accept_invite(_org_id: String, _org_user_id: String, data: JsonUpcase<AcceptD
None => err!("Invited user not found"),
}
- if let Some(ref mail_config) = CONFIG.mail {
+ if let Some(ref mail_config) = CONFIG.mail() {
let mut org_name = String::from("bitwarden_rs");
if let Some(org_id) = &claims.org_id {
org_name = match Organization::find_by_uuid(&org_id, &conn) {
@@ -686,7 +686,7 @@ fn confirm_invite(
None => err!("Invalid key provided"),
};
- if let Some(ref mail_config) = CONFIG.mail {
+ if let Some(ref mail_config) = CONFIG.mail() {
let org_name = match Organization::find_by_uuid(&org_id, &conn) {
Some(org) => org.name,
None => err!("Error looking up organization."),
diff --git a/src/api/core/two_factor.rs b/src/api/core/two_factor.rs
@@ -179,7 +179,7 @@ fn activate_authenticator(data: JsonUpcase<EnableAuthenticatorData>, headers: He
Some(n) => n as u64,
None => err!("Malformed token"),
};
-
+
let mut user = headers.user;
if !user.check_valid_password(&password_hash) {
@@ -236,13 +236,13 @@ use crate::CONFIG;
const U2F_VERSION: &str = "U2F_V2";
lazy_static! {
- static ref APP_ID: String = format!("{}/app-id.json", &CONFIG.domain);
+ static ref APP_ID: String = format!("{}/app-id.json", &CONFIG.domain());
static ref U2F: U2f = U2f::new(APP_ID.clone());
}
#[post("/two-factor/get-u2f", data = "<data>")]
fn generate_u2f(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> JsonResult {
- if !CONFIG.domain_set {
+ if !CONFIG.domain_set() {
err!("`DOMAIN` environment variable is not set. U2F disabled")
}
@@ -286,6 +286,8 @@ fn generate_u2f_challenge(data: JsonUpcase<PasswordData>, headers: Headers, conn
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct EnableU2FData {
+ Id: NumberOrString, // 1..5
+ Name: String,
MasterPasswordHash: String,
DeviceResponse: String,
}
@@ -321,54 +323,52 @@ fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn)
err!("Invalid password");
}
- let tf_challenge =
- TwoFactor::find_by_user_and_type(&user.uuid, TwoFactorType::U2fRegisterChallenge as i32, &conn);
-
- if let Some(tf_challenge) = tf_challenge {
- let challenge: Challenge = serde_json::from_str(&tf_challenge.data)?;
+ let tf_type = TwoFactorType::U2fRegisterChallenge as i32;
+ let tf_challenge = match TwoFactor::find_by_user_and_type(&user.uuid, tf_type, &conn) {
+ Some(c) => c,
+ None => err!("Can't recover challenge"),
+ };
- tf_challenge.delete(&conn)?;
+ let challenge: Challenge = serde_json::from_str(&tf_challenge.data)?;
+ tf_challenge.delete(&conn)?;
- let response_copy: RegisterResponseCopy = serde_json::from_str(&data.DeviceResponse)?;
+ let response_copy: RegisterResponseCopy = serde_json::from_str(&data.DeviceResponse)?;
- let error_code = response_copy
- .error_code
- .clone()
- .map_or("0".into(), NumberOrString::into_string);
+ let error_code = response_copy
+ .error_code
+ .clone()
+ .map_or("0".into(), NumberOrString::into_string);
- if error_code != "0" {
- err!("Error registering U2F token")
- }
+ if error_code != "0" {
+ err!("Error registering U2F token")
+ }
- let response = response_copy.into_response();
+ let response = response_copy.into_response();
- let registration = U2F.register_response(challenge.clone(), response)?;
- // TODO: Allow more than one U2F device
- let mut registrations = Vec::new();
- registrations.push(registration);
+ let registration = U2F.register_response(challenge.clone(), response)?;
+ // TODO: Allow more than one U2F device
+ let mut registrations = Vec::new();
+ registrations.push(registration);
- let tf_registration = TwoFactor::new(
- user.uuid.clone(),
- TwoFactorType::U2f,
- serde_json::to_string(®istrations).unwrap(),
- );
- tf_registration.save(&conn)?;
+ let tf_registration = TwoFactor::new(
+ user.uuid.clone(),
+ TwoFactorType::U2f,
+ serde_json::to_string(®istrations).unwrap(),
+ );
+ tf_registration.save(&conn)?;
- _generate_recover_code(&mut user, &conn);
+ _generate_recover_code(&mut user, &conn);
- Ok(Json(json!({
- "Enabled": true,
- "Challenge": {
- "UserId": user.uuid,
- "AppId": APP_ID.to_string(),
- "Challenge": challenge,
- "Version": U2F_VERSION,
- },
- "Object": "twoFactorU2f"
- })))
- } else {
- err!("Can't recover challenge")
- }
+ Ok(Json(json!({
+ "Enabled": true,
+ "Challenge": {
+ "UserId": user.uuid,
+ "AppId": APP_ID.to_string(),
+ "Challenge": challenge,
+ "Version": U2F_VERSION,
+ },
+ "Object": "twoFactorU2f"
+ })))
}
#[put("/two-factor/u2f", data = "<data>")]
@@ -493,29 +493,9 @@ use yubico::config::Config;
use yubico::Yubico;
fn parse_yubikeys(data: &EnableYubikeyData) -> Vec<String> {
- let mut yubikeys: Vec<String> = Vec::new();
-
- if data.Key1.is_some() {
- yubikeys.push(data.Key1.as_ref().unwrap().to_owned());
- }
+ let data_keys = [&data.Key1, &data.Key2, &data.Key3, &data.Key4, &data.Key5];
- if data.Key2.is_some() {
- yubikeys.push(data.Key2.as_ref().unwrap().to_owned());
- }
-
- if data.Key3.is_some() {
- yubikeys.push(data.Key3.as_ref().unwrap().to_owned());
- }
-
- if data.Key4.is_some() {
- yubikeys.push(data.Key4.as_ref().unwrap().to_owned());
- }
-
- if data.Key5.is_some() {
- yubikeys.push(data.Key5.as_ref().unwrap().to_owned());
- }
-
- yubikeys
+ data_keys.into_iter().filter_map(|e| e.as_ref().cloned()).collect()
}
fn jsonify_yubikeys(yubikeys: Vec<String>) -> serde_json::Value {
@@ -529,17 +509,17 @@ fn jsonify_yubikeys(yubikeys: Vec<String>) -> serde_json::Value {
}
fn verify_yubikey_otp(otp: String) -> JsonResult {
- if !CONFIG.yubico_cred_set {
+ if !CONFIG.yubico_cred_set() {
err!("`YUBICO_CLIENT_ID` or `YUBICO_SECRET_KEY` environment variable is not set. Yubikey OTP Disabled")
}
let yubico = Yubico::new();
let config = Config::default()
- .set_client_id(CONFIG.yubico_client_id.to_owned())
- .set_key(CONFIG.yubico_secret_key.to_owned());
+ .set_client_id(CONFIG.yubico_client_id())
+ .set_key(CONFIG.yubico_secret_key());
- let result = match CONFIG.yubico_server {
- Some(ref server) => yubico.verify(otp, config.set_api_hosts(vec![server.to_owned()])),
+ let result = match CONFIG.yubico_server() {
+ Some(server) => yubico.verify(otp, config.set_api_hosts(vec![server])),
None => yubico.verify(otp, config),
};
@@ -551,7 +531,7 @@ fn verify_yubikey_otp(otp: String) -> JsonResult {
#[post("/two-factor/get-yubikey", data = "<data>")]
fn generate_yubikey(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> JsonResult {
- if !CONFIG.yubico_cred_set {
+ if !CONFIG.yubico_cred_set() {
err!("`YUBICO_CLIENT_ID` or `YUBICO_SECRET_KEY` environment variable is not set. Yubikey OTP Disabled")
}
@@ -637,7 +617,7 @@ fn activate_yubikey(data: JsonUpcase<EnableYubikeyData>, headers: Headers, conn:
serde_json::to_string(&yubikey_metadata).unwrap(),
);
yubikey_registration.save(&conn)?;
-
+
_generate_recover_code(&mut user, &conn);
let mut result = jsonify_yubikeys(yubikey_metadata.Keys);
diff --git a/src/api/icons.rs b/src/api/icons.rs
@@ -32,7 +32,7 @@ fn icon(domain: String) -> Content<Vec<u8>> {
}
fn get_icon(domain: &str) -> Vec<u8> {
- let path = format!("{}/{}.png", CONFIG.icon_cache_folder, domain);
+ let path = format!("{}/{}.png", CONFIG.icon_cache_folder(), domain);
if let Some(icon) = get_cached_icon(&path) {
return icon;
@@ -87,7 +87,7 @@ fn file_is_expired(path: &str, ttl: u64) -> Result<bool, Error> {
fn icon_is_negcached(path: &str) -> bool {
let miss_indicator = path.to_owned() + ".miss";
- let expired = file_is_expired(&miss_indicator, CONFIG.icon_cache_negttl);
+ let expired = file_is_expired(&miss_indicator, CONFIG.icon_cache_negttl());
match expired {
// No longer negatively cached, drop the marker
@@ -110,12 +110,12 @@ fn mark_negcache(path: &str) {
}
fn icon_is_expired(path: &str) -> bool {
- let expired = file_is_expired(path, CONFIG.icon_cache_ttl);
+ let expired = file_is_expired(path, CONFIG.icon_cache_ttl());
expired.unwrap_or(true)
}
fn get_icon_url(domain: &str) -> String {
- if CONFIG.local_icon_extractor {
+ if CONFIG.local_icon_extractor() {
format!("http://{}/favicon.ico", domain)
} else {
format!("https://icons.bitwarden.com/{}/icon.png", domain)
@@ -135,7 +135,7 @@ fn download_icon(url: &str) -> Result<Vec<u8>, Error> {
}
fn save_icon(path: &str, icon: &[u8]) {
- create_dir_all(&CONFIG.icon_cache_folder).expect("Error creating icon cache");
+ create_dir_all(&CONFIG.icon_cache_folder()).expect("Error creating icon cache");
if let Ok(mut f) = File::create(path) {
f.write_all(icon).expect("Error writing icon file");
diff --git a/src/api/identity.rs b/src/api/identity.rs
@@ -234,7 +234,7 @@ fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> Api
match TwoFactorType::from_i32(*provider) {
Some(TwoFactorType::Authenticator) => { /* Nothing to do for TOTP */ }
- Some(TwoFactorType::U2f) if CONFIG.domain_set => {
+ Some(TwoFactorType::U2f) if CONFIG.domain_set() => {
let request = two_factor::generate_u2f_login(user_uuid, conn)?;
let mut challenge_list = Vec::new();
diff --git a/src/api/notifications.rs b/src/api/notifications.rs
@@ -25,7 +25,7 @@ fn negotiate(_headers: Headers, _conn: DbConn) -> JsonResult {
let conn_id = BASE64URL.encode(&crypto::get_random(vec![0u8; 16]));
let mut available_transports: Vec<JsonValue> = Vec::new();
- if CONFIG.websocket_enabled {
+ if CONFIG.websocket_enabled() {
available_transports.push(json!({"transport":"WebSockets", "transferFormats":["Text","Binary"]}));
}
@@ -90,7 +90,7 @@ fn serialize_date(date: NaiveDateTime) -> Value {
let seconds: i64 = date.timestamp();
let nanos: i64 = date.timestamp_subsec_nanos() as i64;
let timestamp = nanos << 34 | seconds;
-
+
let bs = timestamp.to_be_bytes();
// -1 is Timestamp
@@ -349,9 +349,12 @@ pub fn start_notification_server() -> WebSocketUsers {
let factory = WSFactory::init();
let users = factory.users.clone();
- if CONFIG.websocket_enabled {
+ if CONFIG.websocket_enabled() {
thread::spawn(move || {
- WebSocket::new(factory).unwrap().listen(&CONFIG.websocket_url).unwrap();
+ WebSocket::new(factory)
+ .unwrap()
+ .listen(&CONFIG.websocket_url())
+ .unwrap();
});
}
diff --git a/src/api/web.rs b/src/api/web.rs
@@ -8,11 +8,11 @@ use rocket::Route;
use rocket_contrib::json::Json;
use serde_json::Value;
-use crate::CONFIG;
use crate::util::Cached;
+use crate::CONFIG;
pub fn routes() -> Vec<Route> {
- if CONFIG.web_vault_enabled {
+ if CONFIG.web_vault_enabled() {
routes![web_index, app_id, web_files, attachments, alive]
} else {
routes![attachments, alive]
@@ -21,7 +21,9 @@ pub fn routes() -> Vec<Route> {
#[get("/")]
fn web_index() -> Cached<io::Result<NamedFile>> {
- Cached::short(NamedFile::open(Path::new(&CONFIG.web_vault_folder).join("index.html")))
+ Cached::short(NamedFile::open(
+ Path::new(&CONFIG.web_vault_folder()).join("index.html"),
+ ))
}
#[get("/app-id.json")]
@@ -35,7 +37,7 @@ fn app_id() -> Cached<Content<Json<Value>>> {
{
"version": { "major": 1, "minor": 0 },
"ids": [
- &CONFIG.domain,
+ &CONFIG.domain(),
"ios:bundle-id:com.8bit.bitwarden",
"android:apk-key-hash:dUGFzUzf3lmHSLBDBIv+WaFyZMI" ]
}]
@@ -45,12 +47,12 @@ fn app_id() -> Cached<Content<Json<Value>>> {
#[get("/<p..>", rank = 10)] // Only match this if the other routes don't match
fn web_files(p: PathBuf) -> Cached<io::Result<NamedFile>> {
- Cached::long(NamedFile::open(Path::new(&CONFIG.web_vault_folder).join(p)))
+ Cached::long(NamedFile::open(Path::new(&CONFIG.web_vault_folder()).join(p)))
}
#[get("/attachments/<uuid>/<file..>")]
fn attachments(uuid: String, file: PathBuf) -> io::Result<NamedFile> {
- NamedFile::open(Path::new(&CONFIG.attachments_folder).join(uuid).join(file))
+ NamedFile::open(Path::new(&CONFIG.attachments_folder()).join(uuid).join(file))
}
#[get("/alive")]
diff --git a/src/auth.rs b/src/auth.rs
@@ -16,21 +16,21 @@ const JWT_ALGORITHM: Algorithm = Algorithm::RS256;
lazy_static! {
pub static ref DEFAULT_VALIDITY: Duration = Duration::hours(2);
static ref JWT_HEADER: Header = Header::new(JWT_ALGORITHM);
- pub static ref JWT_LOGIN_ISSUER: String = format!("{}|login", CONFIG.domain);
- pub static ref JWT_INVITE_ISSUER: String = format!("{}|invite", CONFIG.domain);
- pub static ref JWT_ADMIN_ISSUER: String = format!("{}|admin", CONFIG.domain);
- static ref PRIVATE_RSA_KEY: Vec<u8> = match read_file(&CONFIG.private_rsa_key) {
+ pub static ref JWT_LOGIN_ISSUER: String = format!("{}|login", CONFIG.domain());
+ pub static ref JWT_INVITE_ISSUER: String = format!("{}|invite", CONFIG.domain());
+ pub static ref JWT_ADMIN_ISSUER: String = format!("{}|admin", CONFIG.domain());
+ static ref PRIVATE_RSA_KEY: Vec<u8> = match read_file(&CONFIG.private_rsa_key()) {
Ok(key) => key,
Err(e) => panic!(
"Error loading private RSA Key from {}\n Error: {}",
- CONFIG.private_rsa_key, e
+ CONFIG.private_rsa_key(), e
),
};
- static ref PUBLIC_RSA_KEY: Vec<u8> = match read_file(&CONFIG.public_rsa_key) {
+ static ref PUBLIC_RSA_KEY: Vec<u8> = match read_file(&CONFIG.public_rsa_key()) {
Ok(key) => key,
Err(e) => panic!(
"Error loading public RSA Key from {}\n Error: {}",
- CONFIG.public_rsa_key, e
+ CONFIG.public_rsa_key(), e
),
};
}
@@ -185,8 +185,8 @@ impl<'a, 'r> FromRequest<'a, 'r> for Headers {
let headers = request.headers();
// Get host
- let host = if CONFIG.domain_set {
- CONFIG.domain.clone()
+ let host = if CONFIG.domain_set() {
+ CONFIG.domain()
} else if let Some(referer) = headers.get_one("Referer") {
referer.to_string()
} else {
diff --git a/src/config.rs b/src/config.rs
@@ -0,0 +1,245 @@
+use std::process::exit;
+use std::sync::RwLock;
+
+use handlebars::Handlebars;
+
+lazy_static! {
+ pub static ref CONFIG: Config = Config::load();
+}
+
+macro_rules! make_config {
+ ( $( $name:ident: $ty:ty ),+ $(,)* ) => {
+
+ pub struct Config { inner: RwLock<_Config> }
+
+ #[derive(Default)]
+ struct _Config {
+ _templates: Handlebars,
+ $(pub $name: $ty),+
+ }
+
+ paste::item! {
+ #[allow(unused)]
+ impl Config {
+ $(
+ pub fn $name(&self) -> $ty {
+ self.inner.read().unwrap().$name.clone()
+ }
+ pub fn [<set_ $name>](&self, value: $ty) {
+ self.inner.write().unwrap().$name = value;
+ }
+ )+
+ }
+ }
+
+ };
+}
+
+make_config! {
+ database_url: String,
+ icon_cache_folder: String,
+ attachments_folder: String,
+
+ icon_cache_ttl: u64,
+ icon_cache_negttl: u64,
+
+ private_rsa_key: String,
+ private_rsa_key_pem: String,
+ public_rsa_key: String,
+
+ web_vault_folder: String,
+ web_vault_enabled: bool,
+
+ websocket_enabled: bool,
+ websocket_url: String,
+
+ extended_logging: bool,
+ log_file: Option<String>,
+
+ local_icon_extractor: bool,
+ signups_allowed: bool,
+ invitations_allowed: bool,
+ admin_token: Option<String>,
+ password_iterations: i32,
+ show_password_hint: bool,
+
+ domain: String,
+ domain_set: bool,
+
+ yubico_cred_set: bool,
+ yubico_client_id: String,
+ yubico_secret_key: String,
+ yubico_server: Option<String>,
+
+ mail: Option<MailConfig>,
+ templates_folder: String,
+ reload_templates: bool,
+}
+
+fn load_templates(path: &str) -> Handlebars {
+ let mut hb = Handlebars::new();
+ // Error on missing params
+ hb.set_strict_mode(true);
+
+ macro_rules! reg {
+ ($name:expr) => {{
+ let template = include_str!(concat!("static/templates/", $name, ".hbs"));
+ hb.register_template_string($name, template).unwrap();
+ }};
+ }
+
+ // First register default templates here
+ reg!("email/invite_accepted");
+ reg!("email/invite_confirmed");
+ reg!("email/pw_hint_none");
+ reg!("email/pw_hint_some");
+ reg!("email/send_org_invite");
+
+ reg!("admin/base");
+ reg!("admin/login");
+ reg!("admin/page");
+
+ // And then load user templates to overwrite the defaults
+ // Use .hbs extension for the files
+ // Templates get registered with their relative name
+ hb.register_templates_directory(".hbs", path).unwrap();
+
+ hb
+}
+
+impl Config {
+ pub fn render_template<T: serde::ser::Serialize>(
+ &self,
+ name: &str,
+ data: &T,
+ ) -> Result<String, crate::error::Error> {
+ if CONFIG.reload_templates() {
+ warn!("RELOADING TEMPLATES");
+ let hb = load_templates(CONFIG.templates_folder().as_ref());
+ hb.render(name, data).map_err(Into::into)
+ } else {
+ let hb = &CONFIG.inner.read().unwrap()._templates;
+ hb.render(name, data).map_err(Into::into)
+ }
+ }
+
+ fn load() -> Self {
+ use crate::util::{get_env, get_env_or};
+ dotenv::dotenv().ok();
+
+ let df = get_env_or("DATA_FOLDER", "data".to_string());
+ let key = get_env_or("RSA_KEY_FILENAME", format!("{}/{}", &df, "rsa_key"));
+
+ let domain = get_env("DOMAIN");
+
+ let yubico_client_id = get_env("YUBICO_CLIENT_ID");
+ let yubico_secret_key = get_env("YUBICO_SECRET_KEY");
+
+ let templates_folder = get_env_or("TEMPLATES_FOLDER", format!("{}/{}", &df, "templates"));
+
+ let cfg = _Config {
+ database_url: get_env_or("DATABASE_URL", format!("{}/{}", &df, "db.sqlite3")),
+ icon_cache_folder: get_env_or("ICON_CACHE_FOLDER", format!("{}/{}", &df, "icon_cache")),
+ attachments_folder: get_env_or("ATTACHMENTS_FOLDER", format!("{}/{}", &df, "attachments")),
+ _templates: load_templates(&templates_folder),
+ templates_folder,
+ reload_templates: get_env_or("RELOAD_TEMPLATES", false),
+
+ // icon_cache_ttl defaults to 30 days (30 * 24 * 60 * 60 seconds)
+ icon_cache_ttl: get_env_or("ICON_CACHE_TTL", 2_592_000),
+ // icon_cache_negttl defaults to 3 days (3 * 24 * 60 * 60 seconds)
+ icon_cache_negttl: get_env_or("ICON_CACHE_NEGTTL", 259_200),
+
+ private_rsa_key: format!("{}.der", &key),
+ private_rsa_key_pem: format!("{}.pem", &key),
+ public_rsa_key: format!("{}.pub.der", &key),
+
+ web_vault_folder: get_env_or("WEB_VAULT_FOLDER", "web-vault/".into()),
+ web_vault_enabled: get_env_or("WEB_VAULT_ENABLED", true),
+
+ websocket_enabled: get_env_or("WEBSOCKET_ENABLED", false),
+ websocket_url: format!(
+ "{}:{}",
+ get_env_or("WEBSOCKET_ADDRESS", "0.0.0.0".to_string()),
+ get_env_or("WEBSOCKET_PORT", 3012)
+ ),
+
+ extended_logging: get_env_or("EXTENDED_LOGGING", true),
+ log_file: get_env("LOG_FILE"),
+
+ local_icon_extractor: get_env_or("LOCAL_ICON_EXTRACTOR", false),
+ signups_allowed: get_env_or("SIGNUPS_ALLOWED", true),
+ admin_token: get_env("ADMIN_TOKEN"),
+ invitations_allowed: get_env_or("INVITATIONS_ALLOWED", true),
+ password_iterations: get_env_or("PASSWORD_ITERATIONS", 100_000),
+ show_password_hint: get_env_or("SHOW_PASSWORD_HINT", true),
+
+ domain_set: domain.is_some(),
+ domain: domain.unwrap_or("http://localhost".into()),
+
+ yubico_cred_set: yubico_client_id.is_some() && yubico_secret_key.is_some(),
+ yubico_client_id: yubico_client_id.unwrap_or("00000".into()),
+ yubico_secret_key: yubico_secret_key.unwrap_or("AAAAAAA".into()),
+ yubico_server: get_env("YUBICO_SERVER"),
+
+ mail: MailConfig::load(),
+ };
+
+ Config {
+ inner: RwLock::new(cfg),
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct MailConfig {
+ pub smtp_host: String,
+ pub smtp_port: u16,
+ pub smtp_ssl: bool,
+ pub smtp_from: String,
+ pub smtp_from_name: String,
+ pub smtp_username: Option<String>,
+ pub smtp_password: Option<String>,
+}
+
+impl MailConfig {
+ fn load() -> Option<Self> {
+ use crate::util::{get_env, get_env_or};
+
+ // When SMTP_HOST is absent, we assume the user does not want to enable it.
+ let smtp_host = match get_env("SMTP_HOST") {
+ Some(host) => host,
+ None => return None,
+ };
+
+ let smtp_from = get_env("SMTP_FROM").unwrap_or_else(|| {
+ error!("Please specify SMTP_FROM to enable SMTP support.");
+ exit(1);
+ });
+
+ let smtp_from_name = get_env_or("SMTP_FROM_NAME", "Bitwarden_RS".into());
+
+ let smtp_ssl = get_env_or("SMTP_SSL", true);
+ let smtp_port = get_env("SMTP_PORT").unwrap_or_else(|| if smtp_ssl { 587u16 } else { 25u16 });
+
+ let smtp_username = get_env("SMTP_USERNAME");
+ let smtp_password = get_env("SMTP_PASSWORD").or_else(|| {
+ if smtp_username.as_ref().is_some() {
+ error!("SMTP_PASSWORD is mandatory when specifying SMTP_USERNAME.");
+ exit(1);
+ } else {
+ None
+ }
+ });
+
+ Some(MailConfig {
+ smtp_host,
+ smtp_port,
+ smtp_ssl,
+ smtp_from,
+ smtp_from_name,
+ smtp_username,
+ smtp_password,
+ })
+ }
+}
diff --git a/src/db/mod.rs b/src/db/mod.rs
@@ -25,13 +25,13 @@ pub mod schema;
/// Initializes a database pool.
pub fn init_pool() -> Pool {
- let manager = ConnectionManager::new(&*CONFIG.database_url);
+ let manager = ConnectionManager::new(CONFIG.database_url());
r2d2::Pool::builder().build(manager).expect("Failed to create pool")
}
pub fn get_connection() -> Result<Connection, ConnectionError> {
- Connection::establish(&CONFIG.database_url)
+ Connection::establish(&CONFIG.database_url())
}
/// Attempts to retrieve a single connection from the managed database pool. If
diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs
@@ -28,7 +28,7 @@ impl Attachment {
}
pub fn get_file_path(&self) -> String {
- format!("{}/{}/{}", CONFIG.attachments_folder, self.cipher_uuid, self.id)
+ format!("{}/{}/{}", CONFIG.attachments_folder(), self.cipher_uuid, self.id)
}
pub fn to_json(&self, host: &str) -> Value {
@@ -86,7 +86,7 @@ impl Attachment {
pub fn find_by_id(id: &str, conn: &DbConn) -> Option<Self> {
let id = id.to_lowercase();
-
+
attachments::table
.filter(attachments::id.eq(id))
.first::<Self>(&**conn)
diff --git a/src/db/models/user.rs b/src/db/models/user.rs
@@ -56,7 +56,7 @@ impl User {
password_hash: Vec::new(),
salt: crypto::get_random_64(),
- password_iterations: CONFIG.password_iterations,
+ password_iterations: CONFIG.password_iterations(),
security_stamp: crate::util::get_uuid(),
@@ -242,7 +242,7 @@ impl Invitation {
}
pub fn take(mail: &str, conn: &DbConn) -> bool {
- CONFIG.invitations_allowed
+ CONFIG.invitations_allowed()
&& match Self::find_by_mail(mail, &conn) {
Some(invitation) => invitation.delete(&conn).is_ok(),
None => false,
diff --git a/src/mail.rs b/src/mail.rs
@@ -6,8 +6,8 @@ use native_tls::{Protocol, TlsConnector};
use crate::api::EmptyResult;
use crate::auth::{encode_jwt, generate_invite_claims};
+use crate::config::MailConfig;
use crate::error::Error;
-use crate::MailConfig;
use crate::CONFIG;
fn mailer(config: &MailConfig) -> SmtpTransport {
@@ -85,7 +85,7 @@ pub fn send_invite(
let (subject, body) = get_text(
"email/send_org_invite",
json!({
- "url": CONFIG.domain,
+ "url": CONFIG.domain(),
"org_id": org_id.unwrap_or("_".to_string()),
"org_user_id": org_user_id.unwrap_or("_".to_string()),
"email": address,
@@ -101,7 +101,7 @@ pub fn send_invite_accepted(new_user_email: &str, address: &str, org_name: &str,
let (subject, body) = get_text(
"email/invite_accepted",
json!({
- "url": CONFIG.domain,
+ "url": CONFIG.domain(),
"email": new_user_email,
"org_name": org_name,
}),
@@ -114,7 +114,7 @@ pub fn send_invite_confirmed(address: &str, org_name: &str, config: &MailConfig)
let (subject, body) = get_text(
"email/invite_confirmed",
json!({
- "url": CONFIG.domain,
+ "url": CONFIG.domain(),
"org_name": org_name,
}),
)?;
diff --git a/src/main.rs b/src/main.rs
@@ -20,7 +20,6 @@ extern crate derive_more;
#[macro_use]
extern crate num_derive;
-use handlebars::Handlebars;
use rocket::{fairing::AdHoc, Rocket};
use std::{
@@ -32,11 +31,14 @@ use std::{
mod error;
mod api;
mod auth;
+mod config;
mod crypto;
mod db;
mod mail;
mod util;
+pub use config::CONFIG;
+
fn init_rocket() -> Rocket {
rocket::ignite()
.mount("/", api::web_routes())
@@ -68,7 +70,7 @@ mod migrations {
}
fn main() {
- if CONFIG.extended_logging {
+ if CONFIG.extended_logging() {
init_logging().ok();
}
@@ -99,7 +101,7 @@ fn init_logging() -> Result<(), fern::InitError> {
.level_for("multipart", log::LevelFilter::Info)
.chain(std::io::stdout());
- if let Some(log_file) = CONFIG.log_file.as_ref() {
+ if let Some(log_file) = CONFIG.log_file() {
logger = logger.chain(fern::log_file(log_file)?);
}
@@ -133,7 +135,8 @@ fn chain_syslog(logger: fern::Dispatch) -> fern::Dispatch {
}
fn check_db() {
- let path = Path::new(&CONFIG.database_url);
+ let url = CONFIG.database_url();
+ let path = Path::new(&url);
if let Some(parent) = path.parent() {
use std::fs;
@@ -153,7 +156,7 @@ fn check_db() {
fn check_rsa_keys() {
// If the RSA keys don't exist, try to create them
- if !util::file_exists(&CONFIG.private_rsa_key) || !util::file_exists(&CONFIG.public_rsa_key) {
+ if !util::file_exists(&CONFIG.private_rsa_key()) || !util::file_exists(&CONFIG.public_rsa_key()) {
info!("JWT keys don't exist, checking if OpenSSL is available...");
Command::new("openssl").arg("version").output().unwrap_or_else(|_| {
@@ -166,7 +169,7 @@ fn check_rsa_keys() {
let mut success = Command::new("openssl")
.arg("genrsa")
.arg("-out")
- .arg(&CONFIG.private_rsa_key_pem)
+ .arg(&CONFIG.private_rsa_key_pem())
.output()
.expect("Failed to create private pem file")
.status
@@ -175,11 +178,11 @@ fn check_rsa_keys() {
success &= Command::new("openssl")
.arg("rsa")
.arg("-in")
- .arg(&CONFIG.private_rsa_key_pem)
+ .arg(&CONFIG.private_rsa_key_pem())
.arg("-outform")
.arg("DER")
.arg("-out")
- .arg(&CONFIG.private_rsa_key)
+ .arg(&CONFIG.private_rsa_key())
.output()
.expect("Failed to create private der file")
.status
@@ -188,14 +191,14 @@ fn check_rsa_keys() {
success &= Command::new("openssl")
.arg("rsa")
.arg("-in")
- .arg(&CONFIG.private_rsa_key)
+ .arg(&CONFIG.private_rsa_key())
.arg("-inform")
.arg("DER")
.arg("-RSAPublicKey_out")
.arg("-outform")
.arg("DER")
.arg("-out")
- .arg(&CONFIG.public_rsa_key)
+ .arg(&CONFIG.public_rsa_key())
.output()
.expect("Failed to create public der file")
.status
@@ -211,11 +214,11 @@ fn check_rsa_keys() {
}
fn check_web_vault() {
- if !CONFIG.web_vault_enabled {
+ if !CONFIG.web_vault_enabled() {
return;
}
- let index_path = Path::new(&CONFIG.web_vault_folder).join("index.html");
+ let index_path = Path::new(&CONFIG.web_vault_folder()).join("index.html");
if !index_path.exists() {
error!("Web vault is not found. Please follow the steps in the README to install it");
@@ -232,215 +235,3 @@ fn unofficial_warning() -> AdHoc {
warn!("\\--------------------------------------------------------------------/");
})
}
-
-lazy_static! {
- // Load the config from .env or from environment variables
- static ref CONFIG: Config = Config::load();
-}
-
-#[derive(Debug)]
-pub struct MailConfig {
- smtp_host: String,
- smtp_port: u16,
- smtp_ssl: bool,
- smtp_from: String,
- smtp_from_name: String,
- smtp_username: Option<String>,
- smtp_password: Option<String>,
-}
-
-impl MailConfig {
- fn load() -> Option<Self> {
- use crate::util::{get_env, get_env_or};
-
- // When SMTP_HOST is absent, we assume the user does not want to enable it.
- let smtp_host = match get_env("SMTP_HOST") {
- Some(host) => host,
- None => return None,
- };
-
- let smtp_from = get_env("SMTP_FROM").unwrap_or_else(|| {
- error!("Please specify SMTP_FROM to enable SMTP support.");
- exit(1);
- });
-
- let smtp_from_name = get_env_or("SMTP_FROM_NAME", "Bitwarden_RS".into());
-
- let smtp_ssl = get_env_or("SMTP_SSL", true);
- let smtp_port = get_env("SMTP_PORT").unwrap_or_else(|| if smtp_ssl { 587u16 } else { 25u16 });
-
- let smtp_username = get_env("SMTP_USERNAME");
- let smtp_password = get_env("SMTP_PASSWORD").or_else(|| {
- if smtp_username.as_ref().is_some() {
- error!("SMTP_PASSWORD is mandatory when specifying SMTP_USERNAME.");
- exit(1);
- } else {
- None
- }
- });
-
- Some(MailConfig {
- smtp_host,
- smtp_port,
- smtp_ssl,
- smtp_from,
- smtp_from_name,
- smtp_username,
- smtp_password,
- })
- }
-}
-
-#[derive(Debug)]
-pub struct Config {
- database_url: String,
- icon_cache_folder: String,
- attachments_folder: String,
-
- icon_cache_ttl: u64,
- icon_cache_negttl: u64,
-
- private_rsa_key: String,
- private_rsa_key_pem: String,
- public_rsa_key: String,
-
- web_vault_folder: String,
- web_vault_enabled: bool,
-
- websocket_enabled: bool,
- websocket_url: String,
-
- extended_logging: bool,
- log_file: Option<String>,
-
- local_icon_extractor: bool,
- signups_allowed: bool,
- invitations_allowed: bool,
- admin_token: Option<String>,
- password_iterations: i32,
- show_password_hint: bool,
-
- domain: String,
- domain_set: bool,
-
- yubico_cred_set: bool,
- yubico_client_id: String,
- yubico_secret_key: String,
- yubico_server: Option<String>,
-
- mail: Option<MailConfig>,
- templates: Handlebars,
- templates_folder: String,
- reload_templates: bool,
-}
-
-fn load_templates(path: &str) -> Handlebars {
- let mut hb = Handlebars::new();
- // Error on missing params
- hb.set_strict_mode(true);
-
- macro_rules! reg {
- ($name:expr) => {{
- let template = include_str!(concat!("static/templates/", $name, ".hbs"));
- hb.register_template_string($name, template).unwrap();
- }};
- }
-
- // First register default templates here
- reg!("email/invite_accepted");
- reg!("email/invite_confirmed");
- reg!("email/pw_hint_none");
- reg!("email/pw_hint_some");
- reg!("email/send_org_invite");
-
- reg!("admin/base");
- reg!("admin/login");
- reg!("admin/page");
-
- // And then load user templates to overwrite the defaults
- // Use .hbs extension for the files
- // Templates get registered with their relative name
- hb.register_templates_directory(".hbs", path).unwrap();
-
- hb
-}
-
-impl Config {
- pub fn render_template<T: serde::ser::Serialize>(&self, name: &str, data: &T) -> Result<String, error::Error> {
- // We add this to signal the compiler not to drop the result of 'load_templates'
- let hb_owned;
-
- let hb = if CONFIG.reload_templates {
- warn!("RELOADING TEMPLATES");
- hb_owned = load_templates(&self.templates_folder);
- &hb_owned
- } else {
- &self.templates
- };
-
- hb.render(name, data).map_err(Into::into)
- }
-
- fn load() -> Self {
- use crate::util::{get_env, get_env_or};
- dotenv::dotenv().ok();
-
- let df = get_env_or("DATA_FOLDER", "data".to_string());
- let key = get_env_or("RSA_KEY_FILENAME", format!("{}/{}", &df, "rsa_key"));
-
- let domain = get_env("DOMAIN");
-
- let yubico_client_id = get_env("YUBICO_CLIENT_ID");
- let yubico_secret_key = get_env("YUBICO_SECRET_KEY");
-
- let templates_folder = get_env_or("TEMPLATES_FOLDER", format!("{}/{}", &df, "templates"));
-
- Config {
- database_url: get_env_or("DATABASE_URL", format!("{}/{}", &df, "db.sqlite3")),
- icon_cache_folder: get_env_or("ICON_CACHE_FOLDER", format!("{}/{}", &df, "icon_cache")),
- attachments_folder: get_env_or("ATTACHMENTS_FOLDER", format!("{}/{}", &df, "attachments")),
- templates: load_templates(&templates_folder),
- templates_folder,
- reload_templates: get_env_or("RELOAD_TEMPLATES", false),
-
- // icon_cache_ttl defaults to 30 days (30 * 24 * 60 * 60 seconds)
- icon_cache_ttl: get_env_or("ICON_CACHE_TTL", 2_592_000),
- // icon_cache_negttl defaults to 3 days (3 * 24 * 60 * 60 seconds)
- icon_cache_negttl: get_env_or("ICON_CACHE_NEGTTL", 259_200),
-
- private_rsa_key: format!("{}.der", &key),
- private_rsa_key_pem: format!("{}.pem", &key),
- public_rsa_key: format!("{}.pub.der", &key),
-
- web_vault_folder: get_env_or("WEB_VAULT_FOLDER", "web-vault/".into()),
- web_vault_enabled: get_env_or("WEB_VAULT_ENABLED", true),
-
- websocket_enabled: get_env_or("WEBSOCKET_ENABLED", false),
- websocket_url: format!(
- "{}:{}",
- get_env_or("WEBSOCKET_ADDRESS", "0.0.0.0".to_string()),
- get_env_or("WEBSOCKET_PORT", 3012)
- ),
-
- extended_logging: get_env_or("EXTENDED_LOGGING", true),
- log_file: get_env("LOG_FILE"),
-
- local_icon_extractor: get_env_or("LOCAL_ICON_EXTRACTOR", false),
- signups_allowed: get_env_or("SIGNUPS_ALLOWED", true),
- admin_token: get_env("ADMIN_TOKEN"),
- invitations_allowed: get_env_or("INVITATIONS_ALLOWED", true),
- password_iterations: get_env_or("PASSWORD_ITERATIONS", 100_000),
- show_password_hint: get_env_or("SHOW_PASSWORD_HINT", true),
-
- domain_set: domain.is_some(),
- domain: domain.unwrap_or("http://localhost".into()),
-
- yubico_cred_set: yubico_client_id.is_some() && yubico_secret_key.is_some(),
- yubico_client_id: yubico_client_id.unwrap_or("00000".into()),
- yubico_secret_key: yubico_secret_key.unwrap_or("AAAAAAA".into()),
- yubico_server: get_env("YUBICO_SERVER"),
-
- mail: MailConfig::load(),
- }
- }
-}
diff --git a/src/util.rs b/src/util.rs
@@ -2,8 +2,8 @@
// Web Headers and caching
//
use rocket::fairing::{Fairing, Info, Kind};
-use rocket::{Request, Response};
use rocket::response::{self, Responder};
+use rocket::{Request, Response};
pub struct AppHeaders();