mirror of https://github.com/LemmyNet/lemmy.git
handle deletion in new fetcher
parent
13eca1b106
commit
64619d7eb1
|
@ -0,0 +1,85 @@
|
||||||
|
use crate::fetcher::post_or_comment::PostOrComment;
|
||||||
|
use lemmy_api_common::blocking;
|
||||||
|
use lemmy_db_queries::source::{
|
||||||
|
comment::Comment_,
|
||||||
|
community::Community_,
|
||||||
|
person::Person_,
|
||||||
|
post::Post_,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
||||||
|
use lemmy_utils::LemmyError;
|
||||||
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
||||||
|
// TODO: merge this trait with ApubObject (means that db_schema needs to depend on apub_lib)
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
pub trait DeletableApubObject {
|
||||||
|
// TODO: pass in tombstone with summary field, to decide between remove/delete
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl DeletableApubObject for Community {
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
let id = self.id;
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Community::update_deleted(conn, id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl DeletableApubObject for Person {
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
let id = self.id;
|
||||||
|
blocking(context.pool(), move |conn| Person::delete_account(conn, id)).await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl DeletableApubObject for Post {
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
let id = self.id;
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Post::update_deleted(conn, id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl DeletableApubObject for Comment {
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
let id = self.id;
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Comment::update_deleted(conn, id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl DeletableApubObject for PostOrComment {
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
match self {
|
||||||
|
PostOrComment::Comment(c) => {
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Comment::update_deleted(conn, c.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
}
|
||||||
|
PostOrComment::Post(p) => {
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Post::update_deleted(conn, p.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod deletable_apub_object;
|
||||||
mod fetch;
|
mod fetch;
|
||||||
pub mod object_id;
|
pub mod object_id;
|
||||||
pub mod post_or_comment;
|
pub mod post_or_comment;
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
use crate::{fetcher::should_refetch_actor, objects::FromApub, APUB_JSON_CONTENT_TYPE};
|
use crate::{
|
||||||
|
fetcher::{deletable_apub_object::DeletableApubObject, should_refetch_actor},
|
||||||
|
objects::FromApub,
|
||||||
|
APUB_JSON_CONTENT_TYPE,
|
||||||
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use diesel::NotFound;
|
use diesel::NotFound;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
|
@ -23,18 +27,18 @@ static REQUEST_LIMIT: i32 = 25;
|
||||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
||||||
pub struct ObjectId<Kind>(Url, #[serde(skip)] PhantomData<Kind>)
|
pub struct ObjectId<Kind>(Url, #[serde(skip)] PhantomData<Kind>)
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject + Send + 'static,
|
Kind: FromApub + ApubObject + DeletableApubObject + Send + 'static,
|
||||||
for<'de2> <Kind as FromApub>::ApubType: serde::Deserialize<'de2>;
|
for<'de2> <Kind as FromApub>::ApubType: serde::Deserialize<'de2>;
|
||||||
|
|
||||||
impl<Kind> ObjectId<Kind>
|
impl<Kind> ObjectId<Kind>
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject + Send + 'static,
|
Kind: FromApub + ApubObject + DeletableApubObject + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
pub fn new<K, T>(url: T) -> ObjectId<K>
|
pub fn new<K, T>(url: T) -> ObjectId<K>
|
||||||
where
|
where
|
||||||
T: Into<Url>,
|
T: Into<Url>,
|
||||||
K: FromApub + ApubObject + Send + 'static,
|
K: FromApub + ApubObject + DeletableApubObject + Send + 'static,
|
||||||
for<'de> <K as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <K as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
ObjectId(url.into(), PhantomData::<K>)
|
ObjectId(url.into(), PhantomData::<K>)
|
||||||
|
@ -64,13 +68,17 @@ where
|
||||||
// TODO: rename to should_refetch_object()
|
// TODO: rename to should_refetch_object()
|
||||||
if should_refetch_actor(last_refreshed_at) {
|
if should_refetch_actor(last_refreshed_at) {
|
||||||
debug!("Refetching remote object {}", self.0.as_str());
|
debug!("Refetching remote object {}", self.0.as_str());
|
||||||
return self.dereference_remotely(context, request_counter).await;
|
return self
|
||||||
|
.dereference_remotely(context, request_counter, Some(object))
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(object)
|
Ok(object)
|
||||||
} else {
|
} else {
|
||||||
debug!("Fetching remote object {}", self.0.as_str());
|
debug!("Fetching remote object {}", self.0.as_str());
|
||||||
self.dereference_remotely(context, request_counter).await
|
self
|
||||||
|
.dereference_remotely(context, request_counter, None)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +97,7 @@ where
|
||||||
&self,
|
&self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
|
db_object: Option<Kind>,
|
||||||
) -> Result<Kind, LemmyError> {
|
) -> Result<Kind, LemmyError> {
|
||||||
// dont fetch local objects this way
|
// dont fetch local objects this way
|
||||||
debug_assert!(self.0.domain() != Some(&Settings::get().hostname));
|
debug_assert!(self.0.domain() != Some(&Settings::get().hostname));
|
||||||
|
@ -109,31 +118,21 @@ where
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if res.status() == StatusCode::GONE {
|
if res.status() == StatusCode::GONE {
|
||||||
self.mark_object_deleted(context).await?;
|
if let Some(db_object) = db_object {
|
||||||
return Err(
|
db_object.delete(context).await?;
|
||||||
anyhow!(
|
}
|
||||||
"Fetched remote object {} which was deleted",
|
return Err(anyhow!("Fetched remote object {} which was deleted", self).into());
|
||||||
self.0.as_str()
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let res2: Kind::ApubType = res.json().await?;
|
let res2: Kind::ApubType = res.json().await?;
|
||||||
|
|
||||||
Ok(Kind::from_apub(&res2, context, self.inner(), request_counter).await?)
|
Ok(Kind::from_apub(&res2, context, self.inner(), request_counter).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn mark_object_deleted(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
// TODO: need to move methods update_deleted, update_removed etc into a trait to use them here.
|
|
||||||
// also, how do we know if the object was deleted vs removed?
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Kind> Display for ObjectId<Kind>
|
impl<Kind> Display for ObjectId<Kind>
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject + Send + 'static,
|
Kind: FromApub + ApubObject + DeletableApubObject + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -143,7 +142,7 @@ where
|
||||||
|
|
||||||
impl<Kind> From<ObjectId<Kind>> for Url
|
impl<Kind> From<ObjectId<Kind>> for Url
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject + Send + 'static,
|
Kind: FromApub + ApubObject + DeletableApubObject + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn from(id: ObjectId<Kind>) -> Self {
|
fn from(id: ObjectId<Kind>) -> Self {
|
||||||
|
@ -153,7 +152,7 @@ where
|
||||||
|
|
||||||
impl<Kind> From<ObjectId<Kind>> for DbUrl
|
impl<Kind> From<ObjectId<Kind>> for DbUrl
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject + Send + 'static,
|
Kind: FromApub + ApubObject + DeletableApubObject + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn from(id: ObjectId<Kind>) -> Self {
|
fn from(id: ObjectId<Kind>) -> Self {
|
||||||
|
|
Loading…
Reference in New Issue