this repo has no description
1pub mod api;
2pub mod auth;
3pub mod cache;
4pub mod circuit_breaker;
5pub mod config;
6pub mod crawlers;
7pub mod image;
8pub mod metrics;
9pub mod notifications;
10pub mod oauth;
11pub mod plc;
12pub mod rate_limit;
13pub mod repo;
14pub mod state;
15pub mod storage;
16pub mod sync;
17pub mod util;
18pub mod validation;
19use axum::{
20 Router,
21 http::Method,
22 middleware,
23 routing::{any, get, post},
24};
25use state::AppState;
26use tower_http::cors::{Any, CorsLayer};
27use tower_http::services::{ServeDir, ServeFile};
28pub fn app(state: AppState) -> Router {
29 let router = Router::new()
30 .route("/metrics", get(metrics::metrics_handler))
31 .route("/health", get(api::server::health))
32 .route("/xrpc/_health", get(api::server::health))
33 .route("/robots.txt", get(api::server::robots_txt))
34 .route(
35 "/xrpc/com.atproto.server.describeServer",
36 get(api::server::describe_server),
37 )
38 .route(
39 "/xrpc/com.atproto.server.createAccount",
40 post(api::identity::create_account),
41 )
42 .route(
43 "/xrpc/com.atproto.server.createSession",
44 post(api::server::create_session),
45 )
46 .route(
47 "/xrpc/com.atproto.server.getSession",
48 get(api::server::get_session),
49 )
50 .route(
51 "/xrpc/com.atproto.server.deleteSession",
52 post(api::server::delete_session),
53 )
54 .route(
55 "/xrpc/com.atproto.server.refreshSession",
56 post(api::server::refresh_session),
57 )
58 .route(
59 "/xrpc/com.atproto.server.confirmSignup",
60 post(api::server::confirm_signup),
61 )
62 .route(
63 "/xrpc/com.atproto.server.resendVerification",
64 post(api::server::resend_verification),
65 )
66 .route(
67 "/xrpc/com.atproto.server.getServiceAuth",
68 get(api::server::get_service_auth),
69 )
70 .route(
71 "/xrpc/com.atproto.identity.resolveHandle",
72 get(api::identity::resolve_handle),
73 )
74 .route(
75 "/xrpc/com.atproto.repo.createRecord",
76 post(api::repo::create_record),
77 )
78 .route(
79 "/xrpc/com.atproto.repo.putRecord",
80 post(api::repo::put_record),
81 )
82 .route(
83 "/xrpc/com.atproto.repo.getRecord",
84 get(api::repo::get_record),
85 )
86 .route(
87 "/xrpc/com.atproto.repo.deleteRecord",
88 post(api::repo::delete_record),
89 )
90 .route(
91 "/xrpc/com.atproto.repo.listRecords",
92 get(api::repo::list_records),
93 )
94 .route(
95 "/xrpc/com.atproto.repo.describeRepo",
96 get(api::repo::describe_repo),
97 )
98 .route(
99 "/xrpc/com.atproto.repo.uploadBlob",
100 post(api::repo::upload_blob),
101 )
102 .route(
103 "/xrpc/com.atproto.repo.applyWrites",
104 post(api::repo::apply_writes),
105 )
106 .route(
107 "/xrpc/com.atproto.sync.getLatestCommit",
108 get(sync::get_latest_commit),
109 )
110 .route(
111 "/xrpc/com.atproto.sync.listRepos",
112 get(sync::list_repos),
113 )
114 .route(
115 "/xrpc/com.atproto.sync.getBlob",
116 get(sync::get_blob),
117 )
118 .route(
119 "/xrpc/com.atproto.sync.listBlobs",
120 get(sync::list_blobs),
121 )
122 .route(
123 "/xrpc/com.atproto.sync.getRepoStatus",
124 get(sync::get_repo_status),
125 )
126 .route(
127 "/xrpc/com.atproto.server.checkAccountStatus",
128 get(api::server::check_account_status),
129 )
130 .route(
131 "/xrpc/com.atproto.identity.getRecommendedDidCredentials",
132 get(api::identity::get_recommended_did_credentials),
133 )
134 .route(
135 "/xrpc/com.atproto.repo.listMissingBlobs",
136 get(api::repo::list_missing_blobs),
137 )
138 .route(
139 "/xrpc/com.atproto.sync.notifyOfUpdate",
140 post(sync::notify_of_update),
141 )
142 .route(
143 "/xrpc/com.atproto.sync.requestCrawl",
144 post(sync::request_crawl),
145 )
146 .route(
147 "/xrpc/com.atproto.sync.getBlocks",
148 get(sync::get_blocks),
149 )
150 .route(
151 "/xrpc/com.atproto.sync.getRepo",
152 get(sync::get_repo),
153 )
154 .route(
155 "/xrpc/com.atproto.sync.getRecord",
156 get(sync::get_record),
157 )
158 .route(
159 "/xrpc/com.atproto.sync.subscribeRepos",
160 get(sync::subscribe_repos),
161 )
162 .route(
163 "/xrpc/com.atproto.sync.getHead",
164 get(sync::get_head),
165 )
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.bspds.admin.createProfile",
184 post(api::admin::create_profile),
185 )
186 .route(
187 "/xrpc/com.bspds.admin.createRecord",
188 post(api::admin::create_record_admin),
189 )
190 .route(
191 "/xrpc/com.atproto.server.activateAccount",
192 post(api::server::activate_account),
193 )
194 .route(
195 "/xrpc/com.atproto.server.deactivateAccount",
196 post(api::server::deactivate_account),
197 )
198 .route(
199 "/xrpc/com.atproto.server.requestAccountDelete",
200 post(api::server::request_account_delete),
201 )
202 .route(
203 "/xrpc/com.atproto.server.deleteAccount",
204 post(api::server::delete_account),
205 )
206 .route(
207 "/xrpc/com.atproto.server.requestPasswordReset",
208 post(api::server::request_password_reset),
209 )
210 .route(
211 "/xrpc/com.atproto.server.resetPassword",
212 post(api::server::reset_password),
213 )
214 .route(
215 "/xrpc/com.atproto.server.requestEmailUpdate",
216 post(api::server::request_email_update),
217 )
218 .route(
219 "/xrpc/com.atproto.server.confirmEmail",
220 post(api::server::confirm_email),
221 )
222 .route(
223 "/xrpc/com.atproto.server.updateEmail",
224 post(api::server::update_email),
225 )
226 .route(
227 "/xrpc/com.atproto.server.reserveSigningKey",
228 post(api::server::reserve_signing_key),
229 )
230 .route(
231 "/xrpc/com.atproto.identity.updateHandle",
232 post(api::identity::update_handle),
233 )
234 .route(
235 "/xrpc/com.atproto.identity.requestPlcOperationSignature",
236 post(api::identity::request_plc_operation_signature),
237 )
238 .route(
239 "/xrpc/com.atproto.identity.signPlcOperation",
240 post(api::identity::sign_plc_operation),
241 )
242 .route(
243 "/xrpc/com.atproto.identity.submitPlcOperation",
244 post(api::identity::submit_plc_operation),
245 )
246 .route(
247 "/xrpc/com.atproto.repo.importRepo",
248 post(api::repo::import_repo),
249 )
250 .route(
251 "/xrpc/com.atproto.admin.deleteAccount",
252 post(api::admin::delete_account),
253 )
254 .route(
255 "/xrpc/com.atproto.admin.updateAccountEmail",
256 post(api::admin::update_account_email),
257 )
258 .route(
259 "/xrpc/com.atproto.admin.updateAccountHandle",
260 post(api::admin::update_account_handle),
261 )
262 .route(
263 "/xrpc/com.atproto.admin.updateAccountPassword",
264 post(api::admin::update_account_password),
265 )
266 .route(
267 "/xrpc/com.atproto.server.listAppPasswords",
268 get(api::server::list_app_passwords),
269 )
270 .route(
271 "/xrpc/com.atproto.server.createAppPassword",
272 post(api::server::create_app_password),
273 )
274 .route(
275 "/xrpc/com.atproto.server.revokeAppPassword",
276 post(api::server::revoke_app_password),
277 )
278 .route(
279 "/xrpc/com.atproto.server.createInviteCode",
280 post(api::server::create_invite_code),
281 )
282 .route(
283 "/xrpc/com.atproto.server.createInviteCodes",
284 post(api::server::create_invite_codes),
285 )
286 .route(
287 "/xrpc/com.atproto.server.getAccountInviteCodes",
288 get(api::server::get_account_invite_codes),
289 )
290 .route(
291 "/xrpc/com.atproto.admin.getInviteCodes",
292 get(api::admin::get_invite_codes),
293 )
294 .route(
295 "/xrpc/com.atproto.admin.disableAccountInvites",
296 post(api::admin::disable_account_invites),
297 )
298 .route(
299 "/xrpc/com.atproto.admin.enableAccountInvites",
300 post(api::admin::enable_account_invites),
301 )
302 .route(
303 "/xrpc/com.atproto.admin.disableInviteCodes",
304 post(api::admin::disable_invite_codes),
305 )
306 .route(
307 "/xrpc/com.atproto.admin.getSubjectStatus",
308 get(api::admin::get_subject_status),
309 )
310 .route(
311 "/xrpc/com.atproto.admin.updateSubjectStatus",
312 post(api::admin::update_subject_status),
313 )
314 .route(
315 "/xrpc/com.atproto.admin.sendEmail",
316 post(api::admin::send_email),
317 )
318 .route(
319 "/xrpc/app.bsky.actor.getPreferences",
320 get(api::actor::get_preferences),
321 )
322 .route(
323 "/xrpc/app.bsky.actor.putPreferences",
324 post(api::actor::put_preferences),
325 )
326 .route(
327 "/xrpc/app.bsky.actor.getProfile",
328 get(api::actor::get_profile),
329 )
330 .route(
331 "/xrpc/app.bsky.actor.getProfiles",
332 get(api::actor::get_profiles),
333 )
334 .route(
335 "/xrpc/app.bsky.feed.getTimeline",
336 get(api::feed::get_timeline),
337 )
338 .route(
339 "/xrpc/app.bsky.feed.getAuthorFeed",
340 get(api::feed::get_author_feed),
341 )
342 .route(
343 "/xrpc/app.bsky.feed.getActorLikes",
344 get(api::feed::get_actor_likes),
345 )
346 .route(
347 "/xrpc/app.bsky.feed.getPostThread",
348 get(api::feed::get_post_thread),
349 )
350 .route(
351 "/xrpc/app.bsky.feed.getFeed",
352 get(api::feed::get_feed),
353 )
354 .route(
355 "/xrpc/app.bsky.notification.registerPush",
356 post(api::notification::register_push),
357 )
358 .route("/.well-known/did.json", get(api::identity::well_known_did))
359 .route("/.well-known/atproto-did", get(api::identity::well_known_atproto_did))
360 .route("/u/{handle}/did.json", get(api::identity::user_did_doc))
361 // OAuth 2.1 endpoints
362 .route(
363 "/.well-known/oauth-protected-resource",
364 get(oauth::endpoints::oauth_protected_resource),
365 )
366 .route(
367 "/.well-known/oauth-authorization-server",
368 get(oauth::endpoints::oauth_authorization_server),
369 )
370 .route("/oauth/jwks", get(oauth::endpoints::oauth_jwks))
371 .route(
372 "/oauth/par",
373 post(oauth::endpoints::pushed_authorization_request),
374 )
375 .route("/oauth/authorize", get(oauth::endpoints::authorize_get))
376 .route("/oauth/authorize", post(oauth::endpoints::authorize_post))
377 .route("/oauth/authorize/select", post(oauth::endpoints::authorize_select))
378 .route("/oauth/authorize/2fa", get(oauth::endpoints::authorize_2fa_get))
379 .route("/oauth/authorize/2fa", post(oauth::endpoints::authorize_2fa_post))
380 .route("/oauth/authorize/deny", post(oauth::endpoints::authorize_deny))
381 .route("/oauth/token", post(oauth::endpoints::token_endpoint))
382 .route("/oauth/revoke", post(oauth::endpoints::revoke_token))
383 .route("/oauth/introspect", post(oauth::endpoints::introspect_token))
384 .route(
385 "/xrpc/com.atproto.temp.checkSignupQueue",
386 get(api::temp::check_signup_queue),
387 )
388 .route(
389 "/xrpc/com.bspds.account.getNotificationPrefs",
390 get(api::notification_prefs::get_notification_prefs),
391 )
392 .route(
393 "/xrpc/com.bspds.account.updateNotificationPrefs",
394 post(api::notification_prefs::update_notification_prefs),
395 )
396 .route("/xrpc/{*method}", any(api::proxy::proxy_handler))
397 .layer(middleware::from_fn(metrics::metrics_middleware))
398 .layer(
399 CorsLayer::new()
400 .allow_origin(Any)
401 .allow_methods([Method::GET, Method::POST, Method::OPTIONS])
402 .allow_headers(Any),
403 )
404 .with_state(state);
405 let frontend_dir = std::env::var("FRONTEND_DIR")
406 .unwrap_or_else(|_| "./frontend/dist".to_string());
407 if std::path::Path::new(&frontend_dir).join("index.html").exists() {
408 let index_path = format!("{}/index.html", frontend_dir);
409 let serve_dir = ServeDir::new(&frontend_dir)
410 .not_found_service(ServeFile::new(index_path));
411 router.fallback_service(serve_dir)
412 } else {
413 router
414 }
415}