this repo has no description
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.getPasswordStatus", 202 get(api::server::get_password_status), 203 ) 204 .route( 205 "/_account.getReauthStatus", 206 get(api::server::get_reauth_status), 207 ) 208 .route( 209 "/_account.reauthPassword", 210 post(api::server::reauth_password), 211 ) 212 .route("/_account.reauthTotp", post(api::server::reauth_totp)) 213 .route( 214 "/_account.reauthPasskeyStart", 215 post(api::server::reauth_passkey_start), 216 ) 217 .route( 218 "/_account.reauthPasskeyFinish", 219 post(api::server::reauth_passkey_finish), 220 ) 221 .route( 222 "/_account.getLegacyLoginPreference", 223 get(api::server::get_legacy_login_preference), 224 ) 225 .route( 226 "/_account.updateLegacyLoginPreference", 227 post(api::server::update_legacy_login_preference), 228 ) 229 .route("/_account.updateLocale", post(api::server::update_locale)) 230 .route( 231 "/_account.listTrustedDevices", 232 get(api::server::list_trusted_devices), 233 ) 234 .route( 235 "/_account.revokeTrustedDevice", 236 post(api::server::revoke_trusted_device), 237 ) 238 .route( 239 "/_account.updateTrustedDevice", 240 post(api::server::update_trusted_device), 241 ) 242 .route( 243 "/_account.createPasskeyAccount", 244 post(api::server::create_passkey_account), 245 ) 246 .route( 247 "/_account.startPasskeyRegistrationForSetup", 248 post(api::server::start_passkey_registration_for_setup), 249 ) 250 .route( 251 "/_account.completePasskeySetup", 252 post(api::server::complete_passkey_setup), 253 ) 254 .route( 255 "/_account.requestPasskeyRecovery", 256 post(api::server::request_passkey_recovery), 257 ) 258 .route( 259 "/_account.recoverPasskeyAccount", 260 post(api::server::recover_passkey_account), 261 ) 262 .route( 263 "/_account.updateDidDocument", 264 post(api::server::update_did_document), 265 ) 266 .route( 267 "/_account.getDidDocument", 268 get(api::server::get_did_document), 269 ) 270 .route( 271 "/com.atproto.server.requestEmailUpdate", 272 post(api::server::request_email_update), 273 ) 274 .route( 275 "/_checkEmailVerified", 276 post(api::server::check_email_verified), 277 ) 278 .route( 279 "/com.atproto.server.confirmEmail", 280 post(api::server::confirm_email), 281 ) 282 .route( 283 "/com.atproto.server.updateEmail", 284 post(api::server::update_email), 285 ) 286 .route( 287 "/com.atproto.server.reserveSigningKey", 288 post(api::server::reserve_signing_key), 289 ) 290 .route( 291 "/com.atproto.server.verifyMigrationEmail", 292 post(api::server::verify_migration_email), 293 ) 294 .route( 295 "/com.atproto.server.resendMigrationVerification", 296 post(api::server::resend_migration_verification), 297 ) 298 .route( 299 "/com.atproto.identity.updateHandle", 300 post(api::identity::update_handle), 301 ) 302 .route( 303 "/com.atproto.identity.requestPlcOperationSignature", 304 post(api::identity::request_plc_operation_signature), 305 ) 306 .route( 307 "/com.atproto.identity.signPlcOperation", 308 post(api::identity::sign_plc_operation), 309 ) 310 .route( 311 "/com.atproto.identity.submitPlcOperation", 312 post(api::identity::submit_plc_operation), 313 ) 314 .route("/com.atproto.repo.importRepo", post(api::repo::import_repo)) 315 .route( 316 "/com.atproto.admin.deleteAccount", 317 post(api::admin::delete_account), 318 ) 319 .route( 320 "/com.atproto.admin.updateAccountEmail", 321 post(api::admin::update_account_email), 322 ) 323 .route( 324 "/com.atproto.admin.updateAccountHandle", 325 post(api::admin::update_account_handle), 326 ) 327 .route( 328 "/com.atproto.admin.updateAccountPassword", 329 post(api::admin::update_account_password), 330 ) 331 .route( 332 "/com.atproto.server.listAppPasswords", 333 get(api::server::list_app_passwords), 334 ) 335 .route( 336 "/com.atproto.server.createAppPassword", 337 post(api::server::create_app_password), 338 ) 339 .route( 340 "/com.atproto.server.revokeAppPassword", 341 post(api::server::revoke_app_password), 342 ) 343 .route( 344 "/com.atproto.server.createInviteCode", 345 post(api::server::create_invite_code), 346 ) 347 .route( 348 "/com.atproto.server.createInviteCodes", 349 post(api::server::create_invite_codes), 350 ) 351 .route( 352 "/com.atproto.server.getAccountInviteCodes", 353 get(api::server::get_account_invite_codes), 354 ) 355 .route( 356 "/com.atproto.server.createTotpSecret", 357 post(api::server::create_totp_secret), 358 ) 359 .route( 360 "/com.atproto.server.enableTotp", 361 post(api::server::enable_totp), 362 ) 363 .route( 364 "/com.atproto.server.disableTotp", 365 post(api::server::disable_totp), 366 ) 367 .route( 368 "/com.atproto.server.getTotpStatus", 369 get(api::server::get_totp_status), 370 ) 371 .route( 372 "/com.atproto.server.regenerateBackupCodes", 373 post(api::server::regenerate_backup_codes), 374 ) 375 .route( 376 "/com.atproto.server.startPasskeyRegistration", 377 post(api::server::start_passkey_registration), 378 ) 379 .route( 380 "/com.atproto.server.finishPasskeyRegistration", 381 post(api::server::finish_passkey_registration), 382 ) 383 .route( 384 "/com.atproto.server.listPasskeys", 385 get(api::server::list_passkeys), 386 ) 387 .route( 388 "/com.atproto.server.deletePasskey", 389 post(api::server::delete_passkey), 390 ) 391 .route( 392 "/com.atproto.server.updatePasskey", 393 post(api::server::update_passkey), 394 ) 395 .route( 396 "/com.atproto.admin.getInviteCodes", 397 get(api::admin::get_invite_codes), 398 ) 399 .route("/_admin.getServerStats", get(api::admin::get_server_stats)) 400 .route("/_server.getConfig", get(api::admin::get_server_config)) 401 .route( 402 "/_admin.updateServerConfig", 403 post(api::admin::update_server_config), 404 ) 405 .route( 406 "/com.atproto.admin.disableAccountInvites", 407 post(api::admin::disable_account_invites), 408 ) 409 .route( 410 "/com.atproto.admin.enableAccountInvites", 411 post(api::admin::enable_account_invites), 412 ) 413 .route( 414 "/com.atproto.admin.disableInviteCodes", 415 post(api::admin::disable_invite_codes), 416 ) 417 .route( 418 "/com.atproto.admin.getSubjectStatus", 419 get(api::admin::get_subject_status), 420 ) 421 .route( 422 "/com.atproto.admin.updateSubjectStatus", 423 post(api::admin::update_subject_status), 424 ) 425 .route("/com.atproto.admin.sendEmail", post(api::admin::send_email)) 426 .route( 427 "/app.bsky.actor.getPreferences", 428 get(api::actor::get_preferences), 429 ) 430 .route( 431 "/app.bsky.actor.putPreferences", 432 post(api::actor::put_preferences), 433 ) 434 .route( 435 "/com.atproto.temp.checkSignupQueue", 436 get(api::temp::check_signup_queue), 437 ) 438 .route( 439 "/com.atproto.temp.dereferenceScope", 440 post(api::temp::dereference_scope), 441 ) 442 .route( 443 "/_account.getNotificationPrefs", 444 get(api::notification_prefs::get_notification_prefs), 445 ) 446 .route( 447 "/_account.updateNotificationPrefs", 448 post(api::notification_prefs::update_notification_prefs), 449 ) 450 .route( 451 "/_account.getNotificationHistory", 452 get(api::notification_prefs::get_notification_history), 453 ) 454 .route( 455 "/_account.confirmChannelVerification", 456 post(api::verification::confirm_channel_verification), 457 ) 458 .route("/_account.verifyToken", post(api::server::verify_token)) 459 .route( 460 "/_delegation.listControllers", 461 get(api::delegation::list_controllers), 462 ) 463 .route( 464 "/_delegation.addController", 465 post(api::delegation::add_controller), 466 ) 467 .route( 468 "/_delegation.removeController", 469 post(api::delegation::remove_controller), 470 ) 471 .route( 472 "/_delegation.updateControllerScopes", 473 post(api::delegation::update_controller_scopes), 474 ) 475 .route( 476 "/_delegation.listControlledAccounts", 477 get(api::delegation::list_controlled_accounts), 478 ) 479 .route( 480 "/_delegation.getAuditLog", 481 get(api::delegation::get_audit_log), 482 ) 483 .route( 484 "/_delegation.getScopePresets", 485 get(api::delegation::get_scope_presets), 486 ) 487 .route( 488 "/_delegation.createDelegatedAccount", 489 post(api::delegation::create_delegated_account), 490 ) 491 .route("/_backup.listBackups", get(api::backup::list_backups)) 492 .route("/_backup.getBackup", get(api::backup::get_backup)) 493 .route("/_backup.createBackup", post(api::backup::create_backup)) 494 .route("/_backup.deleteBackup", post(api::backup::delete_backup)) 495 .route("/_backup.setEnabled", post(api::backup::set_backup_enabled)) 496 .route("/_backup.exportBlobs", get(api::backup::export_blobs)) 497 .route( 498 "/app.bsky.ageassurance.getState", 499 get(api::age_assurance::get_state), 500 ) 501 .route( 502 "/app.bsky.unspecced.getAgeAssuranceState", 503 get(api::age_assurance::get_age_assurance_state), 504 ) 505 .fallback(async || ( 506 StatusCode::NOT_IMPLEMENTED, 507 Json(json!({"error": "MethodNotImplemented", "message": "Method not implemented. For app.bsky.* methods, include an atproto-proxy header specifying your AppView."})), 508 )); 509 let xrpc_service = ServiceBuilder::new() 510 .layer(XrpcProxyLayer::new(state.clone())) 511 .service(xrpc_router.with_state(state.clone())); 512 513 let oauth_router = Router::new() 514 .route("/jwks", get(oauth::endpoints::oauth_jwks)) 515 .route( 516 "/client-metadata.json", 517 get(oauth::endpoints::frontend_client_metadata), 518 ) 519 .route("/par", post(oauth::endpoints::pushed_authorization_request)) 520 .route("/authorize", get(oauth::endpoints::authorize_get)) 521 .route("/authorize", post(oauth::endpoints::authorize_post)) 522 .route( 523 "/authorize/accounts", 524 get(oauth::endpoints::authorize_accounts), 525 ) 526 .route( 527 "/authorize/select", 528 post(oauth::endpoints::authorize_select), 529 ) 530 .route("/authorize/2fa", get(oauth::endpoints::authorize_2fa_get)) 531 .route("/authorize/2fa", post(oauth::endpoints::authorize_2fa_post)) 532 .route( 533 "/authorize/passkey", 534 get(oauth::endpoints::authorize_passkey_start), 535 ) 536 .route( 537 "/authorize/passkey", 538 post(oauth::endpoints::authorize_passkey_finish), 539 ) 540 .route( 541 "/passkey/check", 542 get(oauth::endpoints::check_user_has_passkeys), 543 ) 544 .route( 545 "/security-status", 546 get(oauth::endpoints::check_user_security_status), 547 ) 548 .route("/passkey/start", post(oauth::endpoints::passkey_start)) 549 .route("/passkey/finish", post(oauth::endpoints::passkey_finish)) 550 .route("/authorize/deny", post(oauth::endpoints::authorize_deny)) 551 .route("/authorize/consent", get(oauth::endpoints::consent_get)) 552 .route("/authorize/consent", post(oauth::endpoints::consent_post)) 553 .route( 554 "/authorize/redirect", 555 get(oauth::endpoints::authorize_redirect), 556 ) 557 .route("/delegation/auth", post(oauth::endpoints::delegation_auth)) 558 .route( 559 "/delegation/totp", 560 post(oauth::endpoints::delegation_totp_verify), 561 ) 562 .route("/token", post(oauth::endpoints::token_endpoint)) 563 .route("/revoke", post(oauth::endpoints::revoke_token)) 564 .route("/introspect", post(oauth::endpoints::introspect_token)); 565 566 let well_known_router = Router::new() 567 .route("/did.json", get(api::identity::well_known_did)) 568 .route("/atproto-did", get(api::identity::well_known_atproto_did)) 569 .route( 570 "/oauth-protected-resource", 571 get(oauth::endpoints::oauth_protected_resource), 572 ) 573 .route( 574 "/oauth-authorization-server", 575 get(oauth::endpoints::oauth_authorization_server), 576 ); 577 578 let router = Router::new() 579 .nest_service("/xrpc", xrpc_service) 580 .nest("/oauth", oauth_router) 581 .nest("/.well-known", well_known_router) 582 .route("/metrics", get(metrics::metrics_handler)) 583 .route("/health", get(api::server::health)) 584 .route("/robots.txt", get(api::server::robots_txt)) 585 .route("/logo", get(api::server::get_logo)) 586 .route("/u/{handle}/did.json", get(api::identity::user_did_doc)) 587 .layer(DefaultBodyLimit::max(util::get_max_blob_size())) 588 .layer(middleware::from_fn(metrics::metrics_middleware)) 589 .layer( 590 CorsLayer::new() 591 .allow_origin(Any) 592 .allow_methods([Method::GET, Method::POST, Method::OPTIONS]) 593 .allow_headers(Any), 594 ) 595 .with_state(state); 596 597 let frontend_dir = 598 std::env::var("FRONTEND_DIR").unwrap_or_else(|_| "./frontend/dist".to_string()); 599 if std::path::Path::new(&frontend_dir) 600 .join("index.html") 601 .exists() 602 { 603 let index_path = format!("{}/index.html", frontend_dir); 604 let homepage_path = format!("{}/homepage.html", frontend_dir); 605 606 let homepage_exists = std::path::Path::new(&homepage_path).exists(); 607 let homepage_file = if homepage_exists { 608 homepage_path 609 } else { 610 index_path.clone() 611 }; 612 613 let spa_router = Router::new().fallback_service(ServeFile::new(&index_path)); 614 615 let serve_dir = ServeDir::new(&frontend_dir).not_found_service(ServeFile::new(&index_path)); 616 617 return router 618 .route_service("/", ServeFile::new(&homepage_file)) 619 .nest("/app", spa_router) 620 .fallback_service(serve_dir); 621 } 622 623 router 624}