diff --git a/src/activitypub/actor.rs b/src/activitypub/actor.rs index f286d2e..ffa9df1 100644 --- a/src/activitypub/actor.rs +++ b/src/activitypub/actor.rs @@ -18,7 +18,7 @@ use super::vocabulary::{IMAGE, PERSON, PROPERTY_VALUE, SERVICE}; const W3ID_CONTEXT: &str = "https://w3id.org/security/v1"; -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr(test, derive(Default))] #[serde(rename_all = "camelCase")] pub struct PublicKey { @@ -27,7 +27,7 @@ pub struct PublicKey { pub public_key_pem: String, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Image { #[serde(rename = "type")] @@ -35,14 +35,14 @@ pub struct Image { pub url: String, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct ActorCapabilities { - // Actpr accepts ChatMessage objects + // Actor accepts ChatMessage objects accepts_chat_messages: Option, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct ActorProperty { name: String, #[serde(rename = "type")] @@ -50,8 +50,8 @@ pub struct ActorProperty { value: Option, } -// Clone trait is required by FromSql -#[derive(Clone, Deserialize, Serialize)] +// Clone and Debug traits are required by FromSql +#[derive(Clone, Debug, Deserialize, Serialize)] #[cfg_attr(test, derive(Default))] #[serde(rename_all = "camelCase")] pub struct Actor { diff --git a/src/activitypub/fetcher/fetchers.rs b/src/activitypub/fetcher/fetchers.rs index 85ddf6c..b9f06ed 100644 --- a/src/activitypub/fetcher/fetchers.rs +++ b/src/activitypub/fetcher/fetchers.rs @@ -144,8 +144,7 @@ pub async fn fetch_profile_by_actor_id( return Err(FetchError::OtherError("trying to fetch local profile")); }; let actor_json = send_request(instance, actor_url, &[]).await?; - let actor_value: Value = serde_json::from_str(&actor_json)?; - let actor: Actor = serde_json::from_value(actor_value.clone())?; + let actor: Actor = serde_json::from_str(&actor_json)?; let (avatar, banner) = fetch_avatar_and_banner(&actor, media_dir).await?; let extra_fields = actor.extra_fields(); let actor_address = format!( @@ -154,14 +153,14 @@ pub async fn fetch_profile_by_actor_id( actor_host, ); let profile_data = ProfileCreateData { - username: actor.preferred_username, - display_name: actor.name, + username: actor.preferred_username.clone(), + display_name: actor.name.clone(), acct: actor_address, - bio: actor.summary, + bio: actor.summary.clone(), avatar, banner, extra_fields, - actor_json: Some(actor_value), + actor_json: Some(actor), }; Ok(profile_data) } diff --git a/src/activitypub/receiver.rs b/src/activitypub/receiver.rs index 7b8b273..a9982fb 100644 --- a/src/activitypub/receiver.rs +++ b/src/activitypub/receiver.rs @@ -690,7 +690,6 @@ pub async fn receive_activity( }, (UPDATE, PERSON) => { require_actor_signature(&activity.actor, &signer_id)?; - let actor_value = activity.object.clone(); let actor: Actor = serde_json::from_value(activity.object) .map_err(|_| ValidationError("invalid actor data"))?; if actor.id != activity.actor { @@ -716,13 +715,13 @@ pub async fn receive_activity( ); }; let mut profile_data = ProfileUpdateData { - display_name: actor.name, + display_name: actor.name.clone(), bio: actor.summary.clone(), - bio_source: actor.summary, + bio_source: actor.summary.clone(), avatar, banner, extra_fields, - actor_json: Some(actor_value), + actor_json: Some(actor), }; profile_data.clean()?; update_profile(db_client, &profile.id, profile_data).await?; diff --git a/src/models/profiles/queries.rs b/src/models/profiles/queries.rs index 921ee2e..4f94b7e 100644 --- a/src/models/profiles/queries.rs +++ b/src/models/profiles/queries.rs @@ -471,8 +471,8 @@ pub async fn update_post_count( #[cfg(test)] mod tests { - use serde_json::json; use serial_test::serial; + use crate::activitypub::actor::Actor; use crate::database::test_utils::create_test_database; use crate::models::profiles::queries::create_profile; use crate::models::profiles::types::{ExtraField, ProfileCreateData}; @@ -497,27 +497,20 @@ mod tests { async fn test_actor_id_unique() { let db_client = create_test_database().await; let actor_id = "https://example.com/users/test"; - let create_actor_value = |actor_id| { - json!({ - "id": actor_id, - "type": "Person", - "preferredUsername": "test", - "inbox": "https://test", - "outbox": "https://test", - "publicKey": {"id": "test", "owner": "test", "publicKeyPem": "test"}, - }) + let create_actor = |actor_id: &str| { + Actor { id: actor_id.to_string(), ..Default::default() } }; let profile_data_1 = ProfileCreateData { username: "test-1".to_string(), acct: "test-1@example.com".to_string(), - actor_json: Some(create_actor_value(actor_id)), + actor_json: Some(create_actor(actor_id)), ..Default::default() }; create_profile(&db_client, profile_data_1).await.unwrap(); let profile_data_2 = ProfileCreateData { username: "test-2".to_string(), acct: "test-2@example.com".to_string(), - actor_json: Some(create_actor_value(actor_id)), + actor_json: Some(create_actor(actor_id)), ..Default::default() }; let error = create_profile(&db_client, profile_data_2).await.err().unwrap(); diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index 7728541..96b6077 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -1,7 +1,6 @@ use chrono::{DateTime, Utc}; use postgres_types::FromSql; use serde::{Deserialize, Serialize}; -use serde_json::Value; use uuid::Uuid; use crate::activitypub::actor::Actor; @@ -40,6 +39,7 @@ json_from_sql!(ExtraFields); json_to_sql!(ExtraFields); json_from_sql!(Actor); +json_to_sql!(Actor); #[derive(Clone, FromSql)] #[postgres(name = "actor_profile")] @@ -127,7 +127,7 @@ pub struct ProfileCreateData { pub avatar: Option, pub banner: Option, pub extra_fields: Vec, - pub actor_json: Option, + pub actor_json: Option, } impl ProfileCreateData { @@ -152,7 +152,7 @@ pub struct ProfileUpdateData { pub avatar: Option, pub banner: Option, pub extra_fields: Vec, - pub actor_json: Option, + pub actor_json: Option, } impl ProfileUpdateData {