this repo has no description
at main 22 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 delegation; 10pub mod handle; 11pub mod image; 12pub mod metrics; 13pub mod moderation; 14pub mod oauth; 15pub mod plc; 16pub mod rate_limit; 17pub mod repo; 18pub mod scheduled; 19pub mod state; 20pub mod storage; 21pub mod sync; 22pub mod types; 23pub mod util; 24pub mod validation; 25 26use api::proxy::XrpcProxyLayer; 27use axum::{ 28 Json, Router, 29 extract::DefaultBodyLimit, 30 http::Method, 31 middleware, 32 routing::{get, post}, 33}; 34use http::StatusCode; 35use serde_json::json; 36use state::AppState; 37pub use sync::util::AccountStatus; 38use tower::ServiceBuilder; 39use tower_http::cors::{Any, CorsLayer}; 40use tower_http::services::{ServeDir, ServeFile}; 41pub use types::{AccountState, AtIdentifier, AtUri, Did, Handle, Nsid, Rkey}; 42 43pub fn app(state: AppState) -> Router { 44 let xrpc_router = Router::new() 45 .route("/_health", get(api::server::health)) 46 .route( 47 "/com.atproto.server.describeServer", 48 get(api::server::describe_server), 49 ) 50 .route( 51 "/com.atproto.server.createAccount", 52 post(api::identity::create_account), 53 ) 54 .route( 55 "/com.atproto.server.createSession", 56 post(api::server::create_session), 57 ) 58 .route( 59 "/com.atproto.server.getSession", 60 get(api::server::get_session), 61 ) 62 .route("/_account.listSessions", get(api::server::list_sessions)) 63 .route("/_account.revokeSession", post(api::server::revoke_session)) 64 .route( 65 "/_account.revokeAllSessions", 66 post(api::server::revoke_all_sessions), 67 ) 68 .route( 69 "/com.atproto.server.deleteSession", 70 post(api::server::delete_session), 71 ) 72 .route( 73 "/com.atproto.server.refreshSession", 74 post(api::server::refresh_session), 75 ) 76 .route( 77 "/com.atproto.server.confirmSignup", 78 post(api::server::confirm_signup), 79 ) 80 .route( 81 "/com.atproto.server.resendVerification", 82 post(api::server::resend_verification), 83 ) 84 .route( 85 "/com.atproto.server.getServiceAuth", 86 get(api::server::get_service_auth), 87 ) 88 .route( 89 "/com.atproto.identity.resolveHandle", 90 get(api::identity::resolve_handle), 91 ) 92 .route( 93 "/com.atproto.repo.createRecord", 94 post(api::repo::create_record), 95 ) 96 .route("/com.atproto.repo.putRecord", post(api::repo::put_record)) 97 .route("/com.atproto.repo.getRecord", get(api::repo::get_record)) 98 .route( 99 "/com.atproto.repo.deleteRecord", 100 post(api::repo::delete_record), 101 ) 102 .route( 103 "/com.atproto.repo.listRecords", 104 get(api::repo::list_records), 105 ) 106 .route( 107 "/com.atproto.repo.describeRepo", 108 get(api::repo::describe_repo), 109 ) 110 .route("/com.atproto.repo.uploadBlob", post(api::repo::upload_blob)) 111 .route( 112 "/com.atproto.repo.applyWrites", 113 post(api::repo::apply_writes), 114 ) 115 .route( 116 "/com.atproto.sync.getLatestCommit", 117 get(sync::get_latest_commit), 118 ) 119 .route("/com.atproto.sync.listRepos", get(sync::list_repos)) 120 .route("/com.atproto.sync.getBlob", get(sync::get_blob)) 121 .route("/com.atproto.sync.listBlobs", get(sync::list_blobs)) 122 .route( 123 "/com.atproto.sync.getRepoStatus", 124 get(sync::get_repo_status), 125 ) 126 .route( 127 "/com.atproto.server.checkAccountStatus", 128 get(api::server::check_account_status), 129 ) 130 .route( 131 "/com.atproto.identity.getRecommendedDidCredentials", 132 get(api::identity::get_recommended_did_credentials), 133 ) 134 .route( 135 "/com.atproto.repo.listMissingBlobs", 136 get(api::repo::list_missing_blobs), 137 ) 138 .route( 139 "/com.atproto.sync.notifyOfUpdate", 140 post(sync::notify_of_update), 141 ) 142 .route("/com.atproto.sync.requestCrawl", post(sync::request_crawl)) 143 .route("/com.atproto.sync.getBlocks", get(sync::get_blocks)) 144 .route("/com.atproto.sync.getRepo", get(sync::get_repo)) 145 .route("/com.atproto.sync.getRecord", get(sync::get_record)) 146 .route( 147 "/com.atproto.sync.subscribeRepos", 148 get(sync::subscribe_repos), 149 ) 150 .route("/com.atproto.sync.getHead", get(sync::get_head)) 151 .route("/com.atproto.sync.getCheckout", get(sync::get_checkout)) 152 .route( 153 "/com.atproto.moderation.createReport", 154 post(api::moderation::create_report), 155 ) 156 .route( 157 "/com.atproto.admin.getAccountInfo", 158 get(api::admin::get_account_info), 159 ) 160 .route( 161 "/com.atproto.admin.getAccountInfos", 162 get(api::admin::get_account_infos), 163 ) 164 .route( 165 "/com.atproto.admin.searchAccounts", 166 get(api::admin::search_accounts), 167 ) 168 .route( 169 "/com.atproto.server.activateAccount", 170 post(api::server::activate_account), 171 ) 172 .route( 173 "/com.atproto.server.deactivateAccount", 174 post(api::server::deactivate_account), 175 ) 176 .route( 177 "/com.atproto.server.requestAccountDelete", 178 post(api::server::request_account_delete), 179 ) 180 .route( 181 "/com.atproto.server.deleteAccount", 182 post(api::server::delete_account), 183 ) 184 .route( 185 "/com.atproto.server.requestPasswordReset", 186 post(api::server::request_password_reset), 187 ) 188 .route( 189 "/com.atproto.server.resetPassword", 190 post(api::server::reset_password), 191 ) 192 .route( 193 "/_account.changePassword", 194 post(api::server::change_password), 195 ) 196 .route( 197 "/_account.removePassword", 198 post(api::server::remove_password), 199 ) 200 .route( 201 "/_account.setPassword", 202 post(api::server::set_password), 203 ) 204 .route( 205 "/_account.getPasswordStatus", 206 get(api::server::get_password_status), 207 ) 208 .route( 209 "/_account.getReauthStatus", 210 get(api::server::get_reauth_status), 211 ) 212 .route( 213 "/_account.reauthPassword", 214 post(api::server::reauth_password), 215 ) 216 .route("/_account.reauthTotp", post(api::server::reauth_totp)) 217 .route( 218 "/_account.reauthPasskeyStart", 219 post(api::server::reauth_passkey_start), 220 ) 221 .route( 222 "/_account.reauthPasskeyFinish", 223 post(api::server::reauth_passkey_finish), 224 ) 225 .route( 226 "/_account.getLegacyLoginPreference", 227 get(api::server::get_legacy_login_preference), 228 ) 229 .route( 230 "/_account.updateLegacyLoginPreference", 231 post(api::server::update_legacy_login_preference), 232 ) 233 .route("/_account.updateLocale", post(api::server::update_locale)) 234 .route( 235 "/_account.listTrustedDevices", 236 get(api::server::list_trusted_devices), 237 ) 238 .route( 239 "/_account.revokeTrustedDevice", 240 post(api::server::revoke_trusted_device), 241 ) 242 .route( 243 "/_account.updateTrustedDevice", 244 post(api::server::update_trusted_device), 245 ) 246 .route( 247 "/_account.createPasskeyAccount", 248 post(api::server::create_passkey_account), 249 ) 250 .route( 251 "/_account.startPasskeyRegistrationForSetup", 252 post(api::server::start_passkey_registration_for_setup), 253 ) 254 .route( 255 "/_account.completePasskeySetup", 256 post(api::server::complete_passkey_setup), 257 ) 258 .route( 259 "/_account.requestPasskeyRecovery", 260 post(api::server::request_passkey_recovery), 261 ) 262 .route( 263 "/_account.recoverPasskeyAccount", 264 post(api::server::recover_passkey_account), 265 ) 266 .route( 267 "/_account.updateDidDocument", 268 post(api::server::update_did_document), 269 ) 270 .route( 271 "/_account.getDidDocument", 272 get(api::server::get_did_document), 273 ) 274 .route( 275 "/com.atproto.server.requestEmailUpdate", 276 post(api::server::request_email_update), 277 ) 278 .route( 279 "/_checkEmailVerified", 280 post(api::server::check_email_verified), 281 ) 282 .route( 283 "/com.atproto.server.confirmEmail", 284 post(api::server::confirm_email), 285 ) 286 .route( 287 "/com.atproto.server.updateEmail", 288 post(api::server::update_email), 289 ) 290 .route( 291 "/com.atproto.server.reserveSigningKey", 292 post(api::server::reserve_signing_key), 293 ) 294 .route( 295 "/com.atproto.server.verifyMigrationEmail", 296 post(api::server::verify_migration_email), 297 ) 298 .route( 299 "/com.atproto.server.resendMigrationVerification", 300 post(api::server::resend_migration_verification), 301 ) 302 .route( 303 "/com.atproto.identity.updateHandle", 304 post(api::identity::update_handle), 305 ) 306 .route( 307 "/com.atproto.identity.requestPlcOperationSignature", 308 post(api::identity::request_plc_operation_signature), 309 ) 310 .route( 311 "/com.atproto.identity.signPlcOperation", 312 post(api::identity::sign_plc_operation), 313 ) 314 .route( 315 "/com.atproto.identity.submitPlcOperation", 316 post(api::identity::submit_plc_operation), 317 ) 318 .route("/com.atproto.repo.importRepo", post(api::repo::import_repo)) 319 .route( 320 "/com.atproto.admin.deleteAccount", 321 post(api::admin::delete_account), 322 ) 323 .route( 324 "/com.atproto.admin.updateAccountEmail", 325 post(api::admin::update_account_email), 326 ) 327 .route( 328 "/com.atproto.admin.updateAccountHandle", 329 post(api::admin::update_account_handle), 330 ) 331 .route( 332 "/com.atproto.admin.updateAccountPassword", 333 post(api::admin::update_account_password), 334 ) 335 .route( 336 "/com.atproto.server.listAppPasswords", 337 get(api::server::list_app_passwords), 338 ) 339 .route( 340 "/com.atproto.server.createAppPassword", 341 post(api::server::create_app_password), 342 ) 343 .route( 344 "/com.atproto.server.revokeAppPassword", 345 post(api::server::revoke_app_password), 346 ) 347 .route( 348 "/com.atproto.server.createInviteCode", 349 post(api::server::create_invite_code), 350 ) 351 .route( 352 "/com.atproto.server.createInviteCodes", 353 post(api::server::create_invite_codes), 354 ) 355 .route( 356 "/com.atproto.server.getAccountInviteCodes", 357 get(api::server::get_account_invite_codes), 358 ) 359 .route( 360 "/com.atproto.server.createTotpSecret", 361 post(api::server::create_totp_secret), 362 ) 363 .route( 364 "/com.atproto.server.enableTotp", 365 post(api::server::enable_totp), 366 ) 367 .route( 368 "/com.atproto.server.disableTotp", 369 post(api::server::disable_totp), 370 ) 371 .route( 372 "/com.atproto.server.getTotpStatus", 373 get(api::server::get_totp_status), 374 ) 375 .route( 376 "/com.atproto.server.regenerateBackupCodes", 377 post(api::server::regenerate_backup_codes), 378 ) 379 .route( 380 "/com.atproto.server.startPasskeyRegistration", 381 post(api::server::start_passkey_registration), 382 ) 383 .route( 384 "/com.atproto.server.finishPasskeyRegistration", 385 post(api::server::finish_passkey_registration), 386 ) 387 .route( 388 "/com.atproto.server.listPasskeys", 389 get(api::server::list_passkeys), 390 ) 391 .route( 392 "/com.atproto.server.deletePasskey", 393 post(api::server::delete_passkey), 394 ) 395 .route( 396 "/com.atproto.server.updatePasskey", 397 post(api::server::update_passkey), 398 ) 399 .route( 400 "/com.atproto.admin.getInviteCodes", 401 get(api::admin::get_invite_codes), 402 ) 403 .route("/_admin.getServerStats", get(api::admin::get_server_stats)) 404 .route("/_server.getConfig", get(api::admin::get_server_config)) 405 .route( 406 "/_admin.updateServerConfig", 407 post(api::admin::update_server_config), 408 ) 409 .route( 410 "/com.atproto.admin.disableAccountInvites", 411 post(api::admin::disable_account_invites), 412 ) 413 .route( 414 "/com.atproto.admin.enableAccountInvites", 415 post(api::admin::enable_account_invites), 416 ) 417 .route( 418 "/com.atproto.admin.disableInviteCodes", 419 post(api::admin::disable_invite_codes), 420 ) 421 .route( 422 "/com.atproto.admin.getSubjectStatus", 423 get(api::admin::get_subject_status), 424 ) 425 .route( 426 "/com.atproto.admin.updateSubjectStatus", 427 post(api::admin::update_subject_status), 428 ) 429 .route("/com.atproto.admin.sendEmail", post(api::admin::send_email)) 430 .route( 431 "/app.bsky.actor.getPreferences", 432 get(api::actor::get_preferences), 433 ) 434 .route( 435 "/app.bsky.actor.putPreferences", 436 post(api::actor::put_preferences), 437 ) 438 .route( 439 "/com.atproto.temp.checkSignupQueue", 440 get(api::temp::check_signup_queue), 441 ) 442 .route( 443 "/com.atproto.temp.dereferenceScope", 444 post(api::temp::dereference_scope), 445 ) 446 .route( 447 "/_account.getNotificationPrefs", 448 get(api::notification_prefs::get_notification_prefs), 449 ) 450 .route( 451 "/_account.updateNotificationPrefs", 452 post(api::notification_prefs::update_notification_prefs), 453 ) 454 .route( 455 "/_account.getNotificationHistory", 456 get(api::notification_prefs::get_notification_history), 457 ) 458 .route( 459 "/_account.confirmChannelVerification", 460 post(api::verification::confirm_channel_verification), 461 ) 462 .route("/_account.verifyToken", post(api::server::verify_token)) 463 .route( 464 "/_delegation.listControllers", 465 get(api::delegation::list_controllers), 466 ) 467 .route( 468 "/_delegation.addController", 469 post(api::delegation::add_controller), 470 ) 471 .route( 472 "/_delegation.removeController", 473 post(api::delegation::remove_controller), 474 ) 475 .route( 476 "/_delegation.updateControllerScopes", 477 post(api::delegation::update_controller_scopes), 478 ) 479 .route( 480 "/_delegation.listControlledAccounts", 481 get(api::delegation::list_controlled_accounts), 482 ) 483 .route( 484 "/_delegation.getAuditLog", 485 get(api::delegation::get_audit_log), 486 ) 487 .route( 488 "/_delegation.getScopePresets", 489 get(api::delegation::get_scope_presets), 490 ) 491 .route( 492 "/_delegation.createDelegatedAccount", 493 post(api::delegation::create_delegated_account), 494 ) 495 .route("/_backup.listBackups", get(api::backup::list_backups)) 496 .route("/_backup.getBackup", get(api::backup::get_backup)) 497 .route("/_backup.createBackup", post(api::backup::create_backup)) 498 .route("/_backup.deleteBackup", post(api::backup::delete_backup)) 499 .route("/_backup.setEnabled", post(api::backup::set_backup_enabled)) 500 .route("/_backup.exportBlobs", get(api::backup::export_blobs)) 501 .route( 502 "/app.bsky.ageassurance.getState", 503 get(api::age_assurance::get_state), 504 ) 505 .route( 506 "/app.bsky.unspecced.getAgeAssuranceState", 507 get(api::age_assurance::get_age_assurance_state), 508 ) 509 .fallback(async || ( 510 StatusCode::NOT_IMPLEMENTED, 511 Json(json!({"error": "MethodNotImplemented", "message": "Method not implemented. For app.bsky.* methods, include an atproto-proxy header specifying your AppView."})), 512 )); 513 let xrpc_service = ServiceBuilder::new() 514 .layer(XrpcProxyLayer::new(state.clone())) 515 .service(xrpc_router.with_state(state.clone())); 516 517 let oauth_router = Router::new() 518 .route("/jwks", get(oauth::endpoints::oauth_jwks)) 519 .route( 520 "/client-metadata.json", 521 get(oauth::endpoints::frontend_client_metadata), 522 ) 523 .route("/par", post(oauth::endpoints::pushed_authorization_request)) 524 .route("/authorize", get(oauth::endpoints::authorize_get)) 525 .route("/authorize", post(oauth::endpoints::authorize_post)) 526 .route( 527 "/authorize/accounts", 528 get(oauth::endpoints::authorize_accounts), 529 ) 530 .route( 531 "/authorize/select", 532 post(oauth::endpoints::authorize_select), 533 ) 534 .route("/authorize/2fa", get(oauth::endpoints::authorize_2fa_get)) 535 .route("/authorize/2fa", post(oauth::endpoints::authorize_2fa_post)) 536 .route( 537 "/authorize/passkey", 538 get(oauth::endpoints::authorize_passkey_start), 539 ) 540 .route( 541 "/authorize/passkey", 542 post(oauth::endpoints::authorize_passkey_finish), 543 ) 544 .route( 545 "/passkey/check", 546 get(oauth::endpoints::check_user_has_passkeys), 547 ) 548 .route( 549 "/security-status", 550 get(oauth::endpoints::check_user_security_status), 551 ) 552 .route("/passkey/start", post(oauth::endpoints::passkey_start)) 553 .route("/passkey/finish", post(oauth::endpoints::passkey_finish)) 554 .route("/authorize/deny", post(oauth::endpoints::authorize_deny)) 555 .route("/authorize/consent", get(oauth::endpoints::consent_get)) 556 .route("/authorize/consent", post(oauth::endpoints::consent_post)) 557 .route( 558 "/authorize/redirect", 559 get(oauth::endpoints::authorize_redirect), 560 ) 561 .route("/delegation/auth", post(oauth::endpoints::delegation_auth)) 562 .route( 563 "/delegation/totp", 564 post(oauth::endpoints::delegation_totp_verify), 565 ) 566 .route("/token", post(oauth::endpoints::token_endpoint)) 567 .route("/revoke", post(oauth::endpoints::revoke_token)) 568 .route("/introspect", post(oauth::endpoints::introspect_token)); 569 570 let well_known_router = Router::new() 571 .route("/did.json", get(api::identity::well_known_did)) 572 .route("/atproto-did", get(api::identity::well_known_atproto_did)) 573 .route( 574 "/oauth-protected-resource", 575 get(oauth::endpoints::oauth_protected_resource), 576 ) 577 .route( 578 "/oauth-authorization-server", 579 get(oauth::endpoints::oauth_authorization_server), 580 ); 581 582 let router = Router::new() 583 .nest_service("/xrpc", xrpc_service) 584 .nest("/oauth", oauth_router) 585 .nest("/.well-known", well_known_router) 586 .route("/metrics", get(metrics::metrics_handler)) 587 .route("/health", get(api::server::health)) 588 .route("/robots.txt", get(api::server::robots_txt)) 589 .route("/logo", get(api::server::get_logo)) 590 .route("/u/{handle}/did.json", get(api::identity::user_did_doc)) 591 .layer(DefaultBodyLimit::max(util::get_max_blob_size())) 592 .layer(middleware::from_fn(metrics::metrics_middleware)) 593 .layer( 594 CorsLayer::new() 595 .allow_origin(Any) 596 .allow_methods([Method::GET, Method::POST, Method::OPTIONS]) 597 .allow_headers([ 598 "Authorization".parse().unwrap(), 599 "Content-Type".parse().unwrap(), 600 "Content-Encoding".parse().unwrap(), 601 "Accept-Encoding".parse().unwrap(), 602 "DPoP".parse().unwrap(), 603 "atproto-proxy".parse().unwrap(), 604 "atproto-accept-labelers".parse().unwrap(), 605 "x-bsky-topics".parse().unwrap(), 606 ]) 607 .expose_headers([ 608 "WWW-Authenticate".parse().unwrap(), 609 "DPoP-Nonce".parse().unwrap(), 610 "atproto-repo-rev".parse().unwrap(), 611 "atproto-content-labelers".parse().unwrap(), 612 ]), 613 ) 614 .with_state(state); 615 616 let frontend_dir = 617 std::env::var("FRONTEND_DIR").unwrap_or_else(|_| "./frontend/dist".to_string()); 618 if std::path::Path::new(&frontend_dir) 619 .join("index.html") 620 .exists() 621 { 622 let index_path = format!("{}/index.html", frontend_dir); 623 let homepage_path = format!("{}/homepage.html", frontend_dir); 624 625 let homepage_exists = std::path::Path::new(&homepage_path).exists(); 626 let homepage_file = if homepage_exists { 627 homepage_path 628 } else { 629 index_path.clone() 630 }; 631 632 let spa_router = Router::new().fallback_service(ServeFile::new(&index_path)); 633 634 let serve_dir = ServeDir::new(&frontend_dir).not_found_service(ServeFile::new(&index_path)); 635 636 return router 637 .route_service("/", ServeFile::new(&homepage_file)) 638 .nest("/app", spa_router) 639 .fallback_service(serve_dir); 640 } 641 642 router 643}