diff --git a/upub/core/src/model/relation.rs b/upub/core/src/model/relation.rs index df7fe36b..a2e7d531 100644 --- a/upub/core/src/model/relation.rs +++ b/upub/core/src/model/relation.rs @@ -9,6 +9,8 @@ pub struct Model { pub following: i64, pub accept: Option, pub activity: i64, + pub follower_instance: i64, + pub following_instance: i64, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -45,6 +47,22 @@ pub enum Relation { on_delete = "Cascade" )] ActorsFollowing, + #[sea_orm( + belongs_to = "super::instance::Entity", + from = "Column::FollowerInstance", + to = "super::instance::Column::Internal", + on_update = "Cascade", + on_delete = "NoAction" + )] + InstancesFollower, + #[sea_orm( + belongs_to = "super::instance::Entity", + from = "Column::FollowingInstance", + to = "super::instance::Column::Internal", + on_update = "Cascade", + on_delete = "NoAction" + )] + InstancesFollowing, } impl Related for Entity { @@ -59,6 +77,12 @@ impl Related for Entity { } } +impl Related for Entity { + fn to() -> RelationDef { + Relation::InstancesFollowing.def() + } +} + impl ActiveModelBehavior for ActiveModel {} impl Entity { diff --git a/upub/core/src/traits/process.rs b/upub/core/src/traits/process.rs index 3b197474..60977fee 100644 --- a/upub/core/src/traits/process.rs +++ b/upub/core/src/traits/process.rs @@ -116,15 +116,16 @@ pub async fn like(ctx: &crate::Context, activity: impl apb::Activity, tx: &Datab } pub async fn follow(ctx: &crate::Context, activity: impl apb::Activity, tx: &DatabaseTransaction) -> Result<(), ProcessorError> { - let source_actor_internal = crate::model::actor::Entity::ap_to_internal(activity.actor().id()?, tx) + let source_actor = crate::model::actor::Entity::find_by_ap_id(activity.actor().id()?) + .one(tx) .await? .ok_or(ProcessorError::Incomplete)?; - let usr = ctx.fetch_user(activity.object().id()?, tx).await?; + let target_actor = ctx.fetch_user(activity.object().id()?, tx).await?; let activity_model = ctx.insert_activity(activity, tx).await?; if let Some(relation) = crate::model::relation::Entity::find() - .filter(crate::model::relation::Column::Follower.eq(source_actor_internal)) - .filter(crate::model::relation::Column::Following.eq(usr.internal)) + .filter(crate::model::relation::Column::Follower.eq(source_actor.internal)) + .filter(crate::model::relation::Column::Following.eq(target_actor.internal)) .select_only() .select_column(crate::model::relation::Column::Internal) .into_tuple::() @@ -140,19 +141,29 @@ pub async fn follow(ctx: &crate::Context, activity: impl apb::Activity, tx: &Dat } else { + let follower_instance = crate::model::instance::Entity::domain_to_internal(&source_actor.domain, tx) + .await? + .ok_or(ProcessorError::Incomplete)?; + + let following_instance = crate::model::instance::Entity::domain_to_internal(&target_actor.domain, tx) + .await? + .ok_or(ProcessorError::Incomplete)?; + // new follow request, make new row let relation_model = crate::model::relation::ActiveModel { internal: NotSet, accept: Set(None), activity: Set(activity_model.internal), - follower: Set(source_actor_internal), - following: Set(usr.internal), + follower: Set(source_actor.internal), + follower_instance: Set(follower_instance), + following: Set(target_actor.internal), + following_instance: Set(following_instance), }; crate::model::relation::Entity::insert(relation_model) .exec(tx).await?; } - tracing::info!("{} wants to follow {}", activity_model.actor, usr.id); + tracing::info!("{} wants to follow {}", activity_model.actor, target_actor.id); Ok(()) } diff --git a/upub/migrations/src/lib.rs b/upub/migrations/src/lib.rs index 4b3c1016..bd437c26 100644 --- a/upub/migrations/src/lib.rs +++ b/upub/migrations/src/lib.rs @@ -9,6 +9,7 @@ mod m20240529_000001_add_relation_unique_index; mod m20240605_000001_add_jobs_table; mod m20240606_000001_add_audience_to_objects; mod m20240607_000001_activity_ref_is_optional; +mod m20240609_000001_add_instance_field_to_relations; pub struct Migrator; @@ -25,6 +26,7 @@ impl MigratorTrait for Migrator { Box::new(m20240605_000001_add_jobs_table::Migration), Box::new(m20240606_000001_add_audience_to_objects::Migration), Box::new(m20240607_000001_activity_ref_is_optional::Migration), + Box::new(m20240609_000001_add_instance_field_to_relations::Migration), ] } } diff --git a/upub/migrations/src/m20240524_000002_create_relations_likes_shares.rs b/upub/migrations/src/m20240524_000002_create_relations_likes_shares.rs index 6c6b058e..5029156f 100644 --- a/upub/migrations/src/m20240524_000002_create_relations_likes_shares.rs +++ b/upub/migrations/src/m20240524_000002_create_relations_likes_shares.rs @@ -10,6 +10,8 @@ pub enum Relations { Following, Activity, Accept, + FollowerInstance, // ADDED AFTERWARDS + FollowingInstance, // ADDED AFTERWARDS } #[derive(DeriveIden)] diff --git a/upub/migrations/src/m20240609_000001_add_instance_field_to_relations.rs b/upub/migrations/src/m20240609_000001_add_instance_field_to_relations.rs new file mode 100644 index 00000000..fba756ec --- /dev/null +++ b/upub/migrations/src/m20240609_000001_add_instance_field_to_relations.rs @@ -0,0 +1,96 @@ +use sea_orm_migration::prelude::*; + +use crate::{m20240524_000001_create_actor_activity_object_tables::Instances, m20240524_000002_create_relations_likes_shares::Relations}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + + manager + .alter_table( + Table::alter() + .table(Relations::Table) + .add_column(ColumnDef::new(Relations::FollowerInstance).big_integer().not_null()) + .add_foreign_key( + TableForeignKey::new() + .name("fkey-relations-follower-instance") + .from_tbl(Relations::Table) + .from_col(Relations::FollowerInstance) + .to_tbl(Instances::Table) + .to_col(Instances::Internal) + .on_update(ForeignKeyAction::Cascade) + ) + .add_column(ColumnDef::new(Relations::FollowingInstance).big_integer().not_null()) + .add_foreign_key( + TableForeignKey::new() + .name("fkey-relations-following-instance") + .from_tbl(Relations::Table) + .from_col(Relations::FollowingInstance) + .to_tbl(Instances::Table) + .to_col(Instances::Internal) + .on_update(ForeignKeyAction::Cascade) + ) + .to_owned() + ) + .await?; + + manager + .create_index( + Index::create() + .name("index-relations-follower-instance") + .table(Relations::Table) + .col(Relations::FollowerInstance) + .to_owned() + ).await?; + + manager + .create_index( + Index::create() + .name("index-relations-following-instance") + .table(Relations::Table) + .col(Relations::FollowingInstance) + .to_owned() + ).await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + + manager + .drop_index( + Index::drop() + .name("index-relations-follower-instance") + .table(Relations::Table) + .to_owned() + ) + .await?; + + manager + .drop_index( + Index::drop() + .name("index-relations-following-instance") + .table(Relations::Table) + .to_owned() + ) + .await?; + + manager + .alter_table( + Table::alter() + .table(Relations::Table) + .drop_foreign_key(Alias::new("fkey-relations-follower-instance")) + .drop_column(Relations::FollowerInstance) + .drop_foreign_key(Alias::new("fkey-relations-following-instance")) + .drop_column(Relations::FollowingInstance) + .to_owned() + ) + .await?; + + Ok(()) + } +} +