refactor: consolidate 11 social use cases → SocialCmd/SocialQry enum dispatch

-280 net lines. 11 one-file use cases replaced by execute_command/
execute_query with enum dispatch. Added FollowRejected event (reject
was silently dropping). Command→event mapping now explicit in one match.
This commit is contained in:
2026-07-10 16:26:57 +02:00
parent d60c47199c
commit 7e02f15a85
31 changed files with 659 additions and 939 deletions

View File

@@ -72,6 +72,11 @@ pub enum EventPayload {
requester_kind: String,
requester_id: String,
},
FollowRejected {
owner_id: String,
requester_kind: String,
requester_id: String,
},
Unfollowed {
follower_id: String,
target_kind: String,
@@ -164,6 +169,7 @@ impl EventPayload {
EventPayload::WatchlistEntryRemoved { .. } => "WatchlistEntryRemoved",
EventPayload::FollowRequested { .. } => "FollowRequested",
EventPayload::FollowAccepted { .. } => "FollowAccepted",
EventPayload::FollowRejected { .. } => "FollowRejected",
EventPayload::Unfollowed { .. } => "Unfollowed",
EventPayload::FollowerRemoved { .. } => "FollowerRemoved",
EventPayload::ActorBlocked { .. } => "ActorBlocked",
@@ -328,6 +334,14 @@ impl From<&DomainEvent> for EventPayload {
requester_id: id,
}
}
DomainEvent::FollowRejected { owner, requester } => {
let (kind, id) = identity_to_payload(requester);
EventPayload::FollowRejected {
owner_id: owner.value().to_string(),
requester_kind: kind,
requester_id: id,
}
}
DomainEvent::Unfollowed { follower, target } => {
let (kind, id) = identity_to_payload(target);
EventPayload::Unfollowed {
@@ -559,6 +573,14 @@ impl TryFrom<EventPayload> for DomainEvent {
owner: UserId::from_uuid(parse_uuid(&owner_id, "owner_id")?),
requester: payload_to_identity(&requester_kind, requester_id)?,
}),
EventPayload::FollowRejected {
owner_id,
requester_kind,
requester_id,
} => Ok(DomainEvent::FollowRejected {
owner: UserId::from_uuid(parse_uuid(&owner_id, "owner_id")?),
requester: payload_to_identity(&requester_kind, requester_id)?,
}),
EventPayload::Unfollowed {
follower_id,
target_kind,

View File

@@ -14,6 +14,7 @@ pub fn event_to_subject(prefix: &str, event: &DomainEvent) -> String {
DomainEvent::WatchlistEntryRemoved { .. } => "watchlist.entry.removed",
DomainEvent::FollowRequested { .. } => "follow.requested",
DomainEvent::FollowAccepted { .. } => "follow.accepted",
DomainEvent::FollowRejected { .. } => "follow.rejected",
DomainEvent::Unfollowed { .. } => "follow.unfollowed",
DomainEvent::FollowerRemoved { .. } => "follower.removed",
DomainEvent::ActorBlocked { .. } => "actor.blocked",

View File

@@ -1,23 +0,0 @@
use domain::{errors::DomainError, events::DomainEvent, value_objects::UserId};
use super::{commands::AcceptFollowCommand, deps::SocialCommandDeps};
pub async fn execute(
deps: &SocialCommandDeps,
cmd: AcceptFollowCommand,
) -> Result<(), DomainError> {
let owner = UserId::from_uuid(cmd.owner_id);
deps.social_command
.accept_follow(&owner, &cmd.requester)
.await?;
deps.event_publisher
.publish(&DomainEvent::FollowAccepted {
owner,
requester: cmd.requester,
})
.await
}
#[cfg(test)]
#[path = "tests/accept.rs"]
mod tests;

View File

@@ -1,18 +0,0 @@
use domain::{errors::DomainError, events::DomainEvent, value_objects::UserId};
use super::{commands::BlockCommand, deps::SocialCommandDeps};
pub async fn execute(deps: &SocialCommandDeps, cmd: BlockCommand) -> Result<(), DomainError> {
let blocker = UserId::from_uuid(cmd.blocker_id);
deps.social_command.block(&blocker, &cmd.target).await?;
deps.event_publisher
.publish(&DomainEvent::ActorBlocked {
blocker,
target: cmd.target,
})
.await
}
#[cfg(test)]
#[path = "tests/block.rs"]
mod tests;

View File

@@ -1,37 +1,33 @@
use domain::value_objects::{FollowTarget, SocialIdentity};
use uuid::Uuid;
pub struct FollowCommand {
pub follower_id: Uuid,
pub target: FollowTarget,
}
pub struct UnfollowCommand {
pub follower_id: Uuid,
pub target: SocialIdentity,
}
pub struct AcceptFollowCommand {
pub owner_id: Uuid,
pub requester: SocialIdentity,
}
pub struct RejectFollowCommand {
pub owner_id: Uuid,
pub requester: SocialIdentity,
}
pub struct RemoveFollowerCommand {
pub owner_id: Uuid,
pub follower: SocialIdentity,
}
pub struct BlockCommand {
pub blocker_id: Uuid,
pub target: SocialIdentity,
}
pub struct UnblockCommand {
pub blocker_id: Uuid,
pub target: SocialIdentity,
pub enum SocialCmd {
Follow {
follower_id: Uuid,
target: FollowTarget,
},
Unfollow {
follower_id: Uuid,
target: SocialIdentity,
},
AcceptFollow {
owner_id: Uuid,
requester: SocialIdentity,
},
RejectFollow {
owner_id: Uuid,
requester: SocialIdentity,
},
RemoveFollower {
owner_id: Uuid,
follower: SocialIdentity,
},
Block {
blocker_id: Uuid,
target: SocialIdentity,
},
Unblock {
blocker_id: Uuid,
target: SocialIdentity,
},
}

View File

@@ -0,0 +1,101 @@
use domain::{
errors::DomainError,
events::DomainEvent,
value_objects::{SocialActor, UserId},
};
use super::{
commands::SocialCmd,
deps::{SocialCommandDeps, SocialQueryDeps},
queries::SocialQry,
};
pub async fn execute_command(
deps: &SocialCommandDeps,
cmd: SocialCmd,
) -> Result<(), DomainError> {
let event = match cmd {
SocialCmd::Follow {
follower_id,
target,
} => {
let follower = UserId::from_uuid(follower_id);
deps.social_command.follow(&follower, &target).await?;
DomainEvent::FollowRequested { follower, target }
}
SocialCmd::Unfollow {
follower_id,
target,
} => {
let follower = UserId::from_uuid(follower_id);
deps.social_command.unfollow(&follower, &target).await?;
DomainEvent::Unfollowed { follower, target }
}
SocialCmd::AcceptFollow {
owner_id,
requester,
} => {
let owner = UserId::from_uuid(owner_id);
deps.social_command
.accept_follow(&owner, &requester)
.await?;
DomainEvent::FollowAccepted { owner, requester }
}
SocialCmd::RejectFollow {
owner_id,
requester,
} => {
let owner = UserId::from_uuid(owner_id);
deps.social_command
.reject_follow(&owner, &requester)
.await?;
DomainEvent::FollowRejected { owner, requester }
}
SocialCmd::RemoveFollower { owner_id, follower } => {
let owner = UserId::from_uuid(owner_id);
deps.social_command
.remove_follower(&owner, &follower)
.await?;
DomainEvent::FollowerRemoved { owner, follower }
}
SocialCmd::Block {
blocker_id,
target,
} => {
let blocker = UserId::from_uuid(blocker_id);
deps.social_command.block(&blocker, &target).await?;
DomainEvent::ActorBlocked { blocker, target }
}
SocialCmd::Unblock {
blocker_id,
target,
} => {
let blocker = UserId::from_uuid(blocker_id);
deps.social_command.unblock(&blocker, &target).await?;
DomainEvent::ActorUnblocked { blocker, target }
}
};
deps.event_publisher.publish(&event).await
}
pub async fn execute_query(
deps: &SocialQueryDeps,
query: SocialQry,
) -> Result<Vec<SocialActor>, DomainError> {
let user_id = match &query {
SocialQry::GetFollowing { user_id }
| SocialQry::GetFollowers { user_id }
| SocialQry::GetPending { user_id }
| SocialQry::GetBlocked { user_id } => UserId::from_uuid(*user_id),
};
match query {
SocialQry::GetFollowing { .. } => deps.social_query.get_following(&user_id).await,
SocialQry::GetFollowers { .. } => deps.social_query.get_followers(&user_id).await,
SocialQry::GetPending { .. } => deps.social_query.get_pending_followers(&user_id).await,
SocialQry::GetBlocked { .. } => deps.social_query.get_blocked(&user_id).await,
}
}
#[cfg(test)]
#[path = "tests/execute.rs"]
mod tests;

View File

@@ -1,18 +0,0 @@
use domain::{errors::DomainError, events::DomainEvent, value_objects::UserId};
use super::{commands::FollowCommand, deps::SocialCommandDeps};
pub async fn execute(deps: &SocialCommandDeps, cmd: FollowCommand) -> Result<(), DomainError> {
let follower = UserId::from_uuid(cmd.follower_id);
deps.social_command.follow(&follower, &cmd.target).await?;
deps.event_publisher
.publish(&DomainEvent::FollowRequested {
follower,
target: cmd.target,
})
.await
}
#[cfg(test)]
#[path = "tests/follow.rs"]
mod tests;

View File

@@ -1,14 +0,0 @@
use domain::{
errors::DomainError,
value_objects::{SocialActor, UserId},
};
use super::{deps::SocialQueryDeps, queries::GetBlockedQuery};
pub async fn execute(
deps: &SocialQueryDeps,
query: GetBlockedQuery,
) -> Result<Vec<SocialActor>, DomainError> {
let user_id = UserId::from_uuid(query.user_id);
deps.social_query.get_blocked(&user_id).await
}

View File

@@ -1,18 +0,0 @@
use domain::{
errors::DomainError,
value_objects::{SocialActor, UserId},
};
use super::{deps::SocialQueryDeps, queries::GetFollowersQuery};
pub async fn execute(
deps: &SocialQueryDeps,
query: GetFollowersQuery,
) -> Result<Vec<SocialActor>, DomainError> {
let user_id = UserId::from_uuid(query.user_id);
deps.social_query.get_followers(&user_id).await
}
#[cfg(test)]
#[path = "tests/get_followers.rs"]
mod tests;

View File

@@ -1,18 +0,0 @@
use domain::{
errors::DomainError,
value_objects::{SocialActor, UserId},
};
use super::{deps::SocialQueryDeps, queries::GetFollowingQuery};
pub async fn execute(
deps: &SocialQueryDeps,
query: GetFollowingQuery,
) -> Result<Vec<SocialActor>, DomainError> {
let user_id = UserId::from_uuid(query.user_id);
deps.social_query.get_following(&user_id).await
}
#[cfg(test)]
#[path = "tests/get_following.rs"]
mod tests;

View File

@@ -1,18 +0,0 @@
use domain::{
errors::DomainError,
value_objects::{SocialActor, UserId},
};
use super::{deps::SocialQueryDeps, queries::GetPendingFollowersQuery};
pub async fn execute(
deps: &SocialQueryDeps,
query: GetPendingFollowersQuery,
) -> Result<Vec<SocialActor>, DomainError> {
let user_id = UserId::from_uuid(query.user_id);
deps.social_query.get_pending_followers(&user_id).await
}
#[cfg(test)]
#[path = "tests/get_pending.rs"]
mod tests;

View File

@@ -1,15 +1,4 @@
pub mod commands;
pub mod deps;
pub mod execute;
pub mod queries;
pub mod accept;
pub mod block;
pub mod follow;
pub mod get_blocked;
pub mod get_followers;
pub mod get_following;
pub mod get_pending;
pub mod reject;
pub mod remove_follower;
pub mod unblock;
pub mod unfollow;

View File

@@ -1,17 +1,8 @@
use uuid::Uuid;
pub struct GetFollowingQuery {
pub user_id: Uuid,
}
pub struct GetFollowersQuery {
pub user_id: Uuid,
}
pub struct GetPendingFollowersQuery {
pub user_id: Uuid,
}
pub struct GetBlockedQuery {
pub user_id: Uuid,
pub enum SocialQry {
GetFollowing { user_id: Uuid },
GetFollowers { user_id: Uuid },
GetPending { user_id: Uuid },
GetBlocked { user_id: Uuid },
}

View File

@@ -1,17 +0,0 @@
use domain::{errors::DomainError, value_objects::UserId};
use super::{commands::RejectFollowCommand, deps::SocialCommandDeps};
pub async fn execute(
deps: &SocialCommandDeps,
cmd: RejectFollowCommand,
) -> Result<(), DomainError> {
let owner = UserId::from_uuid(cmd.owner_id);
deps.social_command
.reject_follow(&owner, &cmd.requester)
.await
}
#[cfg(test)]
#[path = "tests/reject.rs"]
mod tests;

View File

@@ -1,23 +0,0 @@
use domain::{errors::DomainError, events::DomainEvent, value_objects::UserId};
use super::{commands::RemoveFollowerCommand, deps::SocialCommandDeps};
pub async fn execute(
deps: &SocialCommandDeps,
cmd: RemoveFollowerCommand,
) -> Result<(), DomainError> {
let owner = UserId::from_uuid(cmd.owner_id);
deps.social_command
.remove_follower(&owner, &cmd.follower)
.await?;
deps.event_publisher
.publish(&DomainEvent::FollowerRemoved {
owner,
follower: cmd.follower,
})
.await
}
#[cfg(test)]
#[path = "tests/remove_follower.rs"]
mod tests;

View File

@@ -1,65 +0,0 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
accept,
commands::{AcceptFollowCommand, FollowCommand},
deps::SocialCommandDeps,
follow,
};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn accept_follow_emits_follow_accepted_event() {
let (_social, events, deps) = make_deps();
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
let requester = SocialIdentity::Local(UserId::from_uuid(follower_id));
follow::execute(
&deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
accept::execute(
&deps,
AcceptFollowCommand {
owner_id,
requester,
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowAccepted { .. }))
);
}

View File

@@ -1,47 +0,0 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{block, commands::BlockCommand, deps::SocialCommandDeps};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn block_emits_actor_blocked_event() {
let (_social, events, deps) = make_deps();
block::execute(
&deps,
BlockCommand {
blocker_id: Uuid::new_v4(),
target: SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4())),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::ActorBlocked { .. }))
);
}

View File

@@ -0,0 +1,449 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
commands::SocialCmd,
deps::{SocialCommandDeps, SocialQueryDeps},
execute::{execute_command, execute_query},
queries::SocialQry,
};
fn make_cmd_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
// ── Follow ──────────────────────────────────────────────────────────────────
#[tokio::test]
async fn follow_emits_follow_requested_event() {
let (_social, events, deps) = make_cmd_deps();
execute_command(
&deps,
SocialCmd::Follow {
follower_id: Uuid::new_v4(),
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(
Uuid::new_v4(),
))),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowRequested { .. }))
);
}
#[tokio::test]
async fn cannot_follow_yourself() {
let (_social, _events, deps) = make_cmd_deps();
let user_id = Uuid::new_v4();
let result = execute_command(
&deps,
SocialCmd::Follow {
follower_id: user_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(user_id))),
},
)
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn cannot_follow_same_target_twice() {
let (_social, _events, deps) = make_cmd_deps();
let follower_id = Uuid::new_v4();
let target = FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4())));
execute_command(
&deps,
SocialCmd::Follow {
follower_id,
target: target.clone(),
},
)
.await
.unwrap();
let result = execute_command(
&deps,
SocialCmd::Follow {
follower_id,
target,
},
)
.await;
assert!(result.is_err());
}
// ── Unfollow ────────────────────────────────────────────────────────────────
#[tokio::test]
async fn unfollow_emits_unfollowed_event() {
let (_social, events, deps) = make_cmd_deps();
let follower_id = Uuid::new_v4();
let target = SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()));
execute_command(
&deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(target.clone()),
},
)
.await
.unwrap();
execute_command(
&deps,
SocialCmd::Unfollow {
follower_id,
target,
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::Unfollowed { .. }))
);
}
// ── Accept ──────────────────────────────────────────────────────────────────
#[tokio::test]
async fn accept_follow_emits_follow_accepted_event() {
let (_social, events, deps) = make_cmd_deps();
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
let requester = SocialIdentity::Local(UserId::from_uuid(follower_id));
execute_command(
&deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
execute_command(
&deps,
SocialCmd::AcceptFollow {
owner_id,
requester,
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowAccepted { .. }))
);
}
// ── Reject ──────────────────────────────────────────────────────────────────
#[tokio::test]
async fn reject_follow_emits_follow_rejected_event() {
let (_social, events, deps) = make_cmd_deps();
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
execute_command(
&deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
execute_command(
&deps,
SocialCmd::RejectFollow {
owner_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowRejected { .. }))
);
}
// ── Remove follower ─────────────────────────────────────────────────────────
#[tokio::test]
async fn remove_follower_emits_follower_removed_event() {
let (_social, events, deps) = make_cmd_deps();
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
execute_command(
&deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
execute_command(
&deps,
SocialCmd::AcceptFollow {
owner_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
execute_command(
&deps,
SocialCmd::RemoveFollower {
owner_id,
follower: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowerRemoved { .. }))
);
}
// ── Block ───────────────────────────────────────────────────────────────────
#[tokio::test]
async fn block_emits_actor_blocked_event() {
let (_social, events, deps) = make_cmd_deps();
execute_command(
&deps,
SocialCmd::Block {
blocker_id: Uuid::new_v4(),
target: SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4())),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::ActorBlocked { .. }))
);
}
// ── Unblock ─────────────────────────────────────────────────────────────────
#[tokio::test]
async fn unblock_emits_actor_unblocked_event() {
let (_social, events, deps) = make_cmd_deps();
let target = SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()));
let blocker_id = Uuid::new_v4();
execute_command(
&deps,
SocialCmd::Block {
blocker_id,
target: target.clone(),
},
)
.await
.unwrap();
execute_command(&deps, SocialCmd::Unblock { blocker_id, target })
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::ActorUnblocked { .. }))
);
}
// ── Get following ───────────────────────────────────────────────────────────
#[tokio::test]
async fn returns_accepted_follows() {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let cmd_deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
let query_deps = SocialQueryDeps {
social_query: Arc::clone(&social) as _,
};
let follower_id = Uuid::new_v4();
let target_id = Uuid::new_v4();
execute_command(
&cmd_deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(target_id))),
},
)
.await
.unwrap();
// Pending follow should not appear
let following = execute_query(
&query_deps,
SocialQry::GetFollowing {
user_id: follower_id,
},
)
.await
.unwrap();
assert!(following.is_empty());
// Accept, then it should appear
execute_command(
&cmd_deps,
SocialCmd::AcceptFollow {
owner_id: target_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let following = execute_query(
&query_deps,
SocialQry::GetFollowing {
user_id: follower_id,
},
)
.await
.unwrap();
assert_eq!(following.len(), 1);
}
// ── Get followers ───────────────────────────────────────────────────────────
#[tokio::test]
async fn returns_accepted_followers() {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let cmd_deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
let query_deps = SocialQueryDeps {
social_query: Arc::clone(&social) as _,
};
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
execute_command(
&cmd_deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
execute_command(
&cmd_deps,
SocialCmd::AcceptFollow {
owner_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let followers = execute_query(&query_deps, SocialQry::GetFollowers { user_id: owner_id })
.await
.unwrap();
assert_eq!(followers.len(), 1);
}
// ── Get pending ─────────────────────────────────────────────────────────────
#[tokio::test]
async fn returns_only_pending_followers() {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let cmd_deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
let query_deps = SocialQueryDeps {
social_query: Arc::clone(&social) as _,
};
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
execute_command(
&cmd_deps,
SocialCmd::Follow {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
let pending = execute_query(&query_deps, SocialQry::GetPending { user_id: owner_id })
.await
.unwrap();
assert_eq!(pending.len(), 1);
}

View File

@@ -1,92 +0,0 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{commands::FollowCommand, deps::SocialCommandDeps, follow};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn follow_emits_follow_requested_event() {
let (_social, events, deps) = make_deps();
follow::execute(
&deps,
FollowCommand {
follower_id: Uuid::new_v4(),
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()))),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowRequested { .. }))
);
}
#[tokio::test]
async fn cannot_follow_yourself() {
let (_social, _events, deps) = make_deps();
let user_id = Uuid::new_v4();
let result = follow::execute(
&deps,
FollowCommand {
follower_id: user_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(user_id))),
},
)
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn cannot_follow_same_target_twice() {
let (_social, _events, deps) = make_deps();
let follower_id = Uuid::new_v4();
let target = FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4())));
follow::execute(
&deps,
FollowCommand {
follower_id,
target: target.clone(),
},
)
.await
.unwrap();
let result = follow::execute(
&deps,
FollowCommand {
follower_id,
target,
},
)
.await;
assert!(result.is_err());
}

