Federate user deletion (#551)

* Federate user deletion

- When someone deletes their account
- When a local user is banned

Fixes #509

* cargo fmt
This commit is contained in:
Baptiste Gelez
2019-04-28 18:01:41 +01:00
committed by GitHub
parent 85aa0883c8
commit 787eb7f399
28 changed files with 157 additions and 72 deletions
+29
View File
@@ -53,6 +53,7 @@ pub fn inbox(ctx: &PlumeRocket, act: serde_json::Value) -> Result<InboxResult, E
.with::<User, Create, Post>()
.with::<User, Delete, Comment>()
.with::<User, Delete, Post>()
.with::<User, Delete, User>()
.with::<User, Follow, User>()
.with::<User, Like, Post>()
.with::<User, Undo, Reshare>()
@@ -286,6 +287,34 @@ pub(crate) mod tests {
});
}
#[test]
fn delete_user() {
let r = rockets();
let conn = &*r.conn;
conn.test_transaction::<_, (), _>(|| {
let (_, users, _) = fill_database(&r);
let fail_act = json!({
"id": "https://plu.me/@/Admin#delete",
"actor": users[1].ap_url, // Not the same account
"object": users[0].ap_url,
"type": "Delete",
});
assert!(super::inbox(&r, fail_act).is_err());
let ok_act = json!({
"id": "https://plu.me/@/Admin#delete",
"actor": users[0].ap_url,
"object": users[0].ap_url,
"type": "Delete",
});
assert!(super::inbox(&r, ok_act).is_ok());
assert!(crate::users::User::get(conn, users[0].id).is_err());
Ok(())
});
}
#[test]
fn follow() {
let r = rockets();
+43 -3
View File
@@ -1,5 +1,9 @@
use activitypub::{
actor::Person, collection::OrderedCollection, object::Image, Activity, CustomObject, Endpoint,
activity::Delete,
actor::Person,
collection::OrderedCollection,
object::{Image, Tombstone},
Activity, CustomObject, Endpoint,
};
use bcrypt;
use chrono::{NaiveDateTime, Utc};
@@ -12,9 +16,9 @@ use openssl::{
};
use plume_common::activity_pub::{
ap_accept_header,
inbox::{AsActor, FromId},
inbox::{AsActor, AsObject, FromId},
sign::{gen_keypair, Signer},
ActivityStream, ApSignature, Id, IntoId, PublicKey,
ActivityStream, ApSignature, Id, IntoId, PublicKey, PUBLIC_VISIBILITY,
};
use plume_common::utils;
use reqwest::{
@@ -632,6 +636,29 @@ impl User {
Ok(CustomPerson::new(actor, ap_signature))
}
pub fn delete_activity(&self, conn: &Connection) -> Result<Delete> {
let mut del = Delete::default();
let mut tombstone = Tombstone::default();
tombstone.object_props.set_id_string(self.ap_url.clone())?;
del.delete_props
.set_actor_link(Id::new(self.ap_url.clone()))?;
del.delete_props.set_object_object(tombstone)?;
del.object_props
.set_id_string(format!("{}#delete", self.ap_url))?;
del.object_props
.set_to_link_vec(vec![Id::new(PUBLIC_VISIBILITY)])?;
del.object_props.set_cc_link_vec(
self.get_followers(conn)?
.into_iter()
.map(|f| Id::new(f.ap_url))
.collect(),
)?;
Ok(del)
}
pub fn avatar_url(&self, conn: &Connection) -> String {
self.avatar_id
.and_then(|id| Media::get(conn, id).and_then(|m| m.url(conn)).ok())
@@ -832,6 +859,19 @@ impl AsActor<&PlumeRocket> for User {
}
}
impl AsObject<User, Delete, &PlumeRocket> for User {
type Error = Error;
type Output = ();
fn activity(self, c: &PlumeRocket, actor: User, _id: &str) -> Result<()> {
if self.id == actor.id {
self.delete(&c.conn, &c.searcher).map(|_| ())
} else {
Err(Error::Unauthorized)
}
}
}
impl Signer for User {
type Error = Error;