Remove AsObject
This commit is contained in:
parent
d8a2e1925f
commit
33afe9111e
@ -519,146 +519,6 @@ pub trait AsActor<C> {
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub trait AsObject<A, V, C>
|
|
||||||
where
|
|
||||||
V: activitypub::Activity,
|
|
||||||
{
|
|
||||||
/// What kind of error is returned when something fails
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
/// What is returned by `AsObject::activity`, if anything is returned
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
/// Handle a specific type of activity dealing with this type of objects.
|
|
||||||
///
|
|
||||||
/// The implementations should check that the actor is actually authorized
|
|
||||||
/// to perform this action.
|
|
||||||
///
|
|
||||||
/// # Parameters
|
|
||||||
///
|
|
||||||
/// - `self`: the object on which the activity acts
|
|
||||||
/// - `ctx`: the context passed to `Inbox::handle`
|
|
||||||
/// - `actor`: the actor who did this activity
|
|
||||||
/// - `id`: the ID of this activity
|
|
||||||
fn activity(self, ctx: C, actor: A, id: &str) -> Result<Self::Output, Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Should be implemented by anything representing an ActivityPub object.
|
|
||||||
///
|
|
||||||
/// # Type parameters
|
|
||||||
///
|
|
||||||
/// - `A`: the actor type
|
|
||||||
/// - `V`: the ActivityPub verb/activity
|
|
||||||
/// - `O`: the ActivityPub type of the Object for this activity (usually the type corresponding to `Self`)
|
|
||||||
/// - `C`: the context needed to handle the activity (usually a database connection)
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// An implementation of AsObject that handles Note creation by an Account model,
|
|
||||||
/// representing the Note by a Message type, without any specific context.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # extern crate activitypub;
|
|
||||||
/// # use activitypub::{activity::Create, actor::Person, object::Note};
|
|
||||||
/// # use plume_common::activity_pub::inbox::{AsActor, AsObject, FromId};
|
|
||||||
/// # use plume_common::activity_pub::sign::{gen_keypair, Error as SignError, Result as SignResult, Signer};
|
|
||||||
/// # use openssl::{hash::MessageDigest, pkey::PKey, rsa::Rsa};
|
|
||||||
/// # use once_cell::sync::Lazy;
|
|
||||||
/// #
|
|
||||||
/// # static MY_SIGNER: Lazy<MySigner> = Lazy::new(|| MySigner::new());
|
|
||||||
/// #
|
|
||||||
/// # struct MySigner {
|
|
||||||
/// # public_key: String,
|
|
||||||
/// # private_key: String,
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # impl MySigner {
|
|
||||||
/// # fn new() -> Self {
|
|
||||||
/// # let (pub_key, priv_key) = gen_keypair();
|
|
||||||
/// # Self {
|
|
||||||
/// # public_key: String::from_utf8(pub_key).unwrap(),
|
|
||||||
/// # private_key: String::from_utf8(priv_key).unwrap(),
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # impl Signer for MySigner {
|
|
||||||
/// # fn get_key_id(&self) -> String {
|
|
||||||
/// # "mysigner".into()
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # fn sign(&self, to_sign: &str) -> SignResult<Vec<u8>> {
|
|
||||||
/// # let key = PKey::from_rsa(Rsa::private_key_from_pem(self.private_key.as_ref()).unwrap())
|
|
||||||
/// # .unwrap();
|
|
||||||
/// # let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &key).unwrap();
|
|
||||||
/// # signer.update(to_sign.as_bytes()).unwrap();
|
|
||||||
/// # signer.sign_to_vec().map_err(|_| SignError())
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # fn verify(&self, data: &str, signature: &[u8]) -> SignResult<bool> {
|
|
||||||
/// # let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref()).unwrap())
|
|
||||||
/// # .unwrap();
|
|
||||||
/// # let mut verifier = openssl::sign::Verifier::new(MessageDigest::sha256(), &key).unwrap();
|
|
||||||
/// # verifier.update(data.as_bytes()).unwrap();
|
|
||||||
/// # verifier.verify(&signature).map_err(|_| SignError())
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # struct Account;
|
|
||||||
/// # impl FromId<()> for Account {
|
|
||||||
/// # type Error = ();
|
|
||||||
/// # type Object = Person;
|
|
||||||
/// #
|
|
||||||
/// # fn from_db(_: &(), _id: &str) -> Result<Self, Self::Error> {
|
|
||||||
/// # Ok(Account)
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # fn from_activity(_: &(), obj: Person) -> Result<Self, Self::Error> {
|
|
||||||
/// # Ok(Account)
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// # fn get_sender() -> &'static dyn Signer {
|
|
||||||
/// # &*MY_SIGNER
|
|
||||||
/// # }
|
|
||||||
/// # }
|
|
||||||
/// # impl AsActor<()> for Account {
|
|
||||||
/// # fn get_inbox_url(&self) -> String {
|
|
||||||
/// # String::new()
|
|
||||||
/// # }
|
|
||||||
/// # fn is_local(&self) -> bool { false }
|
|
||||||
/// # }
|
|
||||||
/// #[derive(Debug)]
|
|
||||||
/// struct Message {
|
|
||||||
/// text: String,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl FromId<()> for Message {
|
|
||||||
/// type Error = ();
|
|
||||||
/// type Object = Note;
|
|
||||||
///
|
|
||||||
/// fn from_db(_: &(), _id: &str) -> Result<Self, Self::Error> {
|
|
||||||
/// Ok(Message { text: "From DB".into() })
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn from_activity(_: &(), obj: Note) -> Result<Self, Self::Error> {
|
|
||||||
/// Ok(Message { text: obj.object_props.content_string().map_err(|_| ())? })
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn get_sender() -> &'static dyn Signer {
|
|
||||||
/// &*MY_SIGNER
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl AsObject<Account, Create, ()> for Message {
|
|
||||||
/// type Error = ();
|
|
||||||
/// type Output = ();
|
|
||||||
///
|
|
||||||
/// fn activity(self, _: (), _actor: Account, _id: &str) -> Result<(), ()> {
|
|
||||||
/// println!("New Note: {:?}", self);
|
|
||||||
/// Ok(())
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub trait AsObject07<A, V, C>
|
pub trait AsObject07<A, V, C>
|
||||||
where
|
where
|
||||||
V: activitystreams::markers::Activity,
|
V: activitystreams::markers::Activity,
|
||||||
@ -769,47 +629,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MyObject;
|
|
||||||
impl AsObject<MyActor, Create, &()> for MyObject {
|
|
||||||
type Error = ();
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, _: &(), _actor: MyActor, _id: &str) -> Result<Self::Output, Self::Error> {
|
|
||||||
println!("MyActor is creating a Note");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject<MyActor, Like, &()> for MyObject {
|
|
||||||
type Error = ();
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, _: &(), _actor: MyActor, _id: &str) -> Result<Self::Output, Self::Error> {
|
|
||||||
println!("MyActor is liking a Note");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject<MyActor, Delete, &()> for MyObject {
|
|
||||||
type Error = ();
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, _: &(), _actor: MyActor, _id: &str) -> Result<Self::Output, Self::Error> {
|
|
||||||
println!("MyActor is deleting a Note");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject<MyActor, Announce, &()> for MyObject {
|
|
||||||
type Error = ();
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, _: &(), _actor: MyActor, _id: &str) -> Result<Self::Output, Self::Error> {
|
|
||||||
println!("MyActor is announcing a Note");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MyObject07;
|
struct MyObject07;
|
||||||
impl FromId<()> for MyObject07 {
|
impl FromId<()> for MyObject07 {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
@ -962,21 +781,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<FailingActor, Create, &()> for MyObject {
|
|
||||||
type Error = ();
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(
|
|
||||||
self,
|
|
||||||
_: &(),
|
|
||||||
_actor: FailingActor,
|
|
||||||
_id: &str,
|
|
||||||
) -> Result<Self::Output, Self::Error> {
|
|
||||||
println!("FailingActor is creating a Note");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromId<()> for FailingActor {
|
impl FromId<()> for FailingActor {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
type Object = Person07;
|
type Object = Person07;
|
||||||
|
@ -30,7 +30,7 @@ use chrono::{self, NaiveDateTime, TimeZone, Utc};
|
|||||||
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
|
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
|
||||||
use plume_common::{
|
use plume_common::{
|
||||||
activity_pub::{
|
activity_pub::{
|
||||||
inbox::{AsActor, AsObject, AsObject07, FromId},
|
inbox::{AsActor, AsObject07, FromId},
|
||||||
sign::Signer,
|
sign::Signer,
|
||||||
Id, IntoId, ToAsString, ToAsUri, PUBLIC_VISIBILITY,
|
Id, IntoId, ToAsString, ToAsUri, PUBLIC_VISIBILITY,
|
||||||
},
|
},
|
||||||
@ -431,45 +431,6 @@ impl FromId<DbConn> for Comment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Create, &DbConn> for Comment {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn activity(self, _conn: &DbConn, _actor: User, _id: &str) -> Result<Self> {
|
|
||||||
// The actual creation takes place in the FromId impl
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject<User, Delete, &DbConn> for Comment {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
if self.author_id != actor.id {
|
|
||||||
return Err(Error::Unauthorized);
|
|
||||||
}
|
|
||||||
|
|
||||||
for m in Mention::list_for_comment(conn, self.id)? {
|
|
||||||
for n in Notification::find_for_mention(conn, &m)? {
|
|
||||||
n.delete(conn)?;
|
|
||||||
}
|
|
||||||
m.delete(conn)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
for n in Notification::find_for_comment(conn, &self)? {
|
|
||||||
n.delete(&**conn)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
diesel::update(comments::table)
|
|
||||||
.filter(comments::in_response_to_id.eq(self.id))
|
|
||||||
.set(comments::in_response_to_id.eq(self.in_response_to_id))
|
|
||||||
.execute(&**conn)?;
|
|
||||||
diesel::delete(&self).execute(&**conn)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Create07, &DbConn> for Comment {
|
impl AsObject07<User, Create07, &DbConn> for Comment {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
@ -12,7 +12,7 @@ use activitystreams::{
|
|||||||
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
|
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
|
||||||
use plume_common::activity_pub::{
|
use plume_common::activity_pub::{
|
||||||
broadcast, broadcast07,
|
broadcast, broadcast07,
|
||||||
inbox::{AsActor, AsObject, AsObject07, FromId},
|
inbox::{AsActor, AsObject07, FromId},
|
||||||
sign::Signer,
|
sign::Signer,
|
||||||
Id, IntoId, PUBLIC_VISIBILITY,
|
Id, IntoId, PUBLIC_VISIBILITY,
|
||||||
};
|
};
|
||||||
@ -242,22 +242,6 @@ impl Follow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, FollowAct, &DbConn> for User {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = Follow;
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Follow> {
|
|
||||||
// Mastodon (at least) requires the full Follow object when accepting it,
|
|
||||||
// so we rebuilt it here
|
|
||||||
let mut follow = FollowAct::default();
|
|
||||||
follow.object_props.set_id_string(id.to_string())?;
|
|
||||||
follow
|
|
||||||
.follow_props
|
|
||||||
.set_actor_link::<Id>(actor.clone().into_id())?;
|
|
||||||
Follow::accept_follow(conn, &actor, &self, follow, actor.id, self.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, FollowAct07, &DbConn> for User {
|
impl AsObject07<User, FollowAct07, &DbConn> for User {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = Follow;
|
type Output = Follow;
|
||||||
@ -312,27 +296,6 @@ impl FromId<DbConn> for Follow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Undo, &DbConn> for Follow {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
let conn = conn;
|
|
||||||
if self.follower_id == actor.id {
|
|
||||||
diesel::delete(&self).execute(&**conn)?;
|
|
||||||
|
|
||||||
// delete associated notification if any
|
|
||||||
if let Ok(notif) = Notification::find(conn, notification_kind::FOLLOW, self.id) {
|
|
||||||
diesel::delete(¬if).execute(&**conn)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::Unauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Undo07, &DbConn> for Follow {
|
impl AsObject07<User, Undo07, &DbConn> for Follow {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
@ -12,7 +12,7 @@ use activitystreams::{
|
|||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
|
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||||
use plume_common::activity_pub::{
|
use plume_common::activity_pub::{
|
||||||
inbox::{AsActor, AsObject, AsObject07, FromId},
|
inbox::{AsActor, AsObject07, FromId},
|
||||||
sign::Signer,
|
sign::Signer,
|
||||||
Id, IntoId, PUBLIC_VISIBILITY,
|
Id, IntoId, PUBLIC_VISIBILITY,
|
||||||
};
|
};
|
||||||
@ -118,26 +118,6 @@ impl Like {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, activity::Like, &DbConn> for Post {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = Like;
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Like> {
|
|
||||||
let res = Like::insert(
|
|
||||||
conn,
|
|
||||||
NewLike {
|
|
||||||
post_id: self.id,
|
|
||||||
user_id: actor.id,
|
|
||||||
ap_url: id.to_string(),
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
res.notify(conn)?;
|
|
||||||
|
|
||||||
Timeline::add_to_all_timelines(conn, &self, Kind::Like(&actor))?;
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Like07, &DbConn> for Post {
|
impl AsObject07<User, Like07, &DbConn> for Post {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = Like;
|
type Output = Like;
|
||||||
@ -207,25 +187,6 @@ impl FromId<DbConn> for Like {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, activity::Undo, &DbConn> for Like {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
if actor.id == self.user_id {
|
|
||||||
diesel::delete(&self).execute(&**conn)?;
|
|
||||||
|
|
||||||
// delete associated notification if any
|
|
||||||
if let Ok(notif) = Notification::find(conn, notification_kind::LIKE, self.id) {
|
|
||||||
diesel::delete(¬if).execute(&**conn)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::Unauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Undo07, &DbConn> for Like {
|
impl AsObject07<User, Undo07, &DbConn> for Like {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
@ -26,7 +26,7 @@ use diesel::{self, BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl};
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use plume_common::{
|
use plume_common::{
|
||||||
activity_pub::{
|
activity_pub::{
|
||||||
inbox::{AsActor, AsObject, AsObject07, FromId},
|
inbox::{AsActor, AsObject07, FromId},
|
||||||
sign::Signer,
|
sign::Signer,
|
||||||
Hashtag, Hashtag07, HashtagType07, Id, IntoId, Licensed, Licensed07,
|
Hashtag, Hashtag07, HashtagType07, Id, IntoId, Licensed, Licensed07,
|
||||||
LicensedArticle as LicensedArticle07, Source, SourceProperty, ToAsString, ToAsUri,
|
LicensedArticle as LicensedArticle07, Source, SourceProperty, ToAsString, ToAsUri,
|
||||||
@ -1054,16 +1054,6 @@ impl FromId<DbConn> for Post {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Create, &DbConn> for Post {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = Post;
|
|
||||||
|
|
||||||
fn activity(self, _conn: &DbConn, _actor: User, _id: &str) -> Result<Post> {
|
|
||||||
// TODO: check that _actor is actually one of the author?
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Create07, &DbConn> for Post {
|
impl AsObject07<User, Create07, &DbConn> for Post {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
@ -1074,23 +1064,6 @@ impl AsObject07<User, Create07, &DbConn> for Post {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Delete, &DbConn> for Post {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
let can_delete = self
|
|
||||||
.get_authors(conn)?
|
|
||||||
.into_iter()
|
|
||||||
.any(|a| actor.id == a.id);
|
|
||||||
if can_delete {
|
|
||||||
self.delete(conn).map(|_| ())
|
|
||||||
} else {
|
|
||||||
Err(Error::Unauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Delete07, &DbConn> for Post {
|
impl AsObject07<User, Delete07, &DbConn> for Post {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
@ -1176,78 +1149,6 @@ impl FromId<DbConn> for PostUpdate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Update, &DbConn> for PostUpdate {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
let mut post =
|
|
||||||
Post::from_id07(conn, &self.ap_url, None, CONFIG.proxy()).map_err(|(_, e)| e)?;
|
|
||||||
|
|
||||||
if !post.is_author(conn, actor.id)? {
|
|
||||||
// TODO: maybe the author was added in the meantime
|
|
||||||
return Err(Error::Unauthorized);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(title) = self.title {
|
|
||||||
post.slug = Post::slug(&title).to_string();
|
|
||||||
post.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(content) = self.content {
|
|
||||||
post.content = SafeString::new(&content);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(subtitle) = self.subtitle {
|
|
||||||
post.subtitle = subtitle;
|
|
||||||
}
|
|
||||||
|
|
||||||
post.cover_id = self.cover;
|
|
||||||
|
|
||||||
if let Some(source) = self.source {
|
|
||||||
post.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(license) = self.license {
|
|
||||||
post.license = license;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut txt_hashtags = md_to_html(&post.source, None, false, None)
|
|
||||||
.2
|
|
||||||
.into_iter()
|
|
||||||
.collect::<HashSet<_>>();
|
|
||||||
if let Some(serde_json::Value::Array(mention_tags)) = self.tags {
|
|
||||||
let mut mentions = vec![];
|
|
||||||
let mut tags = vec![];
|
|
||||||
let mut hashtags = vec![];
|
|
||||||
for tag in mention_tags {
|
|
||||||
serde_json::from_value::<link::Mention>(tag.clone())
|
|
||||||
.map(|m| mentions.push(m))
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
serde_json::from_value::<Hashtag>(tag.clone())
|
|
||||||
.map_err(Error::from)
|
|
||||||
.and_then(|t| {
|
|
||||||
let tag_name = t.name_string()?;
|
|
||||||
if txt_hashtags.remove(&tag_name) {
|
|
||||||
hashtags.push(t);
|
|
||||||
} else {
|
|
||||||
tags.push(t);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
post.update_mentions(conn, mentions)?;
|
|
||||||
post.update_tags(conn, tags)?;
|
|
||||||
post.update_hashtags(conn, hashtags)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
post.update(conn)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Update07, &DbConn> for PostUpdate {
|
impl AsObject07<User, Update07, &DbConn> for PostUpdate {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
@ -12,7 +12,7 @@ use activitystreams::{
|
|||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
|
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
|
||||||
use plume_common::activity_pub::{
|
use plume_common::activity_pub::{
|
||||||
inbox::{AsActor, AsObject, AsObject07, FromId},
|
inbox::{AsActor, AsObject07, FromId},
|
||||||
sign::Signer,
|
sign::Signer,
|
||||||
Id, IntoId, PUBLIC_VISIBILITY,
|
Id, IntoId, PUBLIC_VISIBILITY,
|
||||||
};
|
};
|
||||||
@ -144,27 +144,6 @@ impl Reshare {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Announce, &DbConn> for Post {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = Reshare;
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, id: &str) -> Result<Reshare> {
|
|
||||||
let conn = conn;
|
|
||||||
let reshare = Reshare::insert(
|
|
||||||
conn,
|
|
||||||
NewReshare {
|
|
||||||
post_id: self.id,
|
|
||||||
user_id: actor.id,
|
|
||||||
ap_url: id.to_string(),
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
reshare.notify(conn)?;
|
|
||||||
|
|
||||||
Timeline::add_to_all_timelines(conn, &self, Kind::Reshare(&actor))?;
|
|
||||||
Ok(reshare)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Announce07, &DbConn> for Post {
|
impl AsObject07<User, Announce07, &DbConn> for Post {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = Reshare;
|
type Output = Reshare;
|
||||||
@ -235,26 +214,6 @@ impl FromId<DbConn> for Reshare {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Undo, &DbConn> for Reshare {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
if actor.id == self.user_id {
|
|
||||||
diesel::delete(&self).execute(&**conn)?;
|
|
||||||
|
|
||||||
// delete associated notification if any
|
|
||||||
if let Ok(notif) = Notification::find(conn, notification_kind::RESHARE, self.id) {
|
|
||||||
diesel::delete(¬if).execute(&**conn)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Error::Unauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Undo07, &DbConn> for Reshare {
|
impl AsObject07<User, Undo07, &DbConn> for Reshare {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
@ -35,7 +35,7 @@ use openssl::{
|
|||||||
};
|
};
|
||||||
use plume_common::{
|
use plume_common::{
|
||||||
activity_pub::{
|
activity_pub::{
|
||||||
inbox::{AsActor, AsObject, AsObject07, FromId},
|
inbox::{AsActor, AsObject07, FromId},
|
||||||
request::get,
|
request::get,
|
||||||
sign::{gen_keypair, Error as SignError, Result as SignResult, Signer},
|
sign::{gen_keypair, Error as SignError, Result as SignResult, Signer},
|
||||||
ActivityStream, ApSignature, ApSignature07, CustomPerson as CustomPerson07, Id, IntoId,
|
ActivityStream, ApSignature, ApSignature07, CustomPerson as CustomPerson07, Id, IntoId,
|
||||||
@ -1248,19 +1248,6 @@ impl AsActor<&DbConn> for User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsObject<User, Delete, &DbConn> for User {
|
|
||||||
type Error = Error;
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn activity(self, conn: &DbConn, actor: User, _id: &str) -> Result<()> {
|
|
||||||
if self.id == actor.id {
|
|
||||||
self.delete(conn).map(|_| ())
|
|
||||||
} else {
|
|
||||||
Err(Error::Unauthorized)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsObject07<User, Delete07, &DbConn> for User {
|
impl AsObject07<User, Delete07, &DbConn> for User {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
Loading…
Reference in New Issue
Block a user