Add API method for deleting posts
This commit is contained in:
parent
e7955d8ebb
commit
40dbfc05a2
5 changed files with 85 additions and 1 deletions
|
@ -125,6 +125,7 @@ GET /api/v1/notifications
|
||||||
GET /api/v2/search
|
GET /api/v2/search
|
||||||
POST /api/v1/statuses
|
POST /api/v1/statuses
|
||||||
GET /api/v1/statuses/{status_id}
|
GET /api/v1/statuses/{status_id}
|
||||||
|
DELETE /api/v1/statuses/{status_id}
|
||||||
GET /api/v1/statuses/{status_id}/context
|
GET /api/v1/statuses/{status_id}/context
|
||||||
POST /api/v1/statuses/{status_id}/favourite
|
POST /api/v1/statuses/{status_id}/favourite
|
||||||
POST /api/v1/statuses/{status_id}/unfavourite
|
POST /api/v1/statuses/{status_id}/unfavourite
|
||||||
|
|
|
@ -5,6 +5,19 @@ info:
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
|
/api/v1/statuses/{status_id}:
|
||||||
|
delete:
|
||||||
|
summary: Delete post
|
||||||
|
parameters:
|
||||||
|
- $ref: '#/components/parameters/status_id'
|
||||||
|
responses:
|
||||||
|
204:
|
||||||
|
description: Successful operation
|
||||||
|
content: {}
|
||||||
|
403:
|
||||||
|
description: Post does not belong to user
|
||||||
|
404:
|
||||||
|
description: Post not found
|
||||||
/api/v1/{status_id}/make_permanent:
|
/api/v1/{status_id}/make_permanent:
|
||||||
post:
|
post:
|
||||||
summary: Save post to IPFS
|
summary: Save post to IPFS
|
||||||
|
|
|
@ -249,6 +249,29 @@ pub fn create_activity_announce(
|
||||||
activity
|
activity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_activity_delete_note(
|
||||||
|
instance_url: &str,
|
||||||
|
actor_profile: &DbActorProfile,
|
||||||
|
post: &Post,
|
||||||
|
) -> Activity {
|
||||||
|
let object_id = post.get_object_id(instance_url);
|
||||||
|
let object = Object {
|
||||||
|
context: Some(json!(AP_CONTEXT)),
|
||||||
|
id: object_id,
|
||||||
|
object_type: TOMBSTONE.to_string(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let activity = create_activity(
|
||||||
|
instance_url,
|
||||||
|
&actor_profile.username,
|
||||||
|
DELETE,
|
||||||
|
None,
|
||||||
|
object,
|
||||||
|
AP_PUBLIC,
|
||||||
|
);
|
||||||
|
activity
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_activity_follow(
|
pub fn create_activity_follow(
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
actor_profile: &DbActorProfile,
|
actor_profile: &DbActorProfile,
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub const DOCUMENT: &str = "Document";
|
||||||
pub const IMAGE: &str = "Image";
|
pub const IMAGE: &str = "Image";
|
||||||
pub const MENTION: &str = "Mention";
|
pub const MENTION: &str = "Mention";
|
||||||
pub const NOTE: &str = "Note";
|
pub const NOTE: &str = "Note";
|
||||||
|
pub const TOMBSTONE: &str = "Tombstone";
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
pub const PROPERTY_VALUE: &str = "PropertyValue";
|
pub const PROPERTY_VALUE: &str = "PropertyValue";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/// https://docs.joinmastodon.org/methods/statuses/
|
/// https://docs.joinmastodon.org/methods/statuses/
|
||||||
use actix_web::{get, post, web, HttpResponse, Scope};
|
use actix_web::{delete, get, post, web, HttpResponse, Scope};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -8,6 +8,7 @@ use crate::activitypub::activity::{
|
||||||
create_activity_note,
|
create_activity_note,
|
||||||
create_activity_like,
|
create_activity_like,
|
||||||
create_activity_announce,
|
create_activity_announce,
|
||||||
|
create_activity_delete_note,
|
||||||
};
|
};
|
||||||
use crate::activitypub::actor::Actor;
|
use crate::activitypub::actor::Actor;
|
||||||
use crate::activitypub::deliverer::deliver_activity;
|
use crate::activitypub::deliverer::deliver_activity;
|
||||||
|
@ -31,6 +32,7 @@ use crate::models::posts::queries::{
|
||||||
create_post,
|
create_post,
|
||||||
get_post_by_id,
|
get_post_by_id,
|
||||||
get_thread,
|
get_thread,
|
||||||
|
get_post_author,
|
||||||
find_reposts_by_user,
|
find_reposts_by_user,
|
||||||
update_post,
|
update_post,
|
||||||
delete_post,
|
delete_post,
|
||||||
|
@ -135,6 +137,49 @@ async fn get_status(
|
||||||
Ok(HttpResponse::Ok().json(status))
|
Ok(HttpResponse::Ok().json(status))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[delete("/{status_id}")]
|
||||||
|
async fn delete_status(
|
||||||
|
auth: BearerAuth,
|
||||||
|
config: web::Data<Config>,
|
||||||
|
db_pool: web::Data<Pool>,
|
||||||
|
web::Path(status_id): web::Path<Uuid>,
|
||||||
|
) -> Result<HttpResponse, HttpError> {
|
||||||
|
let db_client = &mut **get_database_client(&db_pool).await?;
|
||||||
|
let current_user = get_current_user(db_client, auth.token()).await?;
|
||||||
|
let post = get_post_by_id(db_client, &status_id).await?;
|
||||||
|
if post.author.id != current_user.id {
|
||||||
|
return Err(HttpError::PermissionError);
|
||||||
|
};
|
||||||
|
let deletion_queue = delete_post(db_client, &status_id).await?;
|
||||||
|
let config_clone = config.clone();
|
||||||
|
actix_rt::spawn(async move {
|
||||||
|
deletion_queue.process(&config_clone).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
let activity = create_activity_delete_note(
|
||||||
|
&config.instance_url(),
|
||||||
|
¤t_user.profile,
|
||||||
|
&post,
|
||||||
|
);
|
||||||
|
let mut audience = get_followers(db_client, ¤t_user.id).await?;
|
||||||
|
if let Some(in_reply_to_id) = post.in_reply_to_id {
|
||||||
|
let in_reply_to_author = get_post_author(db_client, &in_reply_to_id).await?;
|
||||||
|
audience.push(in_reply_to_author);
|
||||||
|
};
|
||||||
|
audience.extend(post.mentions);
|
||||||
|
let mut recipients: Vec<Actor> = Vec::new();
|
||||||
|
for profile in audience {
|
||||||
|
let maybe_remote_actor = profile.remote_actor()
|
||||||
|
.map_err(|_| HttpError::InternalError)?;
|
||||||
|
if let Some(remote_actor) = maybe_remote_actor {
|
||||||
|
recipients.push(remote_actor);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
deliver_activity(&config, ¤t_user, activity, recipients);
|
||||||
|
|
||||||
|
Ok(HttpResponse::NoContent().finish())
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/{status_id}/context")]
|
#[get("/{status_id}/context")]
|
||||||
async fn get_context(
|
async fn get_context(
|
||||||
auth: Option<BearerAuth>,
|
auth: Option<BearerAuth>,
|
||||||
|
@ -426,6 +471,7 @@ pub fn status_api_scope() -> Scope {
|
||||||
.service(create_status)
|
.service(create_status)
|
||||||
// Routes with status ID
|
// Routes with status ID
|
||||||
.service(get_status)
|
.service(get_status)
|
||||||
|
.service(delete_status)
|
||||||
.service(get_context)
|
.service(get_context)
|
||||||
.service(favourite)
|
.service(favourite)
|
||||||
.service(unfavourite)
|
.service(unfavourite)
|
||||||
|
|
Loading…
Reference in a new issue