Add cargo feature for building lemmy_api_common with mininum deps (#2243)

This commit is contained in:
Nutomic 2022-05-03 19:44:13 +02:00 committed by GitHub
parent dd5835fb6e
commit 3aa3d75a1e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
238 changed files with 2735 additions and 2688 deletions

View file

@ -22,6 +22,11 @@ steps:
commands:
- /root/.cargo/bin/cargo fmt -- --check
- name: check lemmy_api_common with minimal deps
image: clux/muslrust:1.56.0
commands:
- cargo check -p lemmy_api_common
- name: cargo clippy
image: clux/muslrust:1.56.0
commands:

12
Cargo.lock generated
View file

@ -1831,18 +1831,24 @@ dependencies = [
name = "lemmy_api_common"
version = "0.16.3"
dependencies = [
"actix-rt",
"actix-web",
"chrono",
"diesel",
"encoding",
"lemmy_db_schema",
"lemmy_db_views",
"lemmy_db_views_actor",
"lemmy_db_views_moderator",
"lemmy_utils",
"percent-encoding",
"reqwest",
"reqwest-middleware",
"rosetta-i18n",
"serde",
"tracing",
"url",
"webpage",
]
[[package]]
@ -2062,7 +2068,6 @@ dependencies = [
name = "lemmy_utils"
version = "0.16.3"
dependencies = [
"actix-rt",
"actix-web",
"anyhow",
"chrono",
@ -2070,7 +2075,6 @@ dependencies = [
"deser-hjson",
"diesel",
"doku",
"encoding",
"futures",
"html2text",
"http",
@ -2080,10 +2084,8 @@ dependencies = [
"once_cell",
"openssl",
"parking_lot 0.12.0",
"percent-encoding",
"rand 0.8.5",
"regex",
"reqwest",
"reqwest-middleware",
"rosetta-build",
"rosetta-i18n",
@ -2092,12 +2094,10 @@ dependencies = [
"smart-default",
"strum",
"strum_macros",
"thiserror",
"tracing",
"tracing-error",
"url",
"uuid",
"webpage",
]
[[package]]

View file

@ -16,15 +16,15 @@ doctest = false
lemmy_apub = { version = "=0.16.3", path = "../apub" }
lemmy_apub_lib = { version = "=0.16.3", path = "../apub_lib" }
lemmy_utils = { version = "=0.16.3", path = "../utils" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema" }
lemmy_db_views = { version = "=0.16.3", path = "../db_views" }
lemmy_db_views_moderator = { version = "=0.16.3", path = "../db_views_moderator" }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor" }
lemmy_api_common = { version = "=0.16.3", path = "../api_common" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema", features = ["full"] }
lemmy_db_views = { version = "=0.16.3", path = "../db_views", features = ["full"] }
lemmy_db_views_moderator = { version = "=0.16.3", path = "../db_views_moderator", features = ["full"] }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor", features = ["full"] }
lemmy_api_common = { version = "=0.16.3", path = "../api_common", features = ["full"] }
lemmy_websocket = { version = "=0.16.3", path = "../websocket" }
diesel = "1.4.8"
bcrypt = "0.12.1"
chrono = { version = "0.4.19", features = ["serde"] }
chrono = { version = "0.4.19", features = ["serde"], default-features = false }
serde_json = { version = "1.0.79", features = ["preserve_order"] }
serde = { version = "1.0.136", features = ["derive"] }
actix-web = { version = "4.0.1", default-features = false }

View file

@ -1,11 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_community_ban,
check_downvotes_enabled,
comment::{CommentResponse, CreateCommentLike},
get_local_user_view_from_jwt,
utils::{blocking, check_community_ban, check_downvotes_enabled, get_local_user_view_from_jwt},
};
use lemmy_apub::{
fetcher::post_or_comment::PostOrComment,
@ -19,7 +16,7 @@ use lemmy_db_schema::{
source::comment::{CommentLike, CommentLikeForm},
traits::Likeable,
};
use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
use lemmy_db_views::structs::{CommentView, LocalUserView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
use std::convert::TryInto;

View file

@ -1,12 +1,11 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
comment::{CommentResponse, MarkCommentAsRead},
get_local_user_view_from_jwt,
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::source::comment::Comment;
use lemmy_db_views::comment_view::CommentView;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,15 +1,14 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
comment::{CommentResponse, SaveComment},
get_local_user_view_from_jwt,
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{
source::comment::{CommentSaved, CommentSavedForm},
traits::Saveable,
};
use lemmy_db_views::comment_view::CommentView;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,10 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_community_ban,
comment::{CommentReportResponse, CreateCommentReport},
get_local_user_view_from_jwt,
utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
};
use lemmy_apub::protocol::activities::community::report::Report;
use lemmy_apub_lib::object_id::ObjectId;
@ -12,7 +10,7 @@ use lemmy_db_schema::{
source::comment_report::{CommentReport, CommentReportForm},
traits::Reportable,
};
use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView};
use lemmy_db_views::structs::{CommentReportView, CommentView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
comment::{ListCommentReports, ListCommentReportsResponse},
get_local_user_view_from_jwt,
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_views::comment_report_view::CommentReportQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};

View file

@ -1,13 +1,11 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
comment::{CommentReportResponse, ResolveCommentReport},
get_local_user_view_from_jwt,
is_mod_or_admin,
utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin},
};
use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
use lemmy_db_views::comment_report_view::CommentReportView;
use lemmy_db_views::structs::CommentReportView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};

View file

@ -1,10 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
community::{AddModToCommunity, AddModToCommunityResponse},
get_local_user_view_from_jwt,
is_mod_or_admin,
utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin},
};
use lemmy_apub::{
objects::{community::ApubCommunity, person::ApubPerson},
@ -18,7 +16,7 @@ use lemmy_db_schema::{
},
traits::{Crud, Joinable},
};
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};

View file

@ -1,11 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
community::{BanFromCommunity, BanFromCommunityResponse},
get_local_user_view_from_jwt,
is_mod_or_admin,
remove_user_data_in_community,
utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin, remove_user_data_in_community},
};
use lemmy_apub::{
activities::block::SiteOrCommunity,
@ -26,7 +23,7 @@ use lemmy_db_schema::{
},
traits::{Bannable, Crud, Followable},
};
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
community::{BlockCommunity, BlockCommunityResponse},
get_local_user_view_from_jwt,
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_apub::protocol::activities::following::undo_follow::UndoFollowCommunity;
use lemmy_db_schema::{
@ -13,7 +12,7 @@ use lemmy_db_schema::{
},
traits::{Blockable, Crud, Followable},
};
use lemmy_db_views_actor::community_view::CommunityView;
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,11 +1,13 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, FollowCommunity},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
community::{CommunityResponse, FollowCommunity},
get_local_user_view_from_jwt,
},
};
use lemmy_apub::{
objects::community::ApubCommunity,
@ -18,7 +20,7 @@ use lemmy_db_schema::{
source::community::{Community, CommunityFollower, CommunityFollowerForm},
traits::{Crud, Followable},
};
use lemmy_db_views_actor::community_view::CommunityView;
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,19 +1,17 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
community::{CommunityResponse, HideCommunity},
get_local_user_view_from_jwt,
is_admin,
utils::{blocking, get_local_user_view_from_jwt, is_admin},
};
use lemmy_apub::protocol::activities::community::update::UpdateCommunity;
use lemmy_db_schema::{
naive_now,
source::{
community::{Community, CommunityForm},
moderator::{ModHideCommunity, ModHideCommunityForm},
},
traits::Crud,
utils::naive_now,
};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};

View file

@ -2,9 +2,8 @@ use crate::Perform;
use actix_web::web::Data;
use anyhow::Context;
use lemmy_api_common::{
blocking,
community::{GetCommunityResponse, TransferCommunity},
get_local_user_view_from_jwt,
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{
source::{
@ -13,11 +12,7 @@ use lemmy_db_schema::{
},
traits::{Crud, Joinable},
};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
person_view::PersonViewSafe,
};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView, PersonViewSafe};
use lemmy_utils::{location_info, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -206,15 +206,15 @@ pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
#[cfg(test)]
mod tests {
use lemmy_api_common::check_validator_time;
use lemmy_api_common::utils::check_validator_time;
use lemmy_db_schema::{
establish_unpooled_connection,
source::{
local_user::{LocalUser, LocalUserForm},
person::{Person, PersonForm},
secret::Secret,
},
traits::Crud,
utils::establish_unpooled_connection,
};
use lemmy_utils::{claims::Claims, settings::structs::Settings};

View file

@ -1,10 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_admin,
person::{AddAdmin, AddAdminResponse},
utils::{blocking, get_local_user_view_from_jwt, is_admin},
};
use lemmy_db_schema::{
source::{
@ -13,7 +11,7 @@ use lemmy_db_schema::{
},
traits::Crud,
};
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperation};

View file

@ -1,11 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_admin,
person::{BanPerson, BanPersonResponse},
remove_user_data,
utils::{blocking, get_local_user_view_from_jwt, is_admin, remove_user_data},
};
use lemmy_apub::{
activities::block::SiteOrCommunity,
@ -19,7 +16,7 @@ use lemmy_db_schema::{
},
traits::Crud,
};
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperation};

View file

@ -1,15 +1,14 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{BlockPerson, BlockPersonResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{
source::person_block::{PersonBlock, PersonBlockForm},
traits::Blockable,
};
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -2,10 +2,8 @@ use crate::Perform;
use actix_web::web::Data;
use bcrypt::verify;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
password_length_check,
person::{ChangePassword, LoginResponse},
utils::{blocking, get_local_user_view_from_jwt, password_length_check},
};
use lemmy_db_schema::source::local_user::LocalUser;
use lemmy_utils::{claims::Claims, ConnectionId, LemmyError};

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
password_length_check,
person::{LoginResponse, PasswordChangeAfterReset},
utils::{blocking, password_length_check},
};
use lemmy_db_schema::source::{
local_user::LocalUser,

View file

@ -3,7 +3,7 @@ use actix_web::web::Data;
use captcha::{gen, Difficulty};
use chrono::Duration;
use lemmy_api_common::person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse};
use lemmy_db_schema::naive_now;
use lemmy_db_schema::utils::naive_now;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::CaptchaItem, LemmyContext};

View file

