]> Untitled Git - lemmy.git/blob - src/code_migrations.rs
2feefbdfb82909b6ef93ea3aa4233253e5be759d
[lemmy.git] / src / code_migrations.rs
1 // This is for db migrations that require code
2 use diesel::{
3   sql_types::{Nullable, Text},
4   *,
5 };
6 use lemmy_apub::{
7   generate_followers_url,
8   generate_inbox_url,
9   generate_local_apub_endpoint,
10   generate_shared_inbox_url,
11   EndpointType,
12 };
13 use lemmy_db_schema::{
14   naive_now,
15   source::{
16     comment::Comment,
17     community::{Community, CommunityForm},
18     person::{Person, PersonForm},
19     post::Post,
20     private_message::PrivateMessage,
21   },
22   traits::Crud,
23 };
24 use lemmy_utils::{apub::generate_actor_keypair, LemmyError};
25 use log::info;
26
27 pub fn run_advanced_migrations(
28   conn: &PgConnection,
29   protocol_and_hostname: &str,
30 ) -> Result<(), LemmyError> {
31   user_updates_2020_04_02(conn, protocol_and_hostname)?;
32   community_updates_2020_04_02(conn, protocol_and_hostname)?;
33   post_updates_2020_04_03(conn, protocol_and_hostname)?;
34   comment_updates_2020_04_03(conn, protocol_and_hostname)?;
35   private_message_updates_2020_05_05(conn, protocol_and_hostname)?;
36   post_thumbnail_url_updates_2020_07_27(conn, protocol_and_hostname)?;
37   apub_columns_2021_02_02(conn)?;
38
39   Ok(())
40 }
41
42 fn user_updates_2020_04_02(
43   conn: &PgConnection,
44   protocol_and_hostname: &str,
45 ) -> Result<(), LemmyError> {
46   use lemmy_db_schema::schema::person::dsl::*;
47
48   info!("Running user_updates_2020_04_02");
49
50   // Update the actor_id, private_key, and public_key, last_refreshed_at
51   let incorrect_persons = person
52     .filter(actor_id.like("http://changeme_%"))
53     .filter(local.eq(true))
54     .load::<Person>(conn)?;
55
56   for cperson in &incorrect_persons {
57     let keypair = generate_actor_keypair()?;
58
59     let form = PersonForm {
60       name: cperson.name.to_owned(),
61       actor_id: Some(generate_local_apub_endpoint(
62         EndpointType::Person,
63         &cperson.name,
64         protocol_and_hostname,
65       )?),
66       private_key: Some(Some(keypair.private_key)),
67       public_key: Some(Some(keypair.public_key)),
68       last_refreshed_at: Some(naive_now()),
69       ..PersonForm::default()
70     };
71
72     Person::update(conn, cperson.id, &form)?;
73   }
74
75   info!("{} person rows updated.", incorrect_persons.len());
76
77   Ok(())
78 }
79
80 fn community_updates_2020_04_02(
81   conn: &PgConnection,
82   protocol_and_hostname: &str,
83 ) -> Result<(), LemmyError> {
84   use lemmy_db_schema::schema::community::dsl::*;
85
86   info!("Running community_updates_2020_04_02");
87
88   // Update the actor_id, private_key, and public_key, last_refreshed_at
89   let incorrect_communities = community
90     .filter(actor_id.like("http://changeme_%"))
91     .filter(local.eq(true))
92     .load::<Community>(conn)?;
93
94   for ccommunity in &incorrect_communities {
95     let keypair = generate_actor_keypair()?;
96     let community_actor_id = generate_local_apub_endpoint(
97       EndpointType::Community,
98       &ccommunity.name,
99       protocol_and_hostname,
100     )?;
101
102     let form = CommunityForm {
103       name: ccommunity.name.to_owned(),
104       title: ccommunity.title.to_owned(),
105       description: ccommunity.description.to_owned(),
106       removed: None,
107       deleted: None,
108       nsfw: None,
109       updated: None,
110       actor_id: Some(community_actor_id.to_owned()),
111       local: Some(ccommunity.local),
112       private_key: Some(keypair.private_key),
113       public_key: Some(keypair.public_key),
114       last_refreshed_at: Some(naive_now()),
115       published: None,
116       icon: Some(ccommunity.icon.to_owned()),
117       banner: Some(ccommunity.banner.to_owned()),
118       followers_url: None,
119       inbox_url: None,
120       shared_inbox_url: None,
121     };
122
123     Community::update(conn, ccommunity.id, &form)?;
124   }
125
126   info!("{} community rows updated.", incorrect_communities.len());
127
128   Ok(())
129 }
130
131 fn post_updates_2020_04_03(
132   conn: &PgConnection,
133   protocol_and_hostname: &str,
134 ) -> Result<(), LemmyError> {
135   use lemmy_db_schema::schema::post::dsl::*;
136
137   info!("Running post_updates_2020_04_03");
138
139   // Update the ap_id
140   let incorrect_posts = post
141     .filter(ap_id.like("http://changeme_%"))
142     .filter(local.eq(true))
143     .load::<Post>(conn)?;
144
145   for cpost in &incorrect_posts {
146     let apub_id = generate_local_apub_endpoint(
147       EndpointType::Post,
148       &cpost.id.to_string(),
149       protocol_and_hostname,
150     )?;
151     Post::update_ap_id(conn, cpost.id, apub_id)?;
152   }
153
154   info!("{} post rows updated.", incorrect_posts.len());
155
156   Ok(())
157 }
158
159 fn comment_updates_2020_04_03(
160   conn: &PgConnection,
161   protocol_and_hostname: &str,
162 ) -> Result<(), LemmyError> {
163   use lemmy_db_schema::schema::comment::dsl::*;
164
165   info!("Running comment_updates_2020_04_03");
166
167   // Update the ap_id
168   let incorrect_comments = comment
169     .filter(ap_id.like("http://changeme_%"))
170     .filter(local.eq(true))
171     .load::<Comment>(conn)?;
172
173   for ccomment in &incorrect_comments {
174     let apub_id = generate_local_apub_endpoint(
175       EndpointType::Comment,
176       &ccomment.id.to_string(),
177       protocol_and_hostname,
178     )?;
179     Comment::update_ap_id(conn, ccomment.id, apub_id)?;
180   }
181
182   info!("{} comment rows updated.", incorrect_comments.len());
183
184   Ok(())
185 }
186
187 fn private_message_updates_2020_05_05(
188   conn: &PgConnection,
189   protocol_and_hostname: &str,
190 ) -> Result<(), LemmyError> {
191   use lemmy_db_schema::schema::private_message::dsl::*;
192
193   info!("Running private_message_updates_2020_05_05");
194
195   // Update the ap_id
196   let incorrect_pms = private_message
197     .filter(ap_id.like("http://changeme_%"))
198     .filter(local.eq(true))
199     .load::<PrivateMessage>(conn)?;
200
201   for cpm in &incorrect_pms {
202     let apub_id = generate_local_apub_endpoint(
203       EndpointType::PrivateMessage,
204       &cpm.id.to_string(),
205       protocol_and_hostname,
206     )?;
207     PrivateMessage::update_ap_id(conn, cpm.id, apub_id)?;
208   }
209
210   info!("{} private message rows updated.", incorrect_pms.len());
211
212   Ok(())
213 }
214
215 fn post_thumbnail_url_updates_2020_07_27(
216   conn: &PgConnection,
217   protocol_and_hostname: &str,
218 ) -> Result<(), LemmyError> {
219   use lemmy_db_schema::schema::post::dsl::*;
220
221   info!("Running post_thumbnail_url_updates_2020_07_27");
222
223   let domain_prefix = format!("{}/pictrs/image/", protocol_and_hostname,);
224
225   let incorrect_thumbnails = post.filter(thumbnail_url.not_like("http%"));
226
227   // Prepend the rows with the update
228   let res = diesel::update(incorrect_thumbnails)
229     .set(
230       thumbnail_url.eq(
231         domain_prefix
232           .into_sql::<Nullable<Text>>()
233           .concat(thumbnail_url),
234       ),
235     )
236     .get_results::<Post>(conn)?;
237
238   info!("{} Post thumbnail_url rows updated.", res.len());
239
240   Ok(())
241 }
242
243 /// We are setting inbox and follower URLs for local and remote actors alike, because for now
244 /// all federated instances are also Lemmy and use the same URL scheme.
245 fn apub_columns_2021_02_02(conn: &PgConnection) -> Result<(), LemmyError> {
246   info!("Running apub_columns_2021_02_02");
247   {
248     use lemmy_db_schema::schema::person::dsl::*;
249     let persons = person
250       .filter(inbox_url.like("http://changeme_%"))
251       .load::<Person>(conn)?;
252
253     for p in &persons {
254       let inbox_url_ = generate_inbox_url(&p.actor_id)?;
255       let shared_inbox_url_ = generate_shared_inbox_url(&p.actor_id)?;
256       diesel::update(person.find(p.id))
257         .set((
258           inbox_url.eq(inbox_url_),
259           shared_inbox_url.eq(shared_inbox_url_),
260         ))
261         .get_result::<Person>(conn)?;
262     }
263   }
264
265   {
266     use lemmy_db_schema::schema::community::dsl::*;
267     let communities = community
268       .filter(inbox_url.like("http://changeme_%"))
269       .load::<Community>(conn)?;
270
271     for c in &communities {
272       let followers_url_ = generate_followers_url(&c.actor_id)?;
273       let inbox_url_ = generate_inbox_url(&c.actor_id)?;
274       let shared_inbox_url_ = generate_shared_inbox_url(&c.actor_id)?;
275       diesel::update(community.find(c.id))
276         .set((
277           followers_url.eq(followers_url_),
278           inbox_url.eq(inbox_url_),
279           shared_inbox_url.eq(shared_inbox_url_),
280         ))
281         .get_result::<Community>(conn)?;
282     }
283   }
284
285   Ok(())
286 }