fix(ap): visibility-aware addressing — correct to/cc outbound, parse inbound to/cc
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Failing after 9m25s
test / unit (pull_request) Successful in 16m39s
test / integration (pull_request) Failing after 17m35s
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Failing after 9m25s
test / unit (pull_request) Successful in 16m39s
test / integration (pull_request) Failing after 17m35s
This commit is contained in:
@@ -36,6 +36,23 @@ fn thought_note_json(
|
||||
base_url: &str,
|
||||
) -> anyhow::Result<(url::Url, serde_json::Value)> {
|
||||
let ap_id = url::Url::parse(&format!("{}/thoughts/{}", base_url, thought.id))?;
|
||||
|
||||
// Build to/cc based on visibility per AP spec.
|
||||
let (to, cc) = match thought.visibility {
|
||||
domain::models::thought::Visibility::Public => (
|
||||
vec![crate::urls::AS_PUBLIC.to_string()],
|
||||
vec![local_actor.followers_url.to_string()],
|
||||
),
|
||||
domain::models::thought::Visibility::Unlisted => (
|
||||
vec![local_actor.followers_url.to_string()],
|
||||
vec![crate::urls::AS_PUBLIC.to_string()],
|
||||
),
|
||||
domain::models::thought::Visibility::Followers => {
|
||||
(vec![local_actor.followers_url.to_string()], vec![])
|
||||
}
|
||||
domain::models::thought::Visibility::Direct => (vec![], vec![]),
|
||||
};
|
||||
|
||||
let mut note = serde_json::json!({
|
||||
"type": "Note",
|
||||
"id": ap_id.to_string(),
|
||||
@@ -43,8 +60,8 @@ fn thought_note_json(
|
||||
"attributedTo": local_actor.ap_id.to_string(),
|
||||
"content": thought.content.as_str(),
|
||||
"published": thought.created_at.to_rfc3339(),
|
||||
"to": [crate::urls::AS_PUBLIC],
|
||||
"cc": [local_actor.followers_url.to_string()],
|
||||
"to": to,
|
||||
"cc": cc,
|
||||
"sensitive": thought.sensitive,
|
||||
});
|
||||
if let Some(ref cw) = thought.content_warning {
|
||||
|
||||
@@ -111,6 +111,24 @@ impl ApObjectHandler for ThoughtsObjectHandler {
|
||||
.intern_remote_actor(actor_url)
|
||||
.await
|
||||
.map_err(|e| anyhow!("{e}"))?;
|
||||
|
||||
// Derive visibility from AP addressing conventions.
|
||||
let as_public = "https://www.w3.org/ns/activitystreams#Public";
|
||||
let in_to = note.to.iter().any(|s| s == as_public);
|
||||
let in_cc = note.cc.iter().any(|s| s == as_public);
|
||||
let has_followers = note.to.iter().any(|s| s.ends_with("/followers"))
|
||||
|| note.cc.iter().any(|s| s.ends_with("/followers"));
|
||||
|
||||
let visibility = if in_to {
|
||||
"public"
|
||||
} else if in_cc {
|
||||
"unlisted"
|
||||
} else if has_followers {
|
||||
"followers"
|
||||
} else {
|
||||
"direct"
|
||||
};
|
||||
|
||||
self.repo
|
||||
.accept_note(
|
||||
ap_id,
|
||||
@@ -119,6 +137,7 @@ impl ApObjectHandler for ThoughtsObjectHandler {
|
||||
note.published,
|
||||
note.sensitive,
|
||||
note.summary,
|
||||
visibility,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| anyhow!("{e}"))
|
||||
|
||||
@@ -187,11 +187,12 @@ impl ActivityPubRepository for PgActivityPubRepository {
|
||||
published: DateTime<Utc>,
|
||||
sensitive: bool,
|
||||
content_warning: Option<String>,
|
||||
visibility: &str,
|
||||
) -> Result<(), DomainError> {
|
||||
let capped: String = content.chars().take(500).collect();
|
||||
sqlx::query(
|
||||
"INSERT INTO thoughts(id,user_id,content,ap_id,visibility,sensitive,local,content_warning,created_at)
|
||||
VALUES($1,$2,$3,$4,'public',$5,false,$6,$7) ON CONFLICT(ap_id) DO NOTHING",
|
||||
VALUES($1,$2,$3,$4,$8,$5,false,$6,$7) ON CONFLICT(ap_id) DO NOTHING",
|
||||
)
|
||||
.bind(uuid::Uuid::new_v4())
|
||||
.bind(author_id.as_uuid())
|
||||
@@ -200,6 +201,7 @@ impl ActivityPubRepository for PgActivityPubRepository {
|
||||
.bind(sensitive)
|
||||
.bind(content_warning)
|
||||
.bind(published)
|
||||
.bind(visibility)
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(|e| DomainError::Internal(e.to_string()))
|
||||
@@ -275,6 +277,7 @@ mod tests {
|
||||
chrono::Utc::now(),
|
||||
false,
|
||||
None,
|
||||
"public",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user