]> Untitled Git - lemmy.git/blob - lemmy_apub/src/objects/mod.rs
Better account deletion (fixes #730) (#143)
[lemmy.git] / lemmy_apub / src / objects / mod.rs
1 use crate::check_is_apub_id_valid;
2 use activitystreams::{
3   base::{AsBase, BaseExt, ExtendsExt},
4   markers::Base,
5   mime::{FromStrError, Mime},
6   object::{ApObjectExt, Object, ObjectExt, Tombstone, TombstoneExt},
7 };
8 use anyhow::{anyhow, Context};
9 use chrono::NaiveDateTime;
10 use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
11 use url::Url;
12
13 pub(crate) mod comment;
14 pub(crate) mod community;
15 pub(crate) mod post;
16 pub(crate) mod private_message;
17 pub(crate) mod user;
18
19 /// Updated is actually the deletion time
20 fn create_tombstone<T>(
21   deleted: bool,
22   object_id: &str,
23   updated: Option<NaiveDateTime>,
24   former_type: T,
25 ) -> Result<Tombstone, LemmyError>
26 where
27   T: ToString,
28 {
29   if deleted {
30     if let Some(updated) = updated {
31       let mut tombstone = Tombstone::new();
32       tombstone.set_id(object_id.parse()?);
33       tombstone.set_former_type(former_type.to_string());
34       tombstone.set_deleted(convert_datetime(updated));
35       Ok(tombstone)
36     } else {
37       Err(anyhow!("Cant convert to tombstone because updated time was None.").into())
38     }
39   } else {
40     Err(anyhow!("Cant convert object to tombstone if it wasnt deleted").into())
41   }
42 }
43
44 pub(in crate::objects) fn check_object_domain<T, Kind>(
45   apub: &T,
46   expected_domain: Option<Url>,
47 ) -> Result<String, LemmyError>
48 where
49   T: Base + AsBase<Kind>,
50 {
51   let actor_id = if let Some(url) = expected_domain {
52     check_is_apub_id_valid(&url)?;
53     let domain = url.domain().context(location_info!())?;
54     apub.id(domain)?.context(location_info!())?
55   } else {
56     let actor_id = apub.id_unchecked().context(location_info!())?;
57     check_is_apub_id_valid(&actor_id)?;
58     actor_id
59   };
60   Ok(actor_id.to_string())
61 }
62
63 pub(in crate::objects) fn set_content_and_source<T, Kind1, Kind2>(
64   object: &mut T,
65   markdown_text: &str,
66 ) -> Result<(), LemmyError>
67 where
68   T: ApObjectExt<Kind1> + ObjectExt<Kind2> + AsBase<Kind2>,
69 {
70   let mut source = Object::<()>::new_none_type();
71   source
72     .set_content(markdown_text)
73     .set_media_type(mime_markdown()?);
74   object.set_source(source.into_any_base()?);
75
76   // set `content` to markdown for compatibility with older Lemmy versions
77   // TODO: change this to HTML in a while
78   object.set_content(markdown_text);
79   object.set_media_type(mime_markdown()?);
80   //object.set_content(markdown_to_html(markdown_text));
81   Ok(())
82 }
83
84 pub(in crate::objects) fn get_source_markdown_value<T, Kind1, Kind2>(
85   object: &T,
86 ) -> Result<Option<String>, LemmyError>
87 where
88   T: ApObjectExt<Kind1> + ObjectExt<Kind2> + AsBase<Kind2>,
89 {
90   let content = object
91     .content()
92     .map(|s| s.as_single_xsd_string())
93     .flatten()
94     .map(|s| s.to_string());
95   if content.is_some() {
96     let source = object.source();
97     // updated lemmy version, read markdown from `source.content`
98     if let Some(source) = source {
99       let source = Object::<()>::from_any_base(source.to_owned())?.context(location_info!())?;
100       check_is_markdown(source.media_type())?;
101       let source_content = source
102         .content()
103         .map(|s| s.as_single_xsd_string())
104         .flatten()
105         .context(location_info!())?
106         .to_string();
107       return Ok(Some(source_content));
108     }
109     // older lemmy version, read markdown from `content`
110     // TODO: remove this after a while
111     else {
112       return Ok(content);
113     }
114   }
115   Ok(None)
116 }
117
118 pub(in crate::objects) fn mime_markdown() -> Result<Mime, FromStrError> {
119   "text/markdown".parse()
120 }
121
122 pub(in crate::objects) fn check_is_markdown(mime: Option<&Mime>) -> Result<(), LemmyError> {
123   let mime = mime.context(location_info!())?;
124   if !mime.eq(&mime_markdown()?) {
125     Err(LemmyError::from(anyhow!(
126       "Lemmy only supports markdown content"
127     )))
128   } else {
129     Ok(())
130   }
131 }