View File

@@ -1,57 +0,0 @@
use std::sync::Arc;
use domain::{
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
accept,
commands::{AcceptFollowCommand, FollowCommand},
deps::{SocialCommandDeps, SocialQueryDeps},
follow, get_followers,
queries::GetFollowersQuery,
};
#[tokio::test]
async fn returns_accepted_followers() {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let cmd_deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
let query_deps = SocialQueryDeps {
social_query: Arc::clone(&social) as _,
};
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
follow::execute(
&cmd_deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
accept::execute(
&cmd_deps,
AcceptFollowCommand {
owner_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let followers = get_followers::execute(&query_deps, GetFollowersQuery { user_id: owner_id })
.await
.unwrap();
assert_eq!(followers.len(), 1);
}

View File

@@ -1,74 +0,0 @@
use std::sync::Arc;
use domain::{
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
accept,
commands::{AcceptFollowCommand, FollowCommand},
deps::{SocialCommandDeps, SocialQueryDeps},
follow, get_following,
queries::GetFollowingQuery,
};
#[tokio::test]
async fn returns_accepted_follows() {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let cmd_deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
let query_deps = SocialQueryDeps {
social_query: Arc::clone(&social) as _,
};
let follower_id = Uuid::new_v4();
let target_id = Uuid::new_v4();
follow::execute(
&cmd_deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(target_id))),
},
)
.await
.unwrap();
// Pending follow should not appear
let following = get_following::execute(
&query_deps,
GetFollowingQuery {
user_id: follower_id,
},
)
.await
.unwrap();
assert!(following.is_empty());
// Accept, then it should appear
accept::execute(
&cmd_deps,
AcceptFollowCommand {
owner_id: target_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let following = get_following::execute(
&query_deps,
GetFollowingQuery {
user_id: follower_id,
},
)
.await
.unwrap();
assert_eq!(following.len(), 1);
}

View File

@@ -1,46 +0,0 @@
use std::sync::Arc;
use domain::{
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
commands::FollowCommand,
deps::{SocialCommandDeps, SocialQueryDeps},
follow, get_pending,
queries::GetPendingFollowersQuery,
};
#[tokio::test]
async fn returns_only_pending_followers() {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let cmd_deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
let query_deps = SocialQueryDeps {
social_query: Arc::clone(&social) as _,
};
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
follow::execute(
&cmd_deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
let pending = get_pending::execute(&query_deps, GetPendingFollowersQuery { user_id: owner_id })
.await
.unwrap();
assert_eq!(pending.len(), 1);
}

View File

@@ -1,55 +0,0 @@
use std::sync::Arc;
use domain::{
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
commands::{FollowCommand, RejectFollowCommand},
deps::SocialCommandDeps,
follow, reject,
};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn reject_follow_completes_without_error() {
let (_social, _events, deps) = make_deps();
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
follow::execute(
&deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
reject::execute(
&deps,
RejectFollowCommand {
owner_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
}

View File

@@ -1,74 +0,0 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
accept,
commands::{AcceptFollowCommand, FollowCommand, RemoveFollowerCommand},
deps::SocialCommandDeps,
follow, remove_follower,
};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn remove_follower_emits_follower_removed_event() {
let (_social, events, deps) = make_deps();
let follower_id = Uuid::new_v4();
let owner_id = Uuid::new_v4();
follow::execute(
&deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
},
)
.await
.unwrap();
accept::execute(
&deps,
AcceptFollowCommand {
owner_id,
requester: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
remove_follower::execute(
&deps,
RemoveFollowerCommand {
owner_id,
follower: SocialIdentity::Local(UserId::from_uuid(follower_id)),
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::FollowerRemoved { .. }))
);
}

View File

@@ -1,58 +0,0 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
block,
commands::{BlockCommand, UnblockCommand},
deps::SocialCommandDeps,
unblock,
};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn unblock_emits_actor_unblocked_event() {
let (_social, events, deps) = make_deps();
let target = SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()));
let blocker_id = Uuid::new_v4();
block::execute(
&deps,
BlockCommand {
blocker_id,
target: target.clone(),
},
)
.await
.unwrap();
unblock::execute(&deps, UnblockCommand { blocker_id, target })
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::ActorUnblocked { .. }))
);
}

