-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathput_preferences.rs
More file actions
143 lines (130 loc) · 4.01 KB
/
Copy pathput_preferences.rs
File metadata and controls
143 lines (130 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! app.bsky.actor.putPreferences endpoint.
//!
//! Stores the user's preferences on the PDS.
//! Preferences are the exception to the rule of proxying app.bsky.* to the AppView.
use std::net::SocketAddr;
use std::sync::Arc;
use axum::{
body::Bytes,
extract::{ConnectInfo, State},
http::{HeaderMap, StatusCode},
response::{IntoResponse, Response},
Json,
};
use serde_json::Value as JsonValue;
use crate::pds::db::StatisticKey;
use crate::pds::server::PdsState;
use crate::pds::auth::{auth_failure_response, check_user_auth};
use super::{get_caller_info};
/// POST /xrpc/app.bsky.actor.putPreferences - Set user preferences.
///
/// Stores the authenticated user's preferences on the PDS.
///
/// # Headers
///
/// * `Authorization: Bearer <access_jwt>` - Required
/// * `Content-Type: application/json` - Required
///
/// # Request Body
///
/// JSON object containing user preferences.
///
/// # Returns
///
/// * `200 OK` with success message on success
/// * `400 Bad Request` if the JSON is invalid
/// * `401 Unauthorized` if not authenticated
pub async fn put_preferences(
State(state): State<Arc<PdsState>>,
ConnectInfo(addr): ConnectInfo<SocketAddr>,
headers: HeaderMap,
body: Bytes,
) -> Response {
// Get caller info for statistics
let (ip_address, user_agent) = get_caller_info(&headers, Some(addr));
// Increment statistics
let stat_key = StatisticKey {
name: "xrpc/app.bsky.actor.putPreferences".to_string(),
ip_address,
user_agent,
};
let _ = state.db.increment_statistic_for_endpoint(&stat_key);
// Check authentication (supports Legacy and OAuth)
let auth_result = check_user_auth(
&state,
&headers,
None,
"POST",
"/xrpc/app.bsky.actor.putPreferences",
);
if !auth_result.is_authenticated {
return auth_failure_response(&auth_result);
}
// Parse the request body as JSON
let prefs_json: JsonValue = match serde_json::from_slice(&body) {
Ok(json) => json,
Err(e) => {
state.log.warning(&format!(
"[PREFS] Failed to parse preferences JSON: {}",
e
));
return (
StatusCode::BAD_REQUEST,
Json(serde_json::json!({
"error": "InvalidRequest",
"message": "Failed to parse preferences JSON"
})),
)
.into_response();
}
};
// Convert back to string for storage
let prefs_string = prefs_json.to_string();
// Check if preferences already exist
let prefs_count = match state.db.get_preferences_count() {
Ok(count) => count,
Err(e) => {
state.log.error(&format!(
"[PREFS] Failed to get preferences count: {}",
e
));
return (
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({
"error": "InternalServerError",
"message": "Failed to update preferences"
})),
)
.into_response();
}
};
// Insert or update preferences
let result = if prefs_count == 0 {
state.db.insert_preferences(&prefs_string)
} else {
state.db.update_preferences(&prefs_string)
};
match result {
Ok(()) => {
state.log.trace("[PREFS] Preferences updated successfully");
Json(serde_json::json!({
"message": "Preferences updated"
}))
.into_response()
}
Err(e) => {
state.log.error(&format!(
"[PREFS] Failed to save preferences: {}",
e
));
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({
"error": "InternalServerError",
"message": "Failed to save preferences"
})),
)
.into_response()
}
}
}