diff --git a/Cargo.lock b/Cargo.lock
index 1242514e7c4e51f27895fae1aa959bc0241267c1..672289490961e4d3282ea8cf64bba40ce05bdca5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,6 +17,12 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
 
+[[package]]
+name = "ahash"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
+
 [[package]]
 name = "aho-corasick"
 version = "0.7.15"
@@ -44,8 +50,8 @@ version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
 dependencies = [
- "quote 1.0.9",
- "syn 1.0.60",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -87,7 +93,7 @@ dependencies = [
  "futures-lite",
  "num_cpus",
  "once_cell",
- "tokio",
+ "tokio 0.2.25",
 ]
 
 [[package]]
@@ -156,6 +162,27 @@ dependencies = [
  "wasm-bindgen-futures",
 ]
 
+[[package]]
+name = "async-stream"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "async-task"
 version = "4.0.3"
@@ -164,13 +191,13 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
 
 [[package]]
 name = "async-trait"
-version = "0.1.42"
+version = "0.1.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
+checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -360,11 +387,11 @@ dependencies = [
 
 [[package]]
 name = "bson"
-version = "1.1.0"
+version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c11f16001d679cb13d14b2c93c7d0fa13bb484a87c34a6c4c39707ad936499b5"
+checksum = "38b6553abdb9d2d8f262f0b5bccf807321d5b7d1a12796bcede8e1f150e85f2e"
 dependencies = [
- "base64 0.12.3",
+ "base64 0.13.0",
  "chrono",
  "hex",
  "lazy_static",
@@ -372,6 +399,7 @@ dependencies = [
  "rand 0.7.3",
  "serde",
  "serde_json",
+ "uuid",
 ]
 
 [[package]]
@@ -483,6 +511,17 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "cookie"
+version = "0.15.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d"
+dependencies = [
+ "percent-encoding",
+ "time 0.2.25",
+ "version_check",
+]
+
 [[package]]
 name = "core-foundation"
 version = "0.9.1"
@@ -532,8 +571,8 @@ version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19"
 dependencies = [
- "quote 1.0.9",
- "syn 1.0.60",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -564,10 +603,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "strsim 0.9.3",
- "syn 1.0.60",
+ "syn",
 ]
 
 [[package]]
@@ -577,8 +616,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
 dependencies = [
  "darling_core",
- "quote 1.0.9",
- "syn 1.0.60",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "dashmap"
+version = "4.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
+dependencies = [
+ "cfg-if 1.0.0",
+ "num_cpus",
 ]
 
 [[package]]
@@ -587,9 +636,9 @@ version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -597,8 +646,18 @@ name = "devise"
 version = "0.3.0"
 source = "git+https://github.com/SergioBenitez/Devise.git?rev=3648468#3648468a9ede9ca896cd35bc1eb818c7a9fb3047"
 dependencies = [
- "devise_codegen",
- "devise_core",
+ "devise_codegen 0.3.0",
+ "devise_core 0.3.0",
+]
+
+[[package]]
+name = "devise"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595"
+dependencies = [
+ "devise_codegen 0.3.1",
+ "devise_core 0.3.1",
 ]
 
 [[package]]
@@ -606,8 +665,18 @@ name = "devise_codegen"
 version = "0.3.0"
 source = "git+https://github.com/SergioBenitez/Devise.git?rev=3648468#3648468a9ede9ca896cd35bc1eb818c7a9fb3047"
 dependencies = [
- "devise_core",
- "quote 1.0.9",
+ "devise_core 0.3.0",
+ "quote",
+]
+
+[[package]]
+name = "devise_codegen"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2"
+dependencies = [
+ "devise_core 0.3.1",
+ "quote",
 ]
 
 [[package]]
@@ -616,10 +685,23 @@ version = "0.3.0"
 source = "git+https://github.com/SergioBenitez/Devise.git?rev=3648468#3648468a9ede9ca896cd35bc1eb818c7a9fb3047"
 dependencies = [
  "bitflags",
- "proc-macro2 1.0.24",
+ "proc-macro2",
+ "proc-macro2-diagnostics",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "devise_core"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0"
+dependencies = [
+ "bitflags",
+ "proc-macro2",
  "proc-macro2-diagnostics",
- "quote 1.0.9",
- "syn 1.0.60",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -674,9 +756,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
 dependencies = [
  "heck",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -708,10 +790,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4"
 dependencies = [
  "proc-macro-error",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "rustversion",
- "syn 1.0.60",
+ "syn",
  "synstructure",
 ]
 
@@ -738,10 +820,11 @@ dependencies = [
 
 [[package]]
 name = "figment"
-version = "0.10.2"
+version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3add2ec7727c9584a0ce75ee3c0f54f0ab692c7934450cc3a0287251e3a4f06"
+checksum = "790b4292c72618abbab50f787a477014fe15634f96291de45672ce46afe122df"
 dependencies = [
+ "atomic",
  "pear",
  "serde",
  "toml",
@@ -850,17 +933,6 @@ dependencies = [
  "futures-util",
 ]
 
-[[package]]
-name = "futures-intrusive"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc1529d07bd55fa54fc6c2d8460f621cfde0ae3fd2b96b2fa7eb4883478e1703"
-dependencies = [
- "futures-core",
- "lock_api 0.3.4",
- "parking_lot 0.10.2",
-]
-
 [[package]]
 name = "futures-io"
 version = "0.3.12"
@@ -889,9 +961,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
 dependencies = [
  "proc-macro-hack",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -909,6 +981,12 @@ dependencies = [
  "once_cell",
 ]
 
+[[package]]
+name = "futures-timer"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
+
 [[package]]
 name = "futures-util"
 version = "0.3.12"
@@ -929,6 +1007,19 @@ dependencies = [
  "slab",
 ]
 
+[[package]]
+name = "generator"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee"
+dependencies = [
+ "cc",
+ "libc",
+ "log",
+ "rustversion",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "generic-array"
 version = "0.12.3"
@@ -995,6 +1086,23 @@ dependencies = [
  "web-sys",
 ]
 
+[[package]]
+name = "governor"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06c5d2f987ee8f6dff3fa1a352058dc59b990e447e4c7846aa7d804971314f7b"
+dependencies = [
+ "dashmap",
+ "futures",
+ "futures-timer",
+ "no-std-compat",
+ "nonzero_ext",
+ "parking_lot",
+ "quanta",
+ "rand 0.8.3",
+ "smallvec",
+]
+
 [[package]]
 name = "h2"
 version = "0.2.7"
@@ -1009,12 +1117,31 @@ dependencies = [
  "http",
  "indexmap",
  "slab",
- "tokio",
- "tokio-util",
+ "tokio 0.2.25",
+ "tokio-util 0.3.1",
  "tracing",
  "tracing-futures",
 ]
 
+[[package]]
+name = "h2"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726"
+dependencies = [
+ "bytes 1.0.1",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio 1.9.0",
+ "tokio-util 0.6.7",
+ "tracing",
+]
+
 [[package]]
 name = "handlebars"
 version = "3.5.2"
@@ -1029,6 +1156,16 @@ dependencies = [
  "serde_json",
 ]
 
+[[package]]
+name = "hashbrown"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
+dependencies = [
+ "ahash",
+ "autocfg 1.0.1",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.9.1"
@@ -1062,8 +1199,7 @@ checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
 [[package]]
 name = "hive_pubsub"
 version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ac4635b1e9faf304ccb33c2f0edbc615030e40d249183281fc788ef20ef5c76"
+source = "git+https://gitlab.insrt.uk/insert/hive?rev=a89826df2b30166220e68a6ed01a58b751456604#a89826df2b30166220e68a6ed01a58b751456604"
 dependencies = [
  "futures",
  "many-to-many",
@@ -1115,11 +1251,22 @@ dependencies = [
  "http",
 ]
 
+[[package]]
+name = "http-body"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9"
+dependencies = [
+ "bytes 1.0.1",
+ "http",
+ "pin-project-lite 0.2.4",
+]
+
 [[package]]
 name = "httparse"
-version = "1.3.5"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
+checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68"
 
 [[package]]
 name = "httpdate"
@@ -1127,6 +1274,12 @@ version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
 
+[[package]]
+name = "httpdate"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
+
 [[package]]
 name = "humantime"
 version = "1.3.0"
@@ -1146,15 +1299,39 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2",
+ "h2 0.2.7",
  "http",
- "http-body",
+ "http-body 0.3.1",
  "httparse",
- "httpdate",
+ "httpdate 0.3.2",
  "itoa",
  "pin-project 1.0.5",
- "socket2",
- "tokio",
+ "socket2 0.3.19",
+ "tokio 0.2.25",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper"
+version = "0.14.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11"
+dependencies = [
+ "bytes 1.0.1",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2 0.3.3",
+ "http",
+ "http-body 0.4.2",
+ "httparse",
+ "httpdate 1.0.1",
+ "itoa",
+ "pin-project-lite 0.2.4",
+ "socket2 0.4.1",
+ "tokio 1.9.0",
  "tower-service",
  "tracing",
  "want",
@@ -1168,10 +1345,10 @@ checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6"
 dependencies = [
  "bytes 0.5.6",
  "futures-util",
- "hyper",
+ "hyper 0.13.10",
  "log",
  "rustls 0.18.1",
- "tokio",
+ "tokio 0.2.25",
  "tokio-rustls 0.14.1",
  "webpki",
 ]
@@ -1183,29 +1360,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed"
 dependencies = [
  "bytes 0.5.6",
- "hyper",
+ "hyper 0.13.10",
  "native-tls",
- "tokio",
+ "tokio 0.2.25",
  "tokio-tls",
 ]
 
-[[package]]
-name = "hyperx"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82566a1ace7f56f604d83b7b2c259c78e243d99c565f23d7b4ae34466442c5a2"
-dependencies = [
- "base64 0.13.0",
- "bytes 1.0.1",
- "http",
- "httparse",
- "httpdate",
- "language-tags",
- "mime",
- "percent-encoding",
- "unicase",
-]
-
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -1242,7 +1402,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
 dependencies = [
  "autocfg 1.0.1",
- "hashbrown",
+ "hashbrown 0.9.1",
+ "serde",
 ]
 
 [[package]]
@@ -1284,7 +1445,7 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
 dependencies = [
- "socket2",
+ "socket2 0.3.19",
  "widestring",
  "winapi 0.3.9",
  "winreg 0.6.2",
@@ -1336,12 +1497,6 @@ dependencies = [
  "log",
 ]
 
-[[package]]
-name = "language-tags"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
-
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -1350,13 +1505,14 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "lettre"
-version = "0.10.0-alpha.5"
+version = "0.10.0-rc.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34f3dd8d917156976a47ef421a2e771423d6da95e93696f1814e76768625c162"
+checksum = "d8697ded52353bdd6fec234b3135972433397e86d0493d9fc38fbf407b7c106a"
 dependencies = [
  "base64 0.13.0",
+ "fastrand",
  "hostname",
- "hyperx",
+ "httpdate 1.0.1",
  "idna",
  "mime",
  "native-tls",
@@ -1364,18 +1520,14 @@ dependencies = [
  "once_cell",
  "quoted_printable",
  "r2d2",
- "rand 0.8.3",
  "regex",
- "serde",
- "serde_json",
- "uuid",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.86"
+version = "0.2.98"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
 
 [[package]]
 name = "linked-hash-map"
@@ -1392,15 +1544,6 @@ dependencies = [
  "memchr",
 ]
 
-[[package]]
-name = "lock_api"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
-dependencies = [
- "scopeguard",
-]
-
 [[package]]
 name = "lock_api"
 version = "0.4.2"
@@ -1420,6 +1563,19 @@ dependencies = [
  "value-bag",
 ]
 
+[[package]]
+name = "loom"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2111607c723d7857e0d8299d5ce7a0bf4b844d3e44f8de136b13da513eaf8fc4"
+dependencies = [
+ "cfg-if 1.0.0",
+ "generator",
+ "scoped-tls",
+ "serde",
+ "serde_json",
+]
+
 [[package]]
 name = "lru-cache"
 version = "0.1.2"
@@ -1515,12 +1671,25 @@ dependencies = [
  "kernel32-sys",
  "libc",
  "log",
- "miow",
+ "miow 0.2.2",
  "net2",
  "slab",
  "winapi 0.2.8",
 ]
 
+[[package]]
+name = "mio"
+version = "0.7.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
+dependencies = [
+ "libc",
+ "log",
+ "miow 0.3.7",
+ "ntapi",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "mio-uds"
 version = "0.6.8"
@@ -1529,7 +1698,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
 dependencies = [
  "iovec",
  "libc",
- "mio",
+ "mio 0.6.23",
 ]
 
 [[package]]
@@ -1544,11 +1713,20 @@ dependencies = [
  "ws2_32-sys",
 ]
 
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "mongodb"
-version = "1.1.1"
+version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a726495d7418c4579ecc9465b53ddade8187c0299e5db0e7250672b67d196913"
+checksum = "af18a0f10c2355e5b9382603076c84159923dd434d0287fe6bf9c1a656dbc09c"
 dependencies = [
  "async-trait",
  "base64 0.11.0",
@@ -1558,7 +1736,6 @@ dependencies = [
  "derivative",
  "err-derive",
  "futures",
- "futures-intrusive",
  "hex",
  "hmac",
  "lazy_static",
@@ -1574,12 +1751,12 @@ dependencies = [
  "serde_with",
  "sha-1 0.8.2",
  "sha2",
- "socket2",
+ "socket2 0.3.19",
  "stringprep",
  "strsim 0.10.0",
  "take_mut",
  "time 0.1.44",
- "tokio",
+ "tokio 0.2.25",
  "tokio-rustls 0.13.1",
  "trust-dns-proto",
  "trust-dns-resolver",
@@ -1590,6 +1767,26 @@ dependencies = [
  "webpki-roots 0.18.0",
 ]
 
+[[package]]
+name = "multer"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "408327e2999b839cd1af003fc01b2019a6c10a1361769542203f6fedc5179680"
+dependencies = [
+ "bytes 1.0.1",
+ "encoding_rs",
+ "futures-util",
+ "http",
+ "httparse",
+ "log",
+ "mime",
+ "spin 0.9.2",
+ "tokio 1.9.0",
+ "tokio-util 0.6.7",
+ "twoway",
+ "version_check",
+]
+
 [[package]]
 name = "nanoid"
 version = "0.3.0"
@@ -1659,6 +1856,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "no-std-compat"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
+dependencies = [
+ "hashbrown 0.8.2",
+]
+
 [[package]]
 name = "nom"
 version = "6.1.0"
@@ -1670,6 +1876,21 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "nonzero_ext"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44a1290799eababa63ea60af0cbc3f03363e328e58f32fb0294798ed3e85f444"
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "num-integer"
 version = "0.1.44"
@@ -1716,9 +1937,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e"
 dependencies = [
  "proc-macro-crate",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -1780,9 +2001,9 @@ dependencies = [
 
 [[package]]
 name = "os_info"
-version = "2.0.8"
+version = "3.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2cc1b4330bb29087e791ae2a5cf56be64fb8946a4ff5aec2ba11c6ca51f5d60"
+checksum = "b3d2536ab8ff7605e8dc7044ec2f3eb0d49750cb559af9e5373c4564a3706cdd"
 dependencies = [
  "log",
  "winapi 0.3.9",
@@ -1794,16 +2015,6 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
 
-[[package]]
-name = "parking_lot"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
-dependencies = [
- "lock_api 0.3.4",
- "parking_lot_core 0.7.2",
-]
-
 [[package]]
 name = "parking_lot"
 version = "0.11.1"
@@ -1811,22 +2022,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
 dependencies = [
  "instant",
- "lock_api 0.4.2",
- "parking_lot_core 0.8.2",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
-dependencies = [
- "cfg-if 0.1.10",
- "cloudabi",
- "libc",
- "redox_syscall 0.1.57",
- "smallvec",
- "winapi 0.3.9",
+ "lock_api",
+ "parking_lot_core",
 ]
 
 [[package]]
@@ -1855,9 +2052,9 @@ dependencies = [
 
 [[package]]
 name = "pear"
-version = "0.2.0"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09f612cbd0f9dd03f5dd28a191c48e4148c3b027e41207b32eee130373c6c941"
+checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702"
 dependencies = [
  "inlinable_string",
  "pear_codegen",
@@ -1866,14 +2063,14 @@ dependencies = [
 
 [[package]]
 name = "pear_codegen"
-version = "0.2.0"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "602cf1780ee9bbca663ea75769e05643e16fe87d7c8ac9f4f385a2ed8940a75c"
+checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0"
 dependencies = [
- "proc-macro2 1.0.24",
+ "proc-macro2",
  "proc-macro2-diagnostics",
- "quote 1.0.9",
- "syn 1.0.60",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -1909,9 +2106,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
 dependencies = [
  "pest",
  "pest_meta",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -1949,9 +2146,9 @@ version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -1960,9 +2157,9 @@ version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -2024,9 +2221,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
  "proc-macro-error-attr",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
  "version_check",
 ]
 
@@ -2036,8 +2233,8 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "version_check",
 ]
 
@@ -2055,20 +2252,11 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
 
 [[package]]
 name = "proc-macro2"
-version = "0.4.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-dependencies = [
- "unicode-xid 0.1.0",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.24"
+version = "1.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
 dependencies = [
- "unicode-xid 0.2.1",
+ "unicode-xid",
 ]
 
 [[package]]
@@ -2077,9 +2265,9 @@ version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
  "version_check",
  "yansi",
 ]
@@ -2093,11 +2281,21 @@ dependencies = [
  "cfg-if 1.0.0",
  "fnv",
  "lazy_static",
- "parking_lot 0.11.1",
+ "parking_lot",
  "regex",
  "thiserror",
 ]
 
+[[package]]
+name = "quanta"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d98dc777a7a39b76b1a26ae9d3f691f4c1bc0455090aa0b64dfa8cb7fc34c135"
+dependencies = [
+ "libc",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "quick-error"
 version = "1.2.3"
@@ -2110,22 +2308,13 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
 
-[[package]]
-name = "quote"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
-dependencies = [
- "proc-macro2 0.4.30",
-]
-
 [[package]]
 name = "quote"
 version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
 dependencies = [
- "proc-macro2 1.0.24",
+ "proc-macro2",
 ]
 
 [[package]]
@@ -2141,7 +2330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f"
 dependencies = [
  "log",
- "parking_lot 0.11.1",
+ "parking_lot",
  "scheduled-thread-pool",
 ]
 
@@ -2165,7 +2354,7 @@ dependencies = [
  "rand_isaac",
  "rand_jitter",
  "rand_os",
- "rand_pcg",
+ "rand_pcg 0.1.2",
  "rand_xorshift",
  "winapi 0.3.9",
 ]
@@ -2181,6 +2370,7 @@ dependencies = [
  "rand_chacha 0.2.2",
  "rand_core 0.5.1",
  "rand_hc 0.2.0",
+ "rand_pcg 0.2.1",
 ]
 
 [[package]]
@@ -2330,6 +2520,15 @@ dependencies = [
  "rand_core 0.4.2",
 ]
 
+[[package]]
+name = "rand_pcg"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
 [[package]]
 name = "rand_xorshift"
 version = "0.1.1"
@@ -2341,8 +2540,8 @@ dependencies = [
 
 [[package]]
 name = "rauth"
-version = "0.2.7-patch.0"
-source = "git+https://gitlab.insrt.uk/insert/rauth?rev=00d3c3dff51cf3242a7d4adda4c5184c97fa2a03#00d3c3dff51cf3242a7d4adda4c5184c97fa2a03"
+version = "0.3.0"
+source = "git+https://gitlab.insrt.uk/insert/rauth?rev=51546e5a1ba0dfe3ec3bd0b060fa51fc3102c96f#51546e5a1ba0dfe3ec3bd0b060fa51fc3102c96f"
 dependencies = [
  "chrono",
  "handlebars",
@@ -2353,12 +2552,11 @@ dependencies = [
  "nanoid 0.3.0",
  "regex",
  "reqwest",
- "rocket",
+ "rocket 0.5.0-dev",
  "rocket_contrib",
  "rust-argon2",
  "serde",
  "serde_json",
- "tokio",
  "ulid",
  "validator",
 ]
@@ -2402,9 +2600,9 @@ version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -2446,8 +2644,8 @@ dependencies = [
  "futures-core",
  "futures-util",
  "http",
- "http-body",
- "hyper",
+ "http-body 0.3.1",
+ "hyper 0.13.10",
  "hyper-rustls",
  "hyper-tls",
  "ipnet",
@@ -2463,7 +2661,7 @@ dependencies = [
  "serde",
  "serde_json",
  "serde_urlencoded",
- "tokio",
+ "tokio 0.2.25",
  "tokio-rustls 0.14.1",
  "tokio-tls",
  "url",
@@ -2513,8 +2711,8 @@ dependencies = [
  "rauth",
  "regex",
  "reqwest",
- "rocket",
- "rocket_contrib",
+ "rocket 0.5.0-rc.1",
+ "rocket-governor",
  "rocket_cors",
  "rocket_prometheus",
  "serde",
@@ -2535,7 +2733,7 @@ dependencies = [
  "cc",
  "libc",
  "once_cell",
- "spin",
+ "spin 0.5.2",
  "untrusted 0.7.1",
  "web-sys",
  "winapi 0.3.9",
@@ -2556,30 +2754,96 @@ dependencies = [
  "log",
  "memchr",
  "num_cpus",
- "parking_lot 0.11.1",
+ "parking_lot",
  "rand 0.7.3",
  "ref-cast",
- "rocket_codegen",
- "rocket_http",
+ "rocket_codegen 0.5.0-dev",
+ "rocket_http 0.5.0-dev",
+ "serde",
+ "state 0.4.2",
+ "time 0.2.25",
+ "tokio 0.2.25",
+ "ubyte",
+ "version_check",
+ "yansi",
+]
+
+[[package]]
+name = "rocket"
+version = "0.5.0-rc.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a71c18c42a0eb15bf3816831caf0dad11e7966f2a41aaf486a701979c4dd1f2"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "atomic",
+ "atty",
+ "binascii",
+ "bytes 1.0.1",
+ "either",
+ "figment",
+ "futures",
+ "indexmap",
+ "log",
+ "memchr",
+ "multer",
+ "num_cpus",
+ "parking_lot",
+ "pin-project-lite 0.2.4",
+ "rand 0.8.3",
+ "ref-cast",
+ "rocket_codegen 0.5.0-rc.1",
+ "rocket_http 0.5.0-rc.1",
  "serde",
- "state",
+ "serde_json",
+ "state 0.5.2",
+ "tempfile",
  "time 0.2.25",
- "tokio",
+ "tokio 1.9.0",
+ "tokio-stream",
+ "tokio-util 0.6.7",
  "ubyte",
  "version_check",
  "yansi",
 ]
 
+[[package]]
+name = "rocket-governor"
+version = "0.0.1-rc.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a7603d1d66d1c4c41997f1f80fb624c16fd8a063a0f562d6e511e7eec4d26d2"
+dependencies = [
+ "governor",
+ "lazy_static",
+ "rocket 0.5.0-rc.1",
+]
+
 [[package]]
 name = "rocket_codegen"
 version = "0.5.0-dev"
 source = "git+https://github.com/SergioBenitez/Rocket?rev=031948c1daaa146128d8a435be116476f2adde00#031948c1daaa146128d8a435be116476f2adde00"
 dependencies = [
- "devise",
+ "devise 0.3.0",
+ "glob",
+ "indexmap",
+ "quote",
+ "rocket_http 0.5.0-dev",
+]
+
+[[package]]
+name = "rocket_codegen"
+version = "0.5.0-rc.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66f5fa462f7eb958bba8710c17c5d774bbbd59809fa76fb1957af7e545aea8bb"
+dependencies = [
+ "devise 0.3.1",
  "glob",
  "indexmap",
- "quote 1.0.9",
- "rocket_http",
+ "proc-macro2",
+ "quote",
+ "rocket_http 0.5.0-rc.1",
+ "syn",
+ "unicode-xid",
 ]
 
 [[package]]
@@ -2588,10 +2852,10 @@ version = "0.5.0-dev"
 source = "git+https://github.com/SergioBenitez/Rocket?rev=031948c1daaa146128d8a435be116476f2adde00#031948c1daaa146128d8a435be116476f2adde00"
 dependencies = [
  "log",
- "rocket",
+ "rocket 0.5.0-dev",
  "serde",
  "serde_json",
- "tokio",
+ "tokio 0.2.25",
 ]
 
 [[package]]
@@ -2601,7 +2865,7 @@ source = "git+https://github.com/insertish/rocket_cors?branch=master#a301882a3ae
 dependencies = [
  "log",
  "regex",
- "rocket",
+ "rocket 0.5.0-dev",
  "serde",
  "serde_derive",
  "unicase",
@@ -2614,33 +2878,61 @@ name = "rocket_http"
 version = "0.5.0-dev"
 source = "git+https://github.com/SergioBenitez/Rocket?rev=031948c1daaa146128d8a435be116476f2adde00#031948c1daaa146128d8a435be116476f2adde00"
 dependencies = [
- "cookie",
+ "cookie 0.15.0-dev",
  "either",
  "http",
- "hyper",
+ "hyper 0.13.10",
  "indexmap",
  "log",
  "mime",
- "parking_lot 0.11.1",
+ "parking_lot",
  "pear",
  "percent-encoding",
  "ref-cast",
  "smallvec",
- "state",
+ "state 0.4.2",
  "time 0.2.25",
- "tokio",
+ "tokio 0.2.25",
  "uncased",
- "unicode-xid 0.2.1",
+ "unicode-xid",
  "version_check",
 ]
 
+[[package]]
+name = "rocket_http"
+version = "0.5.0-rc.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23c8b7d512d2fcac2316ebe590cde67573844b99e6cc9ee0f53375fa16e25ebd"
+dependencies = [
+ "cookie 0.15.1",
+ "either",
+ "http",
+ "hyper 0.14.11",
+ "indexmap",
+ "log",
+ "memchr",
+ "mime",
+ "parking_lot",
+ "pear",
+ "percent-encoding",
+ "pin-project-lite 0.2.4",
+ "ref-cast",
+ "serde",
+ "smallvec",
+ "stable-pattern",
+ "state 0.5.2",
+ "time 0.2.25",
+ "tokio 1.9.0",
+ "uncased",
+]
+
 [[package]]
 name = "rocket_prometheus"
 version = "0.7.0"
 source = "git+https://github.com/insertish/rocket_prometheus?rev=3d825aedb42793246c306a81fe67c5b187948983#3d825aedb42793246c306a81fe67c5b187948983"
 dependencies = [
  "prometheus",
- "rocket",
+ "rocket 0.5.0-dev",
 ]
 
 [[package]]
@@ -2730,9 +3022,15 @@ version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7"
 dependencies = [
- "parking_lot 0.11.1",
+ "parking_lot",
 ]
 
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
@@ -2811,9 +3109,9 @@ version = "1.0.123"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -2857,9 +3155,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1197ff7de45494f290c1e3e1a6f80e108974681984c87a3e480991ef3d0f1950"
 dependencies = [
  "darling",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -2937,12 +3235,37 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
+[[package]]
+name = "socket2"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad"
+dependencies = [
+ "libc",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "spin"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
+[[package]]
+name = "spin"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5"
+
+[[package]]
+name = "stable-pattern"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "standback"
 version = "0.2.15"
@@ -2958,6 +3281,15 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
 
+[[package]]
+name = "state"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cf4f5369e6d3044b5e365c9690f451516ac8f0954084622b49ea3fde2f6de5"
+dependencies = [
+ "loom",
+]
+
 [[package]]
 name = "stdweb"
 version = "0.4.20"
@@ -2978,11 +3310,11 @@ version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "serde",
  "serde_derive",
- "syn 1.0.60",
+ "syn",
 ]
 
 [[package]]
@@ -2992,13 +3324,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
 dependencies = [
  "base-x",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "serde",
  "serde_derive",
  "serde_json",
  "sha1",
- "syn 1.0.60",
+ "syn",
 ]
 
 [[package]]
@@ -3037,24 +3369,13 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
 
 [[package]]
 name = "syn"
-version = "0.15.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
-dependencies = [
- "proc-macro2 0.4.30",
- "quote 0.6.13",
- "unicode-xid 0.1.0",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.60"
+version = "1.0.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
+checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "unicode-xid 0.2.1",
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
 ]
 
 [[package]]
@@ -3063,10 +3384,10 @@ version = "0.12.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
- "unicode-xid 0.2.1",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
 ]
 
 [[package]]
@@ -3119,9 +3440,9 @@ version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -3176,10 +3497,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
 dependencies = [
  "proc-macro-hack",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "standback",
- "syn 1.0.60",
+ "syn",
 ]
 
 [[package]]
@@ -3210,13 +3531,32 @@ dependencies = [
  "lazy_static",
  "libc",
  "memchr",
- "mio",
+ "mio 0.6.23",
  "mio-uds",
  "num_cpus",
  "pin-project-lite 0.1.11",
  "signal-hook-registry",
  "slab",
- "tokio-macros",
+ "tokio-macros 0.2.6",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "tokio"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c"
+dependencies = [
+ "autocfg 1.0.1",
+ "bytes 1.0.1",
+ "libc",
+ "memchr",
+ "mio 0.7.13",
+ "num_cpus",
+ "once_cell",
+ "pin-project-lite 0.2.4",
+ "signal-hook-registry",
+ "tokio-macros 1.3.0",
  "winapi 0.3.9",
 ]
 
@@ -3226,9 +3566,20 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -3239,7 +3590,7 @@ checksum = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4"
 dependencies = [
  "futures-core",
  "rustls 0.17.0",
- "tokio",
+ "tokio 0.2.25",
  "webpki",
 ]
 
@@ -3251,10 +3602,21 @@ checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a"
 dependencies = [
  "futures-core",
  "rustls 0.18.1",
- "tokio",
+ "tokio 0.2.25",
  "webpki",
 ]
 
+[[package]]
+name = "tokio-stream"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
+dependencies = [
+ "futures-core",
+ "pin-project-lite 0.2.4",
+ "tokio 1.9.0",
+]
+
 [[package]]
 name = "tokio-tls"
 version = "0.3.1"
@@ -3262,7 +3624,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
 dependencies = [
  "native-tls",
- "tokio",
+ "tokio 0.2.25",
 ]
 
 [[package]]
@@ -3276,7 +3638,21 @@ dependencies = [
  "futures-sink",
  "log",
  "pin-project-lite 0.1.11",
- "tokio",
+ "tokio 0.2.25",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592"
+dependencies = [
+ "bytes 1.0.1",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite 0.2.4",
+ "tokio 1.9.0",
 ]
 
 [[package]]
@@ -3341,7 +3717,7 @@ dependencies = [
  "rand 0.7.3",
  "smallvec",
  "thiserror",
- "tokio",
+ "tokio 0.2.25",
  "url",
 ]
 
@@ -3361,7 +3737,7 @@ dependencies = [
  "resolv-conf",
  "smallvec",
  "thiserror",
- "tokio",
+ "tokio 0.2.25",
  "trust-dns-proto",
 ]
 
@@ -3390,15 +3766,25 @@ dependencies = [
  "utf-8",
 ]
 
+[[package]]
+name = "twoway"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47"
+dependencies = [
+ "memchr",
+ "unchecked-index",
+]
+
 [[package]]
 name = "typed-builder"
-version = "0.3.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e38507a437aef3b8ead39616219615ff9320d0eb0907f0dce51ea0474889cc6"
+checksum = "dfc955f27acc7a547f328f52f4a5a568986a31efec2fc6de865279f3995787b9"
 dependencies = [
- "proc-macro2 0.4.30",
- "quote 0.6.13",
- "syn 0.15.44",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -3435,13 +3821,20 @@ dependencies = [
 
 [[package]]
 name = "uncased"
-version = "0.9.3"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "369fa7fd7969c5373541d3c9a40dc1b76ce676fc87aba30d87c0ad3b97fad179"
+checksum = "5baeed7327e25054889b9bd4f975f32e5f4c5d434042d59ab6cd4142c0a76ed0"
 dependencies = [
+ "serde",
  "version_check",
 ]
 
+[[package]]
+name = "unchecked-index"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
+
 [[package]]
 name = "unicase"
 version = "2.6.0"
@@ -3485,12 +3878,6 @@ version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
 
-[[package]]
-name = "unicode-xid"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
-
 [[package]]
 name = "unicode-xid"
 version = "0.2.1"
@@ -3568,10 +3955,10 @@ dependencies = [
  "if_chain",
  "lazy_static",
  "proc-macro-error",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
+ "proc-macro2",
+ "quote",
  "regex",
- "syn 1.0.60",
+ "syn",
  "validator_types",
 ]
 
@@ -3657,9 +4044,9 @@ dependencies = [
  "bumpalo",
  "lazy_static",
  "log",
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
  "wasm-bindgen-shared",
 ]
 
@@ -3681,7 +4068,7 @@ version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
 dependencies = [
- "quote 1.0.9",
+ "quote",
  "wasm-bindgen-macro-support",
 ]
 
@@ -3691,9 +4078,9 @@ version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
 dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.9",
- "syn 1.0.60",
+ "proc-macro2",
+ "quote",
+ "syn",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -3715,7 +4102,7 @@ dependencies = [
  "erased-serde",
  "futures",
  "http",
- "hyper",
+ "hyper 0.13.10",
  "hyper-tls",
  "lazy_static",
  "log",
diff --git a/Cargo.toml b/Cargo.toml
index 832d19c2cab6bc3cee81dd8f92dd5a521a7fcf2f..9454cb86f64a185862444ede3a6be1f0abe22a80 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,17 +32,17 @@ serde_json = "1.0.57"
 lazy_static = "1.4.0"
 urlencoding = "1.1.1"
 many-to-many = "0.1.2"
-lettre = "0.10.0-alpha.1"
+lettre = "0.10.0-alpha.4"
+rocket-governor = "0.0.1-rc.9"
 reqwest = { version = "0.10.8", features = ["json"] }
 serde = { version = "1.0.115", features = ["derive"] }
 validator = { version = "0.11", features = ["derive"] }
 ctrlc = { version = "3.0", features = ["termination"] }
-hive_pubsub = { version = "0.4.4", features = ["mongo"] }
 async-std = { version = "1.8.0", features = ["tokio02", "attributes"] }
 async-tungstenite = { version = "0.10.0", features = ["async-std-runtime"] }
+rocket = { version = "0.5.0-rc.1", default-features = false, features = ["json"] }
 rocket_cors = { git = "https://github.com/insertish/rocket_cors", branch = "master" }
-mongodb = { version = "1.1.1", features = ["tokio-runtime"], default-features = false }
-rauth = { git = "https://gitlab.insrt.uk/insert/rauth", rev = "00d3c3dff51cf3242a7d4adda4c5184c97fa2a03" }
-rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", rev = "031948c1daaa146128d8a435be116476f2adde00" }
+mongodb = { version = "1.2.2", features = ["tokio-runtime"], default-features = false }
+rauth = { git = "https://gitlab.insrt.uk/insert/rauth", rev = "51546e5a1ba0dfe3ec3bd0b060fa51fc3102c96f" }
 rocket_prometheus = { git = "https://github.com/insertish/rocket_prometheus", rev = "3d825aedb42793246c306a81fe67c5b187948983" }
-rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "031948c1daaa146128d8a435be116476f2adde00", default-features = false }
+hive_pubsub = { git = "https://gitlab.insrt.uk/insert/hive", rev = "a89826df2b30166220e68a6ed01a58b751456604", features = ["mongo"] }
diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs
index aa17af67096f5fafa489e12cfef90bfd20c9c1e9..1e1e0a7d0f42c0c3467c31817790103c042bb181 100644
--- a/src/database/entities/channel.rs
+++ b/src/database/entities/channel.rs
@@ -9,7 +9,7 @@ use mongodb::{
     bson::{doc, to_document, Document},
     options::FindOptions,
 };
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -139,7 +139,7 @@ impl Channel {
         Ok(())
     }
 
-    pub async fn publish_update(&self, data: JsonValue) -> Result<()> {
+    pub async fn publish_update(&self, data: Value) -> Result<()> {
         let id = self.id().to_string();
         ClientboundNotification::ChannelUpdate {
             id: id.clone(),
diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs
index 86d810ebe3dc2d28ea7e538e143e8bfaaf0971a7..4e8192a4f82f62d6bc1c05f21520373a4c032cd1 100644
--- a/src/database/entities/message.rs
+++ b/src/database/entities/message.rs
@@ -11,7 +11,7 @@ use mongodb::{
     bson::{doc, to_bson, DateTime},
     options::FindOptions,
 };
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 use ulid::Ulid;
 use web_push::{
@@ -323,7 +323,7 @@ impl Message {
         Ok(())
     }
 
-    pub async fn publish_update(self, data: JsonValue) -> Result<()> {
+    pub async fn publish_update(self, data: Value) -> Result<()> {
         let channel = self.channel.clone();
         ClientboundNotification::MessageUpdate {
             id: self.id.clone(),
diff --git a/src/database/entities/server.rs b/src/database/entities/server.rs
index 5e8ff48d1d75e8573af0c702811dfa28ba7da35a..cd0731b1e11f6fb857a03de97ca0f71cfd617e63 100644
--- a/src/database/entities/server.rs
+++ b/src/database/entities/server.rs
@@ -8,7 +8,7 @@ use mongodb::bson::{Bson, doc};
 use mongodb::bson::from_document;
 use mongodb::bson::to_document;
 use mongodb::bson::Document;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -120,7 +120,7 @@ impl Server {
         Ok(())
     }
 
-    pub async fn publish_update(&self, data: JsonValue) -> Result<()> {
+    pub async fn publish_update(&self, data: Value) -> Result<()> {
         ClientboundNotification::ServerUpdate {
             id: self.id.clone(),
             data,
diff --git a/src/database/guards/user.rs b/src/database/guards/user.rs
index 1f44115f3c5d83dd4f88545ab48936b66a6c428c..551d6fc43052845cc83bf72a554bb57ea73f5ad6 100644
--- a/src/database/guards/user.rs
+++ b/src/database/guards/user.rs
@@ -3,6 +3,7 @@ use crate::database::*;
 use mongodb::bson::{doc, from_document};
 use rauth::auth::Session;
 use rocket::http::Status;
+use rocket::outcome::try_outcome;
 use rocket::request::{self, FromRequest, Outcome, Request};
 
 #[rocket::async_trait]
diff --git a/src/main.rs b/src/main.rs
index 46892aabfce725ebd2fdb6ccd615099e098d7307..150a8a994b7464758bc862fa7d996c7cb2baf797 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,8 +4,6 @@
 #[macro_use]
 extern crate rocket;
 #[macro_use]
-extern crate rocket_contrib;
-#[macro_use]
 extern crate lazy_static;
 #[macro_use]
 extern crate impl_ops;
@@ -30,6 +28,7 @@ use rauth::{
 };
 use rocket_cors::AllowedOrigins;
 use rocket_prometheus::PrometheusMetrics;
+use rocket::catchers;
 use util::variables::{
     APP_URL, HCAPTCHA_KEY, INVITE_ONLY, PUBLIC_URL, SMTP_FROM, SMTP_HOST, SMTP_PASSWORD,
     SMTP_USERNAME, USE_EMAIL, USE_HCAPTCHA, USE_PROMETHEUS,
@@ -140,6 +139,7 @@ Reset your password here: {{url}}",
         .manage(auth)
         .manage(cors.clone())
         .attach(cors)
+        .register("/", catchers![rocket_governor::rocket_governor_catcher])
         .launch()
         .await
         .unwrap();
diff --git a/src/notifications/events.rs b/src/notifications/events.rs
index f93925c62929c9525ebbbffd42c8dff54ff41486..3976b7f75239fdbb05b30782c83a5e3b8f3dccda 100644
--- a/src/notifications/events.rs
+++ b/src/notifications/events.rs
@@ -1,7 +1,7 @@
 use hive_pubsub::PubSub;
 use mongodb::bson::doc;
 use rauth::auth::Session;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 
 use super::hive::{get_hive, subscribe_if_exists};
@@ -73,7 +73,7 @@ pub enum ClientboundNotification {
     MessageUpdate {
         id: String,
         channel: String,
-        data: JsonValue,
+        data: Value,
     },
     MessageDelete {
         id: String,
@@ -83,7 +83,7 @@ pub enum ClientboundNotification {
     ChannelCreate(Channel),
     ChannelUpdate {
         id: String,
-        data: JsonValue,
+        data: Value,
         #[serde(skip_serializing_if = "Option::is_none")]
         clear: Option<RemoveChannelField>,
     },
@@ -114,7 +114,7 @@ pub enum ClientboundNotification {
 
     ServerUpdate {
         id: String,
-        data: JsonValue,
+        data: Value,
         #[serde(skip_serializing_if = "Option::is_none")]
         clear: Option<RemoveServerField>,
     },
@@ -123,7 +123,7 @@ pub enum ClientboundNotification {
     },
     ServerMemberUpdate {
         id: MemberCompositeKey,
-        data: JsonValue,
+        data: Value,
         #[serde(skip_serializing_if = "Option::is_none")]
         clear: Option<RemoveMemberField>,
     },
@@ -138,7 +138,7 @@ pub enum ClientboundNotification {
     ServerRoleUpdate {
         id: String,
         role_id: String,
-        data: JsonValue,
+        data: Value,
         #[serde(skip_serializing_if = "Option::is_none")]
         clear: Option<RemoveRoleField>
     },
@@ -149,7 +149,7 @@ pub enum ClientboundNotification {
 
     UserUpdate {
         id: String,
-        data: JsonValue,
+        data: Value,
         #[serde(skip_serializing_if = "Option::is_none")]
         clear: Option<RemoveUserField>,
     },
@@ -160,7 +160,7 @@ pub enum ClientboundNotification {
     },
     UserSettingsUpdate {
         id: String,
-        update: JsonValue,
+        update: Value,
     },
 }
 
diff --git a/src/routes/channels/channel_edit.rs b/src/routes/channels/channel_edit.rs
index 74b16ce64edfb0bde59ed059c699d0e6fb7a78f2..d32a5a87c52cf710162dcb3d837db6883e6b55f3 100644
--- a/src/routes/channels/channel_edit.rs
+++ b/src/routes/channels/channel_edit.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 use crate::{database::*, notifications::events::RemoveChannelField};
 
 use mongodb::bson::{doc, to_document};
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/channels/channel_fetch.rs b/src/routes/channels/channel_fetch.rs
index cacb983c5dbb91f89c11bf630b7e783a7220e18f..bda94df846d387311b177a1bea66a9b40a11f535 100644
--- a/src/routes/channels/channel_fetch.rs
+++ b/src/routes/channels/channel_fetch.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::{Error, Result};
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_channel().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/channels/group_create.rs b/src/routes/channels/group_create.rs
index 19d5bcaebd8de9809e949236b220bcb4b374d40c..ced86a7293c533b787e8fbd716c3f1d2074f3630 100644
--- a/src/routes/channels/group_create.rs
+++ b/src/routes/channels/group_create.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 use crate::util::variables::MAX_GROUP_SIZE;
 
 use mongodb::bson::doc;
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 use std::collections::HashSet;
 use std::iter::FromIterator;
@@ -23,7 +23,7 @@ pub struct Data {
 }
 
 #[post("/create", data = "<info>")]
-pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> {
+pub async fn req(user: User, info: Json<Data>) -> Result<Value> {
     let info = info.into_inner();
     info.validate()
         .map_err(|error| Error::FailedValidation { error })?;
diff --git a/src/routes/channels/invite_create.rs b/src/routes/channels/invite_create.rs
index 0018b3b444f4d6e25c5e24a73147eda238f6a545..7413af646750a9e140a9d61f5baee4280f62a692 100644
--- a/src/routes/channels/invite_create.rs
+++ b/src/routes/channels/invite_create.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
 use nanoid::nanoid;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 lazy_static! {
     static ref ALPHABET: [char; 54] = [
@@ -14,7 +14,7 @@ lazy_static! {
 }
 
 #[post("/<target>/invites")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_channel().await?;
     let perm = permissions::PermissionCalculator::new(&user)
         .with_channel(&target)
diff --git a/src/routes/channels/members_fetch.rs b/src/routes/channels/members_fetch.rs
index 4f42e695095c097d0d60f89f64624921ca4b325c..1eabd8d433ddad1da0d2530d52c24f1a6bfe5036 100644
--- a/src/routes/channels/members_fetch.rs
+++ b/src/routes/channels/members_fetch.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::{Error, Result};
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>/members")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_channel().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/channels/message_edit.rs b/src/routes/channels/message_edit.rs
index cf8f7f0572f3823a83dfe8a90c18d82a32f3ff90..8c9900a0c147c85eb0bd5dbcfffecf0cdbbce5b0 100644
--- a/src/routes/channels/message_edit.rs
+++ b/src/routes/channels/message_edit.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 
 use chrono::Utc;
 use mongodb::bson::{doc, Bson, DateTime, Document};
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/channels/message_fetch.rs b/src/routes/channels/message_fetch.rs
index c87a33344071d2f17f5513256dea8a61d20ec018..72edecffd339e584d0a5be537220c8f2e9b18f91 100644
--- a/src/routes/channels/message_fetch.rs
+++ b/src/routes/channels/message_fetch.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::{Error, Result};
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>/messages/<msg>")]
-pub async fn req(user: User, target: Ref, msg: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, msg: Ref) -> Result<Value> {
     let channel = target.fetch_channel().await?;
     channel.has_messaging()?;
 
diff --git a/src/routes/channels/message_query.rs b/src/routes/channels/message_query.rs
index da58526e1e3b6b1df8eb64f4e098402f37a62cab..9af8abb7b23ba68bd970849b1659051f5a8b250f 100644
--- a/src/routes/channels/message_query.rs
+++ b/src/routes/channels/message_query.rs
@@ -8,12 +8,12 @@ use mongodb::{
     bson::{doc, from_document},
     options::FindOptions,
 };
-use rocket::request::Form;
-use rocket_contrib::json::JsonValue;
+use rocket::form::Form;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
-#[derive(Serialize, Deserialize, FromFormValue)]
+#[derive(Serialize, Deserialize, FromFormField)]
 pub enum Sort {
     Latest,
     Oldest,
@@ -37,7 +37,7 @@ pub struct Options {
 }
 
 #[get("/<target>/messages?<options..>")]
-pub async fn req(user: User, target: Ref, options: Form<Options>) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, options: Form<Options>) -> Result<Value> {
     options
         .validate()
         .map_err(|error| Error::FailedValidation { error })?;
diff --git a/src/routes/channels/message_query_stale.rs b/src/routes/channels/message_query_stale.rs
index 5f83081841c952807f74fae73c786b7362de0188..0802a0e27abd77bfd00486320ee45e83fc503725 100644
--- a/src/routes/channels/message_query_stale.rs
+++ b/src/routes/channels/message_query_stale.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 
 use futures::StreamExt;
 use mongodb::bson::{doc, from_document};
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize)]
@@ -12,7 +12,7 @@ pub struct Options {
 }
 
 #[post("/<target>/messages/stale", data = "<data>")]
-pub async fn req(user: User, target: Ref, data: Json<Options>) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, data: Json<Options>) -> Result<Value> {
     if data.ids.len() > 150 {
         return Err(Error::TooManyIds);
     }
diff --git a/src/routes/channels/message_search.rs b/src/routes/channels/message_search.rs
index 352093ed97ac125ff636160d34bc5b178803e224..350ab57daa16cc6540908f3cba8c94d568419db6 100644
--- a/src/routes/channels/message_search.rs
+++ b/src/routes/channels/message_search.rs
@@ -8,11 +8,11 @@ use mongodb::{
     bson::{doc, from_document},
     options::FindOptions,
 };
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
-#[derive(Serialize, Deserialize, FromFormValue)]
+#[derive(Serialize, Deserialize, FromFormField)]
 pub enum Sort {
     Relevance,
     Latest,
@@ -42,7 +42,7 @@ pub struct Options {
 }
 
 #[post("/<target>/search", data = "<options>")]
-pub async fn req(user: User, target: Ref, options: Json<Options>) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, options: Json<Options>) -> Result<Value> {
     options
         .validate()
         .map_err(|error| Error::FailedValidation { error })?;
diff --git a/src/routes/channels/message_send.rs b/src/routes/channels/message_send.rs
index 7e768a7e572240592c186e3b35167486bc0abe0f..dfc596f84d40ca6fe8122e7db1538700ae4af5b6 100644
--- a/src/routes/channels/message_send.rs
+++ b/src/routes/channels/message_send.rs
@@ -5,7 +5,7 @@ use crate::util::result::{Error, Result};
 
 use mongodb::{bson::doc, options::FindOneOptions};
 use regex::Regex;
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 use ulid::Ulid;
 use validator::Validate;
@@ -33,7 +33,7 @@ lazy_static! {
 }
 
 #[post("/<target>/messages", data = "<message>")]
-pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<Value> {
     let message = message.into_inner();
     message
         .validate()
diff --git a/src/routes/channels/permissions_set.rs b/src/routes/channels/permissions_set.rs
index f9960d7c31643fc4e1cbf55bd2c9b9ac66b87327..bd464a92809630334ec8bddf4337ff33ad601bc4 100644
--- a/src/routes/channels/permissions_set.rs
+++ b/src/routes/channels/permissions_set.rs
@@ -1,5 +1,5 @@
 use mongodb::bson::doc;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Serialize, Deserialize};
 use validator::Contains;
 
diff --git a/src/routes/channels/permissions_set_default.rs b/src/routes/channels/permissions_set_default.rs
index 49c8e30f198b5b3bdb2e4f91e9ca05001f230bf8..4907b2781578cabbf860cd320edf0032e9ca6a27 100644
--- a/src/routes/channels/permissions_set_default.rs
+++ b/src/routes/channels/permissions_set_default.rs
@@ -1,5 +1,5 @@
 use mongodb::bson::doc;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Serialize, Deserialize};
 
 use crate::database::*;
diff --git a/src/routes/channels/voice_join.rs b/src/routes/channels/voice_join.rs
index 1b632b94719101af246f071cdcb672da84d9fc01..98fdabec79b0d1b3415ec552130215b0dc019135 100644
--- a/src/routes/channels/voice_join.rs
+++ b/src/routes/channels/voice_join.rs
@@ -2,7 +2,7 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 use crate::util::variables::{USE_VOSO, VOSO_MANAGE_TOKEN, VOSO_URL};
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize)]
@@ -11,7 +11,7 @@ struct CreateUserResponse {
 }
 
 #[post("/<target>/join_call")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     if !*USE_VOSO {
         return Err(Error::VosoUnavailable);
     }
diff --git a/src/routes/invites/invite_fetch.rs b/src/routes/invites/invite_fetch.rs
index a905c2dd89b18f216eb773147a68bf49e3f3f52d..521e124e2e5e2018d7a9d0c4c14f1e156748cb82 100644
--- a/src/routes/invites/invite_fetch.rs
+++ b/src/routes/invites/invite_fetch.rs
@@ -1,7 +1,7 @@
 use crate::database::*;
 use crate::util::result::Result;
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::Serialize;
 
 #[derive(Serialize, Debug, Clone)]
@@ -26,7 +26,7 @@ pub enum InviteResponse {
 }
 
 #[get("/<target>")]
-pub async fn req(target: Ref) -> Result<JsonValue> {
+pub async fn req(target: Ref) -> Result<Value> {
     let target = target.fetch_invite().await?;
 
     match target {
diff --git a/src/routes/invites/invite_join.rs b/src/routes/invites/invite_join.rs
index 517b732e2d64cfec6033c4e651d7a1a6b85e7130..8c2c68313ebbe08385006eb373d6d79741b4c98a 100644
--- a/src/routes/invites/invite_join.rs
+++ b/src/routes/invites/invite_join.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::Result;
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[post("/<target>")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_invite().await?;
 
     match target {
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index ab626446bc0586b0a935315f7c506fb568af92b0..179acccc558d544f7e3e9efdb8ed2914b75d63cd 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -1,6 +1,6 @@
-pub use rocket::http::Status;
 pub use rocket::response::Redirect;
-use rocket::Rocket;
+pub use rocket::http::Status;
+use rocket::{Phase, Rocket};
 
 mod channels;
 mod invites;
@@ -11,7 +11,7 @@ mod servers;
 mod sync;
 mod users;
 
-pub fn mount(rocket: Rocket) -> Rocket {
+pub fn mount<T: Phase>(rocket: Rocket<T>) -> Rocket<T> {
     rocket
         .mount("/", routes![root::root])
         .mount("/onboard", onboard::routes())
diff --git a/src/routes/onboard/complete.rs b/src/routes/onboard/complete.rs
index 5ebb1f15ca87947a52556d21379791f19adf24b4..25726771861fa56ff30b310201b7079c850347b5 100644
--- a/src/routes/onboard/complete.rs
+++ b/src/routes/onboard/complete.rs
@@ -4,7 +4,7 @@ use crate::util::result::{Error, Result};
 use mongodb::bson::doc;
 use rauth::auth::Session;
 use regex::Regex;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/onboard/hello.rs b/src/routes/onboard/hello.rs
index 2aaabdbae650ef1f3a4ed49be293a130220c6041..050e7561d0a6ecf976bcee9323ea7ab8dd571140 100644
--- a/src/routes/onboard/hello.rs
+++ b/src/routes/onboard/hello.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 
 use rauth::auth::Session;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/hello")]
-pub async fn req(_session: Session, user: Option<User>) -> JsonValue {
+pub async fn req(_session: Session, user: Option<User>) -> Value {
     json!({
         "onboarding": user.is_none()
     })
diff --git a/src/routes/push/subscribe.rs b/src/routes/push/subscribe.rs
index d2a060472f604ec098728d19735856f0f88ac4df..ac23628b0822b040b3663c1d94f44793dbb0509a 100644
--- a/src/routes/push/subscribe.rs
+++ b/src/routes/push/subscribe.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 
 use mongodb::bson::{doc, to_document};
 use rauth::auth::Session;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize)]
diff --git a/src/routes/root.rs b/src/routes/root.rs
index 044394927e03af9c77291838820b9c9d1f4a8b65..1cca6e8a613ba8aebb372bb629786f9b3fa296e5 100644
--- a/src/routes/root.rs
+++ b/src/routes/root.rs
@@ -1,13 +1,14 @@
-use crate::util::variables::{
+use crate::util::{ratelimit::RateLimitGuard, variables::{
     APP_URL, AUTUMN_URL, EXTERNAL_WS_URL, HCAPTCHA_SITEKEY, INVITE_ONLY, JANUARY_URL, USE_AUTUMN,
     USE_EMAIL, USE_HCAPTCHA, USE_JANUARY, USE_VOSO, VAPID_PUBLIC_KEY, VOSO_URL, VOSO_WS_HOST,
-};
+}};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
+use rocket_governor::RocketGovernor;
 
 #[get("/")]
-pub async fn root() -> JsonValue {
+pub async fn root(_limitguard: RocketGovernor<'_, RateLimitGuard>) -> Value {
     json!({
         "revolt": crate::version::VERSION,
         "features": {
diff --git a/src/routes/servers/ban_create.rs b/src/routes/servers/ban_create.rs
index 53c9d07133dea6b85b58e18ad09ea1e60fbfda2f..3207f492ae7766308e75d7480d66a830d9c474ac 100644
--- a/src/routes/servers/ban_create.rs
+++ b/src/routes/servers/ban_create.rs
@@ -2,7 +2,7 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/servers/ban_list.rs b/src/routes/servers/ban_list.rs
index 3993d3e7229bbbee587ad91f86b04704e5a10876..141c4a9bfc12a5b81472b789818de747f28dac0a 100644
--- a/src/routes/servers/ban_list.rs
+++ b/src/routes/servers/ban_list.rs
@@ -4,7 +4,7 @@ use crate::util::result::{Error, Result};
 use futures::StreamExt;
 use mongodb::options::FindOptions;
 use serde::{Serialize, Deserialize};
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use mongodb::bson::{doc, from_document};
 
 #[derive(Serialize, Deserialize)]
@@ -15,7 +15,7 @@ struct BannedUser {
 }
 
 #[get("/<target>/bans")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_server().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/servers/channel_create.rs b/src/routes/servers/channel_create.rs
index 3d8c2c3cd162ef2248be9b17fe76f88ad15b1369..ce472726e1628ea930fcaac2c92ef3484fa4066b 100644
--- a/src/routes/servers/channel_create.rs
+++ b/src/routes/servers/channel_create.rs
@@ -4,7 +4,7 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 use ulid::Ulid;
 use validator::Validate;
@@ -35,7 +35,7 @@ pub struct Data {
 }
 
 #[post("/<target>/channels", data = "<info>")]
-pub async fn req(user: User, target: Ref, info: Json<Data>) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, info: Json<Data>) -> Result<Value> {
     let info = info.into_inner();
     info.validate()
         .map_err(|error| Error::FailedValidation { error })?;
diff --git a/src/routes/servers/invites_fetch.rs b/src/routes/servers/invites_fetch.rs
index d307051b0eb2e2819ac54c4ca310deb23545d2e6..f6b48dc363e98e198abefdc663054b9cfe42eb88 100644
--- a/src/routes/servers/invites_fetch.rs
+++ b/src/routes/servers/invites_fetch.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 
 use futures::StreamExt;
 use mongodb::bson::{doc, from_document};
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -15,7 +15,7 @@ pub struct ServerInvite {
 }
 
 #[get("/<target>/invites")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_server().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/servers/member_edit.rs b/src/routes/servers/member_edit.rs
index 79b342a0e93fda3876c0e69a30f2d6294eedc3f3..4e834a8f238fe40a5006609bbde21215385bcf06 100644
--- a/src/routes/servers/member_edit.rs
+++ b/src/routes/servers/member_edit.rs
@@ -5,7 +5,7 @@ use crate::util::result::{Error, Result};
 use crate::{database::*, notifications::events::RemoveMemberField};
 
 use mongodb::bson::{doc, to_document};
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/servers/member_fetch.rs b/src/routes/servers/member_fetch.rs
index 7631c2f29161f6aff2fa225168d187428428d35b..0b786a3203de98e39e9c996bed8d5d90e33587f0 100644
--- a/src/routes/servers/member_fetch.rs
+++ b/src/routes/servers/member_fetch.rs
@@ -2,10 +2,10 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>/members/<member>")]
-pub async fn req(user: User, target: Ref, member: String) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, member: String) -> Result<Value> {
     let target = target.fetch_server().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/servers/member_fetch_all.rs b/src/routes/servers/member_fetch_all.rs
index 4733c642d97257abde4564363b942d9d3b0f763c..b5c54ed0793e18897b31122666f956c3ffc718b1 100644
--- a/src/routes/servers/member_fetch_all.rs
+++ b/src/routes/servers/member_fetch_all.rs
@@ -3,12 +3,12 @@ use crate::util::result::{Error, Result};
 
 use futures::StreamExt;
 use mongodb::bson::{doc, from_document, Document};
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 // ! FIXME: this is a temporary route while permissions are being worked on.
 
 #[get("/<target>/members")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_server().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/servers/permissions_set.rs b/src/routes/servers/permissions_set.rs
index 74359a24e2b85f1f681b7cb50a5aaee96fb3ef61..49ad53c82108ebc4afa2f750173ff83c2a76934f 100644
--- a/src/routes/servers/permissions_set.rs
+++ b/src/routes/servers/permissions_set.rs
@@ -1,5 +1,5 @@
 use mongodb::bson::doc;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Serialize, Deserialize};
 
 use crate::database::*;
diff --git a/src/routes/servers/permissions_set_default.rs b/src/routes/servers/permissions_set_default.rs
index c98dcac4b819506d868a7de511a766a2ebf26967..d69827674e18443591c0098e084a636007e6d862 100644
--- a/src/routes/servers/permissions_set_default.rs
+++ b/src/routes/servers/permissions_set_default.rs
@@ -1,5 +1,5 @@
 use mongodb::bson::doc;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Serialize, Deserialize};
 
 use crate::database::*;
diff --git a/src/routes/servers/roles_create.rs b/src/routes/servers/roles_create.rs
index 3f13d753d740fc5e754f7437fb8b9887d09e3e47..4410b69cb58afa928a4d8a1d388ec55586683f63 100644
--- a/src/routes/servers/roles_create.rs
+++ b/src/routes/servers/roles_create.rs
@@ -6,7 +6,7 @@ use ulid::Ulid;
 use mongodb::bson::doc;
 use validator::Validate;
 use serde::{Serialize, Deserialize};
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 
 #[derive(Validate, Serialize, Deserialize)]
 pub struct Data {
@@ -15,7 +15,7 @@ pub struct Data {
 }
 
 #[post("/<target>/roles", data = "<data>")]
-pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<Value> {
     let data = data.into_inner();
     data.validate()
         .map_err(|error| Error::FailedValidation { error })?;
diff --git a/src/routes/servers/roles_edit.rs b/src/routes/servers/roles_edit.rs
index 3cc796e2481ee6c5cee69fe7da686d44ed23296a..81b22c8f33d34278e7ffb560a5d42af631dfc149 100644
--- a/src/routes/servers/roles_edit.rs
+++ b/src/routes/servers/roles_edit.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 use crate::{database::*, notifications::events::RemoveRoleField};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/servers/server_create.rs b/src/routes/servers/server_create.rs
index dfff554942ca1736c43dbf7ccec10d82b763c6ce..d75d66a1478e2b2fedeb69ac77cc208633169afa 100644
--- a/src/routes/servers/server_create.rs
+++ b/src/routes/servers/server_create.rs
@@ -4,7 +4,7 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 use ulid::Ulid;
 use validator::Validate;
@@ -21,7 +21,7 @@ pub struct Data {
 }
 
 #[post("/create", data = "<info>")]
-pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> {
+pub async fn req(user: User, info: Json<Data>) -> Result<Value> {
     let info = info.into_inner();
     info.validate()
         .map_err(|error| Error::FailedValidation { error })?;
diff --git a/src/routes/servers/server_edit.rs b/src/routes/servers/server_edit.rs
index a6e1d4808f888544e9c25df14e4a31f07431a9b0..b4f7368a581c53fea0f999f300fd17645eaf2f26 100644
--- a/src/routes/servers/server_edit.rs
+++ b/src/routes/servers/server_edit.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 use crate::{database::*, notifications::events::RemoveServerField};
 
 use mongodb::bson::{doc, to_bson, to_document};
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/servers/server_fetch.rs b/src/routes/servers/server_fetch.rs
index 8208464de96eb35942173b7df2407cb5aa8f7f47..a46b4fdae7fc1cb4d59a9c090d13789123e48d16 100644
--- a/src/routes/servers/server_fetch.rs
+++ b/src/routes/servers/server_fetch.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::{Error, Result};
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_server().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/sync/get_settings.rs b/src/routes/sync/get_settings.rs
index 582e49c677ca8ebec37e8d6f1e07ec7c45682687..de5f58f9bb57c11f3d1ec68de8bf23867ceff280 100644
--- a/src/routes/sync/get_settings.rs
+++ b/src/routes/sync/get_settings.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
 use mongodb::options::FindOneOptions;
-use rocket_contrib::json::{Json, JsonValue};
+use rocket::serde::json::{Json, Value};
 use serde::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize)]
@@ -12,7 +12,7 @@ pub struct Options {
 }
 
 #[post("/settings/fetch", data = "<options>")]
-pub async fn req(user: User, options: Json<Options>) -> Result<JsonValue> {
+pub async fn req(user: User, options: Json<Options>) -> Result<Value> {
     let options = options.into_inner();
     let mut projection = doc! {
         "_id": 0,
diff --git a/src/routes/sync/get_unreads.rs b/src/routes/sync/get_unreads.rs
index ffd1af8aa2efe09aa55e4dc79658924e9b3e8157..7f135d088292b0298e16df7599886e47ae8822f7 100644
--- a/src/routes/sync/get_unreads.rs
+++ b/src/routes/sync/get_unreads.rs
@@ -2,9 +2,9 @@ use crate::database::*;
 use crate::util::result::Result;
 
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/unreads")]
-pub async fn req(user: User) -> Result<JsonValue> {
+pub async fn req(user: User) -> Result<Value> {
     Ok(json!(User::fetch_unreads(&user.id).await?))
 }
diff --git a/src/routes/sync/set_settings.rs b/src/routes/sync/set_settings.rs
index cbff28e7a34a60196f641ca4c8e1477f16a0b543..6502757d85222e8908d3741d377288b51d4eb4c7 100644
--- a/src/routes/sync/set_settings.rs
+++ b/src/routes/sync/set_settings.rs
@@ -5,8 +5,8 @@ use crate::util::result::{Error, Result};
 use chrono::prelude::*;
 use mongodb::bson::{doc, to_bson};
 use mongodb::options::UpdateOptions;
-use rocket::request::Form;
-use rocket_contrib::json::Json;
+use rocket::form::Form;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 
diff --git a/src/routes/users/add_friend.rs b/src/routes/users/add_friend.rs
index b2c8697096779251f5ab0fd89b910d19e08326df..74b5765fbfd9502493af8a81675f86d816d6320e 100644
--- a/src/routes/users/add_friend.rs
+++ b/src/routes/users/add_friend.rs
@@ -5,10 +5,10 @@ use crate::util::result::{Error, Result};
 use futures::try_join;
 use mongodb::bson::doc;
 use mongodb::options::{Collation, FindOneOptions};
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[put("/<username>/friend")]
-pub async fn req(user: User, username: String) -> Result<JsonValue> {
+pub async fn req(user: User, username: String) -> Result<Value> {
     let col = get_collection("users");
     let doc = col
         .find_one(
diff --git a/src/routes/users/block_user.rs b/src/routes/users/block_user.rs
index a786eb6cc5132ac6d85854020d8e821e02b498ec..c8721d8539569e57268394ff00b9103acfce706d 100644
--- a/src/routes/users/block_user.rs
+++ b/src/routes/users/block_user.rs
@@ -4,10 +4,10 @@ use crate::util::result::{Error, Result};
 
 use futures::try_join;
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[put("/<target>/block")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let col = get_collection("users");
 
     let target = target.fetch_user().await?;
diff --git a/src/routes/users/change_username.rs b/src/routes/users/change_username.rs
index b25edc133d76094c8566b25fe2ab2d946b3c166b..f93fb1b60335d66168184eda4f3205c14486b1a3 100644
--- a/src/routes/users/change_username.rs
+++ b/src/routes/users/change_username.rs
@@ -6,7 +6,7 @@ use mongodb::bson::doc;
 use rauth::auth::{Auth, Session};
 use regex::Regex;
 use rocket::State;
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
@@ -25,7 +25,7 @@ pub struct Data {
 
 #[patch("/<_ignore_id>/username", data = "<data>")]
 pub async fn req(
-    auth: State<'_, Auth>,
+    auth: &State<Auth>,
     session: Session,
     user: User,
     data: Json<Data>,
diff --git a/src/routes/users/edit_user.rs b/src/routes/users/edit_user.rs
index 14a9c841e15c7879241b45b563fb5a6f74a03594..e17ebb548668f096d28e01b602a1fded72d2c963 100644
--- a/src/routes/users/edit_user.rs
+++ b/src/routes/users/edit_user.rs
@@ -3,7 +3,7 @@ use crate::util::result::{Error, Result};
 use crate::{database::*, notifications::events::RemoveUserField};
 
 use mongodb::bson::{doc, to_document};
-use rocket_contrib::json::Json;
+use rocket::serde::json::Json;
 use serde::{Deserialize, Serialize};
 use validator::Validate;
 
diff --git a/src/routes/users/fetch_dms.rs b/src/routes/users/fetch_dms.rs
index 87aa4dfab3ab19f1aa675df5d85dd79d5aac6678..ec7630fb479fbd6d34877a1213cf6a7415a6a95e 100644
--- a/src/routes/users/fetch_dms.rs
+++ b/src/routes/users/fetch_dms.rs
@@ -3,10 +3,10 @@ use crate::util::result::{Error, Result};
 
 use futures::StreamExt;
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/dms")]
-pub async fn req(user: User) -> Result<JsonValue> {
+pub async fn req(user: User) -> Result<Value> {
     let mut cursor = get_collection("channels")
         .find(
             doc! {
diff --git a/src/routes/users/fetch_profile.rs b/src/routes/users/fetch_profile.rs
index 7975f81404bb347c7090880ee4e43f5b4cc2f2dd..44457d8b5444c898fb4cb2d66e3b952c108853b9 100644
--- a/src/routes/users/fetch_profile.rs
+++ b/src/routes/users/fetch_profile.rs
@@ -2,10 +2,10 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>/profile")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_user().await?;
     let perm = permissions::PermissionCalculator::new(&user)
         .with_user(&target)
diff --git a/src/routes/users/fetch_relationship.rs b/src/routes/users/fetch_relationship.rs
index 2f2b171b6c04f1b0adc1bce041071a4128bb7184..d8018a15a9189693aefaba4f9a48c30bcfcb45c1 100644
--- a/src/routes/users/fetch_relationship.rs
+++ b/src/routes/users/fetch_relationship.rs
@@ -1,9 +1,9 @@
 use crate::database::*;
 use crate::util::result::Result;
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>/relationship")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     Ok(json!({ "status": get_relationship(&user, &target.id) }))
 }
diff --git a/src/routes/users/fetch_relationships.rs b/src/routes/users/fetch_relationships.rs
index bff43f0f9cb987ef6963a2461880ed3120514308..f4023b89ab86e1a2b6854e2777df686ac49e0354 100644
--- a/src/routes/users/fetch_relationships.rs
+++ b/src/routes/users/fetch_relationships.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::Result;
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/relationships")]
-pub async fn req(user: User) -> Result<JsonValue> {
+pub async fn req(user: User) -> Result<Value> {
     Ok(if let Some(vec) = user.relations {
         json!(vec)
     } else {
diff --git a/src/routes/users/fetch_user.rs b/src/routes/users/fetch_user.rs
index 063ddf34d6b09bfa1ae1138d5d6486d3cb5fedca..831735f38812aa543a59052e2a90dad34dcea501 100644
--- a/src/routes/users/fetch_user.rs
+++ b/src/routes/users/fetch_user.rs
@@ -1,10 +1,10 @@
 use crate::database::*;
 use crate::util::result::{Error, Result};
 
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let target = target.fetch_user().await?;
 
     let perm = permissions::PermissionCalculator::new(&user)
diff --git a/src/routes/users/find_mutual.rs b/src/routes/users/find_mutual.rs
index 4527cfe355b82be33506483017df120c5bf7b73d..42af684749b28bd2a7322cdf869857116ab6ebf6 100644
--- a/src/routes/users/find_mutual.rs
+++ b/src/routes/users/find_mutual.rs
@@ -4,10 +4,10 @@ use crate::util::result::{Error, Result};
 use futures::StreamExt;
 use mongodb::bson::{doc, Document};
 use mongodb::options::FindOptions;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[get("/<target>/mutual")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let users = get_collection("users")
         .find(
             doc! {
diff --git a/src/routes/users/get_default_avatar.rs b/src/routes/users/get_default_avatar.rs
index d2504cf1a6601a2a9abfe4fff12f48c96b76bdc3..86b069276f70617b4eb6c58f83cfad65d3f8a0ee 100644
--- a/src/routes/users/get_default_avatar.rs
+++ b/src/routes/users/get_default_avatar.rs
@@ -1,5 +1,6 @@
 use rocket::{Request, Response};
-use rocket::response::{self, NamedFile, Responder};
+use rocket::response::{self, Responder};
+use rocket::fs::NamedFile;
 use std::path::Path;
 
 use crate::database::Ref;
diff --git a/src/routes/users/open_dm.rs b/src/routes/users/open_dm.rs
index 4712cba8ae51ef5c052d3d170c96260daf690844..64bef6a2239d16a500c06d93d02c63bd71791eb4 100644
--- a/src/routes/users/open_dm.rs
+++ b/src/routes/users/open_dm.rs
@@ -2,11 +2,11 @@ use crate::database::*;
 use crate::util::result::{Error, Result};
 
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 use ulid::Ulid;
 
 #[get("/<target>/dm")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let query = if user.id == target.id {
         doc! {
             "channel_type": "SavedMessages",
diff --git a/src/routes/users/remove_friend.rs b/src/routes/users/remove_friend.rs
index 847e99cec92bf34e4d2d6638a97a45a737b01e8b..3fbb60abef6d0d94decb992f8da4d8707dede6b1 100644
--- a/src/routes/users/remove_friend.rs
+++ b/src/routes/users/remove_friend.rs
@@ -4,10 +4,10 @@ use crate::util::result::{Error, Result};
 
 use futures::try_join;
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[delete("/<target>/friend")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let col = get_collection("users");
 
     let target = target.fetch_user().await?;
diff --git a/src/routes/users/unblock_user.rs b/src/routes/users/unblock_user.rs
index 6f94b1819a2ebbae6f894a345269cb72bbb8ef53..0b294903c04c6fd84ae4934390018f61dcf91f2b 100644
--- a/src/routes/users/unblock_user.rs
+++ b/src/routes/users/unblock_user.rs
@@ -4,10 +4,10 @@ use crate::util::result::{Error, Result};
 
 use futures::try_join;
 use mongodb::bson::doc;
-use rocket_contrib::json::JsonValue;
+use rocket::serde::json::Value;
 
 #[delete("/<target>/block")]
-pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
+pub async fn req(user: User, target: Ref) -> Result<Value> {
     let col = get_collection("users");
     let target = target.fetch_user().await?;
 
diff --git a/src/util/mod.rs b/src/util/mod.rs
index 7743f0ec127dd8b19d6e6ef95f4fc0ce4420d49f..08aa9ccf3daeac436503972cc5818cb18d66c67f 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -1,2 +1,3 @@
 pub mod result;
 pub mod variables;
+pub mod ratelimit;
diff --git a/src/util/ratelimit.rs b/src/util/ratelimit.rs
new file mode 100644
index 0000000000000000000000000000000000000000..462122f198556c9a15e3fc0c5d4e19a90a458e9d
--- /dev/null
+++ b/src/util/ratelimit.rs
@@ -0,0 +1,9 @@
+use rocket_governor::{Method, Quota, RocketGovernable, RocketGovernor};
+
+pub struct RateLimitGuard;
+
+impl<'r> RocketGovernable<'r> for RateLimitGuard {
+    fn quota(_method: Method, _route_name: &str) -> Quota {
+        Quota::per_second(Self::nonzero(1u32))
+    }
+}