From 453544b7551f1bac4e1f6ce1b07373cf2c28ac4c Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 9 Jul 2021 10:50:51 +0200 Subject: [PATCH] setup sqlx with migrations --- Cargo.lock | 515 +++++++++++++++++- matrix-authentication-service/Cargo.toml | 1 + .../migrations/20210709081439_initial.sql | 1 + .../src/config/database.rs | 86 +++ .../src/config/mod.rs | 3 + .../src/handlers/health.rs | 30 + .../src/handlers/mod.rs | 7 +- matrix-authentication-service/src/main.rs | 34 +- matrix-authentication-service/src/state.rs | 11 +- .../src/storage/client.rs | 4 +- .../src/storage/mod.rs | 22 +- .../src/storage/user.rs | 2 +- 12 files changed, 698 insertions(+), 18 deletions(-) create mode 100644 matrix-authentication-service/migrations/20210709081439_initial.sql create mode 100644 matrix-authentication-service/src/config/database.rs create mode 100644 matrix-authentication-service/src/handlers/health.rs diff --git a/Cargo.lock b/Cargo.lock index 7a11898fb..a66301d19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,17 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "ahash" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" +dependencies = [ + "getrandom 0.2.3", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -271,6 +282,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "async-rustls" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c86f33abd5a4f3e2d6d9251a9e0c6a7e52eb1113caf893dae8429bf4a53f378" +dependencies = [ + "futures-lite", + "rustls", + "webpki", +] + [[package]] name = "async-session" version = "2.0.1" @@ -352,6 +374,15 @@ dependencies = [ "syn", ] +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic" version = "0.5.0" @@ -406,6 +437,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake3" version = "0.3.8" @@ -483,6 +526,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + [[package]] name = "bumpalo" version = "3.7.0" @@ -650,6 +699,25 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.2" @@ -768,18 +836,50 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "discard" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dtoa" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "event-listener" version = "2.5.1" @@ -847,6 +947,27 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "futures" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.15" @@ -854,6 +975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -862,6 +984,17 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" +[[package]] +name = "futures-executor" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.15" @@ -896,6 +1029,12 @@ dependencies = [ "syn", ] +[[package]] +name = "futures-sink" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" + [[package]] name = "futures-task" version = "0.3.15" @@ -909,9 +1048,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" dependencies = [ "autocfg", + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite 0.2.6", "pin-utils", "proc-macro-hack", @@ -1007,6 +1150,33 @@ dependencies = [ "web-sys", ] +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.18" @@ -1016,6 +1186,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hkdf" version = "0.10.0" @@ -1202,6 +1378,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if 1.0.0", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.96" @@ -1214,6 +1403,15 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +[[package]] +name = "lock_api" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -1258,6 +1456,7 @@ dependencies = [ "mime", "oauth2-types", "serde", + "sqlx", "tera", "thiserror", "tide", @@ -1268,6 +1467,17 @@ dependencies = [ "url", ] +[[package]] +name = "md-5" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "memchr" version = "2.4.0" @@ -1280,6 +1490,19 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "nom" +version = "6.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +dependencies = [ + "bitvec", + "funty", + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -1346,6 +1569,31 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + [[package]] name = "parse-display" version = "0.5.0" @@ -1450,7 +1698,7 @@ checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" dependencies = [ "maplit", "pest", - "sha-1", + "sha-1 0.8.2", ] [[package]] @@ -1574,6 +1822,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "rand" version = "0.7.3" @@ -1655,6 +1909,25 @@ dependencies = [ "rand_core 0.6.2", ] +[[package]] +name = "redox_syscall" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom 0.2.3", + "redox_syscall", +] + [[package]] name = "regex" version = "1.5.4" @@ -1681,6 +1954,21 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "route-recognizer" version = "0.2.0" @@ -1696,6 +1984,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64 0.13.0", + "log", + "ring", + "sct", + "webpki", +] + [[package]] name = "ryu" version = "1.0.5" @@ -1711,6 +2012,22 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "semver" version = "0.9.0" @@ -1805,6 +2122,19 @@ dependencies = [ "opaque-debug 0.2.3", ] +[[package]] +name = "sha-1" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "sha1" version = "0.6.0" @@ -1892,6 +2222,114 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "sqlformat" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d86e3c77ff882a828346ba401a7ef4b8e440df804491c6064fe8295765de71c" +dependencies = [ + "lazy_static", + "maplit", + "nom", + "regex", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba82f79b31f30acebf19905bcd8b978f46891b9d0723f578447361a8910b6584" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f23af36748ec8ea8d49ef8499839907be41b0b1178a4e82b8cb45d29f531dc9" +dependencies = [ + "ahash", + "atoi", + "base64 0.13.0", + "bitflags", + "byteorder", + "bytes", + "crc", + "crossbeam-channel", + "crossbeam-queue", + "crossbeam-utils", + "dirs", + "either", + "futures-channel", + "futures-core", + "futures-util", + "hashlink", + "hex", + "hmac 0.10.1", + "itoa", + "libc", + "log", + "md-5", + "memchr", + "once_cell", + "parking_lot", + "percent-encoding", + "rand 0.8.3", + "rustls", + "serde", + "serde_json", + "sha-1 0.9.6", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "url", + "webpki", + "webpki-roots", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4a2349d1ffd60a03ca0de3f116ba55d7f406e55a0d84c64a5590866d94c06" +dependencies = [ + "dotenv", + "either", + "futures", + "heck", + "once_cell", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8199b421ecf3493ee9ef3e7bc90c904844cfb2ea7ea2f57347a93f52bfd3e057" +dependencies = [ + "async-rustls", + "async-std", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1907,6 +2345,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stdweb" version = "0.4.20" @@ -1965,6 +2409,16 @@ dependencies = [ "generic-array 0.14.4", ] +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "structmeta" version = "0.1.3" @@ -2011,6 +2465,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tera" version = "1.11.0" @@ -2335,12 +2795,24 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "unindent" version = "0.1.7" @@ -2357,6 +2829,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -2494,6 +2972,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki", +] + [[package]] name = "wepoll-sys" version = "3.0.1" @@ -2503,6 +3000,16 @@ dependencies = [ "cc", ] +[[package]] +name = "whoami" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4abacf325c958dfeaf1046931d37f2a901b6dfe0968ee965a29e94c6766b2af6" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2534,6 +3041,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/matrix-authentication-service/Cargo.toml b/matrix-authentication-service/Cargo.toml index 47b5eb059..96d191f26 100644 --- a/matrix-authentication-service/Cargo.toml +++ b/matrix-authentication-service/Cargo.toml @@ -23,3 +23,4 @@ data-encoding = "2.3.2" time = "0.2.27" tide-tracing = "0.0.11" mime = "0.3.16" +sqlx = { version = "0.5.5", features = ["runtime-async-std-rustls", "postgres", "migrate"] } diff --git a/matrix-authentication-service/migrations/20210709081439_initial.sql b/matrix-authentication-service/migrations/20210709081439_initial.sql new file mode 100644 index 000000000..8ddc1d3ff --- /dev/null +++ b/matrix-authentication-service/migrations/20210709081439_initial.sql @@ -0,0 +1 @@ +-- Add migration script here diff --git a/matrix-authentication-service/src/config/database.rs b/matrix-authentication-service/src/config/database.rs new file mode 100644 index 000000000..69073a200 --- /dev/null +++ b/matrix-authentication-service/src/config/database.rs @@ -0,0 +1,86 @@ +// Copyright 2021 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::time::Duration; + +use serde::Deserialize; +use sqlx::postgres::{PgPool, PgPoolOptions}; + +fn default_uri() -> String { + "postgresql://".to_string() +} + +fn default_max_connections() -> u32 { + 10 +} + +fn default_connect_timeout() -> Duration { + Duration::from_secs(30) +} + +fn default_idle_timeout() -> Option { + Some(Duration::from_secs(10 * 60)) +} + +fn default_max_lifetime() -> Option { + Some(Duration::from_secs(30 * 60)) +} + +impl Default for Config { + fn default() -> Self { + Self { + uri: default_uri(), + max_connections: default_max_connections(), + min_connections: Default::default(), + connect_timeout: default_connect_timeout(), + idle_timeout: default_idle_timeout(), + max_lifetime: default_max_lifetime(), + } + } +} + +#[derive(Debug, Deserialize)] +pub struct Config { + #[serde(default = "default_uri")] + uri: String, + + #[serde(default = "default_max_connections")] + max_connections: u32, + + #[serde(default)] + min_connections: u32, + + #[serde(default = "default_connect_timeout")] + connect_timeout: Duration, + + #[serde(default = "default_idle_timeout")] + idle_timeout: Option, + + #[serde(default = "default_max_lifetime")] + max_lifetime: Option, +} + +impl Config { + #[tracing::instrument(err)] + pub async fn connect(&self) -> Result { + PgPoolOptions::new() + .max_connections(self.max_connections) + .min_connections(self.min_connections) + .connect_timeout(self.connect_timeout) + .idle_timeout(self.idle_timeout) + .max_lifetime(self.max_lifetime) + .connect(&self.uri) + .await + } +} diff --git a/matrix-authentication-service/src/config/mod.rs b/matrix-authentication-service/src/config/mod.rs index 783187fed..b7b39924a 100644 --- a/matrix-authentication-service/src/config/mod.rs +++ b/matrix-authentication-service/src/config/mod.rs @@ -19,9 +19,11 @@ use figment::{ }; use serde::Deserialize; +mod database; mod http; mod oauth2; +pub use self::database::Config as DatabaseConfig; pub use self::http::Config as HttpConfig; pub use self::oauth2::{ClientConfig as OAuth2ClientConfig, Config as OAuth2Config}; @@ -30,6 +32,7 @@ pub use self::oauth2::{ClientConfig as OAuth2ClientConfig, Config as OAuth2Confi pub struct RootConfig { pub oauth2: OAuth2Config, pub http: HttpConfig, + pub database: DatabaseConfig, } impl RootConfig { diff --git a/matrix-authentication-service/src/handlers/health.rs b/matrix-authentication-service/src/handlers/health.rs new file mode 100644 index 000000000..cb6d02a59 --- /dev/null +++ b/matrix-authentication-service/src/handlers/health.rs @@ -0,0 +1,30 @@ +// Copyright 2021 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use tide::Request; +use tracing::{info_span, Instrument}; + +use crate::state::State; + +pub async fn get(req: Request) -> tide::Result { + let pool = req.state().storage().pool(); + + sqlx::query("SELECT $1") + .bind(1_i64) + .execute(pool) + .instrument(info_span!("DB health")) + .await?; + + Ok("ok".into()) +} diff --git a/matrix-authentication-service/src/handlers/mod.rs b/matrix-authentication-service/src/handlers/mod.rs index b41969d09..bdadefd4c 100644 --- a/matrix-authentication-service/src/handlers/mod.rs +++ b/matrix-authentication-service/src/handlers/mod.rs @@ -27,6 +27,7 @@ use crate::{ storage::{ClientLookupError, InvalidRedirectUriError, Storage}, }; +mod health; mod oauth2; mod views; @@ -53,9 +54,9 @@ struct QueryParams { redirect_uri: Option, } -async fn redirect_uri_from_params( +async fn redirect_uri_from_params( params: QueryParams, - storage: &Storage, + storage: &Storage, ) -> Result { use RedirectUriLookupError::*; let client_id = params.client_id.ok_or(MissingClientId)?; @@ -110,6 +111,8 @@ pub fn install(app: &mut Server) { .allow_origin(Origin::from("*")) .allow_credentials(false); + app.at("/health").get(self::health::get); + app.at("/").nest({ let mut views = tide::with_state(state.clone()); views.with(state.session_middleware()); diff --git a/matrix-authentication-service/src/main.rs b/matrix-authentication-service/src/main.rs index 6c8e62719..839ec640c 100644 --- a/matrix-authentication-service/src/main.rs +++ b/matrix-authentication-service/src/main.rs @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![forbid(unsafe_code)] + +use anyhow::Context; +use tracing::{info_span, Instrument}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry}; mod config; @@ -24,6 +28,7 @@ mod templates; use self::config::RootConfig; use self::state::State; +use self::storage::MIGRATOR; #[async_std::main] async fn main() -> tide::Result<()> { @@ -32,26 +37,45 @@ async fn main() -> tide::Result<()> { let filter_layer = EnvFilter::try_from_default_env().or_else(|_| EnvFilter::try_new("info"))?; let subscriber = Registry::default().with(filter_layer).with(fmt_layer); - subscriber.try_init()?; + subscriber + .try_init() + .context("could not initialize logging")?; // Loading the config - let config = RootConfig::load()?; + let config = RootConfig::load().context("could not load config")?; + + // Connect to the database + let pool = config + .database + .connect() + .await + .context("could not connect to database")?; // Load and compile the templates - let templates = self::templates::load()?; + let templates = self::templates::load().context("could not load templates")?; // Create the shared state - let state = State::new(config, templates); + let state = State::new(config, templates, pool); state .storage() .load_static_clients(&state.config().oauth2.clients) .await; + // Run pending migrations + // TODO: make this a separate command + MIGRATOR + .run(state.storage().pool()) + .instrument(info_span!("migrations")) + .await + .context("could not run migrations")?; + // Start the server let address = state.config().http.address.clone(); let mut app = tide::with_state(state); app.with(tide_tracing::TraceMiddleware::new()); self::handlers::install(&mut app); - app.listen(address).await?; + app.listen(address) + .await + .context("could not start server")?; Ok(()) } diff --git a/matrix-authentication-service/src/state.rs b/matrix-authentication-service/src/state.rs index eb9c1a060..c282c4d98 100644 --- a/matrix-authentication-service/src/state.rs +++ b/matrix-authentication-service/src/state.rs @@ -16,6 +16,7 @@ use std::sync::Arc; use async_trait::async_trait; use csrf::AesGcmCsrfProtection; +use sqlx::PgPool; use tera::Tera; use tide::{ sessions::{MemoryStore, SessionMiddleware, SessionStore}, @@ -29,23 +30,23 @@ use crate::{config::RootConfig, storage::Storage}; pub struct State { config: Arc, templates: Arc, - storage: Arc, + storage: Arc>, session_store: Arc, csrf: Arc, } impl std::fmt::Debug for State { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "State") + f.debug_struct("State").finish_non_exhaustive() } } impl State { - pub fn new(config: RootConfig, templates: Tera) -> Self { + pub fn new(config: RootConfig, templates: Tera, pool: PgPool) -> Self { Self { config: Arc::new(config), templates: Arc::new(templates), - storage: Default::default(), + storage: Arc::new(Storage::new(pool)), session_store: Arc::new(MemoryStore::new()), csrf: Arc::new(AesGcmCsrfProtection::from_key( *b"01234567012345670123456701234567", @@ -57,7 +58,7 @@ impl State { &self.config } - pub fn storage(&self) -> &Storage { + pub fn storage(&self) -> &Storage { &self.storage } diff --git a/matrix-authentication-service/src/storage/client.rs b/matrix-authentication-service/src/storage/client.rs index 2c41f87d0..ec61ff703 100644 --- a/matrix-authentication-service/src/storage/client.rs +++ b/matrix-authentication-service/src/storage/client.rs @@ -57,7 +57,7 @@ impl Client { } } -impl super::Storage { +impl super::Storage { pub async fn load_static_clients(&self, clients: &[OAuth2ClientConfig]) { let mut storage = self.clients.write().await; for config in clients { @@ -93,7 +93,7 @@ mod tests { #[async_std::test] async fn test_login() { - let storage = Storage::default(); + let storage = Storage::new(()); // "bad" is a bad password and should not insert assert_eq!(storage.users.read().await.len(), 0); diff --git a/matrix-authentication-service/src/storage/mod.rs b/matrix-authentication-service/src/storage/mod.rs index 7eae5df24..2071f58ca 100644 --- a/matrix-authentication-service/src/storage/mod.rs +++ b/matrix-authentication-service/src/storage/mod.rs @@ -15,6 +15,7 @@ use std::collections::HashMap; use async_std::sync::RwLock; +use sqlx::migrate::Migrator; mod client; mod user; @@ -22,8 +23,25 @@ mod user; pub use self::client::{Client, ClientLookupError, InvalidRedirectUriError}; pub use self::user::User; -#[derive(Debug, Default)] -pub struct Storage { +pub static MIGRATOR: Migrator = sqlx::migrate!(); + +#[derive(Debug)] +pub struct Storage { + pool: Pool, clients: RwLock>, users: RwLock>, } + +impl Storage { + pub fn new(pool: Pool) -> Self { + Self { + pool, + clients: Default::default(), + users: Default::default(), + } + } + + pub fn pool(&self) -> &Pool { + &self.pool + } +} diff --git a/matrix-authentication-service/src/storage/user.rs b/matrix-authentication-service/src/storage/user.rs index f6adb293e..30f429e56 100644 --- a/matrix-authentication-service/src/storage/user.rs +++ b/matrix-authentication-service/src/storage/user.rs @@ -35,7 +35,7 @@ pub struct UserLoginError; #[error("Could not find user")] pub struct UserLookupError; -impl super::Storage { +impl super::Storage { pub async fn login(&self, name: &str, password: &str) -> Result { // Hardcoded bad password to test login failures if password == "bad" {