Alternative ATProto PDS implementation
1use atrium_api::app::bsky::actor;
2use axum::{Json, routing::post};
3use constcat::concat;
4use diesel::prelude::*;
5
6use super::*;
7
8async fn put_preferences(
9 user: AuthenticatedUser,
10 State(db): State<Db>,
11 Json(input): Json<actor::put_preferences::Input>,
12) -> Result<()> {
13 let did = user.did();
14 let json_string =
15 serde_json::to_string(&input.preferences).context("failed to serialize preferences")?;
16
17 // Use the db connection pool to execute the update
18 let conn = &mut db.get().context("failed to get database connection")?;
19 diesel::sql_query("UPDATE accounts SET private_prefs = ? WHERE did = ?")
20 .bind::<diesel::sql_types::Text, _>(json_string)
21 .bind::<diesel::sql_types::Text, _>(did)
22 .execute(conn)
23 .context("failed to update user preferences")?;
24
25 Ok(())
26}
27
28async fn get_preferences(
29 user: AuthenticatedUser,
30 State(db): State<Db>,
31) -> Result<Json<actor::get_preferences::Output>> {
32 let did = user.did();
33 let conn = &mut db.get().context("failed to get database connection")?;
34
35 #[derive(QueryableByName)]
36 struct Prefs {
37 #[diesel(sql_type = diesel::sql_types::Text)]
38 private_prefs: Option<String>,
39 }
40
41 let result = diesel::sql_query("SELECT private_prefs FROM accounts WHERE did = ?")
42 .bind::<diesel::sql_types::Text, _>(did)
43 .get_result::<Prefs>(conn)
44 .context("failed to fetch preferences")?;
45
46 if let Some(prefs_json) = result.private_prefs {
47 let prefs: actor::defs::Preferences =
48 serde_json::from_str(&prefs_json).context("failed to deserialize preferences")?;
49
50 Ok(Json(
51 actor::get_preferences::OutputData { preferences: prefs }.into(),
52 ))
53 } else {
54 Ok(Json(
55 actor::get_preferences::OutputData {
56 preferences: Vec::new(),
57 }
58 .into(),
59 ))
60 }
61}
62
63/// Register all actor endpoints.
64pub(crate) fn routes() -> Router<AppState> {
65 // AP /xrpc/app.bsky.actor.putPreferences
66 // AG /xrpc/app.bsky.actor.getPreferences
67 Router::new()
68 .route(
69 concat!("/", actor::put_preferences::NSID),
70 post(put_preferences),
71 )
72 .route(
73 concat!("/", actor::get_preferences::NSID),
74 get(get_preferences),
75 )
76}