View File

@@ -1,63 +0,0 @@
use std::sync::Arc;
use domain::{
events::DomainEvent,
testing::{InMemorySocialRepository, NoopEventPublisher},
value_objects::{FollowTarget, SocialIdentity, UserId},
};
use uuid::Uuid;
use crate::social::{
commands::{FollowCommand, UnfollowCommand},
deps::SocialCommandDeps,
follow, unfollow,
};
fn make_deps() -> (
Arc<InMemorySocialRepository>,
Arc<NoopEventPublisher>,
SocialCommandDeps,
) {
let social = InMemorySocialRepository::new();
let events = NoopEventPublisher::new();
let deps = SocialCommandDeps {
social_command: Arc::clone(&social) as _,
social_query: Arc::clone(&social) as _,
event_publisher: Arc::clone(&events) as _,
};
(social, events, deps)
}
#[tokio::test]
async fn unfollow_emits_unfollowed_event() {
let (_social, events, deps) = make_deps();
let follower_id = Uuid::new_v4();
let target = SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()));
follow::execute(
&deps,
FollowCommand {
follower_id,
target: FollowTarget::Identity(target.clone()),
},
)
.await
.unwrap();
unfollow::execute(
&deps,
UnfollowCommand {
follower_id,
target,
},
)
.await
.unwrap();
let published = events.published();
assert!(
published
.iter()
.any(|e| matches!(e, DomainEvent::Unfollowed { .. }))
);
}

