1 use crate::api_routes_websocket::websocket;
2 use actix_web::{guard, web, Error, HttpResponse, Result};
3 use lemmy_api::Perform;
4 use lemmy_api_common::{
33 context::LemmyContext,
49 MarkCommentReplyAsRead,
50 MarkPersonMentionAsRead,
51 PasswordChangeAfterReset,
76 CreatePrivateMessageReport,
80 ListPrivateMessageReports,
81 MarkPrivateMessageAsRead,
82 ResolvePrivateMessageReport,
85 ApproveRegistrationApplication,
90 GetUnreadRegistrationApplicationCount,
92 ListRegistrationApplications,
100 websocket::structs::{CommunityJoin, ModJoin, PostJoin, UserJoin},
102 use lemmy_api_crud::PerformCrud;
103 use lemmy_apub::{api::PerformApub, SendActivity};
104 use lemmy_utils::rate_limit::RateLimitCell;
105 use serde::Deserialize;
107 pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
109 web::scope("/api/v3")
111 .service(web::resource("/ws").to(websocket))
115 .wrap(rate_limit.message())
116 .route("", web::get().to(route_get_crud::<GetSite>))
118 .route("", web::post().to(route_post_crud::<CreateSite>))
119 .route("", web::put().to(route_post_crud::<EditSite>)),
122 web::resource("/modlog")
123 .wrap(rate_limit.message())
124 .route(web::get().to(route_get::<GetModlog>)),
127 web::resource("/search")
128 .wrap(rate_limit.search())
129 .route(web::get().to(route_get_apub::<Search>)),
132 web::resource("/resolve_object")
133 .wrap(rate_limit.message())
134 .route(web::get().to(route_get_apub::<ResolveObject>)),
138 web::resource("/community")
139 .guard(guard::Post())
140 .wrap(rate_limit.register())
141 .route(web::post().to(route_post_crud::<CreateCommunity>)),
144 web::scope("/community")
145 .wrap(rate_limit.message())
146 .route("", web::get().to(route_get_apub::<GetCommunity>))
147 .route("", web::put().to(route_post_crud::<EditCommunity>))
148 .route("/hide", web::put().to(route_post::<HideCommunity>))
149 .route("/list", web::get().to(route_get_crud::<ListCommunities>))
150 .route("/follow", web::post().to(route_post::<FollowCommunity>))
151 .route("/block", web::post().to(route_post::<BlockCommunity>))
154 web::post().to(route_post_crud::<DeleteCommunity>),
159 web::post().to(route_post_crud::<RemoveCommunity>),
161 .route("/transfer", web::post().to(route_post::<TransferCommunity>))
162 .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
163 .route("/mod", web::post().to(route_post::<AddModToCommunity>))
164 .route("/join", web::post().to(route_post::<CommunityJoin>))
165 .route("/mod/join", web::post().to(route_post::<ModJoin>)),
169 // Handle POST to /post separately to add the post() rate limitter
170 web::resource("/post")
171 .guard(guard::Post())
172 .wrap(rate_limit.post())
173 .route(web::post().to(route_post_crud::<CreatePost>)),
177 .wrap(rate_limit.message())
178 .route("", web::get().to(route_get_crud::<GetPost>))
179 .route("", web::put().to(route_post_crud::<EditPost>))
180 .route("/delete", web::post().to(route_post_crud::<DeletePost>))
181 .route("/remove", web::post().to(route_post_crud::<RemovePost>))
184 web::post().to(route_post::<MarkPostAsRead>),
186 .route("/lock", web::post().to(route_post::<LockPost>))
187 .route("/feature", web::post().to(route_post::<FeaturePost>))
188 .route("/list", web::get().to(route_get_apub::<GetPosts>))
189 .route("/like", web::post().to(route_post::<CreatePostLike>))
190 .route("/save", web::put().to(route_post::<SavePost>))
191 .route("/join", web::post().to(route_post::<PostJoin>))
192 .route("/report", web::post().to(route_post::<CreatePostReport>))
195 web::put().to(route_post::<ResolvePostReport>),
197 .route("/report/list", web::get().to(route_get::<ListPostReports>))
200 web::get().to(route_get::<GetSiteMetadata>),
205 // Handle POST to /comment separately to add the comment() rate limitter
206 web::resource("/comment")
207 .guard(guard::Post())
208 .wrap(rate_limit.comment())
209 .route(web::post().to(route_post_crud::<CreateComment>)),
212 web::scope("/comment")
213 .wrap(rate_limit.message())
214 .route("", web::get().to(route_get_crud::<GetComment>))
215 .route("", web::put().to(route_post_crud::<EditComment>))
216 .route("/delete", web::post().to(route_post_crud::<DeleteComment>))
217 .route("/remove", web::post().to(route_post_crud::<RemoveComment>))
220 web::post().to(route_post::<MarkCommentReplyAsRead>),
224 web::post().to(route_post::<DistinguishComment>),
226 .route("/like", web::post().to(route_post::<CreateCommentLike>))
227 .route("/save", web::put().to(route_post::<SaveComment>))
228 .route("/list", web::get().to(route_get_apub::<GetComments>))
229 .route("/report", web::post().to(route_post::<CreateCommentReport>))
232 web::put().to(route_post::<ResolveCommentReport>),
236 web::get().to(route_get::<ListCommentReports>),
241 web::scope("/private_message")
242 .wrap(rate_limit.message())
243 .route("/list", web::get().to(route_get_crud::<GetPrivateMessages>))
244 .route("", web::post().to(route_post_crud::<CreatePrivateMessage>))
245 .route("", web::put().to(route_post_crud::<EditPrivateMessage>))
248 web::post().to(route_post_crud::<DeletePrivateMessage>),
252 web::post().to(route_post::<MarkPrivateMessageAsRead>),
256 web::post().to(route_post::<CreatePrivateMessageReport>),
260 web::put().to(route_post::<ResolvePrivateMessageReport>),
264 web::get().to(route_get::<ListPrivateMessageReports>),
269 // Account action, I don't like that it's in /user maybe /accounts
270 // Handle /user/register separately to add the register() rate limitter
271 web::resource("/user/register")
272 .guard(guard::Post())
273 .wrap(rate_limit.register())
274 .route(web::post().to(route_post_crud::<Register>)),
277 // Handle captcha separately
278 web::resource("/user/get_captcha")
279 .wrap(rate_limit.post())
280 .route(web::get().to(route_get::<GetCaptcha>)),
285 .wrap(rate_limit.message())
286 .route("", web::get().to(route_get_apub::<GetPersonDetails>))
287 .route("/mention", web::get().to(route_get::<GetPersonMentions>))
289 "/mention/mark_as_read",
290 web::post().to(route_post::<MarkPersonMentionAsRead>),
292 .route("/replies", web::get().to(route_get::<GetReplies>))
293 .route("/join", web::post().to(route_post::<UserJoin>))
294 // Admin action. I don't like that it's in /user
295 .route("/ban", web::post().to(route_post::<BanPerson>))
296 .route("/banned", web::get().to(route_get::<GetBannedPersons>))
297 .route("/block", web::post().to(route_post::<BlockPerson>))
298 // Account actions. I don't like that they're in /user maybe /accounts
299 .route("/login", web::post().to(route_post::<Login>))
302 web::post().to(route_post_crud::<DeleteAccount>),
306 web::post().to(route_post::<PasswordReset>),
310 web::post().to(route_post::<PasswordChangeAfterReset>),
312 // mark_all_as_read feels off being in this section as well
315 web::post().to(route_post::<MarkAllAsRead>),
318 "/save_user_settings",
319 web::put().to(route_post::<SaveUserSettings>),
323 web::put().to(route_post::<ChangePassword>),
325 .route("/report_count", web::get().to(route_get::<GetReportCount>))
326 .route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
327 .route("/verify_email", web::post().to(route_post::<VerifyEmail>))
328 .route("/leave_admin", web::post().to(route_post::<LeaveAdmin>)),
333 .wrap(rate_limit.message())
334 .route("/add", web::post().to(route_post::<AddAdmin>))
336 "/registration_application/count",
337 web::get().to(route_get::<GetUnreadRegistrationApplicationCount>),
340 "/registration_application/list",
341 web::get().to(route_get::<ListRegistrationApplications>),
344 "/registration_application/approve",
345 web::put().to(route_post::<ApproveRegistrationApplication>),
349 web::scope("/admin/purge")
350 .wrap(rate_limit.message())
351 .route("/person", web::post().to(route_post::<PurgePerson>))
352 .route("/community", web::post().to(route_post::<PurgeCommunity>))
353 .route("/post", web::post().to(route_post::<PurgePost>))
354 .route("/comment", web::post().to(route_post::<PurgeComment>)),
359 async fn perform<'a, Data>(
361 context: web::Data<LemmyContext>,
362 ) -> Result<HttpResponse, Error>
365 + SendActivity<Response = <Data as Perform>::Response>
371 let res = data.perform(&context, None).await?;
372 SendActivity::send_activity(&data, &res, &context).await?;
373 Ok(HttpResponse::Ok().json(res))
376 async fn route_get<'a, Data>(
377 data: web::Query<Data>,
378 context: web::Data<LemmyContext>,
379 ) -> Result<HttpResponse, Error>
382 + SendActivity<Response = <Data as Perform>::Response>
388 perform::<Data>(data.0, context).await
391 async fn route_get_apub<'a, Data>(
392 data: web::Query<Data>,
393 context: web::Data<LemmyContext>,
394 ) -> Result<HttpResponse, Error>
397 + SendActivity<Response = <Data as PerformApub>::Response>
403 let res = data.perform(&context, None).await?;
404 SendActivity::send_activity(&data.0, &res, &context).await?;
405 Ok(HttpResponse::Ok().json(res))
408 async fn route_post<'a, Data>(
409 data: web::Json<Data>,
410 context: web::Data<LemmyContext>,
411 ) -> Result<HttpResponse, Error>
414 + SendActivity<Response = <Data as Perform>::Response>
420 perform::<Data>(data.0, context).await
423 async fn perform_crud<'a, Data>(
425 context: web::Data<LemmyContext>,
426 ) -> Result<HttpResponse, Error>
429 + SendActivity<Response = <Data as PerformCrud>::Response>
435 let res = data.perform(&context, None).await?;
436 SendActivity::send_activity(&data, &res, &context).await?;
437 Ok(HttpResponse::Ok().json(res))
440 async fn route_get_crud<'a, Data>(
441 data: web::Query<Data>,
442 context: web::Data<LemmyContext>,
443 ) -> Result<HttpResponse, Error>
446 + SendActivity<Response = <Data as PerformCrud>::Response>
452 perform_crud::<Data>(data.0, context).await
455 async fn route_post_crud<'a, Data>(
456 data: web::Json<Data>,
457 context: web::Data<LemmyContext>,
458 ) -> Result<HttpResponse, Error>
461 + SendActivity<Response = <Data as PerformCrud>::Response>
467 perform_crud::<Data>(data.0, context).await