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