I've been saying "PDSes seem easy enough, they're what, some CRUD to a db? I can do that in my sleep". well i'm sleeping rn so let's go
at main 16 kB view raw
1pub mod api; 2pub mod appview; 3pub mod auth; 4pub mod cache; 5pub mod circuit_breaker; 6pub mod comms; 7pub mod config; 8pub mod crawlers; 9pub mod handle; 10pub mod image; 11pub mod metrics; 12pub mod oauth; 13pub mod plc; 14pub mod rate_limit; 15pub mod repo; 16pub mod state; 17pub mod storage; 18pub mod sync; 19pub mod util; 20pub mod validation; 21 22use axum::{ 23 Router, 24 http::Method, 25 middleware, 26 routing::{any, get, post}, 27}; 28use state::AppState; 29use tower_http::cors::{Any, CorsLayer}; 30use tower_http::services::{ServeDir, ServeFile}; 31 32pub fn app(state: AppState) -> Router { 33 let router = Router::new() 34 .route("/metrics", get(metrics::metrics_handler)) 35 .route("/health", get(api::server::health)) 36 .route("/xrpc/_health", get(api::server::health)) 37 .route("/robots.txt", get(api::server::robots_txt)) 38 .route( 39 "/xrpc/com.atproto.server.describeServer", 40 get(api::server::describe_server), 41 ) 42 .route( 43 "/xrpc/com.atproto.server.createAccount", 44 post(api::identity::create_account), 45 ) 46 .route( 47 "/xrpc/com.atproto.server.createSession", 48 post(api::server::create_session), 49 ) 50 .route( 51 "/xrpc/com.atproto.server.getSession", 52 get(api::server::get_session), 53 ) 54 .route( 55 "/xrpc/com.tranquil.account.listSessions", 56 get(api::server::list_sessions), 57 ) 58 .route( 59 "/xrpc/com.tranquil.account.revokeSession", 60 post(api::server::revoke_session), 61 ) 62 .route( 63 "/xrpc/com.atproto.server.deleteSession", 64 post(api::server::delete_session), 65 ) 66 .route( 67 "/xrpc/com.atproto.server.refreshSession", 68 post(api::server::refresh_session), 69 ) 70 .route( 71 "/xrpc/com.atproto.server.confirmSignup", 72 post(api::server::confirm_signup), 73 ) 74 .route( 75 "/xrpc/com.atproto.server.resendVerification", 76 post(api::server::resend_verification), 77 ) 78 .route( 79 "/xrpc/com.atproto.server.getServiceAuth", 80 get(api::server::get_service_auth), 81 ) 82 .route( 83 "/xrpc/com.atproto.identity.resolveHandle", 84 get(api::identity::resolve_handle), 85 ) 86 .route( 87 "/xrpc/com.atproto.repo.createRecord", 88 post(api::repo::create_record), 89 ) 90 .route( 91 "/xrpc/com.atproto.repo.putRecord", 92 post(api::repo::put_record), 93 ) 94 .route( 95 "/xrpc/com.atproto.repo.getRecord", 96 get(api::repo::get_record), 97 ) 98 .route( 99 "/xrpc/com.atproto.repo.deleteRecord", 100 post(api::repo::delete_record), 101 ) 102 .route( 103 "/xrpc/com.atproto.repo.listRecords", 104 get(api::repo::list_records), 105 ) 106 .route( 107 "/xrpc/com.atproto.repo.describeRepo", 108 get(api::repo::describe_repo), 109 ) 110 .route( 111 "/xrpc/com.atproto.repo.uploadBlob", 112 post(api::repo::upload_blob), 113 ) 114 .route( 115 "/xrpc/com.atproto.repo.applyWrites", 116 post(api::repo::apply_writes), 117 ) 118 .route( 119 "/xrpc/com.atproto.sync.getLatestCommit", 120 get(sync::get_latest_commit), 121 ) 122 .route("/xrpc/com.atproto.sync.listRepos", get(sync::list_repos)) 123 .route("/xrpc/com.atproto.sync.getBlob", get(sync::get_blob)) 124 .route("/xrpc/com.atproto.sync.listBlobs", get(sync::list_blobs)) 125 .route( 126 "/xrpc/com.atproto.sync.getRepoStatus", 127 get(sync::get_repo_status), 128 ) 129 .route( 130 "/xrpc/com.atproto.server.checkAccountStatus", 131 get(api::server::check_account_status), 132 ) 133 .route( 134 "/xrpc/com.atproto.identity.getRecommendedDidCredentials", 135 get(api::identity::get_recommended_did_credentials), 136 ) 137 .route( 138 "/xrpc/com.atproto.repo.listMissingBlobs", 139 get(api::repo::list_missing_blobs), 140 ) 141 .route( 142 "/xrpc/com.atproto.sync.notifyOfUpdate", 143 post(sync::notify_of_update), 144 ) 145 .route( 146 "/xrpc/com.atproto.sync.requestCrawl", 147 post(sync::request_crawl), 148 ) 149 .route("/xrpc/com.atproto.sync.getBlocks", get(sync::get_blocks)) 150 .route("/xrpc/com.atproto.sync.getRepo", get(sync::get_repo)) 151 .route("/xrpc/com.atproto.sync.getRecord", get(sync::get_record)) 152 .route( 153 "/xrpc/com.atproto.sync.subscribeRepos", 154 get(sync::subscribe_repos), 155 ) 156 .route("/xrpc/com.atproto.sync.getHead", get(sync::get_head)) 157 .route( 158 "/xrpc/com.atproto.sync.getCheckout", 159 get(sync::get_checkout), 160 ) 161 .route( 162 "/xrpc/com.atproto.moderation.createReport", 163 post(api::moderation::create_report), 164 ) 165 .route( 166 "/xrpc/com.atproto.admin.getAccountInfo", 167 get(api::admin::get_account_info), 168 ) 169 .route( 170 "/xrpc/com.atproto.admin.getAccountInfos", 171 get(api::admin::get_account_infos), 172 ) 173 .route( 174 "/xrpc/com.atproto.admin.searchAccounts", 175 get(api::admin::search_accounts), 176 ) 177 .route( 178 "/xrpc/com.atproto.server.activateAccount", 179 post(api::server::activate_account), 180 ) 181 .route( 182 "/xrpc/com.atproto.server.deactivateAccount", 183 post(api::server::deactivate_account), 184 ) 185 .route( 186 "/xrpc/com.atproto.server.requestAccountDelete", 187 post(api::server::request_account_delete), 188 ) 189 .route( 190 "/xrpc/com.atproto.server.deleteAccount", 191 post(api::server::delete_account), 192 ) 193 .route( 194 "/xrpc/com.atproto.server.requestPasswordReset", 195 post(api::server::request_password_reset), 196 ) 197 .route( 198 "/xrpc/com.atproto.server.resetPassword", 199 post(api::server::reset_password), 200 ) 201 .route( 202 "/xrpc/com.tranquil.account.changePassword", 203 post(api::server::change_password), 204 ) 205 .route( 206 "/xrpc/com.atproto.server.requestEmailUpdate", 207 post(api::server::request_email_update), 208 ) 209 .route( 210 "/xrpc/com.atproto.server.confirmEmail", 211 post(api::server::confirm_email), 212 ) 213 .route( 214 "/xrpc/com.atproto.server.updateEmail", 215 post(api::server::update_email), 216 ) 217 .route( 218 "/xrpc/com.atproto.server.reserveSigningKey", 219 post(api::server::reserve_signing_key), 220 ) 221 .route( 222 "/xrpc/com.atproto.identity.updateHandle", 223 post(api::identity::update_handle), 224 ) 225 .route( 226 "/xrpc/com.atproto.identity.requestPlcOperationSignature", 227 post(api::identity::request_plc_operation_signature), 228 ) 229 .route( 230 "/xrpc/com.atproto.identity.signPlcOperation", 231 post(api::identity::sign_plc_operation), 232 ) 233 .route( 234 "/xrpc/com.atproto.identity.submitPlcOperation", 235 post(api::identity::submit_plc_operation), 236 ) 237 .route( 238 "/xrpc/com.atproto.repo.importRepo", 239 post(api::repo::import_repo), 240 ) 241 .route( 242 "/xrpc/com.atproto.admin.deleteAccount", 243 post(api::admin::delete_account), 244 ) 245 .route( 246 "/xrpc/com.atproto.admin.updateAccountEmail", 247 post(api::admin::update_account_email), 248 ) 249 .route( 250 "/xrpc/com.atproto.admin.updateAccountHandle", 251 post(api::admin::update_account_handle), 252 ) 253 .route( 254 "/xrpc/com.atproto.admin.updateAccountPassword", 255 post(api::admin::update_account_password), 256 ) 257 .route( 258 "/xrpc/com.atproto.server.listAppPasswords", 259 get(api::server::list_app_passwords), 260 ) 261 .route( 262 "/xrpc/com.atproto.server.createAppPassword", 263 post(api::server::create_app_password), 264 ) 265 .route( 266 "/xrpc/com.atproto.server.revokeAppPassword", 267 post(api::server::revoke_app_password), 268 ) 269 .route( 270 "/xrpc/com.atproto.server.createInviteCode", 271 post(api::server::create_invite_code), 272 ) 273 .route( 274 "/xrpc/com.atproto.server.createInviteCodes", 275 post(api::server::create_invite_codes), 276 ) 277 .route( 278 "/xrpc/com.atproto.server.getAccountInviteCodes", 279 get(api::server::get_account_invite_codes), 280 ) 281 .route( 282 "/xrpc/com.atproto.server.createTotpSecret", 283 post(api::server::create_totp_secret), 284 ) 285 .route( 286 "/xrpc/com.atproto.server.enableTotp", 287 post(api::server::enable_totp), 288 ) 289 .route( 290 "/xrpc/com.atproto.server.disableTotp", 291 post(api::server::disable_totp), 292 ) 293 .route( 294 "/xrpc/com.atproto.server.getTotpStatus", 295 get(api::server::get_totp_status), 296 ) 297 .route( 298 "/xrpc/com.atproto.server.regenerateBackupCodes", 299 post(api::server::regenerate_backup_codes), 300 ) 301 .route( 302 "/xrpc/com.atproto.server.startPasskeyRegistration", 303 post(api::server::start_passkey_registration), 304 ) 305 .route( 306 "/xrpc/com.atproto.server.finishPasskeyRegistration", 307 post(api::server::finish_passkey_registration), 308 ) 309 .route( 310 "/xrpc/com.atproto.server.listPasskeys", 311 get(api::server::list_passkeys), 312 ) 313 .route( 314 "/xrpc/com.atproto.server.deletePasskey", 315 post(api::server::delete_passkey), 316 ) 317 .route( 318 "/xrpc/com.atproto.server.updatePasskey", 319 post(api::server::update_passkey), 320 ) 321 .route( 322 "/xrpc/com.atproto.admin.getInviteCodes", 323 get(api::admin::get_invite_codes), 324 ) 325 .route( 326 "/xrpc/com.tranquil.admin.getServerStats", 327 get(api::admin::get_server_stats), 328 ) 329 .route( 330 "/xrpc/com.atproto.admin.disableAccountInvites", 331 post(api::admin::disable_account_invites), 332 ) 333 .route( 334 "/xrpc/com.atproto.admin.enableAccountInvites", 335 post(api::admin::enable_account_invites), 336 ) 337 .route( 338 "/xrpc/com.atproto.admin.disableInviteCodes", 339 post(api::admin::disable_invite_codes), 340 ) 341 .route( 342 "/xrpc/com.atproto.admin.getSubjectStatus", 343 get(api::admin::get_subject_status), 344 ) 345 .route( 346 "/xrpc/com.atproto.admin.updateSubjectStatus", 347 post(api::admin::update_subject_status), 348 ) 349 .route( 350 "/xrpc/com.atproto.admin.sendEmail", 351 post(api::admin::send_email), 352 ) 353 .route( 354 "/xrpc/app.bsky.actor.getPreferences", 355 get(api::actor::get_preferences), 356 ) 357 .route( 358 "/xrpc/app.bsky.actor.putPreferences", 359 post(api::actor::put_preferences), 360 ) 361 .route("/.well-known/did.json", get(api::identity::well_known_did)) 362 .route( 363 "/.well-known/atproto-did", 364 get(api::identity::well_known_atproto_did), 365 ) 366 .route("/u/{handle}/did.json", get(api::identity::user_did_doc)) 367 .route( 368 "/.well-known/oauth-protected-resource", 369 get(oauth::endpoints::oauth_protected_resource), 370 ) 371 .route( 372 "/.well-known/oauth-authorization-server", 373 get(oauth::endpoints::oauth_authorization_server), 374 ) 375 .route("/oauth/jwks", get(oauth::endpoints::oauth_jwks)) 376 .route( 377 "/oauth/client-metadata.json", 378 get(oauth::endpoints::frontend_client_metadata), 379 ) 380 .route( 381 "/oauth/par", 382 post(oauth::endpoints::pushed_authorization_request), 383 ) 384 .route("/oauth/authorize", get(oauth::endpoints::authorize_get)) 385 .route("/oauth/authorize", post(oauth::endpoints::authorize_post)) 386 .route( 387 "/oauth/authorize/accounts", 388 get(oauth::endpoints::authorize_accounts), 389 ) 390 .route( 391 "/oauth/authorize/select", 392 post(oauth::endpoints::authorize_select), 393 ) 394 .route( 395 "/oauth/authorize/2fa", 396 get(oauth::endpoints::authorize_2fa_get), 397 ) 398 .route( 399 "/oauth/authorize/2fa", 400 post(oauth::endpoints::authorize_2fa_post), 401 ) 402 .route( 403 "/oauth/passkey/check", 404 get(oauth::endpoints::check_user_has_passkeys), 405 ) 406 .route( 407 "/oauth/security-status", 408 get(oauth::endpoints::check_user_security_status), 409 ) 410 .route( 411 "/oauth/passkey/start", 412 post(oauth::endpoints::passkey_start), 413 ) 414 .route( 415 "/oauth/passkey/finish", 416 post(oauth::endpoints::passkey_finish), 417 ) 418 .route( 419 "/oauth/authorize/deny", 420 post(oauth::endpoints::authorize_deny), 421 ) 422 .route( 423 "/oauth/authorize/consent", 424 get(oauth::endpoints::consent_get), 425 ) 426 .route( 427 "/oauth/authorize/consent", 428 post(oauth::endpoints::consent_post), 429 ) 430 .route("/oauth/token", post(oauth::endpoints::token_endpoint)) 431 .route("/oauth/revoke", post(oauth::endpoints::revoke_token)) 432 .route( 433 "/oauth/introspect", 434 post(oauth::endpoints::introspect_token), 435 ) 436 .route( 437 "/xrpc/com.atproto.temp.checkSignupQueue", 438 get(api::temp::check_signup_queue), 439 ) 440 .route( 441 "/xrpc/com.atproto.temp.dereferenceScope", 442 post(api::temp::dereference_scope), 443 ) 444 .route( 445 "/xrpc/com.tranquil.account.getNotificationPrefs", 446 get(api::notification_prefs::get_notification_prefs), 447 ) 448 .route( 449 "/xrpc/com.tranquil.account.updateNotificationPrefs", 450 post(api::notification_prefs::update_notification_prefs), 451 ) 452 .route( 453 "/xrpc/com.tranquil.account.getNotificationHistory", 454 get(api::notification_prefs::get_notification_history), 455 ) 456 .route( 457 "/xrpc/com.tranquil.account.confirmChannelVerification", 458 post(api::verification::confirm_channel_verification), 459 ) 460 .route("/xrpc/{*method}", any(api::proxy::proxy_handler)) 461 .layer(middleware::from_fn(metrics::metrics_middleware)) 462 .layer( 463 CorsLayer::new() 464 .allow_origin(Any) 465 .allow_methods([Method::GET, Method::POST, Method::OPTIONS]) 466 .allow_headers(Any), 467 ) 468 .with_state(state); 469 470 let frontend_dir = 471 std::env::var("FRONTEND_DIR").unwrap_or_else(|_| "./frontend/dist".to_string()); 472 473 if std::path::Path::new(&frontend_dir) 474 .join("index.html") 475 .exists() 476 { 477 let index_path = format!("{}/index.html", frontend_dir); 478 let serve_dir = ServeDir::new(&frontend_dir).not_found_service(ServeFile::new(index_path)); 479 router.fallback_service(serve_dir) 480 } else { 481 router 482 } 483}