]> Untitled Git - lemmy.git/blob - lemmy_db/src/activity.rs
539820fc2e0c2f975d0e2d1ba43e8a816ff6f15b
[lemmy.git] / lemmy_db / src / activity.rs
1 use crate::{schema::activity, Crud};
2 use diesel::{dsl::*, result::Error, *};
3 use log::debug;
4 use serde::Serialize;
5 use serde_json::Value;
6 use std::{
7   fmt::Debug,
8   io::{Error as IoError, ErrorKind},
9 };
10
11 #[derive(Queryable, Identifiable, PartialEq, Debug)]
12 #[table_name = "activity"]
13 pub struct Activity {
14   pub id: i32,
15   pub ap_id: String,
16   pub user_id: i32,
17   pub data: Value,
18   pub local: bool,
19   pub published: chrono::NaiveDateTime,
20   pub updated: Option<chrono::NaiveDateTime>,
21 }
22
23 #[derive(Insertable, AsChangeset)]
24 #[table_name = "activity"]
25 pub struct ActivityForm {
26   pub ap_id: String,
27   pub user_id: i32,
28   pub data: Value,
29   pub local: bool,
30   pub updated: Option<chrono::NaiveDateTime>,
31 }
32
33 impl Crud<ActivityForm> for Activity {
34   fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
35     use crate::schema::activity::dsl::*;
36     activity.find(activity_id).first::<Self>(conn)
37   }
38
39   fn create(conn: &PgConnection, new_activity: &ActivityForm) -> Result<Self, Error> {
40     use crate::schema::activity::dsl::*;
41     insert_into(activity)
42       .values(new_activity)
43       .get_result::<Self>(conn)
44   }
45
46   fn update(
47     conn: &PgConnection,
48     activity_id: i32,
49     new_activity: &ActivityForm,
50   ) -> Result<Self, Error> {
51     use crate::schema::activity::dsl::*;
52     diesel::update(activity.find(activity_id))
53       .set(new_activity)
54       .get_result::<Self>(conn)
55   }
56 }
57
58 impl Activity {
59   pub fn insert<T>(
60     conn: &PgConnection,
61     ap_id: String,
62     user_id: i32,
63     data: &T,
64     local: bool,
65   ) -> Result<Self, IoError>
66   where
67     T: Serialize + Debug,
68   {
69     debug!("inserting activity for user {}: ", user_id);
70     debug!("{}", serde_json::to_string_pretty(&data)?);
71     let activity_form = ActivityForm {
72       ap_id,
73       user_id,
74       data: serde_json::to_value(&data)?,
75       local,
76       updated: None,
77     };
78     let result = Activity::create(&conn, &activity_form);
79     match result {
80       Ok(s) => Ok(s),
81       Err(e) => Err(IoError::new(
82         ErrorKind::Other,
83         format!("Failed to insert activity into database: {}", e),
84       )),
85     }
86   }
87
88   pub fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Self, Error> {
89     use crate::schema::activity::dsl::*;
90     activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
91   }
92 }
93
94 #[cfg(test)]
95 mod tests {
96   use crate::{
97     activity::{Activity, ActivityForm},
98     tests::establish_unpooled_connection,
99     user::{UserForm, User_},
100     Crud,
101     ListingType,
102     SortType,
103   };
104   use serde_json::Value;
105
106   #[test]
107   fn test_crud() {
108     let conn = establish_unpooled_connection();
109
110     let creator_form = UserForm {
111       name: "activity_creator_pm".into(),
112       preferred_username: None,
113       password_encrypted: "nope".into(),
114       email: None,
115       matrix_user_id: None,
116       avatar: None,
117       banner: None,
118       admin: false,
119       banned: false,
120       published: None,
121       updated: None,
122       show_nsfw: false,
123       theme: "browser".into(),
124       default_sort_type: SortType::Hot as i16,
125       default_listing_type: ListingType::Subscribed as i16,
126       lang: "browser".into(),
127       show_avatars: true,
128       send_notifications_to_email: false,
129       actor_id: None,
130       bio: None,
131       local: true,
132       private_key: None,
133       public_key: None,
134       last_refreshed_at: None,
135     };
136
137     let inserted_creator = User_::create(&conn, &creator_form).unwrap();
138
139     let ap_id =
140       "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c";
141     let test_json: Value = serde_json::from_str(
142       r#"{
143     "@context": "https://www.w3.org/ns/activitystreams",
144     "id": "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
145     "type": "Delete",
146     "actor": "https://enterprise.lemmy.ml/u/riker",
147     "to": "https://www.w3.org/ns/activitystreams#Public",
148     "cc": [
149         "https://enterprise.lemmy.ml/c/main/"
150     ],
151     "object": "https://enterprise.lemmy.ml/post/32"
152     }"#,
153     )
154     .unwrap();
155     let activity_form = ActivityForm {
156       ap_id: ap_id.to_string(),
157       user_id: inserted_creator.id,
158       data: test_json.to_owned(),
159       local: true,
160       updated: None,
161     };
162
163     let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
164
165     let expected_activity = Activity {
166       ap_id: ap_id.to_string(),
167       id: inserted_activity.id,
168       user_id: inserted_creator.id,
169       data: test_json,
170       local: true,
171       published: inserted_activity.published,
172       updated: None,
173     };
174
175     let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
176     let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, ap_id).unwrap();
177     User_::delete(&conn, inserted_creator.id).unwrap();
178
179     assert_eq!(expected_activity, read_activity);
180     assert_eq!(expected_activity, read_activity_by_apub_id);
181     assert_eq!(expected_activity, inserted_activity);
182   }
183 }