@ -1,12 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_admin,
person::{BannedPersonsResponse, GetBannedPersons},
utils::{blocking, get_local_user_view_from_jwt, is_admin},
};
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -2,12 +2,11 @@ use crate::Perform;
use actix_web::web::Data;
use bcrypt::verify;
use lemmy_api_common::{
blocking,
check_registration_application,
person::{Login, LoginResponse},
utils::{blocking, check_registration_application},
};
use lemmy_db_schema::source::site::Site;
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::{claims::Claims, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,11 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{GetPersonMentions, GetPersonMentionsResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType};
use lemmy_db_schema::utils::{from_opt_str_to_opt_enum, SortType};
use lemmy_db_views_actor::person_mention_view::PersonMentionQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,11 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{GetReplies, GetRepliesResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType};
use lemmy_db_schema::utils::{from_opt_str_to_opt_enum, SortType};
use lemmy_db_views::comment_view::CommentQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{GetRepliesResponse, MarkAllAsRead},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::source::{
comment::Comment,

View file

@ -1,12 +1,11 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{MarkPersonMentionAsRead, PersonMentionResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{source::person_mention::PersonMention, traits::Crud};
use lemmy_db_views_actor::person_mention_view::PersonMentionView;
use lemmy_db_views_actor::structs::PersonMentionView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,12 +1,11 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{GetUnreadCount, GetUnreadCountResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_views::{comment_view::CommentView, private_message_view::PrivateMessageView};
use lemmy_db_views_actor::person_mention_view::PersonMentionView;
use lemmy_db_views::structs::{CommentView, PrivateMessageView};
use lemmy_db_views_actor::structs::PersonMentionView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,11 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{GetReportCount, GetReportCountResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::PostReportView};
use lemmy_db_views::structs::{CommentReportView, PostReportView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,11 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
person::{PasswordReset, PasswordResetResponse},
send_password_reset_email,
utils::{blocking, send_password_reset_email},
};
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,22 +1,22 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
person::{LoginResponse, SaveUserSettings},
utils::{
blocking,
check_image_has_local_domain,
get_local_user_view_from_jwt,
person::{LoginResponse, SaveUserSettings},
send_verification_email,
},
};
use lemmy_db_schema::{
diesel_option_overwrite,
diesel_option_overwrite_to_url,
naive_now,
source::{
local_user::{LocalUser, LocalUserForm},
person::{Person, PersonForm},
site::Site,
},
traits::Crud,
utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now},
};
use lemmy_utils::{
claims::Claims,

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
person::{VerifyEmail, VerifyEmailResponse},
send_email_verification_success,
utils::{blocking, send_email_verification_success},
};
use lemmy_db_schema::{
source::{
@ -12,7 +11,7 @@ use lemmy_db_schema::{
},
traits::Crud,
};
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;

View file

@ -1,7 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::post::{GetSiteMetadata, GetSiteMetadataResponse};
use lemmy_utils::{request::fetch_site_metadata, ConnectionId, LemmyError};
use lemmy_api_common::{
post::{GetSiteMetadata, GetSiteMetadataResponse},
request::fetch_site_metadata,
};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;
#[async_trait::async_trait(?Send)]

View file

@ -1,13 +1,15 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
post::{CreatePostLike, PostResponse},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
check_downvotes_enabled,
get_local_user_view_from_jwt,
mark_post_as_read,
post::{CreatePostLike, PostResponse},
},
};
use lemmy_apub::{
fetcher::post_or_comment::PostOrComment,

View file

@ -1,12 +1,14 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
post::{LockPost, PostResponse},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
get_local_user_view_from_jwt,
is_mod_or_admin,
post::{LockPost, PostResponse},
},
};
use lemmy_apub::{
objects::post::ApubPost,

View file

@ -1,13 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
mark_post_as_read,
mark_post_as_unread,
post::{MarkPostAsRead, PostResponse},
utils::{blocking, get_local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread},
};
use lemmy_db_views::post_view::PostView;
use lemmy_db_views::structs::PostView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,16 +1,14 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
mark_post_as_read,
post::{PostResponse, SavePost},
utils::{blocking, get_local_user_view_from_jwt, mark_post_as_read},
};
use lemmy_db_schema::{
source::post::{PostSaved, PostSavedForm},
traits::Saveable,
};
use lemmy_db_views::post_view::PostView;
use lemmy_db_views::structs::PostView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,12 +1,14 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
post::{PostResponse, StickyPost},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
get_local_user_view_from_jwt,
is_mod_or_admin,
post::{PostResponse, StickyPost},
},
};
use lemmy_apub::{
objects::post::ApubPost,

View file

@ -1,10 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_community_ban,
get_local_user_view_from_jwt,
post::{CreatePostReport, PostReportResponse},
utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
};
use lemmy_apub::protocol::activities::community::report::Report;
use lemmy_apub_lib::object_id::ObjectId;
@ -12,7 +10,7 @@ use lemmy_db_schema::{
source::post_report::{PostReport, PostReportForm},
traits::Reportable,
};
use lemmy_db_views::{post_report_view::PostReportView, post_view::PostView};
use lemmy_db_views::structs::{PostReportView, PostView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
post::{ListPostReports, ListPostReportsResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_views::post_report_view::PostReportQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};

View file

@ -1,13 +1,11 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_mod_or_admin,
post::{PostReportResponse, ResolvePostReport},
utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin},
};
use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
use lemmy_db_views::post_report_view::PostReportView;
use lemmy_db_views::structs::PostReportView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{MarkPrivateMessageAsRead, PrivateMessageResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
use lemmy_utils::{ConnectionId, LemmyError};

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
get_local_user_view_from_jwt,
is_admin,
site::{GetSiteConfig, GetSiteConfigResponse},
utils::{get_local_user_view_from_jwt, is_admin},
};
use lemmy_utils::{settings::structs::Settings, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,9 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
get_local_user_view_from_jwt,
is_admin,
site::{GetSiteConfigResponse, SaveSiteConfig},
utils::{get_local_user_view_from_jwt, is_admin},
};
use lemmy_utils::{settings::structs::Settings, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,11 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
build_federated_instances,
get_local_user_view_from_jwt,
is_admin,
site::{GetSiteResponse, LeaveAdmin},
utils::{blocking, build_federated_instances, get_local_user_view_from_jwt, is_admin},
};
use lemmy_db_schema::{
source::{
@ -14,8 +11,8 @@ use lemmy_db_schema::{
},
traits::Crud,
};
use lemmy_db_views::site_view::SiteView;
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views::structs::SiteView;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{version, ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,23 +1,21 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
get_local_user_view_from_jwt_opt,
site::{GetModlog, GetModlogResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_db_views_moderator::{
mod_add_community_view::ModAddCommunityView,
mod_add_view::ModAddView,
mod_ban_from_community_view::ModBanFromCommunityView,
mod_ban_view::ModBanView,
mod_hide_community_view::ModHideCommunityView,
mod_lock_post_view::ModLockPostView,
mod_remove_comment_view::ModRemoveCommentView,
mod_remove_community_view::ModRemoveCommunityView,
mod_remove_post_view::ModRemovePostView,
mod_sticky_post_view::ModStickyPostView,
mod_transfer_community_view::ModTransferCommunityView,
use lemmy_db_views_moderator::structs::{
ModAddCommunityView,
ModAddView,
ModBanFromCommunityView,
ModBanView,
ModHideCommunityView,
ModLockPostView,
ModRemoveCommentView,
ModRemoveCommunityView,
ModRemovePostView,
ModStickyPostView,
ModTransferCommunityView,
};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,24 +1,18 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_admin,
send_application_approved_email,
site::*,
site::{ApproveRegistrationApplication, RegistrationApplicationResponse},
utils::{blocking, get_local_user_view_from_jwt, is_admin, send_application_approved_email},
};
use lemmy_db_schema::{
diesel_option_overwrite,
source::{
local_user::{LocalUser, LocalUserForm},
registration_application::{RegistrationApplication, RegistrationApplicationForm},
},
traits::Crud,
utils::diesel_option_overwrite,
};
use lemmy_db_views::{
local_user_view::LocalUserView,
registration_application_view::RegistrationApplicationView,
};
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,10 +1,8 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_admin,
site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
utils::{blocking, get_local_user_view_from_jwt, is_admin},
};
use lemmy_db_schema::source::site::Site;
use lemmy_db_views::registration_application_view::RegistrationApplicationQueryBuilder;

View file

@ -1,13 +1,11 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
is_admin,
site::{GetUnreadRegistrationApplicationCount, GetUnreadRegistrationApplicationCountResponse},
utils::{blocking, get_local_user_view_from_jwt, is_admin},
};
use lemmy_db_schema::source::site::Site;
use lemmy_db_views::registration_application_view::RegistrationApplicationView;
use lemmy_db_views::structs::RegistrationApplicationView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -2,15 +2,13 @@ use crate::Perform;
use actix_web::web::Data;
use diesel::NotFound;
use lemmy_api_common::{
blocking,
check_private_instance,
get_local_user_view_from_jwt_opt,
site::{ResolveObject, ResolveObjectResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_apub::fetcher::search::{search_by_apub_id, SearchableObjects};
use lemmy_db_schema::{newtypes::PersonId, DbPool};
use lemmy_db_views::{comment_view::CommentView, post_view::PostView};
use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe};
use lemmy_db_schema::{newtypes::PersonId, utils::DbPool};
use lemmy_db_views::structs::{CommentView, PostView};
use lemmy_db_views_actor::structs::{CommunityView, PersonViewSafe};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,19 +1,14 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
get_local_user_view_from_jwt_opt,
site::{Search, SearchResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
use lemmy_db_schema::{
from_opt_str_to_opt_enum,
source::community::Community,
traits::DeleteableOrRemoveable,
ListingType,
SearchType,
SortType,
utils::{from_opt_str_to_opt_enum, ListingType, SearchType, SortType},
};
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
use lemmy_db_views_actor::{

View file

@ -1,6 +1,6 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{get_local_user_view_from_jwt, websocket::*};
use lemmy_api_common::{utils::get_local_user_view_from_jwt, websocket::*};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{
messages::{JoinCommunityRoom, JoinModRoom, JoinPostRoom, JoinUserRoom},

View file

@ -12,16 +12,29 @@ name = "lemmy_api_common"
path = "src/lib.rs"
doctest = false
[features]
full = ["diesel", "tracing", "rosetta-i18n", "chrono", "actix-web", "lemmy_utils",
"lemmy_db_views/full", "lemmy_db_views_actor/full", "lemmy_db_views_moderator/full",
"percent-encoding", "encoding", "reqwest-middleware", "webpage"]
[dependencies]
lemmy_db_views = { version = "=0.16.3", path = "../db_views" }
lemmy_db_views_moderator = { version = "=0.16.3", path = "../db_views_moderator" }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema" }
lemmy_utils = { version = "=0.16.3", path = "../utils" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema", default-features = false }
lemmy_utils = { version = "=0.16.3", path = "../utils", optional = true }
serde = { version = "1.0.136", features = ["derive"] }
diesel = "1.4.8"
actix-web = { version = "4.0.1", default-features = false, features = ["cookies"] }
chrono = { version = "0.4.19", features = ["serde"] }
tracing = "0.1.32"
url = "2.2.2"
rosetta-i18n = "0.1.2"
actix-web = { version = "4.0.1", default-features = false, features = ["cookies"], optional = true }
chrono = { version = "0.4.19", features = ["serde"], optional = true }
diesel = { version = "1.4.8", optional = true }
tracing = { version = "0.1.32", optional = true }
rosetta-i18n = { version = "0.1.2", optional = true }
percent-encoding = { version = "2.1.0", optional = true }
encoding = { version = "0.2.33", optional = true }
reqwest-middleware = { version = "0.1.5", optional = true }
webpage = { version = "1.4.0", default-features = false, features = ["serde"], optional = true }
[dev-dependencies]
actix-rt = { version = "2.7.0", default-features = false }
reqwest = { version = "0.11.10", features = ["json"] }

View file

@ -1,6 +1,6 @@
use crate::sensitive::Sensitive;
use lemmy_db_schema::newtypes::{CommentId, CommentReportId, CommunityId, LocalUserId, PostId};
use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView};
use lemmy_utils::Sensitive;
use lemmy_db_views::structs::{CommentReportView, CommentView};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]

View file

@ -1,13 +1,9 @@
use crate::sensitive::Sensitive;
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},
source::site::Site,
};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
person_view::PersonViewSafe,
};
use lemmy_utils::Sensitive;
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView, PersonViewSafe};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]

View file

