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