diff --git a/crates/api/src/site/leave_admin.rs b/crates/api/src/site/leave_admin.rs index a22b898c6..cb59bb10d 100644 --- a/crates/api/src/site/leave_admin.rs +++ b/crates/api/src/site/leave_admin.rs @@ -75,5 +75,6 @@ pub async fn leave_admin( admin_oauth_providers: None, blocked_urls, tagline, + my_user: None, })) } diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index 838214406..f23fa27ef 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -448,6 +448,8 @@ pub struct GetSiteResponse { pub site_view: SiteView, pub admins: Vec, pub version: String, + #[cfg_attr(feature = "full", ts(optional))] + pub my_user: Option, pub all_languages: Vec, pub discussion_languages: Vec, /// If the site has any taglines, a random one is included here for displaying diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index 2954bbb14..220fe1bd5 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -1,3 +1,4 @@ +use crate::user::my_user::get_my_user; use actix_web::web::{Data, Json}; use lemmy_api_common::{context::LemmyContext, site::GetSiteResponse}; use lemmy_db_schema::source::{ @@ -13,7 +14,19 @@ use lemmy_utils::{build_cache, error::LemmyResult, CacheLock, VERSION}; use std::sync::LazyLock; #[tracing::instrument(skip(context))] -pub async fn get_site( +pub async fn get_site_v3( + local_user_view: Option, + context: Data, +) -> LemmyResult> { + let mut site = get_site_v4(local_user_view.clone(), context.clone()).await?; + if let Some(local_user_view) = local_user_view { + site.my_user = Some(get_my_user(local_user_view, context).await?.0); + } + Ok(site) +} + +#[tracing::instrument(skip(context))] +pub async fn get_site_v4( local_user_view: Option, context: Data, ) -> LemmyResult> { @@ -56,7 +69,5 @@ async fn read_site(context: &LemmyContext) -> LemmyResult { tagline, oauth_providers: Some(oauth_providers), admin_oauth_providers: Some(admin_oauth_providers), - taglines: vec![], - custom_emojis: vec![], }) } diff --git a/src/api_routes_v3.rs b/src/api_routes_v3.rs new file mode 100644 index 000000000..a36f8b7b1 --- /dev/null +++ b/src/api_routes_v3.rs @@ -0,0 +1,443 @@ +use actix_web::{guard, web}; +use lemmy_api::{ + comment::{ + distinguish::distinguish_comment, + like::like_comment, + list_comment_likes::list_comment_likes, + save::save_comment, + }, + comment_report::{ + create::create_comment_report, + list::list_comment_reports, + resolve::resolve_comment_report, + }, + community::{ + add_mod::add_mod_to_community, + ban::ban_from_community, + block::block_community, + follow::follow_community, + hide::hide_community, + pending_follows::{ + approve::post_pending_follows_approve, + count::get_pending_follows_count, + list::get_pending_follows_list, + }, + random::get_random_community, + transfer::transfer_community, + }, + local_user::{ + add_admin::add_admin, + ban_person::ban_from_site, + block::block_person, + change_password::change_password, + change_password_after_reset::change_password_after_reset, + generate_totp_secret::generate_totp_secret, + get_captcha::get_captcha, + list_banned::list_banned_users, + list_logins::list_logins, + list_media::list_media, + login::login, + logout::logout, + notifications::{ + list_mentions::list_mentions, + list_replies::list_replies, + mark_all_read::mark_all_notifications_read, + mark_mention_read::mark_person_mention_as_read, + mark_reply_read::mark_reply_as_read, + unread_count::unread_count, + }, + report_count::report_count, + reset_password::reset_password, + save_settings::save_user_settings, + update_totp::update_totp, + validate_auth::validate_auth, + verify_email::verify_email, + }, + post::{ + feature::feature_post, + get_link_metadata::get_link_metadata, + hide::hide_post, + like::like_post, + list_post_likes::list_post_likes, + lock::lock_post, + mark_many_read::mark_posts_as_read, + mark_read::mark_post_as_read, + save::save_post, + }, + post_report::{ + create::create_post_report, + list::list_post_reports, + resolve::resolve_post_report, + }, + private_message::mark_read::mark_pm_as_read, + private_message_report::{ + create::create_pm_report, + list::list_pm_reports, + resolve::resolve_pm_report, + }, + site::{ + block::block_instance, + federated_instances::get_federated_instances, + leave_admin::leave_admin, + list_all_media::list_all_media, + mod_log::get_mod_log, + purge::{ + comment::purge_comment, + community::purge_community, + person::purge_person, + post::purge_post, + }, + registration_applications::{ + approve::approve_registration_application, + get::get_registration_application, + list::list_registration_applications, + unread_count::get_unread_registration_application_count, + }, + }, + sitemap::get_sitemap, +}; +use lemmy_api_crud::{ + comment::{ + create::create_comment, + delete::delete_comment, + read::get_comment, + remove::remove_comment, + update::update_comment, + }, + community::{ + create::create_community, + delete::delete_community, + list::list_communities, + remove::remove_community, + update::update_community, + }, + custom_emoji::{ + create::create_custom_emoji, + delete::delete_custom_emoji, + list::list_custom_emojis, + update::update_custom_emoji, + }, + oauth_provider::{ + create::create_oauth_provider, + delete::delete_oauth_provider, + update::update_oauth_provider, + }, + post::{ + create::create_post, + delete::delete_post, + read::get_post, + remove::remove_post, + update::update_post, + }, + private_message::{ + create::create_private_message, + delete::delete_private_message, + read::get_private_message, + update::update_private_message, + }, + site::{create::create_site, read::get_site_v3, update::update_site}, + tagline::{ + create::create_tagline, + delete::delete_tagline, + list::list_taglines, + update::update_tagline, + }, + user::{ + create::{authenticate_with_oauth, register}, + delete::delete_account, + }, +}; +use lemmy_apub::api::{ + list_comments::list_comments, + list_posts::list_posts, + read_community::get_community, + read_person::read_person, + resolve_object::resolve_object, + search::search, + user_settings_backup::{export_settings, import_settings}, +}; +use lemmy_routes::images::image_proxy; +use lemmy_utils::rate_limit::RateLimitCell; + +pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { + cfg.service( + web::scope("/api/v3") + .route("/image_proxy", web::get().to(image_proxy)) + // Site + .service( + web::scope("/site") + .wrap(rate_limit.message()) + .route("", web::get().to(get_site_v3)) + // Admin Actions + .route("", web::post().to(create_site)) + .route("", web::put().to(update_site)) + .route("/block", web::post().to(block_instance)), + ) + .service( + web::resource("/modlog") + .wrap(rate_limit.message()) + .route(web::get().to(get_mod_log)), + ) + .service( + web::resource("/search") + .wrap(rate_limit.search()) + .route(web::get().to(search)), + ) + .service( + web::resource("/resolve_object") + .wrap(rate_limit.message()) + .route(web::get().to(resolve_object)), + ) + // Community + .service( + web::resource("/community") + .guard(guard::Post()) + .wrap(rate_limit.register()) + .route(web::post().to(create_community)), + ) + .service( + web::scope("/community") + .wrap(rate_limit.message()) + .route("", web::get().to(get_community)) + .route("", web::put().to(update_community)) + .route("/random", web::get().to(get_random_community)) + .route("/hide", web::put().to(hide_community)) + .route("/list", web::get().to(list_communities)) + .route("/follow", web::post().to(follow_community)) + .route("/block", web::post().to(block_community)) + .route("/delete", web::post().to(delete_community)) + // Mod Actions + .route("/remove", web::post().to(remove_community)) + .route("/transfer", web::post().to(transfer_community)) + .route("/ban_user", web::post().to(ban_from_community)) + .route("/mod", web::post().to(add_mod_to_community)) + .service( + web::scope("/pending_follows") + .wrap(rate_limit.message()) + .route("/count", web::get().to(get_pending_follows_count)) + .route("/list", web::get().to(get_pending_follows_list)) + .route("/approve", web::post().to(post_pending_follows_approve)), + ), + ) + .service( + web::scope("/federated_instances") + .wrap(rate_limit.message()) + .route("", web::get().to(get_federated_instances)), + ) + // Post + .service( + // Handle POST to /post separately to add the post() rate limitter + web::resource("/post") + .guard(guard::Post()) + .wrap(rate_limit.post()) + .route(web::post().to(create_post)), + ) + .service( + web::scope("/post") + .wrap(rate_limit.message()) + .route("", web::get().to(get_post)) + .route("", web::put().to(update_post)) + .route("/delete", web::post().to(delete_post)) + .route("/remove", web::post().to(remove_post)) + .route("/mark_as_read", web::post().to(mark_post_as_read)) + .route("/mark_many_as_read", web::post().to(mark_posts_as_read)) + .route("/hide", web::post().to(hide_post)) + .route("/lock", web::post().to(lock_post)) + .route("/feature", web::post().to(feature_post)) + .route("/list", web::get().to(list_posts)) + .route("/like", web::post().to(like_post)) + .route("/like/list", web::get().to(list_post_likes)) + .route("/save", web::put().to(save_post)) + .route("/report", web::post().to(create_post_report)) + .route("/report/resolve", web::put().to(resolve_post_report)) + .route("/report/list", web::get().to(list_post_reports)) + .route("/site_metadata", web::get().to(get_link_metadata)), + ) + // Comment + .service( + // Handle POST to /comment separately to add the comment() rate limitter + web::resource("/comment") + .guard(guard::Post()) + .wrap(rate_limit.comment()) + .route(web::post().to(create_comment)), + ) + .service( + web::scope("/comment") + .wrap(rate_limit.message()) + .route("", web::get().to(get_comment)) + .route("", web::put().to(update_comment)) + .route("/delete", web::post().to(delete_comment)) + .route("/remove", web::post().to(remove_comment)) + .route("/mark_as_read", web::post().to(mark_reply_as_read)) + .route("/distinguish", web::post().to(distinguish_comment)) + .route("/like", web::post().to(like_comment)) + .route("/like/list", web::get().to(list_comment_likes)) + .route("/save", web::put().to(save_comment)) + .route("/list", web::get().to(list_comments)) + .route("/report", web::post().to(create_comment_report)) + .route("/report/resolve", web::put().to(resolve_comment_report)) + .route("/report/list", web::get().to(list_comment_reports)), + ) + // Private Message + .service( + web::scope("/private_message") + .wrap(rate_limit.message()) + .route("/list", web::get().to(get_private_message)) + .route("", web::post().to(create_private_message)) + .route("", web::put().to(update_private_message)) + .route("/delete", web::post().to(delete_private_message)) + .route("/mark_as_read", web::post().to(mark_pm_as_read)) + .route("/report", web::post().to(create_pm_report)) + .route("/report/resolve", web::put().to(resolve_pm_report)) + .route("/report/list", web::get().to(list_pm_reports)), + ) + // User + .service( + // Account action, I don't like that it's in /user maybe /accounts + // Handle /user/register separately to add the register() rate limiter + web::resource("/user/register") + .guard(guard::Post()) + .wrap(rate_limit.register()) + .route(web::post().to(register)), + ) + // User + .service( + // Handle /user/login separately to add the register() rate limiter + // TODO: pretty annoying way to apply rate limits for register and login, we should + // group them under a common path so that rate limit is only applied once (eg under + // /account). + web::resource("/user/login") + .guard(guard::Post()) + .wrap(rate_limit.register()) + .route(web::post().to(login)), + ) + .service( + web::resource("/user/password_reset") + .wrap(rate_limit.register()) + .route(web::post().to(reset_password)), + ) + .service( + // Handle captcha separately + web::resource("/user/get_captcha") + .wrap(rate_limit.post()) + .route(web::get().to(get_captcha)), + ) + .service( + web::resource("/user/export_settings") + .wrap(rate_limit.import_user_settings()) + .route(web::get().to(export_settings)), + ) + .service( + web::resource("/user/import_settings") + .wrap(rate_limit.import_user_settings()) + .route(web::post().to(import_settings)), + ) + // TODO, all the current account related actions under /user need to get moved here eventually + .service( + web::scope("/account") + .wrap(rate_limit.message()) + .route("/list_media", web::get().to(list_media)), + ) + // User actions + .service( + web::scope("/user") + .wrap(rate_limit.message()) + .route("", web::get().to(read_person)) + .route("/mention", web::get().to(list_mentions)) + .route( + "/mention/mark_as_read", + web::post().to(mark_person_mention_as_read), + ) + .route("/replies", web::get().to(list_replies)) + // Admin action. I don't like that it's in /user + .route("/ban", web::post().to(ban_from_site)) + .route("/banned", web::get().to(list_banned_users)) + .route("/block", web::post().to(block_person)) + // TODO Account actions. I don't like that they're in /user maybe /accounts + .route("/logout", web::post().to(logout)) + .route("/delete_account", web::post().to(delete_account)) + .route( + "/password_change", + web::post().to(change_password_after_reset), + ) + // TODO mark_all_as_read feels off being in this section as well + .route( + "/mark_all_as_read", + web::post().to(mark_all_notifications_read), + ) + .route("/save_user_settings", web::put().to(save_user_settings)) + .route("/change_password", web::put().to(change_password)) + .route("/report_count", web::get().to(report_count)) + .route("/unread_count", web::get().to(unread_count)) + .route("/verify_email", web::post().to(verify_email)) + .route("/leave_admin", web::post().to(leave_admin)) + .route("/totp/generate", web::post().to(generate_totp_secret)) + .route("/totp/update", web::post().to(update_totp)) + .route("/list_logins", web::get().to(list_logins)) + .route("/validate_auth", web::get().to(validate_auth)), + ) + // Admin Actions + .service( + web::scope("/admin") + .wrap(rate_limit.message()) + .route("/add", web::post().to(add_admin)) + .route( + "/registration_application/count", + web::get().to(get_unread_registration_application_count), + ) + .route( + "/registration_application/list", + web::get().to(list_registration_applications), + ) + .route( + "/registration_application/approve", + web::put().to(approve_registration_application), + ) + .route( + "/registration_application", + web::get().to(get_registration_application), + ) + .route("/list_all_media", web::get().to(list_all_media)) + .service( + web::scope("/purge") + .route("/person", web::post().to(purge_person)) + .route("/community", web::post().to(purge_community)) + .route("/post", web::post().to(purge_post)) + .route("/comment", web::post().to(purge_comment)), + ) + .service( + web::scope("/tagline") + .wrap(rate_limit.message()) + .route("", web::post().to(create_tagline)) + .route("", web::put().to(update_tagline)) + .route("/delete", web::post().to(delete_tagline)) + .route("/list", web::get().to(list_taglines)), + ), + ) + .service( + web::scope("/custom_emoji") + .wrap(rate_limit.message()) + .route("", web::post().to(create_custom_emoji)) + .route("", web::put().to(update_custom_emoji)) + .route("/delete", web::post().to(delete_custom_emoji)) + .route("/list", web::get().to(list_custom_emojis)), + ) + .service( + web::scope("/oauth_provider") + .wrap(rate_limit.message()) + .route("", web::post().to(create_oauth_provider)) + .route("", web::put().to(update_oauth_provider)) + .route("/delete", web::post().to(delete_oauth_provider)), + ) + .service( + web::scope("/oauth") + .wrap(rate_limit.register()) + .route("/authenticate", web::post().to(authenticate_with_oauth)), + ), + ); + cfg.service( + web::scope("/sitemap.xml") + .wrap(rate_limit.message()) + .route("", web::get().to(get_sitemap)), + ); +} diff --git a/src/api_routes_http.rs b/src/api_routes_v4.rs similarity index 98% rename from src/api_routes_http.rs rename to src/api_routes_v4.rs index 42a2cf0ab..42f25628f 100644 --- a/src/api_routes_http.rs +++ b/src/api_routes_v4.rs @@ -135,7 +135,7 @@ use lemmy_api_crud::{ read::get_private_message, update::update_private_message, }, - site::{create::create_site, read::get_site, update::update_site}, + site::{create::create_site, read::get_site_v4, update::update_site}, tagline::{ create::create_tagline, delete::delete_tagline, @@ -162,13 +162,13 @@ use lemmy_utils::rate_limit::RateLimitCell; pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { cfg.service( - web::scope("/api/v4") + web::scope("/api/v3") .wrap(rate_limit.message()) .route("/image_proxy", web::get().to(image_proxy)) // Site .service( web::scope("/site") - .route("", web::get().to(get_site)) + .route("", web::get().to(get_site_v4)) // Admin Actions .route("", web::post().to(create_site)) .route("", web::put().to(update_site)) diff --git a/src/lib.rs b/src/lib.rs index 319efd224..5586b6159 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ -pub mod api_routes_http; +pub mod api_routes_v3; +pub mod api_routes_v4; pub mod code_migrations; pub mod prometheus_metrics; pub mod scheduled_tasks; @@ -318,7 +319,8 @@ fn create_http_server( // The routes app - .configure(|cfg| api_routes_http::config(cfg, &rate_limit_cell)) + .configure(|cfg| api_routes_v3::config(cfg, &rate_limit_cell)) + .configure(|cfg| api_routes_v4::config(cfg, &rate_limit_cell)) .configure(|cfg| { if federation_enabled { lemmy_apub::http::routes::config(cfg);