mirror of
https://tangled.org/tranquil.farm/tranquil-pds
synced 2026-09-19 00:34:15 +00:00
Actor preferences
This commit is contained in:
+375
@@ -0,0 +1,375 @@
|
||||
mod common;
|
||||
|
||||
use common::{base_url, client, create_account_and_login};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_preferences_empty() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
assert!(body.get("preferences").is_some());
|
||||
assert!(body["preferences"].as_array().unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_preferences_no_auth() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 401);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_success() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#adultContentPref",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#contentLabelPref",
|
||||
"label": "nsfw",
|
||||
"visibility": "warn"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
let prefs_arr = body["preferences"].as_array().unwrap();
|
||||
assert_eq!(prefs_arr.len(), 2);
|
||||
|
||||
let adult_pref = prefs_arr.iter().find(|p| {
|
||||
p.get("$type").and_then(|t| t.as_str()) == Some("app.bsky.actor.defs#adultContentPref")
|
||||
});
|
||||
assert!(adult_pref.is_some());
|
||||
assert_eq!(adult_pref.unwrap()["enabled"], true);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_no_auth() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": []
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 401);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_missing_type() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 400);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
assert_eq!(body["error"], "InvalidRequest");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_invalid_namespace() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "com.example.somePref",
|
||||
"value": "test"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 400);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
assert_eq!(body["error"], "InvalidRequest");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_read_only_rejected() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#declaredAgePref",
|
||||
"isOverAge18": true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 400);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
assert_eq!(body["error"], "InvalidRequest");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_replaces_all() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs1 = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#adultContentPref",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#contentLabelPref",
|
||||
"label": "nsfw",
|
||||
"visibility": "warn"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs1)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let prefs2 = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#threadViewPref",
|
||||
"sort": "newest"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs2)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
let prefs_arr = body["preferences"].as_array().unwrap();
|
||||
assert_eq!(prefs_arr.len(), 1);
|
||||
assert_eq!(prefs_arr[0]["$type"], "app.bsky.actor.defs#threadViewPref");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_saved_feeds() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#savedFeedsPrefV2",
|
||||
"items": [
|
||||
{
|
||||
"type": "feed",
|
||||
"value": "at://did:plc:example/app.bsky.feed.generator/my-feed",
|
||||
"pinned": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
let prefs_arr = body["preferences"].as_array().unwrap();
|
||||
assert_eq!(prefs_arr.len(), 1);
|
||||
|
||||
let saved_feeds = &prefs_arr[0];
|
||||
assert_eq!(saved_feeds["$type"], "app.bsky.actor.defs#savedFeedsPrefV2");
|
||||
assert!(saved_feeds["items"].as_array().unwrap().len() == 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_put_preferences_muted_words() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
let (token, _did) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#mutedWordsPref",
|
||||
"items": [
|
||||
{
|
||||
"value": "spoiler",
|
||||
"targets": ["content", "tag"],
|
||||
"actorTarget": "all"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.json(&prefs)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
let prefs_arr = body["preferences"].as_array().unwrap();
|
||||
assert_eq!(prefs_arr[0]["$type"], "app.bsky.actor.defs#mutedWordsPref");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_preferences_isolation_between_users() {
|
||||
let client = client();
|
||||
let base = base_url().await;
|
||||
|
||||
let (token1, _did1) = create_account_and_login(&client).await;
|
||||
let (token2, _did2) = create_account_and_login(&client).await;
|
||||
|
||||
let prefs1 = json!({
|
||||
"preferences": [
|
||||
{
|
||||
"$type": "app.bsky.actor.defs#adultContentPref",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
client
|
||||
.post(format!("{}/xrpc/app.bsky.actor.putPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token1))
|
||||
.json(&prefs1)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let resp = client
|
||||
.get(format!("{}/xrpc/app.bsky.actor.getPreferences", base))
|
||||
.header("Authorization", format!("Bearer {}", token2))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body: Value = resp.json().await.unwrap();
|
||||
assert!(body["preferences"].as_array().unwrap().is_empty());
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
mod common;
|
||||
|
||||
use bspds::notifications::{
|
||||
enqueue_notification, enqueue_welcome_email, NewNotification, NotificationChannel,
|
||||
enqueue_notification, enqueue_welcome, NewNotification, NotificationChannel,
|
||||
NotificationStatus, NotificationType,
|
||||
};
|
||||
use sqlx::PgPool;
|
||||
@@ -64,19 +64,19 @@ async fn test_enqueue_notification() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_enqueue_welcome_email() {
|
||||
async fn test_enqueue_welcome() {
|
||||
let pool = get_pool().await;
|
||||
|
||||
let (_, did) = common::create_account_and_login(&common::client()).await;
|
||||
|
||||
let user_id: uuid::Uuid = sqlx::query_scalar!("SELECT id FROM users WHERE did = $1", did)
|
||||
let user_row = sqlx::query!("SELECT id, email, handle FROM users WHERE did = $1", did)
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.expect("User not found");
|
||||
|
||||
let notification_id = enqueue_welcome_email(&pool, user_id, "user@example.com", "testhandle", "example.com")
|
||||
let notification_id = enqueue_welcome(&pool, user_row.id, "example.com")
|
||||
.await
|
||||
.expect("Failed to enqueue welcome email");
|
||||
.expect("Failed to enqueue welcome notification");
|
||||
|
||||
let row = sqlx::query!(
|
||||
r#"
|
||||
@@ -92,9 +92,9 @@ async fn test_enqueue_welcome_email() {
|
||||
.await
|
||||
.expect("Notification not found");
|
||||
|
||||
assert_eq!(row.recipient, "user@example.com");
|
||||
assert_eq!(row.recipient, user_row.email);
|
||||
assert_eq!(row.subject.as_deref(), Some("Welcome to example.com"));
|
||||
assert!(row.body.contains("@testhandle"));
|
||||
assert!(row.body.contains(&format!("@{}", user_row.handle)));
|
||||
assert_eq!(row.notification_type, NotificationType::Welcome);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1428,7 +1428,7 @@ async fn test_state_with_special_chars() {
|
||||
let mock_client = setup_mock_client_metadata(redirect_uri).await;
|
||||
let client_id = mock_client.uri();
|
||||
|
||||
let (code_verifier, code_challenge) = generate_pkce();
|
||||
let (_code_verifier, code_challenge) = generate_pkce();
|
||||
let special_state = "state=with&special=chars&plus+more";
|
||||
|
||||
let par_body: Value = http_client
|
||||
|
||||
@@ -11,7 +11,6 @@ fn create_dpop_proof(
|
||||
iat_offset_secs: i64,
|
||||
) -> String {
|
||||
use p256::ecdsa::{SigningKey, Signature, signature::Signer};
|
||||
use p256::elliptic_curve::sec1::ToEncodedPoint;
|
||||
|
||||
let signing_key = SigningKey::random(&mut rand::thread_rng());
|
||||
let verifying_key = signing_key.verifying_key();
|
||||
|
||||
Reference in New Issue
Block a user