forked from
lewis.moe/bspds-sandbox
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
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}