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