View File

@@ -1,18 +0,0 @@
use domain::{errors::DomainError, events::DomainEvent, value_objects::UserId};
use super::{commands::UnblockCommand, deps::SocialCommandDeps};
pub async fn execute(deps: &SocialCommandDeps, cmd: UnblockCommand) -> Result<(), DomainError> {
let blocker = UserId::from_uuid(cmd.blocker_id);
deps.social_command.unblock(&blocker, &cmd.target).await?;
deps.event_publisher
.publish(&DomainEvent::ActorUnblocked {
blocker,
target: cmd.target,
})
.await
}
#[cfg(test)]
#[path = "tests/unblock.rs"]
mod tests;

View File

@@ -1,18 +0,0 @@
use domain::{errors::DomainError, events::DomainEvent, value_objects::UserId};
use super::{commands::UnfollowCommand, deps::SocialCommandDeps};
pub async fn execute(deps: &SocialCommandDeps, cmd: UnfollowCommand) -> Result<(), DomainError> {
let follower = UserId::from_uuid(cmd.follower_id);
deps.social_command.unfollow(&follower, &cmd.target).await?;
deps.event_publisher
.publish(&DomainEvent::Unfollowed {
follower,
target: cmd.target,
})
.await
}
#[cfg(test)]
#[path = "tests/unfollow.rs"]
mod tests;

