Microservice to bring 2FA to self hosted PDSes

eat: add opt-in per-request logging with JSON format support: eriko.eurosky.social #15

merged opened by baileytownsend.dev targeting main from feat/structured-request-logging
Labels

None yet.

Participants 1
AT URI
at://did:plc:rnpkyqnmsw4ipey6eotbdnnf/sh.tangled.repo.pull/3mg4yntcdwl22
+90 -337
Diff #0
+16 -262
Cargo.lock
··· 85 85 ] 86 86 87 87 [[package]] 88 - name = "async-channel" 89 - version = "1.9.0" 90 - source = "registry+https://github.com/rust-lang/crates.io-index" 91 - checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" 92 - dependencies = [ 93 - "concurrent-queue", 94 - "event-listener 2.5.3", 95 - "futures-core", 96 - ] 97 - 98 - [[package]] 99 - name = "async-channel" 100 - version = "2.5.0" 101 - source = "registry+https://github.com/rust-lang/crates.io-index" 102 - checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" 103 - dependencies = [ 104 - "concurrent-queue", 105 - "event-listener-strategy", 106 - "futures-core", 107 - "pin-project-lite", 108 - ] 109 - 110 - [[package]] 111 88 name = "async-compression" 112 89 version = "0.4.36" 113 90 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 121 98 ] 122 99 123 100 [[package]] 124 - name = "async-executor" 125 - version = "1.13.3" 126 - source = "registry+https://github.com/rust-lang/crates.io-index" 127 - checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" 128 - dependencies = [ 129 - "async-task", 130 - "concurrent-queue", 131 - "fastrand", 132 - "futures-lite", 133 - "pin-project-lite", 134 - "slab", 135 - ] 136 - 137 - [[package]] 138 - name = "async-global-executor" 139 - version = "2.4.1" 140 - source = "registry+https://github.com/rust-lang/crates.io-index" 141 - checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" 142 - dependencies = [ 143 - "async-channel 2.5.0", 144 - "async-executor", 145 - "async-io", 146 - "async-lock", 147 - "blocking", 148 - "futures-lite", 149 - "once_cell", 150 - ] 151 - 152 - [[package]] 153 - name = "async-io" 154 - version = "2.6.0" 155 - source = "registry+https://github.com/rust-lang/crates.io-index" 156 - checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" 157 - dependencies = [ 158 - "autocfg", 159 - "cfg-if", 160 - "concurrent-queue", 161 - "futures-io", 162 - "futures-lite", 163 - "parking", 164 - "polling", 165 - "rustix", 166 - "slab", 167 - "windows-sys 0.61.2", 168 - ] 169 - 170 - [[package]] 171 - name = "async-lock" 172 - version = "3.4.2" 173 - source = "registry+https://github.com/rust-lang/crates.io-index" 174 - checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" 175 - dependencies = [ 176 - "event-listener 5.4.1", 177 - "event-listener-strategy", 178 - "pin-project-lite", 179 - ] 180 - 181 - [[package]] 182 - name = "async-process" 183 - version = "2.5.0" 184 - source = "registry+https://github.com/rust-lang/crates.io-index" 185 - checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" 186 - dependencies = [ 187 - "async-channel 2.5.0", 188 - "async-io", 189 - "async-lock", 190 - "async-signal", 191 - "async-task", 192 - "blocking", 193 - "cfg-if", 194 - "event-listener 5.4.1", 195 - "futures-lite", 196 - "rustix", 197 - ] 198 - 199 - [[package]] 200 - name = "async-signal" 201 - version = "0.2.13" 202 - source = "registry+https://github.com/rust-lang/crates.io-index" 203 - checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" 204 - dependencies = [ 205 - "async-io", 206 - "async-lock", 207 - "atomic-waker", 208 - "cfg-if", 209 - "futures-core", 210 - "futures-io", 211 - "rustix", 212 - "signal-hook-registry", 213 - "slab", 214 - "windows-sys 0.61.2", 215 - ] 216 - 217 - [[package]] 218 - name = "async-std" 219 - version = "1.13.2" 220 - source = "registry+https://github.com/rust-lang/crates.io-index" 221 - checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" 222 - dependencies = [ 223 - "async-channel 1.9.0", 224 - "async-global-executor", 225 - "async-io", 226 - "async-lock", 227 - "async-process", 228 - "crossbeam-utils", 229 - "futures-channel", 230 - "futures-core", 231 - "futures-io", 232 - "futures-lite", 233 - "gloo-timers", 234 - "kv-log-macro", 235 - "log", 236 - "memchr", 237 - "once_cell", 238 - "pin-project-lite", 239 - "pin-utils", 240 - "slab", 241 - "wasm-bindgen-futures", 242 - ] 243 - 244 - [[package]] 245 - name = "async-task" 246 - version = "4.7.1" 247 - source = "registry+https://github.com/rust-lang/crates.io-index" 248 - checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" 249 - 250 - [[package]] 251 101 name = "async-trait" 252 102 version = "0.1.89" 253 103 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 437 287 checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 438 288 dependencies = [ 439 289 "generic-array", 440 - ] 441 - 442 - [[package]] 443 - name = "blocking" 444 - version = "1.6.2" 445 - source = "registry+https://github.com/rust-lang/crates.io-index" 446 - checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" 447 - dependencies = [ 448 - "async-channel 2.5.0", 449 - "async-task", 450 - "futures-io", 451 - "futures-lite", 452 - "piper", 453 290 ] 454 291 455 292 [[package]] ··· 1172 1009 1173 1010 [[package]] 1174 1011 name = "event-listener" 1175 - version = "2.5.3" 1176 - source = "registry+https://github.com/rust-lang/crates.io-index" 1177 - checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 1178 - 1179 - [[package]] 1180 - name = "event-listener" 1181 1012 version = "5.4.1" 1182 1013 source = "registry+https://github.com/rust-lang/crates.io-index" 1183 1014 checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" ··· 1188 1019 ] 1189 1020 1190 1021 [[package]] 1191 - name = "event-listener-strategy" 1192 - version = "0.5.4" 1193 - source = "registry+https://github.com/rust-lang/crates.io-index" 1194 - checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" 1195 - dependencies = [ 1196 - "event-listener 5.4.1", 1197 - "pin-project-lite", 1198 - ] 1199 - 1200 - [[package]] 1201 1022 name = "fastrand" 1202 1023 version = "2.3.0" 1203 1024 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1481 1302 ] 1482 1303 1483 1304 [[package]] 1484 - name = "gloo-timers" 1485 - version = "0.3.0" 1486 - source = "registry+https://github.com/rust-lang/crates.io-index" 1487 - checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" 1488 - dependencies = [ 1489 - "futures-channel", 1490 - "futures-core", 1491 - "js-sys", 1492 - "wasm-bindgen", 1493 - ] 1494 - 1495 - [[package]] 1496 1305 name = "governor" 1497 1306 version = "0.10.4" 1498 1307 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1654 1463 version = "0.5.0" 1655 1464 source = "registry+https://github.com/rust-lang/crates.io-index" 1656 1465 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1657 - 1658 - [[package]] 1659 - name = "hermit-abi" 1660 - version = "0.5.2" 1661 - source = "registry+https://github.com/rust-lang/crates.io-index" 1662 - checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" 1663 1466 1664 1467 [[package]] 1665 1468 name = "hex" ··· 2247 2050 ] 2248 2051 2249 2052 [[package]] 2250 - name = "kv-log-macro" 2251 - version = "1.0.7" 2252 - source = "registry+https://github.com/rust-lang/crates.io-index" 2253 - checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" 2254 - dependencies = [ 2255 - "log", 2256 - ] 2257 - 2258 - [[package]] 2259 2053 name = "langtag" 2260 2054 version = "0.4.0" 2261 2055 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2281 2075 source = "registry+https://github.com/rust-lang/crates.io-index" 2282 2076 checksum = "9e13e10e8818f8b2a60f52cb127041d388b89f3a96a62be9ceaffa22262fef7f" 2283 2077 dependencies = [ 2284 - "async-std", 2285 2078 "async-trait", 2286 2079 "base64", 2287 2080 "chumsky", ··· 2339 2132 ] 2340 2133 2341 2134 [[package]] 2342 - name = "linux-raw-sys" 2343 - version = "0.11.0" 2344 - source = "registry+https://github.com/rust-lang/crates.io-index" 2345 - checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" 2346 - 2347 - [[package]] 2348 2135 name = "litemap" 2349 2136 version = "0.8.1" 2350 2137 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2364 2151 version = "0.4.29" 2365 2152 source = "registry+https://github.com/rust-lang/crates.io-index" 2366 2153 checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" 2367 - dependencies = [ 2368 - "value-bag", 2369 - ] 2370 2154 2371 2155 [[package]] 2372 2156 name = "loom" ··· 2810 2594 "tower_governor", 2811 2595 "tracing", 2812 2596 "tracing-subscriber", 2813 - "url", 2814 2597 "urlencoding", 2598 + "valuable", 2815 2599 ] 2816 2600 2817 2601 [[package]] ··· 2905 2689 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 2906 2690 2907 2691 [[package]] 2908 - name = "piper" 2909 - version = "0.2.4" 2910 - source = "registry+https://github.com/rust-lang/crates.io-index" 2911 - checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" 2912 - dependencies = [ 2913 - "atomic-waker", 2914 - "fastrand", 2915 - "futures-io", 2916 - ] 2917 - 2918 - [[package]] 2919 2692 name = "pkcs1" 2920 2693 version = "0.7.5" 2921 2694 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2941 2714 version = "0.3.32" 2942 2715 source = "registry+https://github.com/rust-lang/crates.io-index" 2943 2716 checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 2944 - 2945 - [[package]] 2946 - name = "polling" 2947 - version = "3.11.0" 2948 - source = "registry+https://github.com/rust-lang/crates.io-index" 2949 - checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" 2950 - dependencies = [ 2951 - "cfg-if", 2952 - "concurrent-queue", 2953 - "hermit-abi", 2954 - "pin-project-lite", 2955 - "rustix", 2956 - "windows-sys 0.61.2", 2957 - ] 2958 2717 2959 2718 [[package]] 2960 2719 name = "portable-atomic" ··· 3448 3207 ] 3449 3208 3450 3209 [[package]] 3451 - name = "rustix" 3452 - version = "1.1.3" 3453 - source = "registry+https://github.com/rust-lang/crates.io-index" 3454 - checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" 3455 - dependencies = [ 3456 - "bitflags", 3457 - "errno", 3458 - "libc", 3459 - "linux-raw-sys", 3460 - "windows-sys 0.52.0", 3461 - ] 3462 - 3463 - [[package]] 3464 3210 name = "rustls" 3465 3211 version = "0.23.35" 3466 3212 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3921 3667 "crc", 3922 3668 "crossbeam-queue", 3923 3669 "either", 3924 - "event-listener 5.4.1", 3670 + "event-listener", 3925 3671 "futures-core", 3926 3672 "futures-intrusive", 3927 3673 "futures-io", ··· 4457 4203 "tower", 4458 4204 "tower-layer", 4459 4205 "tower-service", 4206 + "tracing", 4460 4207 ] 4461 4208 4462 4209 [[package]] ··· 4533 4280 ] 4534 4281 4535 4282 [[package]] 4283 + name = "tracing-serde" 4284 + version = "0.2.0" 4285 + source = "registry+https://github.com/rust-lang/crates.io-index" 4286 + checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" 4287 + dependencies = [ 4288 + "serde", 4289 + "tracing-core", 4290 + ] 4291 + 4292 + [[package]] 4536 4293 name = "tracing-subscriber" 4537 4294 version = "0.3.22" 4538 4295 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4542 4299 "nu-ansi-term", 4543 4300 "once_cell", 4544 4301 "regex-automata", 4302 + "serde", 4303 + "serde_json", 4545 4304 "sharded-slab", 4546 4305 "smallvec", 4547 4306 "thread_local", 4548 4307 "tracing", 4549 4308 "tracing-core", 4550 4309 "tracing-log", 4310 + "tracing-serde", 4551 4311 ] 4552 4312 4553 4313 [[package]] ··· 4677 4437 version = "0.1.1" 4678 4438 source = "registry+https://github.com/rust-lang/crates.io-index" 4679 4439 checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 4680 - 4681 - [[package]] 4682 - name = "value-bag" 4683 - version = "1.12.0" 4684 - source = "registry+https://github.com/rust-lang/crates.io-index" 4685 - checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" 4686 4440 4687 4441 [[package]] 4688 4442 name = "vcpkg"
+5 -5
Cargo.toml
··· 11 11 dotenvy = "0.15.7" 12 12 serde = { version = "1.0", features = ["derive"] } 13 13 serde_json = "1.0" 14 - tracing = "0.1" 15 - tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] } 14 + tracing = { version = "0.1.44" } 15 + tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json", "serde", ] } 16 16 hyper-util = { version = "0.1.19", features = ["client", "client-legacy"] } 17 - tower-http = { version = "0.6", features = ["cors", "compression-zstd"] } 17 + tower-http = { version = "0.6", features = ["cors", "compression-zstd", "trace"] } 18 18 tower_governor = { version = "0.8.0", features = ["axum", "tracing"] } 19 19 hex = "0.4" 20 20 jwt-compact = { version = "0.8.0", features = ["es256k"] } ··· 22 22 #Leaveing these two cause I think it is needed by the email crate for ssl 23 23 aws-lc-rs = "1.15.2" 24 24 rustls = { version = "0.23", default-features = false, features = ["tls12", "std", "logging", "aws_lc_rs"] } 25 - lettre = { version = "0.11", default-features = false, features = ["builder", "webpki-roots", "rustls", "aws-lc-rs", "smtp-transport", "sendmail-transport", "tokio1", "tokio1-rustls"] } 25 + lettre = { version = "0.11", default-features = false, features = ["builder", "webpki-roots", "rustls", "aws-lc-rs", "smtp-transport", "tokio1", "tokio1-rustls"] } 26 26 handlebars = { version = "6.4.0", features = ["rust-embed"] } 27 27 rust-embed = "8.9.0" 28 28 axum-template = { version = "3.0.0", features = ["handlebars"] } ··· 35 35 multibase = "0.9.2" 36 36 reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } 37 37 urlencoding = "2.1" 38 - url = "2.5.7" 39 38 html-escape = "0.2.13" 40 39 josekit = "0.10.3" 41 40 dashmap = "6.1" 42 41 tower = "0.5" 42 + valuable = "0.1.1"
+5 -5
src/gate.rs
··· 38 38 redirect_url: Option<String>, 39 39 } 40 40 41 - /// GET /gate/signup - Display the captcha page 41 + /// GET /gate - Display the captcha page 42 42 pub async fn get_gate( 43 43 Query(params): Query<GateQuery>, 44 44 State(state): State<AppState>, ··· 75 75 .into_response() 76 76 } 77 77 78 - /// POST /gate/signup - Verify captcha and redirect 78 + /// POST /gate - Verify captcha and redirect 79 79 pub async fn post_gate( 80 80 State(state): State<AppState>, 81 81 Query(params): Query<GateQuery>, ··· 134 134 log::error!("Failed to verify hCaptcha: {}", e); 135 135 136 136 return Redirect::to(&format!( 137 - "/gate/signup?handle={}&state={}&error={}", 137 + "/gate?handle={}&state={}&error={}", 138 138 url_encode(&params.handle), 139 139 url_encode(&params.state), 140 140 url_encode("Verification failed. Please try again.") ··· 149 149 log::error!("Failed to parse hCaptcha response: {}", e); 150 150 151 151 return Redirect::to(&format!( 152 - "/gate/signup?handle={}&state={}&error={}", 152 + "/gate?handle={}&state={}&error={}", 153 153 url_encode(&params.handle), 154 154 url_encode(&params.state), 155 155 url_encode("Verification failed. Please try again.") ··· 165 165 captcha_result.error_codes 166 166 ); 167 167 return Redirect::to(&format!( 168 - "/gate/signup?handle={}&state={}&error={}", 168 + "/gate?handle={}&state={}&error={}", 169 169 url_encode(&params.handle), 170 170 url_encode(&params.state), 171 171 url_encode("Verification failed. Please try again.")
+1 -1
src/helpers.rs
··· 17 17 use jacquard_identity::{PublicResolver, resolver::IdentityResolver}; 18 18 use josekit::jwe::alg::direct::DirectJweAlgorithm; 19 19 use lettre::{ 20 - Message, 20 + AsyncTransport, Message, 21 21 message::{MultiPart, SinglePart, header}, 22 22 }; 23 23 use rand::Rng;
-46
src/mailer.rs
··· 1 - use anyhow::Context; 2 - use lettre::{AsyncSendmailTransport, AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor}; 3 - use std::env; 4 - use url::Url; 5 - 6 - pub enum Mailer { 7 - Smtp(AsyncSmtpTransport<Tokio1Executor>), 8 - Sendmail(AsyncSendmailTransport<Tokio1Executor>), 9 - } 10 - 11 - impl Mailer { 12 - pub async fn send(&self, msg: Message) -> anyhow::Result<()> { 13 - match self { 14 - Mailer::Smtp(m) => { 15 - m.send(msg).await.context("SMTP send failed")?; 16 - Ok(()) 17 - } 18 - Mailer::Sendmail(m) => { 19 - m.send(msg).await.context("sendmail send failed")?; 20 - Ok(()) 21 - } 22 - } 23 - } 24 - } 25 - 26 - pub fn build_mailer_from_env() -> anyhow::Result<Mailer> { 27 - let raw = env::var("PDS_EMAIL_SMTP_URL") 28 - .context("PDS_EMAIL_SMTP_URL is not set in your pds.env file")?; 29 - 30 - let url = Url::parse(&raw).context("PDS_EMAIL_SMTP_URL is not a valid URL")?; 31 - 32 - let use_sendmail = url.scheme() == "sendmail" 33 - || url 34 - .query_pairs() 35 - .any(|(k, v)| k == "sendmail" && v == "true"); 36 - 37 - if use_sendmail { 38 - Ok(Mailer::Sendmail( 39 - AsyncSendmailTransport::<Tokio1Executor>::new(), 40 - )) 41 - } else { 42 - Ok(Mailer::Smtp( 43 - AsyncSmtpTransport::<Tokio1Executor>::from_url(raw.as_str())?.build(), 44 - )) 45 - } 46 - }
+62 -14
src/main.rs
··· 1 1 #![warn(clippy::unwrap_used)] 2 2 use crate::gate::{get_gate, post_gate}; 3 - use crate::mailer::{Mailer, build_mailer_from_env}; 4 3 use crate::oauth_provider::sign_in; 5 4 use crate::xrpc::com_atproto_server::{ 6 5 create_account, create_session, describe_server, get_session, update_email, 7 6 }; 8 - use anyhow::Result; 9 7 use axum::{ 10 8 Router, 11 9 body::Body, ··· 20 18 use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; 21 19 use jacquard_common::types::did::Did; 22 20 use jacquard_identity::{PublicResolver, resolver::PlcSource}; 21 + use lettre::{AsyncSmtpTransport, Tokio1Executor}; 23 22 use rand::Rng; 24 23 use rust_embed::RustEmbed; 25 24 use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode}; ··· 31 30 use tower_governor::{ 32 31 GovernorLayer, governor::GovernorConfigBuilder, key_extractor::SmartIpKeyExtractor, 33 32 }; 33 + use tower_http::trace::{DefaultOnRequest, HttpMakeClassifier}; 34 34 use tower_http::{ 35 35 compression::CompressionLayer, 36 - cors::{AllowHeaders, Any, CorsLayer}, 36 + cors::{Any, CorsLayer}, 37 + trace::TraceLayer, 37 38 }; 38 - use tracing::log; 39 + use tracing::{Span, log}; 39 40 use tracing_subscriber::{EnvFilter, fmt, prelude::*}; 40 41 41 42 mod auth; 42 43 mod gate; 43 44 pub mod helpers; 44 - pub mod mailer; 45 45 mod middleware; 46 46 mod oauth_provider; 47 47 mod xrpc; ··· 153 153 account_pool: SqlitePool, 154 154 pds_gatekeeper_pool: SqlitePool, 155 155 reverse_proxy_client: HyperUtilClient, 156 - mailer: Arc<Mailer>, 156 + mailer: AsyncSmtpTransport<Tokio1Executor>, 157 157 template_engine: Engine<Handlebars<'static>>, 158 158 resolver: Arc<PublicResolver>, 159 159 handle_cache: auth::HandleCache, ··· 199 199 200 200 #[tokio::main] 201 201 async fn main() -> Result<(), Box<dyn std::error::Error>> { 202 - setup_tracing(); 203 202 let pds_env_location = 204 203 env::var("PDS_ENV_LOCATION").unwrap_or_else(|_| "/pds/pds.env".to_string()); 205 204 ··· 209 208 "Error loading pds.env file (ignore if you loaded your variables in the environment somehow else): {e}" 210 209 ); 211 210 } 211 + // Sets up after the pds.env file is loaded 212 + setup_tracing(); 212 213 213 214 let pds_root = 214 215 env::var("PDS_DATA_DIRECTORY").expect("PDS_DATA_DIRECTORY is not set in your pds.env file"); 215 216 let account_db_url = format!("{pds_root}/account.sqlite"); 216 217 217 218 let account_options = SqliteConnectOptions::new() 218 - .journal_mode(SqliteJournalMode::Wal) 219 219 .filename(account_db_url) 220 220 .busy_timeout(Duration::from_secs(5)); 221 221 ··· 247 247 .build(HttpConnector::new()); 248 248 249 249 //Emailer set up 250 - let mailer = Arc::new(build_mailer_from_env()?); 250 + let smtp_url = 251 + env::var("PDS_EMAIL_SMTP_URL").expect("PDS_EMAIL_SMTP_URL is not set in your pds.env file"); 251 252 253 + let mailer: AsyncSmtpTransport<Tokio1Executor> = 254 + AsyncSmtpTransport::<Tokio1Executor>::from_url(smtp_url.as_str())?.build(); 252 255 //Email templates setup 253 256 let mut hbs = Handlebars::new(); 254 257 ··· 352 355 let cors = CorsLayer::new() 353 356 .allow_origin(Any) 354 357 .allow_methods([Method::GET, Method::OPTIONS, Method::POST]) 355 - .allow_headers(AllowHeaders::mirror_request()); 358 + .allow_headers(Any); 356 359 357 360 let mut app = Router::new() 358 361 .route("/", get(root_handler)) ··· 385 388 ); 386 389 } 387 390 391 + let request_logging = env::var("GATEKEEPER_REQUEST_LOGGING") 392 + .map(|v| v.eq_ignore_ascii_case("true") || v == "1") 393 + .unwrap_or(false); 394 + 395 + if request_logging { 396 + app = app.layer(request_trace_layer()); 397 + } 398 + 388 399 let app = app 389 400 .layer(CompressionLayer::new()) 390 401 .layer(cors) ··· 416 427 417 428 fn setup_tracing() { 418 429 let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); 419 - tracing_subscriber::registry() 420 - .with(env_filter) 421 - .with(fmt::layer()) 422 - .init(); 430 + let json = env::var("GATEKEEPER_LOG_FORMAT") 431 + .map(|v| v.eq_ignore_ascii_case("json")) 432 + .unwrap_or(false); 433 + 434 + if json { 435 + tracing_subscriber::registry() 436 + .with(env_filter) 437 + .with(fmt::layer().json()) 438 + .init(); 439 + } else { 440 + tracing_subscriber::registry() 441 + .with(env_filter) 442 + .with(fmt::layer()) 443 + .init(); 444 + } 423 445 } 424 446 425 447 async fn shutdown_signal() { ··· 447 469 _ = terminate => {}, 448 470 } 449 471 } 472 + 473 + fn request_trace_layer() -> TraceLayer< 474 + HttpMakeClassifier, 475 + impl Fn(&axum::http::Request<Body>) -> Span + Clone, 476 + DefaultOnRequest, 477 + impl Fn(&axum::http::Response<Body>, Duration, &Span) + Clone, 478 + > { 479 + TraceLayer::new_for_http() 480 + .make_span_with(|req: &axum::http::Request<Body>| { 481 + let headers = req.headers(); 482 + tracing::info_span!("request", 483 + method = %req.method(), 484 + path = %req.uri().path(), 485 + headers = %format!("{:?}", headers), 486 + ) 487 + }) 488 + .on_response( 489 + |resp: &axum::http::Response<Body>, latency: Duration, _span: &tracing::Span| { 490 + tracing::info!( 491 + status = resp.status().as_u16(), 492 + latency_ms = latency.as_millis() as u64, 493 + "response" 494 + ); 495 + }, 496 + ) 497 + }
+1 -4
src/xrpc/com_atproto_server.rs
··· 233 233 .bind(&did_row.0) 234 234 .execute(&state.pds_gatekeeper_pool) 235 235 .await 236 - .map_err(|err| { 237 - log::error!("Error enabling 2FA: {err}"); 238 - StatusCode::BAD_REQUEST 239 - })?; 236 + .map_err(|_| StatusCode::BAD_REQUEST)?; 240 237 241 238 Ok(StatusCode::OK.into_response()) 242 239 }

History

2 rounds 0 comments
sign up or login to add to the discussion
2 commits
expand
feat: add opt-in per-request logging
light changes to logging changes
expand 0 comments
pull request successfully merged
2 commits
expand
feat: add opt-in per-request logging
light changes to logging changes
expand 0 comments