@ -2,612 +2,10 @@ pub mod comment;
pub mod community;
pub mod person;
pub mod post;
#[cfg(feature = "full")]
pub mod request;
mod sensitive;
pub mod site;
#[cfg(feature = "full")]
pub mod utils;
pub mod websocket;
use crate::site::FederatedInstances;
use lemmy_db_schema::{
newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId},
source::{
comment::Comment,
community::Community,
email_verification::{EmailVerification, EmailVerificationForm},
password_reset_request::PasswordResetRequest,
person::Person,
person_block::PersonBlock,
post::{Post, PostRead, PostReadForm},
registration_application::RegistrationApplication,
secret::Secret,
site::Site,
},
traits::{Crud, Readable},
DbPool,
};
use lemmy_db_views::{
comment_view::CommentQueryBuilder,
local_user_view::{LocalUserSettingsView, LocalUserView},
};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_person_ban_view::CommunityPersonBanView,
community_view::CommunityView,
};
use lemmy_utils::{
claims::Claims,
email::{send_email, translations::Lang},
settings::structs::Settings,
utils::generate_random_string,
LemmyError,
Sensitive,
};
use rosetta_i18n::{Language, LanguageId};
use tracing::warn;
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
where
F: FnOnce(&diesel::PgConnection) -> T + Send + 'static,
T: Send + 'static,
{
let pool = pool.clone();
let blocking_span = tracing::info_span!("blocking operation");
let res = actix_web::web::block(move || {
let entered = blocking_span.enter();
let conn = pool.get()?;
let res = (f)(&conn);
drop(entered);
Ok(res) as Result<T, LemmyError>
})
.await?;
res
}
#[tracing::instrument(skip_all)]
pub async fn is_mod_or_admin(
pool: &DbPool,
person_id: PersonId,
community_id: CommunityId,
) -> Result<(), LemmyError> {
let is_mod_or_admin = blocking(pool, move |conn| {
CommunityView::is_mod_or_admin(conn, person_id, community_id)
})
.await?;
if !is_mod_or_admin {
return Err(LemmyError::from_message("not_a_mod_or_admin"));
}
Ok(())
}
pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
if !local_user_view.person.admin {
return Err(LemmyError::from_message("not_an_admin"));
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub async fn get_post(post_id: PostId, pool: &DbPool) -> Result<Post, LemmyError> {
blocking(pool, move |conn| Post::read(conn, post_id))
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))
}
#[tracing::instrument(skip_all)]
pub async fn mark_post_as_read(
person_id: PersonId,
post_id: PostId,
pool: &DbPool,
) -> Result<PostRead, LemmyError> {
let post_read_form = PostReadForm { post_id, person_id };
blocking(pool, move |conn| {
PostRead::mark_as_read(conn, &post_read_form)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
}
#[tracing::instrument(skip_all)]
pub async fn mark_post_as_unread(
person_id: PersonId,
post_id: PostId,
pool: &DbPool,
) -> Result<usize, LemmyError> {
let post_read_form = PostReadForm { post_id, person_id };
blocking(pool, move |conn| {
PostRead::mark_as_unread(conn, &post_read_form)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_view_from_jwt(
jwt: &str,
pool: &DbPool,
secret: &Secret,
) -> Result<LocalUserView, LemmyError> {
let claims = Claims::decode(jwt, &secret.jwt_secret)
.map_err(|e| e.with_message("not_logged_in"))?
.claims;
let local_user_id = LocalUserId(claims.sub);
let local_user_view =
blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
// Check for a site ban
if local_user_view.person.is_banned() {
return Err(LemmyError::from_message("site_ban"));
}
// Check for user deletion
if local_user_view.person.deleted {
return Err(LemmyError::from_message("deleted"));
}
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
Ok(local_user_view)
}
/// Checks if user's token was issued before user's password reset.
pub fn check_validator_time(
validator_time: &chrono::NaiveDateTime,
claims: &Claims,
) -> Result<(), LemmyError> {
let user_validation_time = validator_time.timestamp();
if user_validation_time > claims.iat {
Err(LemmyError::from_message("not_logged_in"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_view_from_jwt_opt(
jwt: Option<&Sensitive<String>>,
pool: &DbPool,
secret: &Secret,
) -> Result<Option<LocalUserView>, LemmyError> {
match jwt {
Some(jwt) => Ok(Some(get_local_user_view_from_jwt(jwt, pool, secret).await?)),
None => Ok(None),
}
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_settings_view_from_jwt(
jwt: &Sensitive<String>,
pool: &DbPool,
secret: &Secret,
) -> Result<LocalUserSettingsView, LemmyError> {
let claims = Claims::decode(jwt.as_ref(), &secret.jwt_secret)
.map_err(|e| e.with_message("not_logged_in"))?
.claims;
let local_user_id = LocalUserId(claims.sub);
let local_user_view = blocking(pool, move |conn| {
LocalUserSettingsView::read(conn, local_user_id)
})
.await??;
// Check for a site ban
if local_user_view.person.is_banned() {
return Err(LemmyError::from_message("site_ban"));
}
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
Ok(local_user_view)
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_settings_view_from_jwt_opt(
jwt: Option<&Sensitive<String>>,
pool: &DbPool,
secret: &Secret,
) -> Result<Option<LocalUserSettingsView>, LemmyError> {
match jwt {
Some(jwt) => Ok(Some(
get_local_user_settings_view_from_jwt(jwt, pool, secret).await?,
)),
None => Ok(None),
}
}
#[tracing::instrument(skip_all)]
pub async fn check_community_ban(
person_id: PersonId,
community_id: CommunityId,
pool: &DbPool,
) -> Result<(), LemmyError> {
let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? {
Err(LemmyError::from_message("community_ban"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_community_deleted_or_removed(
community_id: CommunityId,
pool: &DbPool,
) -> Result<(), LemmyError> {
let community = blocking(pool, move |conn| Community::read(conn, community_id))
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
if community.deleted || community.removed {
Err(LemmyError::from_message("deleted"))
} else {
Ok(())
}
}
pub fn check_post_deleted_or_removed(post: &Post) -> Result<(), LemmyError> {
if post.deleted || post.removed {
Err(LemmyError::from_message("deleted"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_person_block(
my_id: PersonId,
potential_blocker_id: PersonId,
pool: &DbPool,
) -> Result<(), LemmyError> {
let is_blocked = move |conn: &'_ _| PersonBlock::read(conn, potential_blocker_id, my_id).is_ok();
if blocking(pool, is_blocked).await? {
Err(LemmyError::from_message("person_block"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
if score == -1 {
let site = blocking(pool, Site::read_local_site).await??;
if !site.enable_downvotes {
return Err(LemmyError::from_message("downvotes_disabled"));
}
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub async fn check_private_instance(
local_user_view: &Option<LocalUserView>,
pool: &DbPool,
) -> Result<(), LemmyError> {
if local_user_view.is_none() {
let site = blocking(pool, Site::read_local_site).await?;
// The site might not be set up yet
if let Ok(site) = site {
if site.private_instance {
return Err(LemmyError::from_message("instance_is_private"));
}
}
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub async fn build_federated_instances(
pool: &DbPool,
settings: &Settings,
) -> Result<Option<FederatedInstances>, LemmyError> {
let federation_config = &settings.federation;
let hostname = &settings.hostname;
let federation = federation_config.to_owned();
if federation.enabled {
let distinct_communities = blocking(pool, move |conn| {
Community::distinct_federated_communities(conn)
})
.await??;
let allowed = federation.allowed_instances;
let blocked = federation.blocked_instances;
let mut linked = distinct_communities
.iter()
.map(|actor_id| Ok(actor_id.host_str().unwrap_or("").to_string()))
.collect::<Result<Vec<String>, LemmyError>>()?;
if let Some(allowed) = allowed.as_ref() {
linked.extend_from_slice(allowed);
}
if let Some(blocked) = blocked.as_ref() {
linked.retain(|a| !blocked.contains(a) && !a.eq(hostname));
}
// Sort and remove dupes
linked.sort_unstable();
linked.dedup();
Ok(Some(FederatedInstances {
linked,
allowed,
blocked,
}))
} else {
Ok(None)
}
}
/// Checks the password length
pub fn password_length_check(pass: &str) -> Result<(), LemmyError> {
if !(10..=60).contains(&pass.len()) {
Err(LemmyError::from_message("invalid_password"))
} else {
Ok(())
}
}
/// Checks the site description length
pub fn site_description_length_check(description: &str) -> Result<(), LemmyError> {
if description.len() > 150 {
Err(LemmyError::from_message("site_description_length_overflow"))
} else {
Ok(())
}
}
/// Checks for a honeypot. If this field is filled, fail the rest of the function
pub fn honeypot_check(honeypot: &Option<String>) -> Result<(), LemmyError> {
if honeypot.is_some() {
Err(LemmyError::from_message("honeypot_fail"))
} else {
Ok(())
}
}
pub fn send_email_to_user(
local_user_view: &LocalUserView,
subject: &str,
body: &str,
settings: &Settings,
) {
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
return;
}
if let Some(user_email) = &local_user_view.local_user.email {
match send_email(
subject,
user_email,
&local_user_view.person.name,
body,
settings,
) {
Ok(_o) => _o,
Err(e) => warn!("{}", e),
};
}
}
pub async fn send_password_reset_email(
user: &LocalUserView,
pool: &DbPool,
settings: &Settings,
) -> Result<(), LemmyError> {
// Generate a random token
let token = generate_random_string();
// Insert the row
let token2 = token.clone();
let local_user_id = user.local_user.id;
blocking(pool, move |conn| {
PasswordResetRequest::create_token(conn, local_user_id, &token2)
})
.await??;
let email = &user.local_user.email.to_owned().expect("email");
let lang = get_user_lang(user);
let subject = &lang.password_reset_subject(&user.person.name);
let protocol_and_hostname = settings.get_protocol_and_hostname();
let reset_link = format!("{}/password_change/{}", protocol_and_hostname, &token);
let body = &lang.password_reset_body(&user.person.name, reset_link);
send_email(subject, email, &user.person.name, body, settings)
}
/// Send a verification email
pub async fn send_verification_email(
user: &LocalUserView,
new_email: &str,
pool: &DbPool,
settings: &Settings,
) -> Result<(), LemmyError> {
let form = EmailVerificationForm {
local_user_id: user.local_user.id,
email: new_email.to_string(),
verification_token: generate_random_string(),
};
let verify_link = format!(
"{}/verify_email/{}",
settings.get_protocol_and_hostname(),
&form.verification_token
);
blocking(pool, move |conn| EmailVerification::create(conn, &form)).await??;
let lang = get_user_lang(user);
let subject = lang.verify_email_subject(&settings.hostname);
let body = lang.verify_email_body(&user.person.name, &settings.hostname, verify_link);
send_email(&subject, new_email, &user.person.name, &body, settings)?;
Ok(())
}
pub fn send_email_verification_success(
user: &LocalUserView,
settings: &Settings,
) -> Result<(), LemmyError> {
let email = &user.local_user.email.to_owned().expect("email");
let lang = get_user_lang(user);
let subject = &lang.email_verified_subject(&user.person.actor_id);
let body = &lang.email_verified_body();
send_email(subject, email, &user.person.name, body, settings)
}
pub fn get_user_lang(user: &LocalUserView) -> Lang {
let user_lang = LanguageId::new(user.local_user.lang.clone());
Lang::from_language_id(&user_lang).unwrap_or_else(|| {
let en = LanguageId::new("en");
Lang::from_language_id(&en).expect("default language")
})
}
pub fn send_application_approved_email(
user: &LocalUserView,
settings: &Settings,
) -> Result<(), LemmyError> {
let email = &user.local_user.email.to_owned().expect("email");
let lang = get_user_lang(user);
let subject = lang.registration_approved_subject(&user.person.actor_id);
let body = lang.registration_approved_body(&settings.hostname);
send_email(&subject, email, &user.person.name, &body, settings)
}
pub async fn check_registration_application(
site: &Site,
local_user_view: &LocalUserView,
pool: &DbPool,
) -> Result<(), LemmyError> {
if site.require_application
&& !local_user_view.local_user.accepted_application
&& !local_user_view.person.admin
{
// Fetch the registration, see if its denied
let local_user_id = local_user_view.local_user.id;
let registration = blocking(pool, move |conn| {
RegistrationApplication::find_by_local_user_id(conn, local_user_id)
})
.await??;
if let Some(deny_reason) = registration.deny_reason {
let lang = get_user_lang(local_user_view);
let registration_denied_message = format!("{}: {}", lang.registration_denied(), &deny_reason);
return Err(LemmyError::from_message(&registration_denied_message));
} else {
return Err(LemmyError::from_message("registration_application_pending"));
}
}
Ok(())
}
/// TODO this check should be removed after https://github.com/LemmyNet/lemmy/issues/868 is done.
pub async fn check_private_instance_and_federation_enabled(
pool: &DbPool,
settings: &Settings,
) -> Result<(), LemmyError> {
let site_opt = blocking(pool, Site::read_local_site).await?;
if let Ok(site) = site_opt {
if site.private_instance && settings.federation.enabled {
return Err(LemmyError::from_message(
"Cannot have both private instance and federation enabled.",
));
}
}
Ok(())
}
pub async fn remove_user_data(banned_person_id: PersonId, pool: &DbPool) -> Result<(), LemmyError> {
// Posts
blocking(pool, move |conn: &'_ _| {
Post::update_removed_for_creator(conn, banned_person_id, None, true)
})
.await??;
// Communities
// Remove all communities where they're the top mod
// for now, remove the communities manually
let first_mod_communities = blocking(pool, move |conn: &'_ _| {
CommunityModeratorView::get_community_first_mods(conn)
})
.await??;
// Filter to only this banned users top communities
let banned_user_first_communities: Vec<CommunityModeratorView> = first_mod_communities
.into_iter()
.filter(|fmc| fmc.moderator.id == banned_person_id)
.collect();
for first_mod_community in banned_user_first_communities {
blocking(pool, move |conn: &'_ _| {
Community::update_removed(conn, first_mod_community.community.id, true)
})
.await??;
}
// Comments
blocking(pool, move |conn: &'_ _| {
Comment::update_removed_for_creator(conn, banned_person_id, true)
})
.await??;
Ok(())
}
pub async fn remove_user_data_in_community(
community_id: CommunityId,
banned_person_id: PersonId,
pool: &DbPool,
) -> Result<(), LemmyError> {
// Posts
blocking(pool, move |conn| {
Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
})
.await??;
// Comments
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
let comments = blocking(pool, move |conn| {
CommentQueryBuilder::create(conn)
.creator_id(banned_person_id)
.community_id(community_id)
.limit(std::i64::MAX)
.list()
})
.await??;
for comment_view in &comments {
let comment_id = comment_view.comment.id;
blocking(pool, move |conn| {
Comment::update_removed(conn, comment_id, true)
})
.await??;
}
Ok(())
}
pub async fn delete_user_account(person_id: PersonId, pool: &DbPool) -> Result<(), LemmyError> {
// Comments
let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, person_id);
blocking(pool, permadelete)
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
// Posts
let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, person_id);
blocking(pool, permadelete)
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_post"))?;
blocking(pool, move |conn| Person::delete_account(conn, person_id)).await??;
Ok(())
}
pub fn check_image_has_local_domain(url: &Option<DbUrl>) -> Result<(), LemmyError> {
if let Some(url) = url {
let settings = Settings::get();
let domain = url.domain().expect("url has domain");
if domain != settings.hostname {
return Err(LemmyError::from_message("image_not_local"));
}
}
Ok(())
}

View file

@ -1,14 +1,6 @@
use lemmy_db_views::{
comment_view::CommentView,
post_view::PostView,
private_message_view::PrivateMessageView,
};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
person_mention_view::PersonMentionView,
person_view::PersonViewSafe,
};
use lemmy_utils::Sensitive;
use crate::sensitive::Sensitive;
use lemmy_db_views::structs::{CommentView, PostView, PrivateMessageView};
use lemmy_db_views_actor::structs::{CommunityModeratorView, PersonMentionView, PersonViewSafe};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]

View file

@ -1,14 +1,7 @@
use crate::sensitive::Sensitive;
use lemmy_db_schema::newtypes::{CommunityId, PostId, PostReportId};
use lemmy_db_views::{
comment_view::CommentView,
post_report_view::PostReportView,
post_view::PostView,
};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
};
use lemmy_utils::{request::SiteMetadata, Sensitive};
use lemmy_db_views::structs::{CommentView, PostReportView, PostView};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
use serde::{Deserialize, Serialize};
use url::Url;
@ -164,3 +157,11 @@ pub struct GetSiteMetadata {
pub struct GetSiteMetadataResponse {
pub metadata: SiteMetadata,
}
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
pub struct SiteMetadata {
pub title: Option<String>,
pub description: Option<String>,
pub(crate) image: Option<Url>,
pub html: Option<String>,
}

View file

@ -0,0 +1,274 @@
use crate::post::SiteMetadata;
use encoding::{all::encodings, DecoderTrap};
use lemmy_utils::{settings::structs::Settings, version::VERSION, LemmyError, REQWEST_TIMEOUT};
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
use reqwest_middleware::ClientWithMiddleware;
use serde::Deserialize;
use tracing::info;
use url::Url;
use webpage::HTML;
/// Fetches the post link html tags (like title, description, image, etc)
#[tracing::instrument(skip_all)]
pub async fn fetch_site_metadata(
client: &ClientWithMiddleware,
url: &Url,
) -> Result<SiteMetadata, LemmyError> {
info!("Fetching site metadata for url: {}", url);
let response = client
.get(url.as_str())
.timeout(REQWEST_TIMEOUT)
.send()
.await?;
// Can't use .text() here, because it only checks the content header, not the actual bytes
// https://github.com/LemmyNet/lemmy/issues/1964
let html_bytes = response.bytes().await.map_err(LemmyError::from)?.to_vec();
let tags = html_to_site_metadata(&html_bytes)?;
Ok(tags)
}
fn html_to_site_metadata(html_bytes: &[u8]) -> Result<SiteMetadata, LemmyError> {
let html = String::from_utf8_lossy(html_bytes);
// Make sure the first line is doctype html
let first_line = html
.trim_start()
.lines()
.into_iter()
.next()
.ok_or_else(|| LemmyError::from_message("No lines in html"))?
.to_lowercase();
if !first_line.starts_with("<!doctype html>") {
return Err(LemmyError::from_message(
"Site metadata page fetch is not DOCTYPE html",
));
}
let mut page = HTML::from_string(html.to_string(), None)?;
// If the web page specifies that it isn't actually UTF-8, re-decode the received bytes with the
// proper encoding. If the specified encoding cannot be found, fall back to the original UTF-8
// version.
if let Some(charset) = page.meta.get("charset") {
if charset.to_lowercase() != "utf-8" {
if let Some(encoding_ref) = encodings().iter().find(|e| e.name() == charset) {
if let Ok(html_with_encoding) = encoding_ref.decode(html_bytes, DecoderTrap::Replace) {
page = HTML::from_string(html_with_encoding, None)?;
}
}
}
}
let page_title = page.title;
let page_description = page.description;
let og_description = page
.opengraph
.properties
.get("description")
.map(|t| t.to_string());
let og_title = page
.opengraph
.properties
.get("title")
.map(|t| t.to_string());
let og_image = page
.opengraph
.images
.get(0)
.and_then(|ogo| Url::parse(&ogo.url).ok());
let title = og_title.or(page_title);
let description = og_description.or(page_description);
let image = og_image;
Ok(SiteMetadata {
title,
description,
image,
html: None,
})
}
#[derive(Deserialize, Debug, Clone)]
pub(crate) struct PictrsResponse {
files: Vec<PictrsFile>,
msg: String,
}
#[derive(Deserialize, Debug, Clone)]
pub(crate) struct PictrsFile {
file: String,
#[allow(dead_code)]
delete_token: String,
}
#[tracing::instrument(skip_all)]
pub(crate) async fn fetch_pictrs(
client: &ClientWithMiddleware,
settings: &Settings,
image_url: &Url,
) -> Result<PictrsResponse, LemmyError> {
if let Some(pictrs_url) = settings.pictrs_url.to_owned() {
is_image_content_type(client, image_url).await?;
let fetch_url = format!(
"{}/image/download?url={}",
pictrs_url,
utf8_percent_encode(image_url.as_str(), NON_ALPHANUMERIC) // TODO this might not be needed
);
let response = client
.get(&fetch_url)
.timeout(REQWEST_TIMEOUT)
.send()
.await?;
let response: PictrsResponse = response.json().await.map_err(LemmyError::from)?;
if response.msg == "ok" {
Ok(response)
} else {
Err(LemmyError::from_message(&response.msg))
}
} else {
Err(LemmyError::from_message("pictrs_url not set up in config"))
}
}
/// Both are options, since the URL might be either an html page, or an image
/// Returns the SiteMetadata, and a Pictrs URL, if there is a picture associated
#[tracing::instrument(skip_all)]
pub async fn fetch_site_data(
client: &ClientWithMiddleware,
settings: &Settings,
url: Option<&Url>,
) -> (Option<SiteMetadata>, Option<Url>) {
match &url {
Some(url) => {
// Fetch metadata
// Ignore errors, since it may be an image, or not have the data.
// Warning, this may ignore SSL errors
let metadata_option = fetch_site_metadata(client, url).await.ok();
// Fetch pictrs thumbnail
let pictrs_hash = match &metadata_option {
Some(metadata_res) => match &metadata_res.image {
// Metadata, with image
// Try to generate a small thumbnail if there's a full sized one from post-links
Some(metadata_image) => fetch_pictrs(client, settings, metadata_image)
.await
.map(|r| r.files[0].file.to_owned()),
// Metadata, but no image
None => fetch_pictrs(client, settings, url)
.await
.map(|r| r.files[0].file.to_owned()),
},
// No metadata, try to fetch the URL as an image
None => fetch_pictrs(client, settings, url)
.await
.map(|r| r.files[0].file.to_owned()),
};
// The full urls are necessary for federation
let pictrs_thumbnail = pictrs_hash
.map(|p| {
Url::parse(&format!(
"{}/pictrs/image/{}",
settings.get_protocol_and_hostname(),
p
))
.ok()
})
.ok()
.flatten();
(metadata_option, pictrs_thumbnail)
}
None => (None, None),
}
}
#[tracing::instrument(skip_all)]
async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> Result<(), LemmyError> {
let response = client
.get(url.as_str())
.timeout(REQWEST_TIMEOUT)
.send()
.await?;
if response
.headers()
.get("Content-Type")
.ok_or_else(|| LemmyError::from_message("No Content-Type header"))?
.to_str()?
.starts_with("image/")
{
Ok(())
} else {
Err(LemmyError::from_message("Not an image type."))
}
}
pub fn build_user_agent(settings: &Settings) -> String {
format!(
"Lemmy/{}; +{}",
VERSION,
settings.get_protocol_and_hostname()
)
}
#[cfg(test)]
mod tests {
use crate::request::{build_user_agent, fetch_site_metadata, SiteMetadata};
use lemmy_utils::settings::structs::Settings;
use url::Url;
// These helped with testing
#[actix_rt::test]
async fn test_site_metadata() {
let settings = Settings::init().unwrap();
let client = reqwest::Client::builder()
.user_agent(build_user_agent(&settings))
.build()
.unwrap()
.into();
let sample_url = Url::parse("https://gitlab.com/IzzyOnDroid/repo/-/wikis/FAQ").unwrap();
let sample_res = fetch_site_metadata(&client, &sample_url).await.unwrap();
assert_eq!(
SiteMetadata {
title: Some("FAQ · Wiki · IzzyOnDroid / repo · GitLab".to_string()),
description: Some(
"The F-Droid compatible repo at https://apt.izzysoft.de/fdroid/".to_string()
),
image: Some(
Url::parse("https://gitlab.com/uploads/-/system/project/avatar/4877469/iod_logo.png")
.unwrap()
),
html: None,
},
sample_res
);
let youtube_url = Url::parse("https://www.youtube.com/watch?v=IquO_TcMZIQ").unwrap();
let youtube_res = fetch_site_metadata(&client, &youtube_url).await.unwrap();
assert_eq!(
SiteMetadata {
title: Some("A Hard Look at Rent and Rent Seeking with Michael Hudson & Pepe Escobar".to_string()),
description: Some("An interactive discussion on wealth inequality and the “Great Game” on the control of natural resources.In this webinar organized jointly by the Henry George...".to_string()),
image: Some(Url::parse("https://i.ytimg.com/vi/IquO_TcMZIQ/maxresdefault.jpg").unwrap()),
html: None,
}, youtube_res);
}
// #[test]
// fn test_pictshare() {
// let res = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpg");
// assert!(res.is_ok());
// let res_other = fetch_pictshare("https://upload.wikimedia.org/wikipedia/en/2/27/The_Mandalorian_logo.jpgaoeu");
// assert!(res_other.is_err());
// }
}

View file

@ -1,9 +1,10 @@
use serde::{Deserialize, Serialize};
use std::{
borrow::Borrow,
ops::{Deref, DerefMut},
};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Deserialize, serde::Serialize)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
#[serde(transparent)]
pub struct Sensitive<T>(T);
@ -12,8 +13,8 @@ impl<T> Sensitive<T> {
Sensitive(item)
}
pub fn into_inner(this: Self) -> T {
this.0
pub fn into_inner(self) -> T {
self.0
}
}

View file

@ -1,33 +1,33 @@
use crate::sensitive::Sensitive;
use lemmy_db_schema::newtypes::{CommunityId, PersonId};
use lemmy_db_views::{
comment_view::CommentView,
local_user_view::LocalUserSettingsView,
post_view::PostView,
registration_application_view::RegistrationApplicationView,
site_view::SiteView,
use lemmy_db_views::structs::{
CommentView,
LocalUserSettingsView,
PostView,
RegistrationApplicationView,
SiteView,
};
use lemmy_db_views_actor::{
community_block_view::CommunityBlockView,
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
person_block_view::PersonBlockView,
person_view::PersonViewSafe,
use lemmy_db_views_actor::structs::{
CommunityBlockView,
CommunityFollowerView,
CommunityModeratorView,
CommunityView,
PersonBlockView,
PersonViewSafe,
};
use lemmy_db_views_moderator::{
mod_add_community_view::ModAddCommunityView,
mod_add_view::ModAddView,
mod_ban_from_community_view::ModBanFromCommunityView,
mod_ban_view::ModBanView,
mod_hide_community_view::ModHideCommunityView,
mod_lock_post_view::ModLockPostView,
mod_remove_comment_view::ModRemoveCommentView,
mod_remove_community_view::ModRemoveCommunityView,
mod_remove_post_view::ModRemovePostView,
mod_sticky_post_view::ModStickyPostView,
mod_transfer_community_view::ModTransferCommunityView,
use lemmy_db_views_moderator::structs::{
ModAddCommunityView,
ModAddView,
ModBanFromCommunityView,
ModBanView,
ModHideCommunityView,
ModLockPostView,
ModRemoveCommentView,
ModRemoveCommunityView,
ModRemovePostView,
ModStickyPostView,
ModTransferCommunityView,
};
use lemmy_utils::Sensitive;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]

View file

@ -0,0 +1,605 @@
use crate::{sensitive::Sensitive, site::FederatedInstances};
use lemmy_db_schema::{
newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId},
source::{
comment::Comment,
community::Community,
email_verification::{EmailVerification, EmailVerificationForm},
password_reset_request::PasswordResetRequest,
person::Person,
person_block::PersonBlock,
post::{Post, PostRead, PostReadForm},
registration_application::RegistrationApplication,
secret::Secret,
site::Site,
},
traits::{Crud, Readable},
utils::DbPool,
};
use lemmy_db_views::{
comment_view::CommentQueryBuilder,
structs::{LocalUserSettingsView, LocalUserView},
};
use lemmy_db_views_actor::structs::{
CommunityModeratorView,
CommunityPersonBanView,
CommunityView,
};
use lemmy_utils::{
claims::Claims,
email::{send_email, translations::Lang},
settings::structs::Settings,
utils::generate_random_string,
LemmyError,
};
use rosetta_i18n::{Language, LanguageId};
use tracing::warn;
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
where
F: FnOnce(&diesel::PgConnection) -> T + Send + 'static,
T: Send + 'static,
{
let pool = pool.clone();
let blocking_span = tracing::info_span!("blocking operation");
let res = actix_web::web::block(move || {
let entered = blocking_span.enter();
let conn = pool.get()?;
let res = (f)(&conn);
drop(entered);
Ok(res) as Result<T, LemmyError>
})
.await?;
res
}
#[tracing::instrument(skip_all)]
pub async fn is_mod_or_admin(
pool: &DbPool,
person_id: PersonId,
community_id: CommunityId,
) -> Result<(), LemmyError> {
let is_mod_or_admin = blocking(pool, move |conn| {
CommunityView::is_mod_or_admin(conn, person_id, community_id)
})
.await?;
if !is_mod_or_admin {
return Err(LemmyError::from_message("not_a_mod_or_admin"));
}
Ok(())
}
pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
if !local_user_view.person.admin {
return Err(LemmyError::from_message("not_an_admin"));
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub async fn get_post(post_id: PostId, pool: &DbPool) -> Result<Post, LemmyError> {
blocking(pool, move |conn| Post::read(conn, post_id))
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))
}
#[tracing::instrument(skip_all)]
pub async fn mark_post_as_read(
person_id: PersonId,
post_id: PostId,
pool: &DbPool,
) -> Result<PostRead, LemmyError> {
let post_read_form = PostReadForm { post_id, person_id };
blocking(pool, move |conn| {
PostRead::mark_as_read(conn, &post_read_form)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
}
#[tracing::instrument(skip_all)]
pub async fn mark_post_as_unread(
person_id: PersonId,
post_id: PostId,
pool: &DbPool,
) -> Result<usize, LemmyError> {
let post_read_form = PostReadForm { post_id, person_id };
blocking(pool, move |conn| {
PostRead::mark_as_unread(conn, &post_read_form)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_view_from_jwt(
jwt: &str,
pool: &DbPool,
secret: &Secret,
) -> Result<LocalUserView, LemmyError> {
let claims = Claims::decode(jwt, &secret.jwt_secret)
.map_err(|e| e.with_message("not_logged_in"))?
.claims;
let local_user_id = LocalUserId(claims.sub);
let local_user_view =
blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
// Check for a site ban
if local_user_view.person.is_banned() {
return Err(LemmyError::from_message("site_ban"));
}
// Check for user deletion
if local_user_view.person.deleted {
return Err(LemmyError::from_message("deleted"));
}
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
Ok(local_user_view)
}
/// Checks if user's token was issued before user's password reset.
pub fn check_validator_time(
validator_time: &chrono::NaiveDateTime,
claims: &Claims,
) -> Result<(), LemmyError> {
let user_validation_time = validator_time.timestamp();
if user_validation_time > claims.iat {
Err(LemmyError::from_message("not_logged_in"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_view_from_jwt_opt(
jwt: Option<&Sensitive<String>>,
pool: &DbPool,
secret: &Secret,
) -> Result<Option<LocalUserView>, LemmyError> {
match jwt {
Some(jwt) => Ok(Some(get_local_user_view_from_jwt(jwt, pool, secret).await?)),
None => Ok(None),
}
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_settings_view_from_jwt(
jwt: &Sensitive<String>,
pool: &DbPool,
secret: &Secret,
) -> Result<LocalUserSettingsView, LemmyError> {
let claims = Claims::decode(jwt.as_ref(), &secret.jwt_secret)
.map_err(|e| e.with_message("not_logged_in"))?
.claims;
let local_user_id = LocalUserId(claims.sub);
let local_user_view = blocking(pool, move |conn| {
LocalUserSettingsView::read(conn, local_user_id)
})
.await??;
// Check for a site ban
if local_user_view.person.is_banned() {
return Err(LemmyError::from_message("site_ban"));
}
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
Ok(local_user_view)
}
#[tracing::instrument(skip_all)]
pub async fn get_local_user_settings_view_from_jwt_opt(
jwt: Option<&Sensitive<String>>,
pool: &DbPool,
secret: &Secret,
) -> Result<Option<LocalUserSettingsView>, LemmyError> {
match jwt {
Some(jwt) => Ok(Some(
get_local_user_settings_view_from_jwt(jwt, pool, secret).await?,
)),
None => Ok(None),
}
}
#[tracing::instrument(skip_all)]
pub async fn check_community_ban(
person_id: PersonId,
community_id: CommunityId,
pool: &DbPool,
) -> Result<(), LemmyError> {
let is_banned =
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
if blocking(pool, is_banned).await? {
Err(LemmyError::from_message("community_ban"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_community_deleted_or_removed(
community_id: CommunityId,
pool: &DbPool,
) -> Result<(), LemmyError> {
let community = blocking(pool, move |conn| Community::read(conn, community_id))
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
if community.deleted || community.removed {
Err(LemmyError::from_message("deleted"))
} else {
Ok(())
}
}
pub fn check_post_deleted_or_removed(post: &Post) -> Result<(), LemmyError> {
if post.deleted || post.removed {
Err(LemmyError::from_message("deleted"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_person_block(
my_id: PersonId,
potential_blocker_id: PersonId,
pool: &DbPool,
) -> Result<(), LemmyError> {
let is_blocked = move |conn: &'_ _| PersonBlock::read(conn, potential_blocker_id, my_id).is_ok();
if blocking(pool, is_blocked).await? {
Err(LemmyError::from_message("person_block"))
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
if score == -1 {
let site = blocking(pool, Site::read_local_site).await??;
if !site.enable_downvotes {
return Err(LemmyError::from_message("downvotes_disabled"));
}
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub async fn check_private_instance(
local_user_view: &Option<LocalUserView>,
pool: &DbPool,
) -> Result<(), LemmyError> {
if local_user_view.is_none() {
let site = blocking(pool, Site::read_local_site).await?;
// The site might not be set up yet
if let Ok(site) = site {
if site.private_instance {
return Err(LemmyError::from_message("instance_is_private"));
}
}
}
Ok(())
}
#[tracing::instrument(skip_all)]
pub async fn build_federated_instances(
pool: &DbPool,
settings: &Settings,
) -> Result<Option<FederatedInstances>, LemmyError> {
let federation_config = &settings.federation;
let hostname = &settings.hostname;
let federation = federation_config.to_owned();
if federation.enabled {
let distinct_communities = blocking(pool, move |conn| {
Community::distinct_federated_communities(conn)
})
.await??;
let allowed = federation.allowed_instances;
let blocked = federation.blocked_instances;
let mut linked = distinct_communities
.iter()
.map(|actor_id| Ok(actor_id.host_str().unwrap_or("").to_string()))
.collect::<Result<Vec<String>, LemmyError>>()?;
if let Some(allowed) = allowed.as_ref() {
linked.extend_from_slice(allowed);
}
if let Some(blocked) = blocked.as_ref() {
linked.retain(|a| !blocked.contains(a) && !a.eq(hostname));
}
// Sort and remove dupes
linked.sort_unstable();
linked.dedup();
Ok(Some(FederatedInstances {
linked,
allowed,
blocked,
}))
} else {
Ok(None)
}
}
/// Checks the password length
pub fn password_length_check(pass: &str) -> Result<(), LemmyError> {
if !(10..=60).contains(&pass.len()) {
Err(LemmyError::from_message("invalid_password"))
} else {
Ok(())
}
}
/// Checks the site description length
pub fn site_description_length_check(description: &str) -> Result<(), LemmyError> {
if description.len() > 150 {
Err(LemmyError::from_message("site_description_length_overflow"))
} else {
Ok(())
}
}
/// Checks for a honeypot. If this field is filled, fail the rest of the function
pub fn honeypot_check(honeypot: &Option<String>) -> Result<(), LemmyError> {
if honeypot.is_some() {
Err(LemmyError::from_message("honeypot_fail"))
} else {
Ok(())
}
}
pub fn send_email_to_user(
local_user_view: &LocalUserView,
subject: &str,
body: &str,
settings: &Settings,
) {
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
return;
}
if let Some(user_email) = &local_user_view.local_user.email {
match send_email(
subject,
user_email,
&local_user_view.person.name,
body,
settings,
) {
Ok(_o) => _o,
Err(e) => warn!("{}", e),
};
}
}
pub async fn send_password_reset_email(
user: &LocalUserView,
pool: &DbPool,
settings: &Settings,
) -> Result<(), LemmyError> {
// Generate a random token
let token = generate_random_string();
// Insert the row
let token2 = token.clone();
let local_user_id = user.local_user.id;
blocking(pool, move |conn| {
PasswordResetRequest::create_token(conn, local_user_id, &token2)
})
.await??;
let email = &user.local_user.email.to_owned().expect("email");
let lang = get_user_lang(user);
let subject = &lang.password_reset_subject(&user.person.name);
let protocol_and_hostname = settings.get_protocol_and_hostname();
let reset_link = format!("{}/password_change/{}", protocol_and_hostname, &token);
let body = &lang.password_reset_body(&user.person.name, reset_link);
send_email(subject, email, &user.person.name, body, settings)
}
/// Send a verification email
pub async fn send_verification_email(
user: &LocalUserView,
new_email: &str,
pool: &DbPool,
settings: &Settings,
) -> Result<(), LemmyError> {
let form = EmailVerificationForm {
local_user_id: user.local_user.id,
email: new_email.to_string(),
verification_token: generate_random_string(),
};
let verify_link = format!(
"{}/verify_email/{}",
settings.get_protocol_and_hostname(),
&form.verification_token
);
blocking(pool, move |conn| EmailVerification::create(conn, &form)).await??;
let lang = get_user_lang(user);
let subject = lang.verify_email_subject(&settings.hostname);
let body = lang.verify_email_body(&user.person.name, &settings.hostname, verify_link);
send_email(&subject, new_email, &user.person.name, &body, settings)?;
Ok(())
}
pub fn send_email_verification_success(
user: &LocalUserView,
settings: &Settings,
) -> Result<(), LemmyError> {
let email = &user.local_user.email.to_owned().expect("email");
let lang = get_user_lang(user);
let subject = &lang.email_verified_subject(&user.person.actor_id);
let body = &lang.email_verified_body();
send_email(subject, email, &user.person.name, body, settings)
}
pub fn get_user_lang(user: &LocalUserView) -> Lang {
let user_lang = LanguageId::new(user.local_user.lang.clone());
Lang::from_language_id(&user_lang).unwrap_or_else(|| {
let en = LanguageId::new("en");
Lang::from_language_id(&en).expect("default language")
})
}
pub fn send_application_approved_email(
user: &LocalUserView,
settings: &Settings,
) -> Result<(), LemmyError> {
let email = &user.local_user.email.to_owned().expect("email");
let lang = get_user_lang(user);
let subject = lang.registration_approved_subject(&user.person.actor_id);
let body = lang.registration_approved_body(&settings.hostname);
send_email(&subject, email, &user.person.name, &body, settings)
}
pub async fn check_registration_application(
site: &Site,
local_user_view: &LocalUserView,
pool: &DbPool,
) -> Result<(), LemmyError> {
if site.require_application
&& !local_user_view.local_user.accepted_application
&& !local_user_view.person.admin
{
// Fetch the registration, see if its denied
let local_user_id = local_user_view.local_user.id;
let registration = blocking(pool, move |conn| {
RegistrationApplication::find_by_local_user_id(conn, local_user_id)
})
.await??;
if let Some(deny_reason) = registration.deny_reason {
let lang = get_user_lang(local_user_view);
let registration_denied_message = format!("{}: {}", lang.registration_denied(), &deny_reason);
return Err(LemmyError::from_message(&registration_denied_message));
} else {
return Err(LemmyError::from_message("registration_application_pending"));
}
}
Ok(())
}
/// TODO this check should be removed after https://github.com/LemmyNet/lemmy/issues/868 is done.
pub async fn check_private_instance_and_federation_enabled(
pool: &DbPool,
settings: &Settings,
) -> Result<(), LemmyError> {
let site_opt = blocking(pool, Site::read_local_site).await?;
if let Ok(site) = site_opt {
if site.private_instance && settings.federation.enabled {
return Err(LemmyError::from_message(
"Cannot have both private instance and federation enabled.",
));
}
}
Ok(())
}
pub async fn remove_user_data(banned_person_id: PersonId, pool: &DbPool) -> Result<(), LemmyError> {
// Posts
blocking(pool, move |conn: &'_ _| {
Post::update_removed_for_creator(conn, banned_person_id, None, true)
})
.await??;
// Communities
// Remove all communities where they're the top mod
// for now, remove the communities manually
let first_mod_communities = blocking(pool, move |conn: &'_ _| {
CommunityModeratorView::get_community_first_mods(conn)
})
.await??;
// Filter to only this banned users top communities
let banned_user_first_communities: Vec<CommunityModeratorView> = first_mod_communities
.into_iter()
.filter(|fmc| fmc.moderator.id == banned_person_id)
.collect();
for first_mod_community in banned_user_first_communities {
blocking(pool, move |conn: &'_ _| {
Community::update_removed(conn, first_mod_community.community.id, true)
})
.await??;
}
// Comments
blocking(pool, move |conn: &'_ _| {
Comment::update_removed_for_creator(conn, banned_person_id, true)
})
.await??;
Ok(())
}
pub async fn remove_user_data_in_community(
community_id: CommunityId,
banned_person_id: PersonId,
pool: &DbPool,
) -> Result<(), LemmyError> {
// Posts
blocking(pool, move |conn| {
Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
})
.await??;
// Comments
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
let comments = blocking(pool, move |conn| {
CommentQueryBuilder::create(conn)
.creator_id(banned_person_id)
.community_id(community_id)
.limit(std::i64::MAX)
.list()
})
.await??;
for comment_view in &comments {
let comment_id = comment_view.comment.id;
blocking(pool, move |conn| {
Comment::update_removed(conn, comment_id, true)
})
.await??;
}
Ok(())
}
pub async fn delete_user_account(person_id: PersonId, pool: &DbPool) -> Result<(), LemmyError> {
// Comments
let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, person_id);
blocking(pool, permadelete)
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
// Posts
let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, person_id);
blocking(pool, permadelete)
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_post"))?;
blocking(pool, move |conn| Person::delete_account(conn, person_id)).await??;
Ok(())
}
pub fn check_image_has_local_domain(url: &Option<DbUrl>) -> Result<(), LemmyError> {
if let Some(url) = url {
let settings = Settings::get();
let domain = url.domain().expect("url has domain");
if domain != settings.hostname {
return Err(LemmyError::from_message("image_not_local"));
}
}
Ok(())
}

View file

@ -1,5 +1,5 @@
use crate::sensitive::Sensitive;
use lemmy_db_schema::newtypes::{CommunityId, PostId};
use lemmy_utils::Sensitive;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]

View file

@ -11,10 +11,10 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
lemmy_apub = { version = "=0.16.3", path = "../apub" }
lemmy_apub_lib = { version = "=0.16.3", path = "../apub_lib" }
lemmy_utils = { version = "=0.16.3", path = "../utils" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema" }
lemmy_db_views = { version = "=0.16.3", path = "../db_views" }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor" }
lemmy_api_common = { version = "=0.16.3", path = "../api_common" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema", features = ["full"] }
lemmy_db_views = { version = "=0.16.3", path = "../db_views", features = ["full"] }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor", features = ["full"] }
lemmy_api_common = { version = "=0.16.3", path = "../api_common", features = ["full"] }
lemmy_websocket = { version = "=0.16.3", path = "../websocket" }
bcrypt = "0.12.1"
serde_json = { version = "1.0.79", features = ["preserve_order"] }

View file

@ -1,13 +1,15 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, CreateComment},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
check_post_deleted_or_removed,
comment::*,
get_local_user_view_from_jwt,
get_post,
},
};
use lemmy_apub::{
generate_local_apub_endpoint,
@ -22,7 +24,7 @@ use lemmy_db_schema::{
},
traits::{Crud, Likeable},
};
use lemmy_db_views::comment_view::CommentView;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{
utils::{remove_slurs, scrape_text_for_mentions},
ConnectionId,

View file

@ -1,23 +1,15 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_community_ban,
comment::*,
get_local_user_view_from_jwt,
is_mod_or_admin,
comment::{CommentResponse, DeleteComment},
utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
comment::Comment,
community::Community,
moderator::{ModRemoveComment, ModRemoveCommentForm},
post::Post,
},
source::{comment::Comment, community::Community, post::Post},
traits::Crud,
};
use lemmy_db_views::comment_view::CommentView;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{
send::{send_comment_ws_message, send_local_notifs},
@ -112,101 +104,3 @@ impl PerformCrud for DeleteComment {
Ok(res)
}
}
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveComment {
type Response = CommentResponse;
#[tracing::instrument(skip(context, websocket_id))]
async fn perform(
&self,
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> {
let data: &RemoveComment = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
let comment_id = data.comment_id;
let orig_comment = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, None)
})
.await??;
check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only a mod or admin can remove
is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_comment.community.id,
)
.await?;
// Do the remove
let removed = data.removed;
let updated_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment_id, removed)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
// Mod tables
let form = ModRemoveCommentForm {
mod_person_id: local_user_view.person.id,
comment_id: data.comment_id,
removed: Some(removed),
reason: data.reason.to_owned(),
};
blocking(context.pool(), move |conn| {
ModRemoveComment::create(conn, &form)
})
.await??;
let post_id = updated_comment.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let recipient_ids = send_local_notifs(
vec![],
&updated_comment,
&local_user_view.person.clone(),
&post,
false,
context,
)
.await?;
let res = send_comment_ws_message(
data.comment_id,
UserOperationCrud::RemoveComment,
websocket_id,
None, // TODO maybe this might clear other forms
Some(local_user_view.person.id),
recipient_ids,
context,
)
.await?;
// Send the apub message
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_comment.post.community_id)
})
.await??;
let deletable = DeletableObjects::Comment(Box::new(updated_comment.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
data.reason.clone().or_else(|| Some("".to_string())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,18 +1,14 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
comment::*,
get_local_user_view_from_jwt_opt,
comment::{GetComments, GetCommentsResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
use lemmy_db_schema::{
from_opt_str_to_opt_enum,
source::community::Community,
traits::DeleteableOrRemoveable,
ListingType,
SortType,
utils::{from_opt_str_to_opt_enum, ListingType, SortType},
};
use lemmy_db_views::comment_view::CommentQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};

View file

@ -2,4 +2,5 @@ mod create;
mod delete;
mod list;
mod read;
mod remove;
mod update;

View file

@ -1,12 +1,10 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
comment::*,
get_local_user_view_from_jwt_opt,
comment::{CommentResponse, GetComment},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_db_views::comment_view::CommentView;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -0,0 +1,121 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, RemoveComment},
utils::{blocking, check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
comment::Comment,
community::Community,
moderator::{ModRemoveComment, ModRemoveCommentForm},
post::Post,
},
traits::Crud,
};
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{
send::{send_comment_ws_message, send_local_notifs},
LemmyContext,
UserOperationCrud,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveComment {
type Response = CommentResponse;
#[tracing::instrument(skip(context, websocket_id))]
async fn perform(
&self,
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<CommentResponse, LemmyError> {
let data: &RemoveComment = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
let comment_id = data.comment_id;
let orig_comment = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment_id, None)
})
.await??;
check_community_ban(
local_user_view.person.id,
orig_comment.community.id,
context.pool(),
)
.await?;
// Verify that only a mod or admin can remove
is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_comment.community.id,
)
.await?;
// Do the remove
let removed = data.removed;
let updated_comment = blocking(context.pool(), move |conn| {
Comment::update_removed(conn, comment_id, removed)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
// Mod tables
let form = ModRemoveCommentForm {
mod_person_id: local_user_view.person.id,
comment_id: data.comment_id,
removed: Some(removed),
reason: data.reason.to_owned(),
};
blocking(context.pool(), move |conn| {
ModRemoveComment::create(conn, &form)
})
.await??;
let post_id = updated_comment.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let recipient_ids = send_local_notifs(
vec![],
&updated_comment,
&local_user_view.person.clone(),
&post,
false,
context,
)
.await?;
let res = send_comment_ws_message(
data.comment_id,
UserOperationCrud::RemoveComment,
websocket_id,
None, // TODO maybe this might clear other forms
Some(local_user_view.person.id),
recipient_ids,
context,
)
.await?;
// Send the apub message
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_comment.post.community_id)
})
.await??;
let deletable = DeletableObjects::Comment(Box::new(updated_comment.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
data.reason.clone().or_else(|| Some("".to_string())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,19 +1,20 @@
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, EditComment},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
check_post_deleted_or_removed,
comment::*,
get_local_user_view_from_jwt,
},
};
use lemmy_apub::protocol::activities::{
create_or_update::comment::CreateOrUpdateComment,
CreateOrUpdateType,
};
use lemmy_db_schema::source::comment::Comment;
use lemmy_db_views::comment_view::CommentView;
use lemmy_db_views::structs::CommentView;
use lemmy_utils::{
utils::{remove_slurs, scrape_text_for_mentions},
ConnectionId,

View file

@ -1,11 +1,8 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_image_has_local_domain,
community::{CommunityResponse, CreateCommunity},
get_local_user_view_from_jwt,
is_admin,
utils::{blocking, check_image_has_local_domain, get_local_user_view_from_jwt, is_admin},
};
use lemmy_apub::{
generate_followers_url,
@ -17,7 +14,6 @@ use lemmy_apub::{
};
use lemmy_apub_lib::object_id::ObjectId;
use lemmy_db_schema::{
diesel_option_overwrite_to_url,
source::{
community::{
Community,
@ -30,8 +26,9 @@ use lemmy_db_schema::{
site::Site,
},
traits::{Crud, Followable, Joinable},
utils::diesel_option_overwrite_to_url,
};
use lemmy_db_views_actor::community_view::CommunityView;
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{
apub::generate_actor_keypair,
utils::{check_slurs, check_slurs_opt, is_valid_actor_name},

View file

@ -1,16 +1,13 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::Community,
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
},
traits::Crud,
use lemmy_api_common::{
community::{CommunityResponse, DeleteCommunity},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::source::community::Community;
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
#[async_trait::async_trait(?Send)]
@ -72,67 +69,3 @@ impl PerformCrud for DeleteCommunity {
Ok(res)
}
}
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveCommunity {
type Response = CommunityResponse;
#[tracing::instrument(skip(context, websocket_id))]
async fn perform(
&self,
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> {
let data: &RemoveCommunity = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
// Verify its an admin (only an admin can remove a community)
is_admin(&local_user_view)?;
// Do the remove
let community_id = data.community_id;
let removed = data.removed;
let updated_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community_id, removed)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
// Mod tables
let expires = data.expires.map(naive_from_unix);
let form = ModRemoveCommunityForm {
mod_person_id: local_user_view.person.id,
community_id: data.community_id,
removed: Some(removed),
reason: data.reason.to_owned(),
expires,
};
blocking(context.pool(), move |conn| {
ModRemoveCommunity::create(conn, &form)
})
.await??;
let res = send_community_ws_message(
data.community_id,
UserOperationCrud::RemoveCommunity,
websocket_id,
Some(local_user_view.person.id),
context,
)
.await?;
// Apub messages
let deletable = DeletableObjects::Community(Box::new(updated_community.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
updated_community,
deletable,
data.reason.clone().or_else(|| Some("".to_string())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,16 +1,12 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
community::*,
get_local_user_view_from_jwt_opt,
community::{ListCommunities, ListCommunitiesResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_db_schema::{
from_opt_str_to_opt_enum,
traits::DeleteableOrRemoveable,
ListingType,
SortType,
utils::{from_opt_str_to_opt_enum, ListingType, SortType},
};
use lemmy_db_views_actor::community_view::CommunityQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};

View file

@ -2,4 +2,5 @@ mod create;
mod delete;
mod list;
mod read;
mod remove;
mod update;

View file

@ -1,10 +1,8 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
community::*,
get_local_user_view_from_jwt_opt,
community::{GetCommunity, GetCommunityResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_apub::{
fetcher::resolve_actor_identifier,
@ -14,10 +12,7 @@ use lemmy_db_schema::{
source::{community::Community, site::Site},
traits::DeleteableOrRemoveable,
};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::GetCommunityUsersOnline, LemmyContext};

View file

@ -0,0 +1,80 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, RemoveCommunity},
utils::{blocking, get_local_user_view_from_jwt, is_admin},
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::Community,
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
},
traits::Crud,
};
use lemmy_utils::{utils::naive_from_unix, ConnectionId, LemmyError};
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveCommunity {
type Response = CommunityResponse;
#[tracing::instrument(skip(context, websocket_id))]
async fn perform(
&self,
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<CommunityResponse, LemmyError> {
let data: &RemoveCommunity = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
// Verify its an admin (only an admin can remove a community)
is_admin(&local_user_view)?;
// Do the remove
let community_id = data.community_id;
let removed = data.removed;
let updated_community = blocking(context.pool(), move |conn| {
Community::update_removed(conn, community_id, removed)
})
.await?
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
// Mod tables
let expires = data.expires.map(naive_from_unix);
let form = ModRemoveCommunityForm {
mod_person_id: local_user_view.person.id,
community_id: data.community_id,
removed: Some(removed),
reason: data.reason.to_owned(),
expires,
};
blocking(context.pool(), move |conn| {
ModRemoveCommunity::create(conn, &form)
})
.await??;
let res = send_community_ws_message(
data.community_id,
UserOperationCrud::RemoveCommunity,
websocket_id,
Some(local_user_view.person.id),
context,
)
.await?;
// Apub messages
let deletable = DeletableObjects::Community(Box::new(updated_community.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
updated_community,
deletable,
data.reason.clone().or_else(|| Some("".to_string())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,20 +1,17 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_image_has_local_domain,
community::{CommunityResponse, EditCommunity},
get_local_user_view_from_jwt,
utils::{blocking, check_image_has_local_domain, get_local_user_view_from_jwt},
};
use lemmy_apub::protocol::activities::community::update::UpdateCommunity;
use lemmy_db_schema::{
diesel_option_overwrite_to_url,
naive_now,
newtypes::PersonId,
source::community::{Community, CommunityForm},
traits::Crud,
utils::{diesel_option_overwrite_to_url, naive_now},
};
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::{utils::check_slurs_opt, ConnectionId, LemmyError};
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};

View file

@ -1,13 +1,16 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
post::{CreatePost, PostResponse},
request::fetch_site_data,
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
get_local_user_view_from_jwt,
honeypot_check,
mark_post_as_read,
post::*,
},
};
use lemmy_apub::{
generate_local_apub_endpoint,
@ -22,9 +25,8 @@ use lemmy_db_schema::{
},
traits::{Crud, Likeable},
};
use lemmy_db_views_actor::community_view::CommunityView;
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{
request::fetch_site_data,
utils::{
check_slurs,
check_slurs_opt,

View file

@ -1,20 +1,17 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
post::{DeletePost, PostResponse},
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
get_local_user_view_from_jwt,
is_mod_or_admin,
post::*,
},
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::Community,
moderator::{ModRemovePost, ModRemovePostForm},
post::Post,
},
source::{community::Community, post::Post},
traits::Crud,
};
use lemmy_utils::{ConnectionId, LemmyError};
@ -90,83 +87,3 @@ impl PerformCrud for DeletePost {
Ok(res)
}
}
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemovePost {
type Response = PostResponse;
#[tracing::instrument(skip(context, websocket_id))]
async fn perform(
&self,
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> {
let data: &RemovePost = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can remove
is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post
let post_id = data.post_id;
let removed = data.removed;
let updated_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post_id, removed)
})
.await??;
// Mod tables
let form = ModRemovePostForm {
mod_person_id: local_user_view.person.id,
post_id: data.post_id,
removed: Some(removed),
reason: data.reason.to_owned(),
};
blocking(context.pool(), move |conn| {
ModRemovePost::create(conn, &form)
})
.await??;
let res = send_post_ws_message(
data.post_id,
UserOperationCrud::RemovePost,
websocket_id,
Some(local_user_view.person.id),
context,
)
.await?;
// apub updates
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_post.community_id)
})
.await??;
let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
data.reason.clone().or_else(|| Some("".to_string())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,18 +1,14 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
get_local_user_view_from_jwt_opt,
post::{GetPosts, GetPostsResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
use lemmy_db_schema::{
from_opt_str_to_opt_enum,
source::{community::Community, site::Site},
traits::DeleteableOrRemoveable,
ListingType,
SortType,
utils::{from_opt_str_to_opt_enum, ListingType, SortType},
};
use lemmy_db_views::post_view::PostQueryBuilder;
use lemmy_utils::{ConnectionId, LemmyError};

View file

@ -2,4 +2,5 @@ mod create;
mod delete;
mod list;
mod read;
mod remove;
mod update;

View file

@ -1,18 +1,12 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
get_local_user_view_from_jwt_opt,
mark_post_as_read,
post::{GetPost, GetPostResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt, mark_post_as_read},
};
use lemmy_db_schema::traits::DeleteableOrRemoveable;
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostView};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
community_view::CommunityView,
};
use lemmy_db_views::{comment_view::CommentQueryBuilder, structs::PostView};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext};

View file

@ -0,0 +1,97 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
post::{PostResponse, RemovePost},
utils::{blocking, check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::Community,
moderator::{ModRemovePost, ModRemovePostForm},
post::Post,
},
traits::Crud,
};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemovePost {
type Response = PostResponse;
#[tracing::instrument(skip(context, websocket_id))]
async fn perform(
&self,
context: &Data<LemmyContext>,
websocket_id: Option<ConnectionId>,
) -> Result<PostResponse, LemmyError> {
let data: &RemovePost = self;
let local_user_view =
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
let post_id = data.post_id;
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
check_community_ban(
local_user_view.person.id,
orig_post.community_id,
context.pool(),
)
.await?;
// Verify that only the mods can remove
is_mod_or_admin(
context.pool(),
local_user_view.person.id,
orig_post.community_id,
)
.await?;
// Update the post
let post_id = data.post_id;
let removed = data.removed;
let updated_post = blocking(context.pool(), move |conn| {
Post::update_removed(conn, post_id, removed)
})
.await??;
// Mod tables
let form = ModRemovePostForm {
mod_person_id: local_user_view.person.id,
post_id: data.post_id,
removed: Some(removed),
reason: data.reason.to_owned(),
};
blocking(context.pool(), move |conn| {
ModRemovePost::create(conn, &form)
})
.await??;
let res = send_post_ws_message(
data.post_id,
UserOperationCrud::RemovePost,
websocket_id,
Some(local_user_view.person.id),
context,
)
.await?;
// apub updates
let community = blocking(context.pool(), move |conn| {
Community::read(conn, orig_post.community_id)
})
.await??;
let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
data.reason.clone().or_else(|| Some("".to_string())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,23 +1,24 @@
use actix_web::web::Data;
use lemmy_api_common::{
post::{EditPost, PostResponse},
request::fetch_site_data,
utils::{
blocking,
check_community_ban,
check_community_deleted_or_removed,
get_local_user_view_from_jwt,
post::*,
},
};
use lemmy_apub::protocol::activities::{
create_or_update::post::CreateOrUpdatePost,
CreateOrUpdateType,
};
use lemmy_db_schema::{
naive_now,
source::post::{Post, PostForm},
traits::Crud,
utils::naive_now,
};
use lemmy_utils::{
request::fetch_site_data,
utils::{check_slurs_opt, clean_optional_text, clean_url_params, is_valid_post_title},
ConnectionId,
LemmyError,

View file

@ -1,12 +1,14 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
person::{CreatePrivateMessage, PrivateMessageResponse},
utils::{
blocking,
check_person_block,
get_local_user_view_from_jwt,
get_user_lang,
person::{CreatePrivateMessage, PrivateMessageResponse},
send_email_to_user,
},
};
use lemmy_apub::{
generate_local_apub_endpoint,
@ -20,7 +22,7 @@ use lemmy_db_schema::{
source::private_message::{PrivateMessage, PrivateMessageForm},
traits::Crud,
};
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};

View file

@ -1,9 +1,8 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{DeletePrivateMessage, PrivateMessageResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_apub::activities::deletion::send_apub_delete_private_message;
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};

View file

@ -1,9 +1,8 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{GetPrivateMessages, PrivateMessagesResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_db_schema::traits::DeleteableOrRemoveable;
use lemmy_db_views::private_message_view::PrivateMessageQueryBuilder;

View file

@ -1,9 +1,8 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
get_local_user_view_from_jwt,
person::{EditPrivateMessage, PrivateMessageResponse},
utils::{blocking, get_local_user_view_from_jwt},
};
use lemmy_apub::protocol::activities::{
create_or_update::private_message::CreateOrUpdatePrivateMessage,

View file

@ -1,23 +1,23 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
site::{CreateSite, SiteResponse},
utils::{
blocking,
check_image_has_local_domain,
get_local_user_view_from_jwt,
is_admin,
site::*,
site_description_length_check,
},
};
use lemmy_apub::generate_site_inbox_url;
use lemmy_db_schema::{
diesel_option_overwrite,
diesel_option_overwrite_to_url,
naive_now,
newtypes::DbUrl,
source::site::{Site, SiteForm},
traits::Crud,
utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now},
};
use lemmy_db_views::site_view::SiteView;
use lemmy_db_views::structs::SiteView;
use lemmy_utils::{
apub::generate_actor_keypair,
settings::structs::Settings,

View file

@ -1,19 +1,17 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
build_federated_instances,
get_local_user_settings_view_from_jwt_opt,
person::Register,
site::*,
site::{CreateSite, GetSite, GetSiteResponse, MyUserInfo},
utils::{blocking, build_federated_instances, get_local_user_settings_view_from_jwt_opt},
};
use lemmy_db_views::site_view::SiteView;
use lemmy_db_views_actor::{
community_block_view::CommunityBlockView,
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
person_block_view::PersonBlockView,
person_view::PersonViewSafe,
use lemmy_db_views::structs::SiteView;
use lemmy_db_views_actor::structs::{
CommunityBlockView,
CommunityFollowerView,
CommunityModeratorView,
PersonBlockView,
PersonViewSafe,
};
use lemmy_utils::{version, ConnectionId, LemmyError};
use lemmy_websocket::{messages::GetUsersOnline, LemmyContext};

View file

@ -1,25 +1,24 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
site::{EditSite, SiteResponse},
utils::{
blocking,
check_image_has_local_domain,
get_local_user_view_from_jwt,
is_admin,
site::{EditSite, SiteResponse},
site_description_length_check,
},
};
use lemmy_db_schema::{
diesel_option_overwrite,
diesel_option_overwrite_to_url,
naive_now,
source::{
local_user::LocalUser,
site::{Site, SiteForm},
},
traits::Crud,
ListingType,
utils::{diesel_option_overwrite, diesel_option_overwrite_to_url, naive_now, ListingType},
};
use lemmy_db_views::site_view::SiteView;
use lemmy_db_views::structs::SiteView;
use lemmy_utils::{utils::check_slurs_opt, ConnectionId, LemmyError};
use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperationCrud};
use std::{default::Default, str::FromStr};

View file

@ -1,11 +1,8 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
honeypot_check,
password_length_check,
person::*,
send_verification_email,
person::{LoginResponse, Register},
utils::{blocking, honeypot_check, password_length_check, send_verification_email},
};
use lemmy_apub::{
generate_followers_url,
@ -15,7 +12,7 @@ use lemmy_apub::{
EndpointType,
};
use lemmy_db_schema::{
aggregates::person_aggregates::PersonAggregates,
aggregates::structs::PersonAggregates,
newtypes::CommunityId,
source::{
community::{
@ -33,8 +30,8 @@ use lemmy_db_schema::{
},
traits::{Crud, Followable, Joinable},
};
use lemmy_db_views::local_user_view::LocalUserView;
use lemmy_db_views_actor::person_view::PersonViewSafe;
use lemmy_db_views::structs::LocalUserView;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{
apub::generate_actor_keypair,
claims::Claims,

View file

@ -1,7 +1,10 @@
use crate::PerformCrud;
use actix_web::web::Data;
use bcrypt::verify;
use lemmy_api_common::{delete_user_account, get_local_user_view_from_jwt, person::*};
use lemmy_api_common::{
person::{DeleteAccount, DeleteAccountResponse},
utils::{delete_user_account, get_local_user_view_from_jwt},
};
use lemmy_apub::protocol::activities::deletion::delete_user::DeleteUser;
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -1,18 +1,16 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
blocking,
check_private_instance,
get_local_user_view_from_jwt_opt,
person::*,
person::{GetPersonDetails, GetPersonDetailsResponse},
utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
};
use lemmy_apub::{fetcher::resolve_actor_identifier, objects::person::ApubPerson};
use lemmy_db_schema::{from_opt_str_to_opt_enum, source::person::Person, SortType};
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
use lemmy_db_views_actor::{
community_moderator_view::CommunityModeratorView,
person_view::PersonViewSafe,
use lemmy_db_schema::{
source::person::Person,
utils::{from_opt_str_to_opt_enum, SortType},
};
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
use lemmy_db_views_actor::structs::{CommunityModeratorView, PersonViewSafe};
use lemmy_utils::{ConnectionId, LemmyError};
use lemmy_websocket::LemmyContext;

View file

@ -15,14 +15,14 @@ doctest = false
[dependencies]
lemmy_utils = { version = "=0.16.3", path = "../utils" }
lemmy_apub_lib = { version = "=0.16.3", path = "../apub_lib" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema" }
lemmy_db_views = { version = "=0.16.3", path = "../db_views" }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor" }
lemmy_api_common = { version = "=0.16.3", path = "../api_common" }
lemmy_db_schema = { version = "=0.16.3", path = "../db_schema", features = ["full"] }
lemmy_db_views = { version = "=0.16.3", path = "../db_views", features = ["full"] }
lemmy_db_views_actor = { version = "=0.16.3", path = "../db_views_actor", features = ["full"] }
lemmy_api_common = { version = "=0.16.3", path = "../api_common", features = ["full"] }
lemmy_websocket = { version = "=0.16.3", path = "../websocket" }
diesel = "1.4.8"
activitystreams-kinds = "0.2.1"
chrono = { version = "0.4.19", features = ["serde"] }
chrono = { version = "0.4.19", features = ["serde"], default-features = false }
serde_json = { version = "1.0.79", features = ["preserve_order"] }
serde = { version = "1.0.136", features = ["derive"] }
serde_with = "1.12.0"

View file

@ -16,7 +16,7 @@ use crate::{
use activitystreams_kinds::{activity::BlockType, public};
use anyhow::anyhow;
use chrono::NaiveDateTime;
use lemmy_api_common::{blocking, remove_user_data, remove_user_data_in_community};
use lemmy_api_common::utils::{blocking, remove_user_data, remove_user_data_in_community};
use lemmy_apub_lib::{
data::Data,
object_id::ObjectId,

View file

@ -3,12 +3,12 @@ use crate::{
protocol::objects::{group::Group, instance::Instance},
};
use chrono::NaiveDateTime;
use lemmy_api_common::blocking;
use lemmy_api_common::utils::blocking;
use lemmy_apub_lib::{
object_id::ObjectId,
traits::{ActorType, ApubObject},
};
use lemmy_db_schema::{source::site::Site, DbPool};
use lemmy_db_schema::{source::site::Site, utils::DbPool};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use serde::Deserialize;

View file

@ -12,7 +12,7 @@ use crate::{
protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
};
use activitystreams_kinds::{activity::UndoType, public};
use lemmy_api_common::blocking;
use lemmy_api_common::utils::blocking;
use lemmy_apub_lib::{
data::Data,
object_id::ObjectId,

Some files were not shown because too many files have changed in this diff Show more