fix: FollowTarget enum — actor_url no longer lies about holding a handle
FollowCommand.target is now FollowTarget (Identity|Handle) instead of SocialIdentity. actor_url field always holds a URL; handles go through FollowTarget::Handle. Adapter resolves handles explicitly. Type system prevents misuse in future commands.
This commit is contained in:
@@ -4,7 +4,7 @@ use async_trait::async_trait;
|
|||||||
use domain::{
|
use domain::{
|
||||||
errors::DomainError,
|
errors::DomainError,
|
||||||
ports::{SocialCommand, SocialQuery, UserRepository},
|
ports::{SocialCommand, SocialQuery, UserRepository},
|
||||||
value_objects::{SocialActor, SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialActor, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
|
|
||||||
use k_ap::RemoteActor;
|
use k_ap::RemoteActor;
|
||||||
@@ -87,15 +87,18 @@ fn ap_err(e: anyhow::Error) -> DomainError {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl SocialCommand for CompositeSocialAdapter {
|
impl SocialCommand for CompositeSocialAdapter {
|
||||||
async fn follow(&self, follower: &UserId, target: &SocialIdentity) -> Result<(), DomainError> {
|
async fn follow(&self, follower: &UserId, target: &FollowTarget) -> Result<(), DomainError> {
|
||||||
if let SocialIdentity::Local(target_id) = target
|
if let FollowTarget::Identity(SocialIdentity::Local(target_id)) = target
|
||||||
&& follower == target_id
|
&& follower == target_id
|
||||||
{
|
{
|
||||||
return Err(DomainError::ValidationError(
|
return Err(DomainError::ValidationError(
|
||||||
"Cannot follow yourself".into(),
|
"Cannot follow yourself".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let handle = self.resolve_handle(target).await?;
|
let handle = match target {
|
||||||
|
FollowTarget::Handle(h) => h.clone(),
|
||||||
|
FollowTarget::Identity(id) => self.resolve_handle(id).await?,
|
||||||
|
};
|
||||||
self.ap_service
|
self.ap_service
|
||||||
.follow(follower.value(), &handle)
|
.follow(follower.value(), &handle)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -196,6 +196,13 @@ fn identity_to_payload(id: &SocialIdentity) -> (String, String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn follow_target_to_payload(target: &domain::value_objects::FollowTarget) -> (String, String) {
|
||||||
|
match target {
|
||||||
|
domain::value_objects::FollowTarget::Identity(id) => identity_to_payload(id),
|
||||||
|
domain::value_objects::FollowTarget::Handle(h) => ("handle".into(), h.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn payload_to_identity(kind: &str, id: String) -> Result<SocialIdentity, DomainError> {
|
fn payload_to_identity(kind: &str, id: String) -> Result<SocialIdentity, DomainError> {
|
||||||
match kind {
|
match kind {
|
||||||
"local" => Ok(SocialIdentity::Local(UserId::from_uuid(parse_uuid(
|
"local" => Ok(SocialIdentity::Local(UserId::from_uuid(parse_uuid(
|
||||||
@@ -208,6 +215,18 @@ fn payload_to_identity(kind: &str, id: String) -> Result<SocialIdentity, DomainE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn payload_to_follow_target(
|
||||||
|
kind: &str,
|
||||||
|
id: String,
|
||||||
|
) -> Result<domain::value_objects::FollowTarget, DomainError> {
|
||||||
|
match kind {
|
||||||
|
"handle" => Ok(domain::value_objects::FollowTarget::Handle(id)),
|
||||||
|
other => Ok(domain::value_objects::FollowTarget::Identity(
|
||||||
|
payload_to_identity(other, id)?,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_ts(ts: i64) -> Result<NaiveDateTime, DomainError> {
|
fn parse_ts(ts: i64) -> Result<NaiveDateTime, DomainError> {
|
||||||
chrono::DateTime::from_timestamp(ts, 0)
|
chrono::DateTime::from_timestamp(ts, 0)
|
||||||
.map(|dt| dt.naive_utc())
|
.map(|dt| dt.naive_utc())
|
||||||
@@ -294,7 +313,7 @@ impl From<&DomainEvent> for EventPayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DomainEvent::FollowRequested { follower, target } => {
|
DomainEvent::FollowRequested { follower, target } => {
|
||||||
let (kind, id) = identity_to_payload(target);
|
let (kind, id) = follow_target_to_payload(target);
|
||||||
EventPayload::FollowRequested {
|
EventPayload::FollowRequested {
|
||||||
follower_id: follower.value().to_string(),
|
follower_id: follower.value().to_string(),
|
||||||
target_kind: kind,
|
target_kind: kind,
|
||||||
@@ -530,7 +549,7 @@ impl TryFrom<EventPayload> for DomainEvent {
|
|||||||
target_id,
|
target_id,
|
||||||
} => Ok(DomainEvent::FollowRequested {
|
} => Ok(DomainEvent::FollowRequested {
|
||||||
follower: UserId::from_uuid(parse_uuid(&follower_id, "follower_id")?),
|
follower: UserId::from_uuid(parse_uuid(&follower_id, "follower_id")?),
|
||||||
target: payload_to_identity(&target_kind, target_id)?,
|
target: payload_to_follow_target(&target_kind, target_id)?,
|
||||||
}),
|
}),
|
||||||
EventPayload::FollowAccepted {
|
EventPayload::FollowAccepted {
|
||||||
owner_id,
|
owner_id,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use domain::value_objects::SocialIdentity;
|
use domain::value_objects::{FollowTarget, SocialIdentity};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub struct FollowCommand {
|
pub struct FollowCommand {
|
||||||
pub follower_id: Uuid,
|
pub follower_id: Uuid,
|
||||||
pub target: SocialIdentity,
|
pub target: FollowTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnfollowCommand {
|
pub struct UnfollowCommand {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
use domain::{
|
use domain::{
|
||||||
events::DomainEvent,
|
events::DomainEvent,
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ async fn accept_follow_emits_follow_accepted_event() {
|
|||||||
&deps,
|
&deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(owner_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
use domain::{
|
use domain::{
|
||||||
events::DomainEvent,
|
events::DomainEvent,
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ async fn follow_emits_follow_requested_event() {
|
|||||||
&deps,
|
&deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id: Uuid::new_v4(),
|
follower_id: Uuid::new_v4(),
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4())),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@@ -55,7 +55,7 @@ async fn cannot_follow_yourself() {
|
|||||||
&deps,
|
&deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id: user_id,
|
follower_id: user_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(user_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(user_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -67,7 +67,7 @@ async fn cannot_follow_yourself() {
|
|||||||
async fn cannot_follow_same_target_twice() {
|
async fn cannot_follow_same_target_twice() {
|
||||||
let (_social, _events, deps) = make_deps();
|
let (_social, _events, deps) = make_deps();
|
||||||
let follower_id = Uuid::new_v4();
|
let follower_id = Uuid::new_v4();
|
||||||
let target = SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4()));
|
let target = FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(Uuid::new_v4())));
|
||||||
|
|
||||||
follow::execute(
|
follow::execute(
|
||||||
&deps,
|
&deps,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use domain::{
|
use domain::{
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ async fn returns_accepted_followers() {
|
|||||||
&cmd_deps,
|
&cmd_deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(owner_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use domain::{
|
use domain::{
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ async fn returns_accepted_follows() {
|
|||||||
&cmd_deps,
|
&cmd_deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(target_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(target_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use domain::{
|
use domain::{
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ async fn returns_only_pending_followers() {
|
|||||||
&cmd_deps,
|
&cmd_deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(owner_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use domain::{
|
use domain::{
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ async fn reject_follow_completes_without_error() {
|
|||||||
&deps,
|
&deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(owner_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
use domain::{
|
use domain::{
|
||||||
events::DomainEvent,
|
events::DomainEvent,
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ async fn remove_follower_emits_follower_removed_event() {
|
|||||||
&deps,
|
&deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: SocialIdentity::Local(UserId::from_uuid(owner_id)),
|
target: FollowTarget::Identity(SocialIdentity::Local(UserId::from_uuid(owner_id))),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
use domain::{
|
use domain::{
|
||||||
events::DomainEvent,
|
events::DomainEvent,
|
||||||
testing::{InMemorySocialRepository, NoopEventPublisher},
|
testing::{InMemorySocialRepository, NoopEventPublisher},
|
||||||
value_objects::{SocialIdentity, UserId},
|
value_objects::{FollowTarget, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ async fn unfollow_emits_unfollowed_event() {
|
|||||||
&deps,
|
&deps,
|
||||||
FollowCommand {
|
FollowCommand {
|
||||||
follower_id,
|
follower_id,
|
||||||
target: target.clone(),
|
target: FollowTarget::Identity(target.clone()),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ pub enum DomainEvent {
|
|||||||
},
|
},
|
||||||
FollowRequested {
|
FollowRequested {
|
||||||
follower: UserId,
|
follower: UserId,
|
||||||
target: crate::value_objects::SocialIdentity,
|
target: crate::value_objects::FollowTarget,
|
||||||
},
|
},
|
||||||
FollowAccepted {
|
FollowAccepted {
|
||||||
owner: UserId,
|
owner: UserId,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ pub struct NoopSocialCommand;
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl super::SocialCommand for NoopSocialCommand {
|
impl super::SocialCommand for NoopSocialCommand {
|
||||||
async fn follow(&self, _: &UserId, _: &SocialIdentity) -> Result<(), DomainError> {
|
async fn follow(&self, _: &UserId, _: &crate::value_objects::FollowTarget) -> Result<(), DomainError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn unfollow(&self, _: &UserId, _: &SocialIdentity) -> Result<(), DomainError> {
|
async fn unfollow(&self, _: &UserId, _: &SocialIdentity) -> Result<(), DomainError> {
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ use crate::{
|
|||||||
DiaryEntry, FederationFlags, RemoteActorInfo, RemoteGoalEntry, RemoteWatchlistEntry,
|
DiaryEntry, FederationFlags, RemoteActorInfo, RemoteGoalEntry, RemoteWatchlistEntry,
|
||||||
WatchlistWithMovie,
|
WatchlistWithMovie,
|
||||||
},
|
},
|
||||||
value_objects::{MovieId, SocialActor, SocialIdentity, UserId},
|
value_objects::{FollowTarget, MovieId, SocialActor, SocialIdentity, UserId},
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Unified social ports (ADR-0002) ─────────────────────────────────────────
|
// ── Unified social ports (ADR-0002) ─────────────────────────────────────────
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait SocialCommand: Send + Sync {
|
pub trait SocialCommand: Send + Sync {
|
||||||
async fn follow(&self, follower: &UserId, target: &SocialIdentity) -> Result<(), DomainError>;
|
async fn follow(&self, follower: &UserId, target: &FollowTarget) -> Result<(), DomainError>;
|
||||||
|
|
||||||
async fn unfollow(&self, follower: &UserId, target: &SocialIdentity)
|
async fn unfollow(&self, follower: &UserId, target: &SocialIdentity)
|
||||||
-> Result<(), DomainError>;
|
-> Result<(), DomainError>;
|
||||||
|
|||||||
@@ -893,8 +893,18 @@ impl InMemorySocialRepository {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl SocialCommand for InMemorySocialRepository {
|
impl SocialCommand for InMemorySocialRepository {
|
||||||
async fn follow(&self, follower: &UserId, target: &SocialIdentity) -> Result<(), DomainError> {
|
async fn follow(
|
||||||
if let SocialIdentity::Local(target_id) = target {
|
&self,
|
||||||
|
follower: &UserId,
|
||||||
|
target: &crate::value_objects::FollowTarget,
|
||||||
|
) -> Result<(), DomainError> {
|
||||||
|
let identity = match target {
|
||||||
|
crate::value_objects::FollowTarget::Identity(id) => id.clone(),
|
||||||
|
crate::value_objects::FollowTarget::Handle(h) => SocialIdentity::Remote {
|
||||||
|
actor_url: h.clone(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if let SocialIdentity::Local(target_id) = &identity {
|
||||||
if follower == target_id {
|
if follower == target_id {
|
||||||
return Err(DomainError::ValidationError(
|
return Err(DomainError::ValidationError(
|
||||||
"Cannot follow yourself".into(),
|
"Cannot follow yourself".into(),
|
||||||
@@ -904,11 +914,11 @@ impl SocialCommand for InMemorySocialRepository {
|
|||||||
let mut store = self.follows.lock().unwrap();
|
let mut store = self.follows.lock().unwrap();
|
||||||
let already = store
|
let already = store
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(f, t, _)| *f == follower.value() && t == target);
|
.any(|(f, t, _)| *f == follower.value() && *t == identity);
|
||||||
if already {
|
if already {
|
||||||
return Err(DomainError::ValidationError("Already following".into()));
|
return Err(DomainError::ValidationError("Already following".into()));
|
||||||
}
|
}
|
||||||
store.push((follower.value(), target.clone(), FollowState::Pending));
|
store.push((follower.value(), identity, FollowState::Pending));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::value_objects::{SocialIdentity, UserId};
|
use crate::value_objects::{FollowTarget, SocialIdentity, UserId};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn follow_accepted_matches() {
|
fn follow_accepted_matches() {
|
||||||
@@ -22,17 +22,33 @@ fn follow_accepted_matches() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn follow_requested_local() {
|
fn follow_requested_with_identity() {
|
||||||
let follower = UserId::from_uuid(uuid::Uuid::new_v4());
|
let follower = UserId::from_uuid(uuid::Uuid::new_v4());
|
||||||
let target = UserId::from_uuid(uuid::Uuid::new_v4());
|
let target = UserId::from_uuid(uuid::Uuid::new_v4());
|
||||||
let event = DomainEvent::FollowRequested {
|
let event = DomainEvent::FollowRequested {
|
||||||
follower: follower.clone(),
|
follower: follower.clone(),
|
||||||
target: SocialIdentity::Local(target.clone()),
|
target: FollowTarget::Identity(SocialIdentity::Local(target.clone())),
|
||||||
};
|
};
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
event,
|
event,
|
||||||
DomainEvent::FollowRequested {
|
DomainEvent::FollowRequested {
|
||||||
target: SocialIdentity::Local(_),
|
target: FollowTarget::Identity(SocialIdentity::Local(_)),
|
||||||
|
..
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn follow_requested_with_handle() {
|
||||||
|
let follower = UserId::from_uuid(uuid::Uuid::new_v4());
|
||||||
|
let event = DomainEvent::FollowRequested {
|
||||||
|
follower: follower.clone(),
|
||||||
|
target: FollowTarget::Handle("@alice@remote.example".into()),
|
||||||
|
};
|
||||||
|
assert!(matches!(
|
||||||
|
event,
|
||||||
|
DomainEvent::FollowRequested {
|
||||||
|
target: FollowTarget::Handle(_),
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ impl SocialIdentity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum FollowTarget {
|
||||||
|
Identity(SocialIdentity),
|
||||||
|
Handle(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SocialActor {
|
pub struct SocialActor {
|
||||||
pub identity: SocialIdentity,
|
pub identity: SocialIdentity,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use api_types::{
|
|||||||
BlockedDomainResponse, FollowRequest, RemoteActorDto,
|
BlockedDomainResponse, FollowRequest, RemoteActorDto,
|
||||||
};
|
};
|
||||||
use application::social::deps::{SocialCommandDeps, SocialQueryDeps};
|
use application::social::deps::{SocialCommandDeps, SocialQueryDeps};
|
||||||
use domain::value_objects::{SocialActor, SocialIdentity};
|
use domain::value_objects::{FollowTarget, SocialActor, SocialIdentity};
|
||||||
use template_askama::{
|
use template_askama::{
|
||||||
BlockedActorsTemplate, BlockedDomainsTemplate, FollowersTemplate, FollowingTemplate,
|
BlockedActorsTemplate, BlockedDomainsTemplate, FollowersTemplate, FollowingTemplate,
|
||||||
RemoteActorData,
|
RemoteActorData,
|
||||||
@@ -359,9 +359,7 @@ pub async fn follow(
|
|||||||
&deps,
|
&deps,
|
||||||
application::social::commands::FollowCommand {
|
application::social::commands::FollowCommand {
|
||||||
follower_id: user.0.value(),
|
follower_id: user.0.value(),
|
||||||
target: SocialIdentity::Remote {
|
target: FollowTarget::Handle(body.handle),
|
||||||
actor_url: body.handle,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -554,9 +552,7 @@ pub async fn follow_remote_user(
|
|||||||
&deps,
|
&deps,
|
||||||
application::social::commands::FollowCommand {
|
application::social::commands::FollowCommand {
|
||||||
follower_id: user_id.value(),
|
follower_id: user_id.value(),
|
||||||
target: SocialIdentity::Remote {
|
target: FollowTarget::Handle(form.handle),
|
||||||
actor_url: form.handle,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
Reference in New Issue
Block a user