Pass Actor object instead of Value when creating/updating profile

This commit is contained in:
silverpill 2022-04-21 22:52:28 +00:00
parent a9504de10d
commit a97456d77a
5 changed files with 23 additions and 32 deletions

View file

@ -18,7 +18,7 @@ use super::vocabulary::{IMAGE, PERSON, PROPERTY_VALUE, SERVICE};
const W3ID_CONTEXT: &str = "https://w3id.org/security/v1"; const W3ID_CONTEXT: &str = "https://w3id.org/security/v1";
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(test, derive(Default))] #[cfg_attr(test, derive(Default))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PublicKey { pub struct PublicKey {
@ -27,7 +27,7 @@ pub struct PublicKey {
pub public_key_pem: String, pub public_key_pem: String,
} }
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Image { pub struct Image {
#[serde(rename = "type")] #[serde(rename = "type")]
@ -35,14 +35,14 @@ pub struct Image {
pub url: String, pub url: String,
} }
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ActorCapabilities { pub struct ActorCapabilities {
// Actpr accepts ChatMessage objects // Actor accepts ChatMessage objects
accepts_chat_messages: Option<bool>, accepts_chat_messages: Option<bool>,
} }
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ActorProperty { pub struct ActorProperty {
name: String, name: String,
#[serde(rename = "type")] #[serde(rename = "type")]
@ -50,8 +50,8 @@ pub struct ActorProperty {
value: Option<String>, value: Option<String>,
} }
// Clone trait is required by FromSql // Clone and Debug traits are required by FromSql
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(test, derive(Default))] #[cfg_attr(test, derive(Default))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Actor { pub struct Actor {

View file

@ -144,8 +144,7 @@ pub async fn fetch_profile_by_actor_id(
return Err(FetchError::OtherError("trying to fetch local profile")); return Err(FetchError::OtherError("trying to fetch local profile"));
}; };
let actor_json = send_request(instance, actor_url, &[]).await?; 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_str(&actor_json)?;
let actor: Actor = serde_json::from_value(actor_value.clone())?;
let (avatar, banner) = fetch_avatar_and_banner(&actor, media_dir).await?; let (avatar, banner) = fetch_avatar_and_banner(&actor, media_dir).await?;
let extra_fields = actor.extra_fields(); let extra_fields = actor.extra_fields();
let actor_address = format!( let actor_address = format!(
@ -154,14 +153,14 @@ pub async fn fetch_profile_by_actor_id(
actor_host, actor_host,
); );
let profile_data = ProfileCreateData { let profile_data = ProfileCreateData {
username: actor.preferred_username, username: actor.preferred_username.clone(),
display_name: actor.name, display_name: actor.name.clone(),
acct: actor_address, acct: actor_address,
bio: actor.summary, bio: actor.summary.clone(),
avatar, avatar,
banner, banner,
extra_fields, extra_fields,
actor_json: Some(actor_value), actor_json: Some(actor),
}; };
Ok(profile_data) Ok(profile_data)
} }

View file

@ -690,7 +690,6 @@ pub async fn receive_activity(
}, },
(UPDATE, PERSON) => { (UPDATE, PERSON) => {
require_actor_signature(&activity.actor, &signer_id)?; require_actor_signature(&activity.actor, &signer_id)?;
let actor_value = activity.object.clone();
let actor: Actor = serde_json::from_value(activity.object) let actor: Actor = serde_json::from_value(activity.object)
.map_err(|_| ValidationError("invalid actor data"))?; .map_err(|_| ValidationError("invalid actor data"))?;
if actor.id != activity.actor { if actor.id != activity.actor {
@ -716,13 +715,13 @@ pub async fn receive_activity(
); );
}; };
let mut profile_data = ProfileUpdateData { let mut profile_data = ProfileUpdateData {
display_name: actor.name, display_name: actor.name.clone(),
bio: actor.summary.clone(), bio: actor.summary.clone(),
bio_source: actor.summary, bio_source: actor.summary.clone(),
avatar, avatar,
banner, banner,
extra_fields, extra_fields,
actor_json: Some(actor_value), actor_json: Some(actor),
}; };
profile_data.clean()?; profile_data.clean()?;
update_profile(db_client, &profile.id, profile_data).await?; update_profile(db_client, &profile.id, profile_data).await?;

View file

@ -471,8 +471,8 @@ pub async fn update_post_count(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde_json::json;
use serial_test::serial; use serial_test::serial;
use crate::activitypub::actor::Actor;
use crate::database::test_utils::create_test_database; use crate::database::test_utils::create_test_database;
use crate::models::profiles::queries::create_profile; use crate::models::profiles::queries::create_profile;
use crate::models::profiles::types::{ExtraField, ProfileCreateData}; use crate::models::profiles::types::{ExtraField, ProfileCreateData};
@ -497,27 +497,20 @@ mod tests {
async fn test_actor_id_unique() { async fn test_actor_id_unique() {
let db_client = create_test_database().await; let db_client = create_test_database().await;
let actor_id = "https://example.com/users/test"; let actor_id = "https://example.com/users/test";
let create_actor_value = |actor_id| { let create_actor = |actor_id: &str| {
json!({ Actor { id: actor_id.to_string(), ..Default::default() }
"id": actor_id,
"type": "Person",
"preferredUsername": "test",
"inbox": "https://test",
"outbox": "https://test",
"publicKey": {"id": "test", "owner": "test", "publicKeyPem": "test"},
})
}; };
let profile_data_1 = ProfileCreateData { let profile_data_1 = ProfileCreateData {
username: "test-1".to_string(), username: "test-1".to_string(),
acct: "test-1@example.com".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() ..Default::default()
}; };
create_profile(&db_client, profile_data_1).await.unwrap(); create_profile(&db_client, profile_data_1).await.unwrap();
let profile_data_2 = ProfileCreateData { let profile_data_2 = ProfileCreateData {
username: "test-2".to_string(), username: "test-2".to_string(),
acct: "test-2@example.com".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() ..Default::default()
}; };
let error = create_profile(&db_client, profile_data_2).await.err().unwrap(); let error = create_profile(&db_client, profile_data_2).await.err().unwrap();

View file

@ -1,7 +1,6 @@
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use postgres_types::FromSql; use postgres_types::FromSql;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid; use uuid::Uuid;
use crate::activitypub::actor::Actor; use crate::activitypub::actor::Actor;
@ -40,6 +39,7 @@ json_from_sql!(ExtraFields);
json_to_sql!(ExtraFields); json_to_sql!(ExtraFields);
json_from_sql!(Actor); json_from_sql!(Actor);
json_to_sql!(Actor);
#[derive(Clone, FromSql)] #[derive(Clone, FromSql)]
#[postgres(name = "actor_profile")] #[postgres(name = "actor_profile")]
@ -127,7 +127,7 @@ pub struct ProfileCreateData {
pub avatar: Option<String>, pub avatar: Option<String>,
pub banner: Option<String>, pub banner: Option<String>,
pub extra_fields: Vec<ExtraField>, pub extra_fields: Vec<ExtraField>,
pub actor_json: Option<Value>, pub actor_json: Option<Actor>,
} }
impl ProfileCreateData { impl ProfileCreateData {
@ -152,7 +152,7 @@ pub struct ProfileUpdateData {
pub avatar: Option<String>, pub avatar: Option<String>,
pub banner: Option<String>, pub banner: Option<String>,
pub extra_fields: Vec<ExtraField>, pub extra_fields: Vec<ExtraField>,
pub actor_json: Option<Value>, pub actor_json: Option<Actor>,
} }
impl ProfileUpdateData { impl ProfileUpdateData {