Save activity ID when processing remote follow request

This commit is contained in:
silverpill 2022-12-12 23:27:01 +00:00
parent b0f9b3537e
commit f2037c9516
2 changed files with 87 additions and 5 deletions

View file

@ -12,8 +12,13 @@ use crate::activitypub::{
use crate::config::Config;
use crate::database::DatabaseError;
use crate::errors::ValidationError;
use crate::models::relationships::queries::follow;
use crate::models::users::queries::get_user_by_name;
use crate::models::{
relationships::queries::{
create_remote_follow_request_opt,
follow_request_accepted,
},
users::queries::get_user_by_name,
};
use super::{HandlerError, HandlerResult};
#[derive(Deserialize)]
@ -45,7 +50,13 @@ pub async fn handle_follow(
&activity.object,
)?;
let target_user = get_user_by_name(db_client, &target_username).await?;
match follow(db_client, &source_profile.id, &target_user.profile.id).await {
let follow_request = create_remote_follow_request_opt(
db_client,
&source_profile.id,
&target_user.id,
&activity.id,
).await?;
match follow_request_accepted(db_client, &follow_request.id).await {
Ok(_) => (),
// Proceed even if relationship already exists
Err(DatabaseError::AlreadyExists(_)) => (),

View file

@ -115,7 +115,7 @@ pub async fn unfollow(
).await?;
let relationship_deleted = deleted_count > 0;
// Delete follow request (for remote follows)
let follow_request_deleted = delete_follow_request(
let follow_request_deleted = delete_follow_request_opt(
&transaction,
source_id,
target_id,
@ -135,6 +135,7 @@ pub async fn unfollow(
Ok(follow_request_deleted)
}
// Follow remote actor
pub async fn create_follow_request(
db_client: &impl GenericClient,
source_id: &Uuid,
@ -160,6 +161,40 @@ pub async fn create_follow_request(
Ok(request)
}
// Save follow request from remote actor
pub async fn create_remote_follow_request_opt(
db_client: &impl GenericClient,
source_id: &Uuid,
target_id: &Uuid,
activity_id: &str,
) -> Result<DbFollowRequest, DatabaseError> {
let request_id = new_uuid();
let row = db_client.query_one(
"
INSERT INTO follow_request (
id,
source_id,
target_id,
activity_id,
request_status
)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (source_id, target_id)
DO UPDATE SET activity_id = $4
RETURNING follow_request
",
&[
&request_id,
&source_id,
&target_id,
&activity_id,
&FollowRequestStatus::Pending,
],
).await?;
let request = row.try_get("follow_request")?;
Ok(request)
}
pub async fn follow_request_accepted(
db_client: &mut impl GenericClient,
request_id: &Uuid,
@ -200,7 +235,7 @@ pub async fn follow_request_rejected(
Ok(())
}
async fn delete_follow_request(
async fn delete_follow_request_opt(
db_client: &impl GenericClient,
source_id: &Uuid,
target_id: &Uuid,
@ -557,4 +592,40 @@ mod tests {
let following = get_following(db_client, &source.id).await.unwrap();
assert!(following.is_empty());
}
#[tokio::test]
#[serial]
async fn test_followed_by_remote_profile() {
let db_client = &mut create_test_database().await;
let source_data = ProfileCreateData {
username: "follower".to_string(),
hostname: Some("example.org".to_string()),
actor_json: Some(Actor::default()),
..Default::default()
};
let source = create_profile(db_client, source_data).await.unwrap();
let target_data = UserCreateData {
username: "test".to_string(),
..Default::default()
};
let target = create_user(db_client, target_data).await.unwrap();
// Create follow request
let activity_id = "https://example.org/objects/123";
let _follow_request = create_remote_follow_request_opt(
db_client, &source.id, &target.id, activity_id,
).await.unwrap();
// Repeat
let follow_request = create_remote_follow_request_opt(
db_client, &source.id, &target.id, activity_id,
).await.unwrap();
assert_eq!(follow_request.source_id, source.id);
assert_eq!(follow_request.target_id, target.id);
assert_eq!(follow_request.activity_id, Some(activity_id.to_string()));
assert_eq!(follow_request.request_status, FollowRequestStatus::Pending);
// Accept follow request
follow_request_accepted(db_client, &follow_request.id).await.unwrap();
let follow_request = get_follow_request_by_id(db_client, &follow_request.id)
.await.unwrap();
assert_eq!(follow_request.request_status, FollowRequestStatus::Accepted);
}
}