]> Untitled Git - lemmy.git/blob - src/api_routes_http.rs
Remove follow community traits (#3737)
[lemmy.git] / src / api_routes_http.rs
1 use actix_web::{guard, web, Error, HttpResponse, Result};
2 use lemmy_api::{
3   comment::{distinguish::distinguish_comment, like::like_comment, save::save_comment},
4   comment_report::{list::list_comment_reports, resolve::resolve_comment_report},
5   community::follow::follow_community,
6   local_user::notifications::mark_reply_read::mark_reply_as_read,
7   post::like::like_post,
8   Perform,
9 };
10 use lemmy_api_common::{
11   comment::CreateCommentReport,
12   community::{
13     AddModToCommunity,
14     BanFromCommunity,
15     BlockCommunity,
16     CreateCommunity,
17     DeleteCommunity,
18     EditCommunity,
19     HideCommunity,
20     RemoveCommunity,
21     TransferCommunity,
22   },
23   context::LemmyContext,
24   custom_emoji::{CreateCustomEmoji, DeleteCustomEmoji, EditCustomEmoji},
25   person::{
26     AddAdmin,
27     BanPerson,
28     BlockPerson,
29     ChangePassword,
30     DeleteAccount,
31     GetBannedPersons,
32     GetCaptcha,
33     GetPersonMentions,
34     GetReplies,
35     GetReportCount,
36     GetUnreadCount,
37     Login,
38     MarkAllAsRead,
39     MarkPersonMentionAsRead,
40     PasswordChangeAfterReset,
41     PasswordReset,
42     Register,
43     SaveUserSettings,
44     VerifyEmail,
45   },
46   post::{
47     CreatePostReport,
48     DeletePost,
49     FeaturePost,
50     GetSiteMetadata,
51     ListPostReports,
52     LockPost,
53     MarkPostAsRead,
54     RemovePost,
55     ResolvePostReport,
56     SavePost,
57   },
58   private_message::{
59     CreatePrivateMessage,
60     CreatePrivateMessageReport,
61     DeletePrivateMessage,
62     EditPrivateMessage,
63     ListPrivateMessageReports,
64     MarkPrivateMessageAsRead,
65     ResolvePrivateMessageReport,
66   },
67   site::{
68     ApproveRegistrationApplication,
69     GetFederatedInstances,
70     GetModlog,
71     GetUnreadRegistrationApplicationCount,
72     LeaveAdmin,
73     ListRegistrationApplications,
74     PurgeComment,
75     PurgeCommunity,
76     PurgePerson,
77     PurgePost,
78   },
79 };
80 use lemmy_api_crud::{
81   comment::{
82     create::create_comment,
83     delete::delete_comment,
84     read::get_comment,
85     remove::remove_comment,
86     update::update_comment,
87   },
88   community::list::list_communities,
89   post::{create::create_post, read::get_post, update::update_post},
90   private_message::read::get_private_message,
91   site::{create::create_site, read::get_site, update::update_site},
92   PerformCrud,
93 };
94 use lemmy_apub::{
95   api::{
96     list_comments::list_comments,
97     list_posts::list_posts,
98     read_community::get_community,
99     read_person::read_person,
100     resolve_object::resolve_object,
101     search::search,
102   },
103   SendActivity,
104 };
105 use lemmy_utils::{rate_limit::RateLimitCell, spawn_try_task, SYNCHRONOUS_FEDERATION};
106 use serde::Deserialize;
107
108 pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
109   cfg.service(
110     web::scope("/api/v3")
111       // Site
112       .service(
113         web::scope("/site")
114           .wrap(rate_limit.message())
115           .route("", web::get().to(get_site))
116           // Admin Actions
117           .route("", web::post().to(create_site))
118           .route("", web::put().to(update_site)),
119       )
120       .service(
121         web::resource("/modlog")
122           .wrap(rate_limit.message())
123           .route(web::get().to(route_get::<GetModlog>)),
124       )
125       .service(
126         web::resource("/search")
127           .wrap(rate_limit.search())
128           .route(web::get().to(search)),
129       )
130       .service(
131         web::resource("/resolve_object")
132           .wrap(rate_limit.message())
133           .route(web::get().to(resolve_object)),
134       )
135       // Community
136       .service(
137         web::resource("/community")
138           .guard(guard::Post())
139           .wrap(rate_limit.register())
140           .route(web::post().to(route_post_crud::<CreateCommunity>)),
141       )
142       .service(
143         web::scope("/community")
144           .wrap(rate_limit.message())
145           .route("", web::get().to(get_community))
146           .route("", web::put().to(route_post_crud::<EditCommunity>))
147           .route("/hide", web::put().to(route_post::<HideCommunity>))
148           .route("/list", web::get().to(list_communities))
149           .route("/follow", web::post().to(follow_community))
150           .route("/block", web::post().to(route_post::<BlockCommunity>))
151           .route(
152             "/delete",
153             web::post().to(route_post_crud::<DeleteCommunity>),
154           )
155           // Mod Actions
156           .route(
157             "/remove",
158             web::post().to(route_post_crud::<RemoveCommunity>),
159           )
160           .route("/transfer", web::post().to(route_post::<TransferCommunity>))
161           .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
162           .route("/mod", web::post().to(route_post::<AddModToCommunity>)),
163       )
164       .service(
165         web::scope("/federated_instances")
166           .wrap(rate_limit.message())
167           .route("", web::get().to(route_get::<GetFederatedInstances>)),
168       )
169       // Post
170       .service(
171         // Handle POST to /post separately to add the post() rate limitter
172         web::resource("/post")
173           .guard(guard::Post())
174           .wrap(rate_limit.post())
175           .route(web::post().to(create_post)),
176       )
177       .service(
178         web::scope("/post")
179           .wrap(rate_limit.message())
180           .route("", web::get().to(get_post))
181           .route("", web::put().to(update_post))
182           .route("/delete", web::post().to(route_post_crud::<DeletePost>))
183           .route("/remove", web::post().to(route_post_crud::<RemovePost>))
184           .route(
185             "/mark_as_read",
186             web::post().to(route_post::<MarkPostAsRead>),
187           )
188           .route("/lock", web::post().to(route_post::<LockPost>))
189           .route("/feature", web::post().to(route_post::<FeaturePost>))
190           .route("/list", web::get().to(list_posts))
191           .route("/like", web::post().to(like_post))
192           .route("/save", web::put().to(route_post::<SavePost>))
193           .route("/report", web::post().to(route_post::<CreatePostReport>))
194           .route(
195             "/report/resolve",
196             web::put().to(route_post::<ResolvePostReport>),
197           )
198           .route("/report/list", web::get().to(route_get::<ListPostReports>))
199           .route(
200             "/site_metadata",
201             web::get().to(route_get::<GetSiteMetadata>),
202           ),
203       )
204       // Comment
205       .service(
206         // Handle POST to /comment separately to add the comment() rate limitter
207         web::resource("/comment")
208           .guard(guard::Post())
209           .wrap(rate_limit.comment())
210           .route(web::post().to(create_comment)),
211       )
212       .service(
213         web::scope("/comment")
214           .wrap(rate_limit.message())
215           .route("", web::get().to(get_comment))
216           .route("", web::put().to(update_comment))
217           .route("/delete", web::post().to(delete_comment))
218           .route("/remove", web::post().to(remove_comment))
219           .route("/mark_as_read", web::post().to(mark_reply_as_read))
220           .route("/distinguish", web::post().to(distinguish_comment))
221           .route("/like", web::post().to(like_comment))
222           .route("/save", web::put().to(save_comment))
223           .route("/list", web::get().to(list_comments))
224           .route("/report", web::post().to(route_post::<CreateCommentReport>))
225           .route("/report/resolve", web::put().to(resolve_comment_report))
226           .route("/report/list", web::get().to(list_comment_reports)),
227       )
228       // Private Message
229       .service(
230         web::scope("/private_message")
231           .wrap(rate_limit.message())
232           .route("/list", web::get().to(get_private_message))
233           .route("", web::post().to(route_post_crud::<CreatePrivateMessage>))
234           .route("", web::put().to(route_post_crud::<EditPrivateMessage>))
235           .route(
236             "/delete",
237             web::post().to(route_post_crud::<DeletePrivateMessage>),
238           )
239           .route(
240             "/mark_as_read",
241             web::post().to(route_post::<MarkPrivateMessageAsRead>),
242           )
243           .route(
244             "/report",
245             web::post().to(route_post::<CreatePrivateMessageReport>),
246           )
247           .route(
248             "/report/resolve",
249             web::put().to(route_post::<ResolvePrivateMessageReport>),
250           )
251           .route(
252             "/report/list",
253             web::get().to(route_get::<ListPrivateMessageReports>),
254           ),
255       )
256       // User
257       .service(
258         // Account action, I don't like that it's in /user maybe /accounts
259         // Handle /user/register separately to add the register() rate limitter
260         web::resource("/user/register")
261           .guard(guard::Post())
262           .wrap(rate_limit.register())
263           .route(web::post().to(route_post_crud::<Register>)),
264       )
265       .service(
266         // Handle captcha separately
267         web::resource("/user/get_captcha")
268           .wrap(rate_limit.post())
269           .route(web::get().to(route_get::<GetCaptcha>)),
270       )
271       // User actions
272       .service(
273         web::scope("/user")
274           .wrap(rate_limit.message())
275           .route("", web::get().to(read_person))
276           .route("/mention", web::get().to(route_get::<GetPersonMentions>))
277           .route(
278             "/mention/mark_as_read",
279             web::post().to(route_post::<MarkPersonMentionAsRead>),
280           )
281           .route("/replies", web::get().to(route_get::<GetReplies>))
282           // Admin action. I don't like that it's in /user
283           .route("/ban", web::post().to(route_post::<BanPerson>))
284           .route("/banned", web::get().to(route_get::<GetBannedPersons>))
285           .route("/block", web::post().to(route_post::<BlockPerson>))
286           // Account actions. I don't like that they're in /user maybe /accounts
287           .route("/login", web::post().to(route_post::<Login>))
288           .route(
289             "/delete_account",
290             web::post().to(route_post_crud::<DeleteAccount>),
291           )
292           .route(
293             "/password_reset",
294             web::post().to(route_post::<PasswordReset>),
295           )
296           .route(
297             "/password_change",
298             web::post().to(route_post::<PasswordChangeAfterReset>),
299           )
300           // mark_all_as_read feels off being in this section as well
301           .route(
302             "/mark_all_as_read",
303             web::post().to(route_post::<MarkAllAsRead>),
304           )
305           .route(
306             "/save_user_settings",
307             web::put().to(route_post::<SaveUserSettings>),
308           )
309           .route(
310             "/change_password",
311             web::put().to(route_post::<ChangePassword>),
312           )
313           .route("/report_count", web::get().to(route_get::<GetReportCount>))
314           .route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
315           .route("/verify_email", web::post().to(route_post::<VerifyEmail>))
316           .route("/leave_admin", web::post().to(route_post::<LeaveAdmin>)),
317       )
318       // Admin Actions
319       .service(
320         web::scope("/admin")
321           .wrap(rate_limit.message())
322           .route("/add", web::post().to(route_post::<AddAdmin>))
323           .route(
324             "/registration_application/count",
325             web::get().to(route_get::<GetUnreadRegistrationApplicationCount>),
326           )
327           .route(
328             "/registration_application/list",
329             web::get().to(route_get::<ListRegistrationApplications>),
330           )
331           .route(
332             "/registration_application/approve",
333             web::put().to(route_post::<ApproveRegistrationApplication>),
334           )
335           .service(
336             web::scope("/purge")
337               .route("/person", web::post().to(route_post::<PurgePerson>))
338               .route("/community", web::post().to(route_post::<PurgeCommunity>))
339               .route("/post", web::post().to(route_post::<PurgePost>))
340               .route("/comment", web::post().to(route_post::<PurgeComment>)),
341           ),
342       )
343       .service(
344         web::scope("/custom_emoji")
345           .wrap(rate_limit.message())
346           .route("", web::post().to(route_post_crud::<CreateCustomEmoji>))
347           .route("", web::put().to(route_post_crud::<EditCustomEmoji>))
348           .route(
349             "/delete",
350             web::post().to(route_post_crud::<DeleteCustomEmoji>),
351           ),
352       ),
353   );
354 }
355
356 async fn perform<'a, Data>(
357   data: Data,
358   context: web::Data<LemmyContext>,
359   apub_data: activitypub_federation::config::Data<LemmyContext>,
360 ) -> Result<HttpResponse, Error>
361 where
362   Data: Perform
363     + SendActivity<Response = <Data as Perform>::Response>
364     + Clone
365     + Deserialize<'a>
366     + Send
367     + 'static,
368 {
369   let res = data.perform(&context).await?;
370   let res_clone = res.clone();
371   let fed_task = async move { SendActivity::send_activity(&data, &res_clone, &apub_data).await };
372   if *SYNCHRONOUS_FEDERATION {
373     fed_task.await?;
374   } else {
375     spawn_try_task(fed_task);
376   }
377   Ok(HttpResponse::Ok().json(&res))
378 }
379
380 async fn route_get<'a, Data>(
381   data: web::Query<Data>,
382   context: web::Data<LemmyContext>,
383   apub_data: activitypub_federation::config::Data<LemmyContext>,
384 ) -> Result<HttpResponse, Error>
385 where
386   Data: Perform
387     + SendActivity<Response = <Data as Perform>::Response>
388     + Clone
389     + Deserialize<'a>
390     + Send
391     + 'static,
392 {
393   perform::<Data>(data.0, context, apub_data).await
394 }
395
396 async fn route_post<'a, Data>(
397   data: web::Json<Data>,
398   context: web::Data<LemmyContext>,
399   apub_data: activitypub_federation::config::Data<LemmyContext>,
400 ) -> Result<HttpResponse, Error>
401 where
402   Data: Perform
403     + SendActivity<Response = <Data as Perform>::Response>
404     + Clone
405     + Deserialize<'a>
406     + Send
407     + 'static,
408 {
409   perform::<Data>(data.0, context, apub_data).await
410 }
411
412 async fn perform_crud<'a, Data>(
413   data: Data,
414   context: web::Data<LemmyContext>,
415   apub_data: activitypub_federation::config::Data<LemmyContext>,
416 ) -> Result<HttpResponse, Error>
417 where
418   Data: PerformCrud
419     + SendActivity<Response = <Data as PerformCrud>::Response>
420     + Clone
421     + Deserialize<'a>
422     + Send
423     + 'static,
424 {
425   let res = data.perform(&context).await?;
426   let res_clone = res.clone();
427   let fed_task = async move { SendActivity::send_activity(&data, &res_clone, &apub_data).await };
428   if *SYNCHRONOUS_FEDERATION {
429     fed_task.await?;
430   } else {
431     spawn_try_task(fed_task);
432   }
433   Ok(HttpResponse::Ok().json(&res))
434 }
435
436 async fn route_post_crud<'a, Data>(
437   data: web::Json<Data>,
438   context: web::Data<LemmyContext>,
439   apub_data: activitypub_federation::config::Data<LemmyContext>,
440 ) -> Result<HttpResponse, Error>
441 where
442   Data: PerformCrud
443     + SendActivity<Response = <Data as PerformCrud>::Response>
444     + Clone
445     + Deserialize<'a>
446     + Send
447     + 'static,
448 {
449   perform_crud::<Data>(data.0, context, apub_data).await
450 }