View File

@@ -74,6 +74,7 @@ impl EventHandler for RecordingHandler {
}
DomainEvent::FollowRequested { .. } => "follow_requested",
DomainEvent::FollowAccepted { .. } => "follow_accepted",
DomainEvent::FollowRejected { .. } => "follow_rejected",
DomainEvent::Unfollowed { .. } => "unfollowed",
DomainEvent::FollowerRemoved { .. } => "follower_removed",
DomainEvent::ActorBlocked { .. } => "actor_blocked",

View File

@@ -71,6 +71,10 @@ pub enum DomainEvent {
owner: UserId,
requester: crate::value_objects::SocialIdentity,
},
FollowRejected {
owner: UserId,
requester: crate::value_objects::SocialIdentity,
},
Unfollowed {
follower: UserId,
target: crate::value_objects::SocialIdentity,

View File

@@ -171,9 +171,9 @@ pub async fn block_actor_api(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::block::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::BlockCommand {
application::social::commands::SocialCmd::Block {
blocker_id: user.0.value(),
target: SocialIdentity::Remote {
actor_url: body.actor_url,
@@ -203,9 +203,9 @@ pub async fn unblock_actor_api(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::unblock::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::UnblockCommand {
application::social::commands::SocialCmd::Unblock {
blocker_id: user.0.value(),
target: SocialIdentity::Remote {
actor_url: body.actor_url,
@@ -231,9 +231,9 @@ pub async fn get_blocked_actors_api(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
let identities = application::social::get_blocked::execute(
let identities = application::social::execute::execute_query(
&deps,
application::social::queries::GetBlockedQuery {
application::social::queries::SocialQry::GetBlocked {
user_id: user.0.value(),
},
)
@@ -261,9 +261,9 @@ pub async fn get_following(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
let identities = application::social::get_following::execute(
let identities = application::social::execute::execute_query(
&deps,
application::social::queries::GetFollowingQuery {
application::social::queries::SocialQry::GetFollowing {
user_id: user.0.value(),
},
)
@@ -288,9 +288,9 @@ pub async fn get_followers(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
let identities = application::social::get_followers::execute(
let identities = application::social::execute::execute_query(
&deps,
application::social::queries::GetFollowersQuery {
application::social::queries::SocialQry::GetFollowers {
user_id: user.0.value(),
},
)
@@ -308,9 +308,9 @@ pub async fn get_user_following(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
let identities = application::social::get_following::execute(
let identities = application::social::execute::execute_query(
&deps,
application::social::queries::GetFollowingQuery { user_id },
application::social::queries::SocialQry::GetFollowing { user_id },
)
.await?;
Ok(Json(ActorListResponse {
@@ -326,9 +326,9 @@ pub async fn get_user_followers(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
let identities = application::social::get_followers::execute(
let identities = application::social::execute::execute_query(
&deps,
application::social::queries::GetFollowersQuery { user_id },
application::social::queries::SocialQry::GetFollowers { user_id },
)
.await?;
Ok(Json(ActorListResponse {
@@ -355,9 +355,9 @@ pub async fn follow(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::follow::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::FollowCommand {
application::social::commands::SocialCmd::Follow {
follower_id: user.0.value(),
target: FollowTarget::Handle(body.handle),
},
@@ -385,9 +385,9 @@ pub async fn unfollow(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::unfollow::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::UnfollowCommand {
application::social::commands::SocialCmd::Unfollow {
follower_id: user.0.value(),
target: SocialIdentity::Remote {
actor_url: body.actor_url,
@@ -417,9 +417,9 @@ pub async fn accept_follower(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::accept::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::AcceptFollowCommand {
application::social::commands::SocialCmd::AcceptFollow {
owner_id: user.0.value(),
requester: SocialIdentity::Remote {
actor_url: body.actor_url,
@@ -449,9 +449,9 @@ pub async fn reject_follower(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::reject::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::RejectFollowCommand {
application::social::commands::SocialCmd::RejectFollow {
owner_id: user.0.value(),
requester: SocialIdentity::Remote {
actor_url: body.actor_url,
@@ -481,9 +481,9 @@ pub async fn remove_follower(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
application::social::remove_follower::execute(
application::social::execute::execute_command(
&deps,
application::social::commands::RemoveFollowerCommand {
application::social::commands::SocialCmd::RemoveFollower {
owner_id: user.0.value(),
follower: SocialIdentity::Remote {
actor_url: body.actor_url,
@@ -509,9 +509,9 @@ pub async fn get_pending_followers(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
let identities = application::social::get_pending::execute(
let identities = application::social::execute::execute_query(
&deps,
application::social::queries::GetPendingFollowersQuery {
application::social::queries::SocialQry::GetPending {
user_id: user.0.value(),
},
)
@@ -548,9 +548,9 @@ pub async fn follow_remote_user(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::follow::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::FollowCommand {
application::social::commands::SocialCmd::Follow {
follower_id: user_id.value(),
target: FollowTarget::Handle(form.handle),
},
@@ -589,9 +589,9 @@ pub async fn unfollow_remote_user(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::unfollow::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::UnfollowCommand {
application::social::commands::SocialCmd::Unfollow {
follower_id: user_id.value(),
target: SocialIdentity::Remote {
actor_url: form.actor_url,
@@ -632,9 +632,9 @@ pub async fn accept_follower_html(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::accept::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::AcceptFollowCommand {
application::social::commands::SocialCmd::AcceptFollow {
owner_id: user_id.value(),
requester: SocialIdentity::Remote {
actor_url: form.actor_url,
@@ -669,9 +669,9 @@ pub async fn reject_follower_html(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::reject::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::RejectFollowCommand {
application::social::commands::SocialCmd::RejectFollow {
owner_id: user_id.value(),
requester: SocialIdentity::Remote {
actor_url: form.actor_url,
@@ -773,9 +773,9 @@ pub async fn get_following_page(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
match application::social::get_following::execute(
match application::social::execute::execute_query(
&deps,
application::social::queries::GetFollowingQuery {
application::social::queries::SocialQry::GetFollowing {
user_id: user_id.value(),
},
)
@@ -824,9 +824,9 @@ pub async fn get_followers_page(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
match application::social::get_followers::execute(
match application::social::execute::execute_query(
&deps,
application::social::queries::GetFollowersQuery {
application::social::queries::SocialQry::GetFollowers {
user_id: user_id.value(),
},
)
@@ -874,9 +874,9 @@ pub async fn remove_follower_html(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::remove_follower::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::RemoveFollowerCommand {
application::social::commands::SocialCmd::RemoveFollower {
owner_id: user_id.value(),
follower: SocialIdentity::Remote {
actor_url: form.actor_url,
@@ -1000,9 +1000,9 @@ pub async fn get_blocked_actors_page(
let deps = SocialQueryDeps {
social_query: state.app_ctx.repos.social_query_unified.clone(),
};
match application::social::get_blocked::execute(
match application::social::execute::execute_query(
&deps,
application::social::queries::GetBlockedQuery {
application::social::queries::SocialQry::GetBlocked {
user_id: user_id.value(),
},
)
@@ -1049,9 +1049,9 @@ pub async fn post_block_actor_html(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::block::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::BlockCommand {
application::social::commands::SocialCmd::Block {
blocker_id: user_id.value(),
target: SocialIdentity::Remote {
actor_url: form.actor_url,
@@ -1082,9 +1082,9 @@ pub async fn post_unblock_actor(
social_query: state.app_ctx.repos.social_query_unified.clone(),
event_publisher: state.app_ctx.services.event_publisher.clone(),
};
match application::social::unblock::execute(
match application::social::execute::execute_command(
&deps,
application::social::commands::UnblockCommand {
application::social::commands::SocialCmd::Unblock {
blocker_id: user_id.value(),
target: SocialIdentity::Remote {
actor_url: form.actor_url,