]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/activity.rs
Adding unique constraint for activity ap_id. Fixes #1878 (#1935)
[lemmy.git] / crates / db_schema / src / impls / activity.rs
1 use crate::{newtypes::DbUrl, source::activity::*, traits::Crud};
2 use diesel::{dsl::*, result::Error, *};
3 use serde_json::Value;
4 use std::io::{Error as IoError, ErrorKind};
5
6 impl Crud for Activity {
7   type Form = ActivityForm;
8   type IdType = i32;
9   fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
10     use crate::schema::activity::dsl::*;
11     activity.find(activity_id).first::<Self>(conn)
12   }
13
14   fn create(conn: &PgConnection, new_activity: &ActivityForm) -> Result<Self, Error> {
15     use crate::schema::activity::dsl::*;
16     insert_into(activity)
17       .values(new_activity)
18       .get_result::<Self>(conn)
19   }
20
21   fn update(
22     conn: &PgConnection,
23     activity_id: i32,
24     new_activity: &ActivityForm,
25   ) -> Result<Self, Error> {
26     use crate::schema::activity::dsl::*;
27     diesel::update(activity.find(activity_id))
28       .set(new_activity)
29       .get_result::<Self>(conn)
30   }
31   fn delete(conn: &PgConnection, activity_id: i32) -> Result<usize, Error> {
32     use crate::schema::activity::dsl::*;
33     diesel::delete(activity.find(activity_id)).execute(conn)
34   }
35 }
36
37 impl Activity {
38   pub fn insert(
39     conn: &PgConnection,
40     ap_id: DbUrl,
41     data: Value,
42     local: bool,
43     sensitive: bool,
44   ) -> Result<Activity, IoError> {
45     let activity_form = ActivityForm {
46       ap_id,
47       data,
48       local: Some(local),
49       sensitive,
50       updated: None,
51     };
52     let result = Activity::create(conn, &activity_form);
53     match result {
54       Ok(s) => Ok(s),
55       Err(e) => Err(IoError::new(
56         ErrorKind::Other,
57         format!("Failed to insert activity into database: {}", e),
58       )),
59     }
60   }
61
62   pub fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error> {
63     use crate::schema::activity::dsl::*;
64     activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
65   }
66
67   pub fn delete_olds(conn: &PgConnection) -> Result<usize, Error> {
68     use crate::schema::activity::dsl::*;
69     diesel::delete(activity.filter(published.lt(now - 6.months()))).execute(conn)
70   }
71 }
72
73 #[cfg(test)]
74 mod tests {
75   use super::*;
76   use crate::{
77     establish_unpooled_connection,
78     newtypes::DbUrl,
79     source::{
80       activity::{Activity, ActivityForm},
81       person::{Person, PersonForm},
82     },
83   };
84   use serde_json::Value;
85   use serial_test::serial;
86   use url::Url;
87
88   #[test]
89   #[serial]
90   fn test_crud() {
91     let conn = establish_unpooled_connection();
92
93     let creator_form = PersonForm {
94       name: "activity_creator_pm".into(),
95       ..PersonForm::default()
96     };
97
98     let inserted_creator = Person::create(&conn, &creator_form).unwrap();
99
100     let ap_id: DbUrl = Url::parse(
101       "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
102     )
103     .unwrap()
104     .into();
105     let test_json: Value = serde_json::from_str(
106       r#"{
107     "@context": "https://www.w3.org/ns/activitystreams",
108     "id": "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
109     "type": "Delete",
110     "actor": "https://enterprise.lemmy.ml/u/riker",
111     "to": "https://www.w3.org/ns/activitystreams#Public",
112     "cc": [
113         "https://enterprise.lemmy.ml/c/main/"
114     ],
115     "object": "https://enterprise.lemmy.ml/post/32"
116     }"#,
117     )
118     .unwrap();
119     let activity_form = ActivityForm {
120       ap_id: ap_id.clone(),
121       data: test_json.to_owned(),
122       local: Some(true),
123       sensitive: false,
124       updated: None,
125     };
126
127     let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
128
129     let expected_activity = Activity {
130       ap_id: ap_id.clone(),
131       id: inserted_activity.id,
132       data: test_json,
133       local: true,
134       sensitive: Some(false),
135       published: inserted_activity.published,
136       updated: None,
137     };
138
139     let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
140     let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, &ap_id).unwrap();
141     Person::delete(&conn, inserted_creator.id).unwrap();
142     Activity::delete(&conn, inserted_activity.id).unwrap();
143
144     assert_eq!(expected_activity, read_activity);
145     assert_eq!(expected_activity, read_activity_by_apub_id);
146     assert_eq!(expected_activity, inserted_activity);
147   }
148 }