mirror of https://github.com/LemmyNet/lemmy.git
Merge branch 'main' into invite_instances
commit
be8f79d700
|
@ -69,9 +69,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "3.0.0-beta.12"
|
||||
version = "3.0.0-beta.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afaeb3d3fcb06b775ac62f05d580aae4afe5a149513333a73f688fdf26c06639"
|
||||
checksum = "1bc3f9d97e32d75fae3ad7d955ac005eea3fd3ea60a89132768700911a60fd94"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-rt",
|
||||
|
@ -130,9 +130,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "actix-rt"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a0c218d0a17c120f10ee0c69c9f0c45d87319e8f66b1f065e8412b612fc3e24"
|
||||
checksum = "05c2f80ce8d0c990941c7a7a931f69fd0701b76d521f8d36298edf59cd3fbf1f"
|
||||
dependencies = [
|
||||
"actix-macros",
|
||||
"futures-core",
|
||||
|
@ -170,9 +170,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "actix-tls"
|
||||
version = "3.0.0-beta.8"
|
||||
version = "3.0.0-beta.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a563b0245222230c860c1b077ca7309179fff0f575b1914967c1ee385aa5da64"
|
||||
checksum = "53d4739910b49c77ea88308a9fbfae544524b34884161527f9978c0102052da0"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-rt",
|
||||
|
@ -182,6 +182,7 @@ dependencies = [
|
|||
"futures-core",
|
||||
"http",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tokio-rustls",
|
||||
"tokio-util",
|
||||
"webpki-roots",
|
||||
|
@ -199,9 +200,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "actix-web"
|
||||
version = "4.0.0-beta.11"
|
||||
version = "4.0.0-beta.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e85aa9bb018d83a0db70f557ba0cde9c6170a5d1de4fede02e377f68c1ac5aa9"
|
||||
checksum = "e87cfc4efaad42f8a054e269d1b85046397ff4e8707e49128dea3f99a512a9d6"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http",
|
||||
|
@ -388,9 +389,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
|||
|
||||
[[package]]
|
||||
name = "awc"
|
||||
version = "3.0.0-beta.10"
|
||||
version = "3.0.0-beta.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f122bed94dc044b13a991b292ff6a3cde4c3fba890a4e3dbbec0f2eedc607f0a"
|
||||
checksum = "f9f7d0c472987e454f41c3f4c7fa336ca139707ab255644b0480144c2060c800"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http",
|
||||
|
@ -1759,6 +1760,7 @@ dependencies = [
|
|||
"strum_macros",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
@ -1777,6 +1779,7 @@ dependencies = [
|
|||
"lemmy_utils",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -1982,6 +1985,7 @@ dependencies = [
|
|||
"serde",
|
||||
"sha2",
|
||||
"strum",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -3998,9 +4002,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-actix-web"
|
||||
version = "0.5.0-beta.2"
|
||||
version = "0.5.0-beta.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cac34827e06f78b69523b2fbe5b2dd4dfc75940b2ea5ba37e4fa2a25d4a0edf"
|
||||
checksum = "994e4a59135823bdca121a8d086e3fcc71741c8677b47fa95a6afdd15e8f646f"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"pin-project",
|
||||
|
|
|
@ -50,7 +50,7 @@ serde = { version = "1.0.130", features = ["derive"] }
|
|||
actix = "0.12.0"
|
||||
actix-web = { version = "4.0.0-beta.9", default-features = false, features = ["rustls"] }
|
||||
tracing = "0.1.29"
|
||||
tracing-actix-web = "0.5.0-beta.2"
|
||||
tracing-actix-web = { version = "0.5.0-beta.3", default-features = false }
|
||||
tracing-error = "0.2.0"
|
||||
tracing-log = "0.1.2"
|
||||
tracing-subscriber = { version = "0.3.2", features = ["env-filter"] }
|
||||
|
|
|
@ -116,14 +116,14 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins
|
|||
### Apps
|
||||
|
||||
- [lemmy-ui - The official web app for lemmy](https://github.com/LemmyNet/lemmy-ui)
|
||||
- [Lemmur - A mobile client for Lemmy (Android, Linux, Windows)](https://github.com/krawieck/lemmur)
|
||||
- [Lemmur - A mobile client for Lemmy (Android, Linux, Windows)](https://github.com/LemmurOrg/lemmur)
|
||||
- [Remmel - A native iOS app](https://github.com/uuttff8/Lemmy-iOS)
|
||||
|
||||
### Libraries
|
||||
|
||||
- [lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client)
|
||||
- [Kotlin API ( under development )](https://github.com/eiknat/lemmy-client)
|
||||
- [Dart API client](https://github.com/krawieck/lemmy_api_client)
|
||||
- [Dart API client](https://github.com/LemmurOrg/lemmy_api_client)
|
||||
|
||||
## Support / Donate
|
||||
|
||||
|
|
|
@ -625,7 +625,7 @@ Since our last release in October of last year, and we've had [~450](https://git
|
|||
|
||||
The biggest changes, as we'll outline below, are a re-work of Lemmy's database structure, a `v2` of Lemmy's API, and activitypub compliance fixes. The new re-worked DB is much faster, easier to maintain, and [now supports hierarchical rather than flat objects in the new API](https://github.com/LemmyNet/lemmy/issues/1275).
|
||||
|
||||
We've also seen the first release of [Lemmur](https://github.com/krawieck/lemmur/releases/tag/v0.1.1), an android / iOS (soon) / windows / linux client, as well as [Lemmer](https://github.com/uuttff8/Lemmy-iOS), a native iOS client. Much thanks to @krawieck, @shilangyu, and @uuttff8 for making these great clients. If you can, please contribute to their [patreon](https://www.patreon.com/lemmur) to help fund lemmur development.
|
||||
We've also seen the first release of [Lemmur](https://github.com/LemmurOrg/lemmur/releases/tag/v0.1.1), an android / iOS (soon) / windows / linux client, as well as [Lemmer](https://github.com/uuttff8/Lemmy-iOS), a native iOS client. Much thanks to @krawieck, @shilangyu, and @uuttff8 for making these great clients. If you can, please contribute to their [patreon](https://www.patreon.com/lemmur) to help fund lemmur development.
|
||||
|
||||
## LemmyNet projects
|
||||
|
||||
|
|
|
@ -48,5 +48,6 @@ async-trait = "0.1.51"
|
|||
captcha = "0.0.8"
|
||||
anyhow = "1.0.44"
|
||||
thiserror = "1.0.29"
|
||||
tracing = "0.1.29"
|
||||
background-jobs = "0.11.0"
|
||||
reqwest = { version = "0.11.4", features = ["json"] }
|
||||
|
|
|
@ -23,7 +23,7 @@ use lemmy_db_schema::{
|
|||
traits::{Likeable, Saveable},
|
||||
};
|
||||
use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
|
||||
|
||||
use crate::Perform;
|
||||
|
@ -32,6 +32,7 @@ use crate::Perform;
|
|||
impl Perform for MarkCommentAsRead {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -56,7 +57,7 @@ impl Perform for MarkCommentAsRead {
|
|||
|
||||
// Verify that only the recipient can mark as read
|
||||
if local_user_view.person.id != orig_comment.get_recipient_id() {
|
||||
return Err(ApiError::err_plain("no_comment_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_comment_edit_allowed"));
|
||||
}
|
||||
|
||||
// Do the mark as read
|
||||
|
@ -65,7 +66,8 @@ impl Perform for MarkCommentAsRead {
|
|||
Comment::update_read(conn, comment_id, read)
|
||||
})
|
||||
.await?
|
||||
.map_err(|_| ApiError::err_plain("couldnt_update_comment"))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
// Refetch it
|
||||
let comment_id = data.comment_id;
|
||||
|
@ -89,6 +91,7 @@ impl Perform for MarkCommentAsRead {
|
|||
impl Perform for SaveComment {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -107,12 +110,14 @@ impl Perform for SaveComment {
|
|||
let save_comment = move |conn: &'_ _| CommentSaved::save(conn, &comment_saved_form);
|
||||
blocking(context.pool(), save_comment)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_save_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_save_comment"))?;
|
||||
} else {
|
||||
let unsave_comment = move |conn: &'_ _| CommentSaved::unsave(conn, &comment_saved_form);
|
||||
blocking(context.pool(), unsave_comment)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_save_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_save_comment"))?;
|
||||
}
|
||||
|
||||
let comment_id = data.comment_id;
|
||||
|
@ -134,6 +139,7 @@ impl Perform for SaveComment {
|
|||
impl Perform for CreateCommentLike {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -201,7 +207,8 @@ impl Perform for CreateCommentLike {
|
|||
let like = move |conn: &'_ _| CommentLike::like(conn, &like_form2);
|
||||
blocking(context.pool(), like)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_like_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_like_comment"))?;
|
||||
|
||||
Vote::send(
|
||||
&object,
|
||||
|
|
|
@ -14,7 +14,7 @@ use lemmy_db_views::{
|
|||
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
||||
comment_view::CommentView,
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
/// Creates a comment report and notifies the moderators of the community
|
||||
|
@ -22,6 +22,7 @@ use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation}
|
|||
impl Perform for CreateCommentReport {
|
||||
type Response = CommentReportResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -34,10 +35,10 @@ impl Perform for CreateCommentReport {
|
|||
// check size of report and check for whitespace
|
||||
let reason = data.reason.trim();
|
||||
if reason.is_empty() {
|
||||
return Err(ApiError::err_plain("report_reason_required").into());
|
||||
return Err(LemmyError::from_message("report_reason_required"));
|
||||
}
|
||||
if reason.chars().count() > 1000 {
|
||||
return Err(ApiError::err_plain("report_too_long").into());
|
||||
return Err(LemmyError::from_message("report_too_long"));
|
||||
}
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
|
@ -60,7 +61,8 @@ impl Perform for CreateCommentReport {
|
|||
CommentReport::report(conn, &report_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_report", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_report"))?;
|
||||
|
||||
let comment_report_view = blocking(context.pool(), move |conn| {
|
||||
CommentReportView::read(conn, report.id, person_id)
|
||||
|
@ -96,6 +98,7 @@ impl Perform for CreateCommentReport {
|
|||
impl Perform for ResolveCommentReport {
|
||||
type Response = CommentReportResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -126,7 +129,8 @@ impl Perform for ResolveCommentReport {
|
|||
|
||||
blocking(context.pool(), resolve_fun)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_resolve_report", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_resolve_report"))?;
|
||||
|
||||
let report_id = data.report_id;
|
||||
let comment_report_view = blocking(context.pool(), move |conn| {
|
||||
|
@ -155,6 +159,7 @@ impl Perform for ResolveCommentReport {
|
|||
impl Perform for ListCommentReports {
|
||||
type Response = ListCommentReportsResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -54,13 +54,14 @@ use lemmy_db_views_actor::{
|
|||
community_view::CommunityView,
|
||||
person_view::PersonViewSafe,
|
||||
};
|
||||
use lemmy_utils::{location_info, utils::naive_from_unix, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{location_info, utils::naive_from_unix, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::SendCommunityRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for FollowCommunity {
|
||||
type Response = CommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -90,13 +91,15 @@ impl Perform for FollowCommunity {
|
|||
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
|
||||
blocking(context.pool(), follow)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_follower_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_follower_already_exists"))?;
|
||||
} else {
|
||||
let unfollow =
|
||||
move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
|
||||
blocking(context.pool(), unfollow)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_follower_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_follower_already_exists"))?;
|
||||
}
|
||||
} else if data.follow {
|
||||
// Dont actually add to the community followers here, because you need
|
||||
|
@ -109,7 +112,8 @@ impl Perform for FollowCommunity {
|
|||
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
|
||||
blocking(context.pool(), unfollow)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_follower_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_follower_already_exists"))?;
|
||||
}
|
||||
|
||||
let community_id = data.community_id;
|
||||
|
@ -134,6 +138,7 @@ impl Perform for FollowCommunity {
|
|||
impl Perform for BlockCommunity {
|
||||
type Response = BlockCommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -154,7 +159,8 @@ impl Perform for BlockCommunity {
|
|||
let block = move |conn: &'_ _| CommunityBlock::block(conn, &community_block_form);
|
||||
blocking(context.pool(), block)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_block_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_block_already_exists"))?;
|
||||
|
||||
// Also, unfollow the community, and send a federated unfollow
|
||||
let community_follower_form = CommunityFollowerForm {
|
||||
|
@ -176,7 +182,8 @@ impl Perform for BlockCommunity {
|
|||
let unblock = move |conn: &'_ _| CommunityBlock::unblock(conn, &community_block_form);
|
||||
blocking(context.pool(), unblock)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_block_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_block_already_exists"))?;
|
||||
}
|
||||
|
||||
let community_view = blocking(context.pool(), move |conn| {
|
||||
|
@ -195,6 +202,7 @@ impl Perform for BlockCommunity {
|
|||
impl Perform for BanFromCommunity {
|
||||
type Response = BanFromCommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -230,7 +238,8 @@ impl Perform for BanFromCommunity {
|
|||
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
||||
blocking(context.pool(), ban)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_user_already_banned", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_user_already_banned"))?;
|
||||
|
||||
// Also unsubscribe them from the community, if they are subscribed
|
||||
let community_follower_form = CommunityFollowerForm {
|
||||
|
@ -255,7 +264,8 @@ impl Perform for BanFromCommunity {
|
|||
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
||||
blocking(context.pool(), unban)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_user_already_banned", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_user_already_banned"))?;
|
||||
UndoBlockUserFromCommunity::send(
|
||||
&community,
|
||||
&banned_person,
|
||||
|
@ -336,6 +346,7 @@ impl Perform for BanFromCommunity {
|
|||
impl Perform for AddModToCommunity {
|
||||
type Response = AddModToCommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -359,12 +370,14 @@ impl Perform for AddModToCommunity {
|
|||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||
blocking(context.pool(), join)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_moderator_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_moderator_already_exists"))?;
|
||||
} else {
|
||||
let leave = move |conn: &'_ _| CommunityModerator::leave(conn, &community_moderator_form);
|
||||
blocking(context.pool(), leave)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_moderator_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_moderator_already_exists"))?;
|
||||
}
|
||||
|
||||
// Mod tables
|
||||
|
@ -434,6 +447,7 @@ impl Perform for AddModToCommunity {
|
|||
impl Perform for TransferCommunity {
|
||||
type Response = GetCommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -472,7 +486,7 @@ impl Perform for TransferCommunity {
|
|||
.map(|a| a.person.id)
|
||||
.any(|x| x == local_user_view.person.id)
|
||||
{
|
||||
return Err(ApiError::err_plain("not_an_admin").into());
|
||||
return Err(LemmyError::from_message("not_an_admin"));
|
||||
}
|
||||
|
||||
// You have to re-do the community_moderator table, reordering it.
|
||||
|
@ -502,7 +516,8 @@ impl Perform for TransferCommunity {
|
|||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||
blocking(context.pool(), join)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_moderator_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_moderator_already_exists"))?;
|
||||
}
|
||||
|
||||
// Mod tables
|
||||
|
@ -523,14 +538,16 @@ impl Perform for TransferCommunity {
|
|||
CommunityView::read(conn, community_id, Some(person_id))
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?;
|
||||
|
||||
let community_id = data.community_id;
|
||||
let moderators = blocking(context.pool(), move |conn| {
|
||||
CommunityModeratorView::for_community(conn, community_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?;
|
||||
|
||||
// Return the jwt
|
||||
Ok(GetCommunityResponse {
|
||||
|
|
|
@ -50,7 +50,6 @@ use lemmy_utils::{
|
|||
email::send_email,
|
||||
location_info,
|
||||
utils::{generate_random_string, is_valid_display_name, is_valid_matrix_id, naive_from_unix},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -65,6 +64,7 @@ use lemmy_websocket::{
|
|||
impl Perform for Login {
|
||||
type Response = LoginResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -78,7 +78,8 @@ impl Perform for Login {
|
|||
LocalUserView::find_by_email_or_name(conn, &username_or_email)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_that_username_or_email", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?;
|
||||
|
||||
// Verify the password
|
||||
let valid: bool = verify(
|
||||
|
@ -87,21 +88,24 @@ impl Perform for Login {
|
|||
)
|
||||
.unwrap_or(false);
|
||||
if !valid {
|
||||
return Err(ApiError::err_plain("password_incorrect").into());
|
||||
return Err(LemmyError::from_message("password_incorrect"));
|
||||
}
|
||||
|
||||
let site = blocking(context.pool(), Site::read_simple).await??;
|
||||
if site.require_email_verification && !local_user_view.local_user.email_verified {
|
||||
return Err(ApiError::err_plain("email_not_verified").into());
|
||||
return Err(LemmyError::from_message("email_not_verified"));
|
||||
}
|
||||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: Some(Claims::jwt(
|
||||
local_user_view.local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?),
|
||||
jwt: Some(
|
||||
Claims::jwt(
|
||||
local_user_view.local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
verify_email_sent: false,
|
||||
registration_created: false,
|
||||
})
|
||||
|
@ -112,6 +116,7 @@ impl Perform for Login {
|
|||
impl Perform for GetCaptcha {
|
||||
type Response = GetCaptchaResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -157,6 +162,7 @@ impl Perform for GetCaptcha {
|
|||
impl Perform for SaveUserSettings {
|
||||
type Response = LoginResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -172,8 +178,9 @@ impl Perform for SaveUserSettings {
|
|||
let display_name = diesel_option_overwrite(&data.display_name);
|
||||
let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id);
|
||||
let bot_account = data.bot_account;
|
||||
let email_deref = data.email.as_deref().map(|e| e.to_owned());
|
||||
|
||||
let email = if let Some(email) = &data.email {
|
||||
let email = if let Some(email) = &email_deref {
|
||||
let site = blocking(context.pool(), Site::read_simple).await??;
|
||||
if site.require_email_verification {
|
||||
send_verification_email(
|
||||
|
@ -185,7 +192,7 @@ impl Perform for SaveUserSettings {
|
|||
.await?;
|
||||
None
|
||||
} else {
|
||||
diesel_option_overwrite(&data.email)
|
||||
diesel_option_overwrite(&email_deref)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
@ -193,7 +200,7 @@ impl Perform for SaveUserSettings {
|
|||
|
||||
if let Some(Some(bio)) = &bio {
|
||||
if bio.chars().count() > 300 {
|
||||
return Err(ApiError::err_plain("bio_length_overflow").into());
|
||||
return Err(LemmyError::from_message("bio_length_overflow"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,13 +209,13 @@ impl Perform for SaveUserSettings {
|
|||
display_name.trim(),
|
||||
context.settings().actor_name_max_length,
|
||||
) {
|
||||
return Err(ApiError::err_plain("invalid_username").into());
|
||||
return Err(LemmyError::from_message("invalid_username"));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(Some(matrix_user_id)) = &matrix_user_id {
|
||||
if !is_valid_matrix_id(matrix_user_id) {
|
||||
return Err(ApiError::err_plain("invalid_matrix_id").into());
|
||||
return Err(LemmyError::from_message("invalid_matrix_id"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +252,8 @@ impl Perform for SaveUserSettings {
|
|||
Person::update(conn, person_id, &person_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("user_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("user_already_exists"))?;
|
||||
|
||||
let local_user_form = LocalUserForm {
|
||||
person_id: Some(person_id),
|
||||
|
@ -281,17 +289,20 @@ impl Perform for SaveUserSettings {
|
|||
"user_already_exists"
|
||||
};
|
||||
|
||||
return Err(ApiError::err(err_type, e).into());
|
||||
return Err(LemmyError::from(e).with_message(err_type));
|
||||
}
|
||||
};
|
||||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: Some(Claims::jwt(
|
||||
updated_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?),
|
||||
jwt: Some(
|
||||
Claims::jwt(
|
||||
updated_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
verify_email_sent: false,
|
||||
registration_created: false,
|
||||
})
|
||||
|
@ -302,6 +313,7 @@ impl Perform for SaveUserSettings {
|
|||
impl Perform for ChangePassword {
|
||||
type Response = LoginResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -309,13 +321,13 @@ impl Perform for ChangePassword {
|
|||
) -> Result<LoginResponse, LemmyError> {
|
||||
let data: &ChangePassword = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt(data.auth.as_ref(), context.pool(), context.secret()).await?;
|
||||
|
||||
password_length_check(&data.new_password)?;
|
||||
|
||||
// Make sure passwords match
|
||||
if data.new_password != data.new_password_verify {
|
||||
return Err(ApiError::err_plain("passwords_dont_match").into());
|
||||
return Err(LemmyError::from_message("passwords_dont_match"));
|
||||
}
|
||||
|
||||
// Check the old password
|
||||
|
@ -325,7 +337,7 @@ impl Perform for ChangePassword {
|
|||
)
|
||||
.unwrap_or(false);
|
||||
if !valid {
|
||||
return Err(ApiError::err_plain("password_incorrect").into());
|
||||
return Err(LemmyError::from_message("password_incorrect"));
|
||||
}
|
||||
|
||||
let local_user_id = local_user_view.local_user.id;
|
||||
|
@ -337,11 +349,14 @@ impl Perform for ChangePassword {
|
|||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: Some(Claims::jwt(
|
||||
updated_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?),
|
||||
jwt: Some(
|
||||
Claims::jwt(
|
||||
updated_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
verify_email_sent: false,
|
||||
registration_created: false,
|
||||
})
|
||||
|
@ -352,6 +367,7 @@ impl Perform for ChangePassword {
|
|||
impl Perform for AddAdmin {
|
||||
type Response = AddAdminResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -370,7 +386,8 @@ impl Perform for AddAdmin {
|
|||
Person::add_admin(conn, added_person_id, added)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_user", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_user"))?;
|
||||
|
||||
// Mod tables
|
||||
let form = ModAddForm {
|
||||
|
@ -410,6 +427,7 @@ impl Perform for AddAdmin {
|
|||
impl Perform for BanPerson {
|
||||
type Response = BanPersonResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -427,7 +445,8 @@ impl Perform for BanPerson {
|
|||
let ban_person = move |conn: &'_ _| Person::ban_person(conn, banned_person_id, ban);
|
||||
blocking(context.pool(), ban_person)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_user", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_user"))?;
|
||||
|
||||
// Remove their data if that's desired
|
||||
if data.remove_data.unwrap_or(false) {
|
||||
|
@ -503,6 +522,7 @@ impl Perform for BanPerson {
|
|||
impl Perform for BlockPerson {
|
||||
type Response = BlockPersonResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -517,7 +537,7 @@ impl Perform for BlockPerson {
|
|||
|
||||
// Don't let a person block themselves
|
||||
if target_id == person_id {
|
||||
return Err(ApiError::err_plain("cant_block_yourself").into());
|
||||
return Err(LemmyError::from_message("cant_block_yourself"));
|
||||
}
|
||||
|
||||
let person_block_form = PersonBlockForm {
|
||||
|
@ -529,12 +549,14 @@ impl Perform for BlockPerson {
|
|||
let block = move |conn: &'_ _| PersonBlock::block(conn, &person_block_form);
|
||||
blocking(context.pool(), block)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("person_block_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("person_block_already_exists"))?;
|
||||
} else {
|
||||
let unblock = move |conn: &'_ _| PersonBlock::unblock(conn, &person_block_form);
|
||||
blocking(context.pool(), unblock)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("person_block_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("person_block_already_exists"))?;
|
||||
}
|
||||
|
||||
// TODO does any federated stuff need to be done here?
|
||||
|
@ -557,6 +579,7 @@ impl Perform for BlockPerson {
|
|||
impl Perform for GetReplies {
|
||||
type Response = GetRepliesResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -595,6 +618,7 @@ impl Perform for GetReplies {
|
|||
impl Perform for GetPersonMentions {
|
||||
type Response = GetPersonMentionsResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -630,6 +654,7 @@ impl Perform for GetPersonMentions {
|
|||
impl Perform for MarkPersonMentionAsRead {
|
||||
type Response = PersonMentionResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -646,7 +671,7 @@ impl Perform for MarkPersonMentionAsRead {
|
|||
.await??;
|
||||
|
||||
if local_user_view.person.id != read_person_mention.recipient_id {
|
||||
return Err(ApiError::err_plain("couldnt_update_comment").into());
|
||||
return Err(LemmyError::from_message("couldnt_update_comment"));
|
||||
}
|
||||
|
||||
let person_mention_id = read_person_mention.id;
|
||||
|
@ -655,7 +680,8 @@ impl Perform for MarkPersonMentionAsRead {
|
|||
move |conn: &'_ _| PersonMention::update_read(conn, person_mention_id, read);
|
||||
blocking(context.pool(), update_mention)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
let person_mention_id = read_person_mention.id;
|
||||
let person_id = local_user_view.person.id;
|
||||
|
@ -674,6 +700,7 @@ impl Perform for MarkPersonMentionAsRead {
|
|||
impl Perform for MarkAllAsRead {
|
||||
type Response = GetRepliesResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -703,7 +730,8 @@ impl Perform for MarkAllAsRead {
|
|||
let mark_as_read = move |conn: &'_ _| Comment::update_read(conn, reply_id, true);
|
||||
blocking(context.pool(), mark_as_read)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
}
|
||||
|
||||
// Mark all user mentions as read
|
||||
|
@ -711,13 +739,15 @@ impl Perform for MarkAllAsRead {
|
|||
move |conn: &'_ _| PersonMention::mark_all_as_read(conn, person_id);
|
||||
blocking(context.pool(), update_person_mentions)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
// Mark all private_messages as read
|
||||
let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, person_id);
|
||||
blocking(context.pool(), update_pm)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_private_message", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_private_message"))?;
|
||||
|
||||
Ok(GetRepliesResponse { replies: vec![] })
|
||||
}
|
||||
|
@ -727,6 +757,7 @@ impl Perform for MarkAllAsRead {
|
|||
impl Perform for PasswordReset {
|
||||
type Response = PasswordResetResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -740,7 +771,8 @@ impl Perform for PasswordReset {
|
|||
LocalUserView::find_by_email(conn, &email)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_that_username_or_email", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?;
|
||||
|
||||
// Generate a random token
|
||||
let token = generate_random_string();
|
||||
|
@ -765,8 +797,7 @@ impl Perform for PasswordReset {
|
|||
&local_user_view.person.name,
|
||||
html,
|
||||
&context.settings(),
|
||||
)
|
||||
.map_err(|e| ApiError::err("email_send_failed", e))?;
|
||||
)?;
|
||||
|
||||
Ok(PasswordResetResponse {})
|
||||
}
|
||||
|
@ -776,6 +807,7 @@ impl Perform for PasswordReset {
|
|||
impl Perform for PasswordChange {
|
||||
type Response = LoginResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -794,7 +826,7 @@ impl Perform for PasswordChange {
|
|||
|
||||
// Make sure passwords match
|
||||
if data.password != data.password_verify {
|
||||
return Err(ApiError::err_plain("passwords_dont_match").into());
|
||||
return Err(LemmyError::from_message("passwords_dont_match"));
|
||||
}
|
||||
|
||||
// Update the user with the new password
|
||||
|
@ -803,15 +835,19 @@ impl Perform for PasswordChange {
|
|||
LocalUser::update_password(conn, local_user_id, &password)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_user", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_user"))?;
|
||||
|
||||
// Return the jwt
|
||||
Ok(LoginResponse {
|
||||
jwt: Some(Claims::jwt(
|
||||
updated_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?),
|
||||
jwt: Some(
|
||||
Claims::jwt(
|
||||
updated_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
verify_email_sent: false,
|
||||
registration_created: false,
|
||||
})
|
||||
|
@ -822,6 +858,7 @@ impl Perform for PasswordChange {
|
|||
impl Perform for GetReportCount {
|
||||
type Response = GetReportCountResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -859,6 +896,7 @@ impl Perform for GetReportCount {
|
|||
impl Perform for GetUnreadCount {
|
||||
type Response = GetUnreadCountResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -909,7 +947,8 @@ impl Perform for VerifyEmail {
|
|||
EmailVerification::read_for_token(conn, &token)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("token_not_found", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("token_not_found"))?;
|
||||
|
||||
let form = LocalUserForm {
|
||||
// necessary in case this is a new signup
|
||||
|
|
|
@ -29,7 +29,7 @@ use lemmy_db_schema::{
|
|||
traits::{Crud, Likeable, Saveable},
|
||||
};
|
||||
use lemmy_db_views::post_view::PostView;
|
||||
use lemmy_utils::{request::fetch_site_metadata, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{request::fetch_site_metadata, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
|
||||
use std::convert::TryInto;
|
||||
|
||||
|
@ -37,6 +37,7 @@ use std::convert::TryInto;
|
|||
impl Perform for CreatePostLike {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -83,7 +84,8 @@ impl Perform for CreatePostLike {
|
|||
let like = move |conn: &'_ _| PostLike::like(conn, &like_form2);
|
||||
blocking(context.pool(), like)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_like_post", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_like_post"))?;
|
||||
|
||||
Vote::send(
|
||||
&object,
|
||||
|
@ -123,6 +125,7 @@ impl Perform for CreatePostLike {
|
|||
impl Perform for MarkPostAsRead {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -158,6 +161,7 @@ impl Perform for MarkPostAsRead {
|
|||
impl Perform for LockPost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -227,6 +231,7 @@ impl Perform for LockPost {
|
|||
impl Perform for StickyPost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -300,6 +305,7 @@ impl Perform for StickyPost {
|
|||
impl Perform for SavePost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -318,12 +324,14 @@ impl Perform for SavePost {
|
|||
let save = move |conn: &'_ _| PostSaved::save(conn, &post_saved_form);
|
||||
blocking(context.pool(), save)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_save_post", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_save_post"))?;
|
||||
} else {
|
||||
let unsave = move |conn: &'_ _| PostSaved::unsave(conn, &post_saved_form);
|
||||
blocking(context.pool(), unsave)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_save_post", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_save_post"))?;
|
||||
}
|
||||
|
||||
let post_id = data.post_id;
|
||||
|
@ -344,6 +352,7 @@ impl Perform for SavePost {
|
|||
impl Perform for GetSiteMetadata {
|
||||
type Response = GetSiteMetadataResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -23,7 +23,7 @@ use lemmy_db_views::{
|
|||
post_report_view::{PostReportQueryBuilder, PostReportView},
|
||||
post_view::PostView,
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
/// Creates a post report and notifies the moderators of the community
|
||||
|
@ -31,6 +31,7 @@ use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation}
|
|||
impl Perform for CreatePostReport {
|
||||
type Response = PostReportResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -43,10 +44,10 @@ impl Perform for CreatePostReport {
|
|||
// check size of report and check for whitespace
|
||||
let reason = data.reason.trim();
|
||||
if reason.is_empty() {
|
||||
return Err(ApiError::err_plain("report_reason_required").into());
|
||||
return Err(LemmyError::from_message("report_reason_required"));
|
||||
}
|
||||
if reason.chars().count() > 1000 {
|
||||
return Err(ApiError::err_plain("report_too_long").into());
|
||||
return Err(LemmyError::from_message("report_too_long"));
|
||||
}
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
|
@ -71,7 +72,8 @@ impl Perform for CreatePostReport {
|
|||
PostReport::report(conn, &report_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_report", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_report"))?;
|
||||
|
||||
let post_report_view = blocking(context.pool(), move |conn| {
|
||||
PostReportView::read(conn, report.id, person_id)
|
||||
|
@ -105,6 +107,7 @@ impl Perform for CreatePostReport {
|
|||
impl Perform for ResolvePostReport {
|
||||
type Response = PostReportResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -135,7 +138,8 @@ impl Perform for ResolvePostReport {
|
|||
|
||||
blocking(context.pool(), resolve_fun)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_resolve_report", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_resolve_report"))?;
|
||||
|
||||
let post_report_view = blocking(context.pool(), move |conn| {
|
||||
PostReportView::read(conn, report_id, person_id)
|
||||
|
@ -161,6 +165,7 @@ impl Perform for ResolvePostReport {
|
|||
impl Perform for ListPostReports {
|
||||
type Response = ListPostReportsResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -6,13 +6,14 @@ use lemmy_api_common::{
|
|||
person::{MarkPrivateMessageAsRead, PrivateMessageResponse},
|
||||
};
|
||||
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperation};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for MarkPrivateMessageAsRead {
|
||||
type Response = PrivateMessageResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -29,7 +30,7 @@ impl Perform for MarkPrivateMessageAsRead {
|
|||
})
|
||||
.await??;
|
||||
if local_user_view.person.id != orig_private_message.recipient_id {
|
||||
return Err(ApiError::err_plain("couldnt_update_private_message").into());
|
||||
return Err(LemmyError::from_message("couldnt_update_private_message"));
|
||||
}
|
||||
|
||||
// Doing the update
|
||||
|
@ -39,7 +40,8 @@ impl Perform for MarkPrivateMessageAsRead {
|
|||
PrivateMessage::update_read(conn, private_message_id, read)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_private_message", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_private_message"))?;
|
||||
|
||||
// No need to send an apub update
|
||||
let op = UserOperation::MarkPrivateMessageAsRead;
|
||||
|
|
|
@ -60,20 +60,14 @@ use lemmy_db_views_moderator::{
|
|||
mod_sticky_post_view::ModStickyPostView,
|
||||
mod_transfer_community_view::ModTransferCommunityView,
|
||||
};
|
||||
use lemmy_utils::{
|
||||
location_info,
|
||||
settings::structs::Settings,
|
||||
version,
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
use lemmy_utils::{location_info, settings::structs::Settings, version, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for GetModlog {
|
||||
type Response = GetModlogResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -154,6 +148,7 @@ impl Perform for GetModlog {
|
|||
impl Perform for Search {
|
||||
type Response = SearchResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -162,7 +157,8 @@ impl Perform for Search {
|
|||
let data: &Search = self;
|
||||
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -396,21 +392,25 @@ impl Perform for Search {
|
|||
impl Perform for ResolveObject {
|
||||
type Response = ResolveObjectResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
_websocket_id: Option<ConnectionId>,
|
||||
) -> Result<ResolveObjectResponse, LemmyError> {
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&self.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(self.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
let res = search_by_apub_id(&self.q, context)
|
||||
.await
|
||||
.map_err(|e| ApiError::err("couldnt_find_object", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_object"))?;
|
||||
convert_response(res, local_user_view.map(|l| l.person.id), context.pool())
|
||||
.await
|
||||
.map_err(|e| ApiError::err("couldnt_find_object", e).into())
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_object"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,6 +457,7 @@ async fn convert_response(
|
|||
impl Perform for TransferSite {
|
||||
type Response = GetSiteResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -472,14 +473,15 @@ impl Perform for TransferSite {
|
|||
|
||||
// Make sure user is the creator
|
||||
if read_site.creator_id != local_user_view.person.id {
|
||||
return Err(ApiError::err_plain("not_an_admin").into());
|
||||
return Err(LemmyError::from_message("not_an_admin"));
|
||||
}
|
||||
|
||||
let new_creator_id = data.person_id;
|
||||
let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id);
|
||||
blocking(context.pool(), transfer_site)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_site", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_site"))?;
|
||||
|
||||
// Mod tables
|
||||
let form = ModAddForm {
|
||||
|
@ -524,6 +526,7 @@ impl Perform for TransferSite {
|
|||
impl Perform for GetSiteConfig {
|
||||
type Response = GetSiteConfigResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -546,6 +549,7 @@ impl Perform for GetSiteConfig {
|
|||
impl Perform for SaveSiteConfig {
|
||||
type Response = GetSiteConfigResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -560,7 +564,8 @@ impl Perform for SaveSiteConfig {
|
|||
|
||||
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
|
||||
let config_hjson = Settings::save_config_file(&data.config_hjson)
|
||||
.map_err(|e| ApiError::err("couldnt_update_site", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_site"))?;
|
||||
|
||||
Ok(GetSiteConfigResponse { config_hjson })
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use lemmy_websocket::{
|
|||
impl Perform for UserJoin {
|
||||
type Response = UserJoinResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -35,6 +36,7 @@ impl Perform for UserJoin {
|
|||
impl Perform for CommunityJoin {
|
||||
type Response = CommunityJoinResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -57,6 +59,7 @@ impl Perform for CommunityJoin {
|
|||
impl Perform for ModJoin {
|
||||
type Response = ModJoinResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -79,6 +82,7 @@ impl Perform for ModJoin {
|
|||
impl Perform for PostJoin {
|
||||
type Response = PostJoinResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -23,4 +23,5 @@ diesel = "1.4.8"
|
|||
actix-web = { version = "4.0.0-beta.9", default-features = false, features = ["cookies"] }
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
serde_json = { version = "1.0.68", features = ["preserve_order"] }
|
||||
tracing = "0.1.29"
|
||||
url = "2.2.2"
|
||||
|
|
|
@ -1,74 +1,75 @@
|
|||
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 serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreateComment {
|
||||
pub content: String,
|
||||
pub post_id: PostId,
|
||||
pub parent_id: Option<CommentId>,
|
||||
pub form_id: Option<String>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetComment {
|
||||
pub id: CommentId,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditComment {
|
||||
pub content: String,
|
||||
pub comment_id: CommentId,
|
||||
pub form_id: Option<String>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DeleteComment {
|
||||
pub comment_id: CommentId,
|
||||
pub deleted: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RemoveComment {
|
||||
pub comment_id: CommentId,
|
||||
pub removed: bool,
|
||||
pub reason: Option<String>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MarkCommentAsRead {
|
||||
pub comment_id: CommentId,
|
||||
pub read: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SaveComment {
|
||||
pub comment_id: CommentId,
|
||||
pub save: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CommentResponse {
|
||||
pub comment_view: CommentView,
|
||||
pub recipient_ids: Vec<LocalUserId>,
|
||||
pub form_id: Option<String>, // An optional front end ID, to tell which is coming back
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreateCommentLike {
|
||||
pub comment_id: CommentId,
|
||||
pub score: i16,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetComments {
|
||||
pub type_: Option<String>,
|
||||
pub sort: Option<String>,
|
||||
|
@ -77,34 +78,34 @@ pub struct GetComments {
|
|||
pub community_id: Option<CommunityId>,
|
||||
pub community_name: Option<String>,
|
||||
pub saved_only: Option<bool>,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetCommentsResponse {
|
||||
pub comments: Vec<CommentView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreateCommentReport {
|
||||
pub comment_id: CommentId,
|
||||
pub reason: String,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CommentReportResponse {
|
||||
pub comment_report_view: CommentReportView,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ResolveCommentReport {
|
||||
pub report_id: CommentReportId,
|
||||
pub resolved: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ListCommentReports {
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
|
@ -112,10 +113,10 @@ pub struct ListCommentReports {
|
|||
pub unresolved_only: Option<bool>,
|
||||
/// if no community is given, it returns reports for all communities moderated by the auth user
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ListCommentReportsResponse {
|
||||
pub comment_reports: Vec<CommentReportView>,
|
||||
}
|
||||
|
|
|
@ -4,24 +4,25 @@ use lemmy_db_views_actor::{
|
|||
community_view::CommunityView,
|
||||
person_view::PersonViewSafe,
|
||||
};
|
||||
use lemmy_utils::Sensitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetCommunity {
|
||||
pub id: Option<CommunityId>,
|
||||
/// Example: star_trek , or star_trek@xyz.tld
|
||||
pub name: Option<String>,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetCommunityResponse {
|
||||
pub community_view: CommunityView,
|
||||
pub moderators: Vec<CommunityModeratorView>,
|
||||
pub online: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreateCommunity {
|
||||
pub name: String,
|
||||
pub title: String,
|
||||
|
@ -29,10 +30,10 @@ pub struct CreateCommunity {
|
|||
pub icon: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CommunityResponse {
|
||||
pub community_view: CommunityView,
|
||||
}
|
||||
|
@ -43,7 +44,7 @@ pub struct ListCommunities {
|
|||
pub sort: Option<String>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -51,7 +52,7 @@ pub struct ListCommunitiesResponse {
|
|||
pub communities: Vec<CommunityView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BanFromCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
|
@ -59,29 +60,29 @@ pub struct BanFromCommunity {
|
|||
pub remove_data: Option<bool>,
|
||||
pub reason: Option<String>,
|
||||
pub expires: Option<i64>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BanFromCommunityResponse {
|
||||
pub person_view: PersonViewSafe,
|
||||
pub banned: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct AddModToCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
pub added: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct AddModToCommunityResponse {
|
||||
pub moderators: Vec<CommunityModeratorView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub title: Option<String>,
|
||||
|
@ -89,48 +90,48 @@ pub struct EditCommunity {
|
|||
pub icon: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DeleteCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub deleted: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RemoveCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub removed: bool,
|
||||
pub reason: Option<String>,
|
||||
pub expires: Option<i64>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct FollowCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub follow: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BlockCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub block: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BlockCommunityResponse {
|
||||
pub community_view: CommunityView,
|
||||
pub blocked: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct TransferCommunity {
|
||||
pub community_id: CommunityId,
|
||||
pub person_id: PersonId,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use lemmy_db_views_actor::{
|
|||
community_person_ban_view::CommunityPersonBanView,
|
||||
community_view::CommunityView,
|
||||
};
|
||||
use lemmy_utils::{claims::Claims, settings::structs::FederationConfig, ApiError, LemmyError};
|
||||
use lemmy_utils::{claims::Claims, settings::structs::FederationConfig, LemmyError, Sensitive};
|
||||
use url::Url;
|
||||
|
||||
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
|
||||
|
@ -32,9 +32,12 @@ where
|
|||
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?;
|
||||
|
@ -52,14 +55,14 @@ pub async fn is_mod_or_admin(
|
|||
})
|
||||
.await?;
|
||||
if !is_mod_or_admin {
|
||||
return Err(ApiError::err_plain("not_a_mod_or_admin").into());
|
||||
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(ApiError::err_plain("not_an_admin").into());
|
||||
return Err(LemmyError::from_message("not_an_admin"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -67,7 +70,8 @@ pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
|
|||
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(|_| ApiError::err_plain("couldnt_find_post").into())
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_post"))
|
||||
}
|
||||
|
||||
pub async fn mark_post_as_read(
|
||||
|
@ -81,7 +85,8 @@ pub async fn mark_post_as_read(
|
|||
PostRead::mark_as_read(conn, &post_read_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_mark_post_as_read", e).into())
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_mark_post_as_read"))
|
||||
}
|
||||
|
||||
pub async fn mark_post_as_unread(
|
||||
|
@ -95,7 +100,8 @@ pub async fn mark_post_as_unread(
|
|||
PostRead::mark_as_unread(conn, &post_read_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_mark_post_as_read", e).into())
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_mark_post_as_read"))
|
||||
}
|
||||
|
||||
pub async fn get_local_user_view_from_jwt(
|
||||
|
@ -104,19 +110,20 @@ pub async fn get_local_user_view_from_jwt(
|
|||
secret: &Secret,
|
||||
) -> Result<LocalUserView, LemmyError> {
|
||||
let claims = Claims::decode(jwt, &secret.jwt_secret)
|
||||
.map_err(|e| ApiError::err("not_logged_in", e))?
|
||||
.map_err(LemmyError::from)
|
||||
.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.banned {
|
||||
return Err(ApiError::err_plain("site_ban").into());
|
||||
return Err(LemmyError::from_message("site_ban"));
|
||||
}
|
||||
|
||||
// Check for user deletion
|
||||
if local_user_view.person.deleted {
|
||||
return Err(ApiError::err_plain("deleted").into());
|
||||
return Err(LemmyError::from_message("deleted"));
|
||||
}
|
||||
|
||||
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
|
||||
|
@ -131,14 +138,14 @@ pub fn check_validator_time(
|
|||
) -> Result<(), LemmyError> {
|
||||
let user_validation_time = validator_time.timestamp();
|
||||
if user_validation_time > claims.iat {
|
||||
Err(ApiError::err_plain("not_logged_in").into())
|
||||
Err(LemmyError::from_message("not_logged_in"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_local_user_view_from_jwt_opt(
|
||||
jwt: &Option<String>,
|
||||
jwt: Option<&Sensitive<String>>,
|
||||
pool: &DbPool,
|
||||
secret: &Secret,
|
||||
) -> Result<Option<LocalUserView>, LemmyError> {
|
||||
|
@ -149,12 +156,13 @@ pub async fn get_local_user_view_from_jwt_opt(
|
|||
}
|
||||
|
||||
pub async fn get_local_user_settings_view_from_jwt(
|
||||
jwt: &str,
|
||||
jwt: &Sensitive<String>,
|
||||
pool: &DbPool,
|
||||
secret: &Secret,
|
||||
) -> Result<LocalUserSettingsView, LemmyError> {
|
||||
let claims = Claims::decode(jwt, &secret.jwt_secret)
|
||||
.map_err(|e| ApiError::err("not_logged_in", e))?
|
||||
let claims = Claims::decode(jwt.as_ref(), &secret.jwt_secret)
|
||||
.map_err(LemmyError::from)
|
||||
.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| {
|
||||
|
@ -163,7 +171,7 @@ pub async fn get_local_user_settings_view_from_jwt(
|
|||
.await??;
|
||||
// Check for a site ban
|
||||
if local_user_view.person.banned {
|
||||
return Err(ApiError::err_plain("site_ban").into());
|
||||
return Err(LemmyError::from_message("site_ban"));
|
||||
}
|
||||
|
||||
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
|
||||
|
@ -172,7 +180,7 @@ pub async fn get_local_user_settings_view_from_jwt(
|
|||
}
|
||||
|
||||
pub async fn get_local_user_settings_view_from_jwt_opt(
|
||||
jwt: &Option<String>,
|
||||
jwt: Option<&Sensitive<String>>,
|
||||
pool: &DbPool,
|
||||
secret: &Secret,
|
||||
) -> Result<Option<LocalUserSettingsView>, LemmyError> {
|
||||
|
@ -192,7 +200,7 @@ pub async fn check_community_ban(
|
|||
let is_banned =
|
||||
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
|
||||
if blocking(pool, is_banned).await? {
|
||||
Err(ApiError::err_plain("community_ban").into())
|
||||
Err(LemmyError::from_message("community_ban"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -204,9 +212,10 @@ pub async fn check_community_deleted_or_removed(
|
|||
) -> Result<(), LemmyError> {
|
||||
let community = blocking(pool, move |conn| Community::read(conn, community_id))
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?;
|
||||
if community.deleted || community.removed {
|
||||
Err(ApiError::err_plain("deleted").into())
|
||||
Err(LemmyError::from_message("deleted"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -214,7 +223,7 @@ pub async fn check_community_deleted_or_removed(
|
|||
|
||||
pub fn check_post_deleted_or_removed(post: &Post) -> Result<(), LemmyError> {
|
||||
if post.deleted || post.removed {
|
||||
Err(ApiError::err_plain("deleted").into())
|
||||
Err(LemmyError::from_message("deleted"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -227,7 +236,7 @@ pub async fn check_person_block(
|
|||
) -> Result<(), LemmyError> {
|
||||
let is_blocked = move |conn: &'_ _| PersonBlock::read(conn, potential_blocker_id, my_id).is_ok();
|
||||
if blocking(pool, is_blocked).await? {
|
||||
Err(ApiError::err_plain("person_block").into())
|
||||
Err(LemmyError::from_message("person_block"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -237,7 +246,7 @@ pub async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), Le
|
|||
if score == -1 {
|
||||
let site = blocking(pool, Site::read_simple).await??;
|
||||
if !site.enable_downvotes {
|
||||
return Err(ApiError::err_plain("downvotes_disabled").into());
|
||||
return Err(LemmyError::from_message("downvotes_disabled"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -250,7 +259,7 @@ pub async fn check_private_instance(
|
|||
if local_user_view.is_none() {
|
||||
let site = blocking(pool, Site::read_simple).await??;
|
||||
if site.private_instance {
|
||||
return Err(ApiError::err_plain("instance_is_private").into());
|
||||
return Err(LemmyError::from_message("instance_is_private"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -301,7 +310,7 @@ pub async fn build_federated_instances(
|
|||
/// Checks the password length
|
||||
pub fn password_length_check(pass: &str) -> Result<(), LemmyError> {
|
||||
if !(10..=60).contains(&pass.len()) {
|
||||
Err(ApiError::err_plain("invalid_password").into())
|
||||
Err(LemmyError::from_message("invalid_password"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -310,7 +319,7 @@ pub fn password_length_check(pass: &str) -> Result<(), LemmyError> {
|
|||
/// Checks the site description length
|
||||
pub fn site_description_length_check(description: &str) -> Result<(), LemmyError> {
|
||||
if description.len() > 150 {
|
||||
Err(ApiError::err_plain("site_description_length_overflow").into())
|
||||
Err(LemmyError::from_message("site_description_length_overflow"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -319,7 +328,7 @@ pub fn site_description_length_check(description: &str) -> Result<(), LemmyError
|
|||
/// 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(ApiError::err_plain("honeypot_fail").into())
|
||||
Err(LemmyError::from_message("honeypot_fail"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -8,23 +8,24 @@ use lemmy_db_views_actor::{
|
|||
person_mention_view::PersonMentionView,
|
||||
person_view::PersonViewSafe,
|
||||
};
|
||||
use lemmy_utils::Sensitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Login {
|
||||
pub username_or_email: String,
|
||||
pub password: String,
|
||||
pub username_or_email: Sensitive<String>,
|
||||
pub password: Sensitive<String>,
|
||||
}
|
||||
use lemmy_db_schema::newtypes::{CommunityId, PersonId, PersonMentionId, PrivateMessageId};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Register {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
pub password_verify: String,
|
||||
pub password: Sensitive<String>,
|
||||
pub password_verify: Sensitive<String>,
|
||||
pub show_nsfw: bool,
|
||||
/// email is mandatory if email verification is enabled on the server
|
||||
pub email: Option<String>,
|
||||
pub email: Option<Sensitive<String>>,
|
||||
pub captcha_uuid: Option<String>,
|
||||
pub captcha_answer: Option<String>,
|
||||
pub honeypot: Option<String>,
|
||||
|
@ -32,22 +33,22 @@ pub struct Register {
|
|||
pub answer: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetCaptcha {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetCaptchaResponse {
|
||||
pub ok: Option<CaptchaResponse>, // Will be None if captchas are disabled
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CaptchaResponse {
|
||||
pub png: String, // A Base64 encoded png
|
||||
pub wav: String, // A Base64 encoded wav audio
|
||||
pub uuid: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SaveUserSettings {
|
||||
pub show_nsfw: Option<bool>,
|
||||
pub show_scores: Option<bool>,
|
||||
|
@ -58,7 +59,7 @@ pub struct SaveUserSettings {
|
|||
pub avatar: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub display_name: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub email: Option<Sensitive<String>>,
|
||||
pub bio: Option<String>,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub show_avatars: Option<bool>,
|
||||
|
@ -67,27 +68,27 @@ pub struct SaveUserSettings {
|
|||
pub show_bot_accounts: Option<bool>,
|
||||
pub show_read_posts: Option<bool>,
|
||||
pub show_new_post_notifs: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ChangePassword {
|
||||
pub new_password: String,
|
||||
pub new_password_verify: String,
|
||||
pub old_password: String,
|
||||
pub auth: String,
|
||||
pub new_password: Sensitive<String>,
|
||||
pub new_password_verify: Sensitive<String>,
|
||||
pub old_password: Sensitive<String>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LoginResponse {
|
||||
/// This is None in response to `Register` if email verification is enabled, and in response to
|
||||
/// `DeleteAccount`.
|
||||
pub jwt: Option<String>,
|
||||
pub jwt: Option<Sensitive<String>>,
|
||||
pub registration_created: bool,
|
||||
pub verify_email_sent: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPersonDetails {
|
||||
pub person_id: Option<PersonId>, // One of these two are required
|
||||
/// Example: dessalines , or dessalines@xyz.tld
|
||||
|
@ -97,10 +98,10 @@ pub struct GetPersonDetails {
|
|||
pub limit: Option<i64>,
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub saved_only: Option<bool>,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPersonDetailsResponse {
|
||||
pub person_view: PersonViewSafe,
|
||||
pub comments: Vec<CommentView>,
|
||||
|
@ -108,178 +109,178 @@ pub struct GetPersonDetailsResponse {
|
|||
pub moderates: Vec<CommunityModeratorView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetRepliesResponse {
|
||||
pub replies: Vec<CommentView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPersonMentionsResponse {
|
||||
pub mentions: Vec<PersonMentionView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MarkAllAsRead {
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct AddAdmin {
|
||||
pub person_id: PersonId,
|
||||
pub added: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct AddAdminResponse {
|
||||
pub admins: Vec<PersonViewSafe>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BanPerson {
|
||||
pub person_id: PersonId,
|
||||
pub ban: bool,
|
||||
pub remove_data: Option<bool>,
|
||||
pub reason: Option<String>,
|
||||
pub expires: Option<i64>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BanPersonResponse {
|
||||
pub person_view: PersonViewSafe,
|
||||
pub banned: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BlockPerson {
|
||||
pub person_id: PersonId,
|
||||
pub block: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct BlockPersonResponse {
|
||||
pub person_view: PersonViewSafe,
|
||||
pub blocked: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetReplies {
|
||||
pub sort: Option<String>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub unread_only: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPersonMentions {
|
||||
pub sort: Option<String>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub unread_only: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MarkPersonMentionAsRead {
|
||||
pub person_mention_id: PersonMentionId,
|
||||
pub read: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PersonMentionResponse {
|
||||
pub person_mention_view: PersonMentionView,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DeleteAccount {
|
||||
pub password: String,
|
||||
pub auth: String,
|
||||
pub password: Sensitive<String>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PasswordReset {
|
||||
pub email: String,
|
||||
pub email: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PasswordResetResponse {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PasswordChange {
|
||||
pub token: String,
|
||||
pub password: String,
|
||||
pub password_verify: String,
|
||||
pub token: Sensitive<String>,
|
||||
pub password: Sensitive<String>,
|
||||
pub password_verify: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreatePrivateMessage {
|
||||
pub content: String,
|
||||
pub recipient_id: PersonId,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditPrivateMessage {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub content: String,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DeletePrivateMessage {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub deleted: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MarkPrivateMessageAsRead {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub read: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPrivateMessages {
|
||||
pub unread_only: Option<bool>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessagesResponse {
|
||||
pub private_messages: Vec<PrivateMessageView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessageResponse {
|
||||
pub private_message_view: PrivateMessageView,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetReportCount {
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct GetReportCountResponse {
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub comment_reports: i64,
|
||||
pub post_reports: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetUnreadCount {
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct GetUnreadCountResponse {
|
||||
pub replies: i64,
|
||||
pub mentions: i64,
|
||||
|
|
|
@ -8,7 +8,7 @@ use lemmy_db_views_actor::{
|
|||
community_moderator_view::CommunityModeratorView,
|
||||
community_view::CommunityView,
|
||||
};
|
||||
use lemmy_utils::request::SiteMetadata;
|
||||
use lemmy_utils::{request::SiteMetadata, Sensitive};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
|
@ -20,21 +20,21 @@ pub struct CreatePost {
|
|||
pub body: Option<String>,
|
||||
pub honeypot: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PostResponse {
|
||||
pub post_view: PostView,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPost {
|
||||
pub id: PostId,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetPostResponse {
|
||||
pub post_view: PostView,
|
||||
pub community_view: CommunityView,
|
||||
|
@ -52,7 +52,7 @@ pub struct GetPosts {
|
|||
pub community_id: Option<CommunityId>,
|
||||
pub community_name: Option<String>,
|
||||
pub saved_only: Option<bool>,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -60,86 +60,86 @@ pub struct GetPostsResponse {
|
|||
pub posts: Vec<PostView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreatePostLike {
|
||||
pub post_id: PostId,
|
||||
pub score: i16,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditPost {
|
||||
pub post_id: PostId,
|
||||
pub name: Option<String>,
|
||||
pub url: Option<Url>,
|
||||
pub body: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DeletePost {
|
||||
pub post_id: PostId,
|
||||
pub deleted: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RemovePost {
|
||||
pub post_id: PostId,
|
||||
pub removed: bool,
|
||||
pub reason: Option<String>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MarkPostAsRead {
|
||||
pub post_id: PostId,
|
||||
pub read: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LockPost {
|
||||
pub post_id: PostId,
|
||||
pub locked: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct StickyPost {
|
||||
pub post_id: PostId,
|
||||
pub stickied: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SavePost {
|
||||
pub post_id: PostId,
|
||||
pub save: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreatePostReport {
|
||||
pub post_id: PostId,
|
||||
pub reason: String,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PostReportResponse {
|
||||
pub post_report_view: PostReportView,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ResolvePostReport {
|
||||
pub report_id: PostReportId,
|
||||
pub resolved: bool,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ListPostReports {
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
|
@ -147,10 +147,10 @@ pub struct ListPostReports {
|
|||
pub unresolved_only: Option<bool>,
|
||||
/// if no community is given, it returns reports for all communities moderated by the auth user
|
||||
pub community_id: Option<CommunityId>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ListPostReportsResponse {
|
||||
pub post_reports: Vec<PostReportView>,
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ use lemmy_db_views_moderator::{
|
|||
mod_sticky_post_view::ModStickyPostView,
|
||||
mod_transfer_community_view::ModTransferCommunityView,
|
||||
};
|
||||
use lemmy_utils::Sensitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -39,7 +40,7 @@ pub struct Search {
|
|||
pub listing_type: Option<String>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -54,10 +55,10 @@ pub struct SearchResponse {
|
|||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ResolveObject {
|
||||
pub q: String,
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct ResolveObjectResponse {
|
||||
pub comment: Option<CommentView>,
|
||||
pub post: Option<PostView>,
|
||||
|
@ -65,7 +66,7 @@ pub struct ResolveObjectResponse {
|
|||
pub person: Option<PersonViewSafe>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetModlog {
|
||||
pub mod_person_id: Option<PersonId>,
|
||||
pub community_id: Option<CommunityId>,
|
||||
|
@ -73,7 +74,7 @@ pub struct GetModlog {
|
|||
pub limit: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetModlogResponse {
|
||||
pub removed_posts: Vec<ModRemovePostView>,
|
||||
pub locked_posts: Vec<ModLockPostView>,
|
||||
|
@ -87,7 +88,7 @@ pub struct GetModlogResponse {
|
|||
pub added: Vec<ModAddView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CreateSite {
|
||||
pub name: String,
|
||||
pub sidebar: Option<String>,
|
||||
|
@ -102,10 +103,10 @@ pub struct CreateSite {
|
|||
pub require_application: Option<bool>,
|
||||
pub application_question: Option<String>,
|
||||
pub private_instance: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct EditSite {
|
||||
pub name: Option<String>,
|
||||
pub sidebar: Option<String>,
|
||||
|
@ -120,20 +121,20 @@ pub struct EditSite {
|
|||
pub require_application: Option<bool>,
|
||||
pub application_question: Option<String>,
|
||||
pub private_instance: Option<bool>,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetSite {
|
||||
pub auth: Option<String>,
|
||||
pub auth: Option<Sensitive<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct SiteResponse {
|
||||
pub site_view: SiteView,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetSiteResponse {
|
||||
pub site_view: Option<SiteView>, // Because the site might not be set up yet
|
||||
pub admins: Vec<PersonViewSafe>,
|
||||
|
@ -144,7 +145,7 @@ pub struct GetSiteResponse {
|
|||
pub federated_instances: Option<FederatedInstances>, // Federation may be disabled
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MyUserInfo {
|
||||
pub local_user_view: LocalUserSettingsView,
|
||||
pub follows: Vec<CommunityFollowerView>,
|
||||
|
@ -153,29 +154,29 @@ pub struct MyUserInfo {
|
|||
pub person_blocks: Vec<PersonBlockView>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct TransferSite {
|
||||
pub person_id: PersonId,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetSiteConfig {
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GetSiteConfigResponse {
|
||||
pub config_hjson: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SaveSiteConfig {
|
||||
pub config_hjson: String,
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct FederatedInstances {
|
||||
pub linked: Vec<String>,
|
||||
pub allowed: Option<Vec<String>>,
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use lemmy_db_schema::newtypes::{CommunityId, PostId};
|
||||
use lemmy_utils::Sensitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct UserJoin {
|
||||
pub auth: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct UserJoinResponse {
|
||||
pub joined: bool,
|
||||
}
|
||||
|
@ -16,7 +17,7 @@ pub struct CommunityJoin {
|
|||
pub community_id: CommunityId,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct CommunityJoinResponse {
|
||||
pub joined: bool,
|
||||
}
|
||||
|
@ -26,7 +27,7 @@ pub struct ModJoin {
|
|||
pub community_id: CommunityId,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ModJoinResponse {
|
||||
pub joined: bool,
|
||||
}
|
||||
|
@ -36,7 +37,7 @@ pub struct PostJoin {
|
|||
pub post_id: PostId,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PostJoinResponse {
|
||||
pub joined: bool,
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use lemmy_api_common::{
|
|||
blocking,
|
||||
check_community_ban,
|
||||
check_community_deleted_or_removed,
|
||||
check_person_block,
|
||||
check_post_deleted_or_removed,
|
||||
comment::*,
|
||||
get_local_user_view_from_jwt,
|
||||
|
@ -31,7 +30,6 @@ use lemmy_db_schema::{
|
|||
use lemmy_db_views::comment_view::CommentView;
|
||||
use lemmy_utils::{
|
||||
utils::{remove_slurs, scrape_text_for_mentions},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -45,6 +43,7 @@ use lemmy_websocket::{
|
|||
impl PerformCrud for CreateComment {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -66,11 +65,9 @@ impl PerformCrud for CreateComment {
|
|||
check_community_deleted_or_removed(community_id, context.pool()).await?;
|
||||
check_post_deleted_or_removed(&post)?;
|
||||
|
||||
check_person_block(local_user_view.person.id, post.creator_id, context.pool()).await?;
|
||||
|
||||
// Check if post is locked, no new comments
|
||||
if post.locked {
|
||||
return Err(ApiError::err_plain("locked").into());
|
||||
return Err(LemmyError::from_message("locked"));
|
||||
}
|
||||
|
||||
// If there's a parent_id, check to make sure that comment is in that post
|
||||
|
@ -78,13 +75,12 @@ impl PerformCrud for CreateComment {
|
|||
// Make sure the parent comment exists
|
||||
let parent = blocking(context.pool(), move |conn| Comment::read(conn, parent_id))
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_comment", e))?;
|
||||
|
||||
check_person_block(local_user_view.person.id, parent.creator_id, context.pool()).await?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_comment"))?;
|
||||
|
||||
// Strange issue where sometimes the post ID is incorrect
|
||||
if parent.post_id != post_id {
|
||||
return Err(ApiError::err_plain("couldnt_create_comment").into());
|
||||
return Err(LemmyError::from_message("couldnt_create_comment"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +98,8 @@ impl PerformCrud for CreateComment {
|
|||
Comment::create(conn, &comment_form2)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_comment"))?;
|
||||
|
||||
// Necessary to update the ap_id
|
||||
let inserted_comment_id = inserted_comment.id;
|
||||
|
@ -118,7 +115,8 @@ impl PerformCrud for CreateComment {
|
|||
Ok(Comment::update_ap_id(conn, inserted_comment_id, apub_id)?)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_comment"))?;
|
||||
|
||||
// Scan the comment for user mentions, add those rows
|
||||
let post_id = post.id;
|
||||
|
@ -144,7 +142,8 @@ impl PerformCrud for CreateComment {
|
|||
let like = move |conn: &'_ _| CommentLike::like(conn, &like_form);
|
||||
blocking(context.pool(), like)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_like_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_like_comment"))?;
|
||||
|
||||
let apub_comment: ApubComment = updated_comment.into();
|
||||
CreateOrUpdateComment::send(
|
||||
|
@ -179,7 +178,8 @@ impl PerformCrud for CreateComment {
|
|||
Comment::update_read(conn, comment_id, true)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
}
|
||||
// If its a reply, mark the parent as read
|
||||
if let Some(parent_id) = data.parent_id {
|
||||
|
@ -192,7 +192,8 @@ impl PerformCrud for CreateComment {
|
|||
Comment::update_read(conn, parent_id, true)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_parent_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_parent_comment"))?;
|
||||
}
|
||||
// If the parent has PersonMentions mark them as read too
|
||||
let person_id = local_user_view.person.id;
|
||||
|
@ -205,7 +206,8 @@ impl PerformCrud for CreateComment {
|
|||
PersonMention::update_read(conn, mention.id, true)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_person_mentions", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_person_mentions"))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::comment_view::CommentView;
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{
|
||||
send::{send_comment_ws_message, send_local_notifs},
|
||||
LemmyContext,
|
||||
|
@ -29,6 +29,7 @@ use lemmy_websocket::{
|
|||
impl PerformCrud for DeleteComment {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -46,7 +47,7 @@ impl PerformCrud for DeleteComment {
|
|||
|
||||
// Dont delete it if its already been deleted.
|
||||
if orig_comment.comment.deleted == data.deleted {
|
||||
return Err(ApiError::err_plain("couldnt_update_comment").into());
|
||||
return Err(LemmyError::from_message("couldnt_update_comment"));
|
||||
}
|
||||
|
||||
check_community_ban(
|
||||
|
@ -58,7 +59,7 @@ impl PerformCrud for DeleteComment {
|
|||
|
||||
// Verify that only the creator can delete
|
||||
if local_user_view.person.id != orig_comment.creator.id {
|
||||
return Err(ApiError::err_plain("no_comment_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_comment_edit_allowed"));
|
||||
}
|
||||
|
||||
// Do the delete
|
||||
|
@ -67,7 +68,8 @@ impl PerformCrud for DeleteComment {
|
|||
Comment::update_deleted(conn, comment_id, deleted)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
let post_id = updated_comment.post_id;
|
||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||
|
@ -112,6 +114,7 @@ impl PerformCrud for DeleteComment {
|
|||
impl PerformCrud for RemoveComment {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -148,7 +151,8 @@ impl PerformCrud for RemoveComment {
|
|||
Comment::update_removed(conn, comment_id, removed)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
// Mod tables
|
||||
let form = ModRemoveCommentForm {
|
||||
|
|
|
@ -18,13 +18,14 @@ use lemmy_db_schema::{
|
|||
SortType,
|
||||
};
|
||||
use lemmy_db_views::comment_view::{CommentQueryBuilder, CommentView};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for GetComment {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -32,7 +33,8 @@ impl PerformCrud for GetComment {
|
|||
) -> Result<Self::Response, LemmyError> {
|
||||
let data = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -42,7 +44,8 @@ impl PerformCrud for GetComment {
|
|||
CommentView::read(conn, id, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_comment"))?;
|
||||
|
||||
Ok(Self::Response {
|
||||
comment_view,
|
||||
|
@ -56,6 +59,7 @@ impl PerformCrud for GetComment {
|
|||
impl PerformCrud for GetComments {
|
||||
type Response = GetCommentsResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -63,7 +67,8 @@ impl PerformCrud for GetComments {
|
|||
) -> Result<GetCommentsResponse, LemmyError> {
|
||||
let data: &GetComments = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -100,7 +105,8 @@ impl PerformCrud for GetComments {
|
|||
.list()
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_get_comments", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_get_comments"))?;
|
||||
|
||||
// Blank out deleted or removed info
|
||||
for cv in comments
|
||||
|
|
|
@ -16,7 +16,6 @@ use lemmy_db_schema::source::comment::Comment;
|
|||
use lemmy_db_views::comment_view::CommentView;
|
||||
use lemmy_utils::{
|
||||
utils::{remove_slurs, scrape_text_for_mentions},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -32,6 +31,7 @@ use crate::PerformCrud;
|
|||
impl PerformCrud for EditComment {
|
||||
type Response = CommentResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -59,7 +59,7 @@ impl PerformCrud for EditComment {
|
|||
|
||||
// Verify that only the creator can edit
|
||||
if local_user_view.person.id != orig_comment.creator.id {
|
||||
return Err(ApiError::err_plain("no_comment_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_comment_edit_allowed"));
|
||||
}
|
||||
|
||||
// Do the update
|
||||
|
@ -70,7 +70,8 @@ impl PerformCrud for EditComment {
|
|||
Comment::update_content(conn, comment_id, &content_slurs_removed)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
// Do the mentions / recipients
|
||||
let updated_comment_content = updated_comment.content.to_owned();
|
||||
|
|
|
@ -34,7 +34,6 @@ use lemmy_db_views_actor::community_view::CommunityView;
|
|||
use lemmy_utils::{
|
||||
apub::generate_actor_keypair,
|
||||
utils::{check_slurs, check_slurs_opt, is_valid_actor_name},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -44,6 +43,7 @@ use lemmy_websocket::LemmyContext;
|
|||
impl PerformCrud for CreateCommunity {
|
||||
type Response = CommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -55,7 +55,9 @@ impl PerformCrud for CreateCommunity {
|
|||
|
||||
let site = blocking(context.pool(), move |conn| Site::read(conn, 0)).await??;
|
||||
if site.community_creation_admin_only && is_admin(&local_user_view).is_err() {
|
||||
return Err(ApiError::err_plain("only_admins_can_create_communities").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"only_admins_can_create_communities",
|
||||
));
|
||||
}
|
||||
|
||||
check_slurs(&data.name, &context.settings().slur_regex())?;
|
||||
|
@ -63,7 +65,7 @@ impl PerformCrud for CreateCommunity {
|
|||
check_slurs_opt(&data.description, &context.settings().slur_regex())?;
|
||||
|
||||
if !is_valid_actor_name(&data.name, context.settings().actor_name_max_length) {
|
||||
return Err(ApiError::err_plain("invalid_community_name").into());
|
||||
return Err(LemmyError::from_message("invalid_community_name"));
|
||||
}
|
||||
|
||||
// Double check for duplicate community actor_ids
|
||||
|
@ -75,7 +77,7 @@ impl PerformCrud for CreateCommunity {
|
|||
let community_actor_id_wrapped = ObjectId::<ApubCommunity>::new(community_actor_id.clone());
|
||||
let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
|
||||
if community_dupe.is_ok() {
|
||||
return Err(ApiError::err_plain("community_already_exists").into());
|
||||
return Err(LemmyError::from_message("community_already_exists"));
|
||||
}
|
||||
|
||||
// Check to make sure the icon and banners are urls
|
||||
|
@ -105,7 +107,8 @@ impl PerformCrud for CreateCommunity {
|
|||
Community::create(conn, &community_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_already_exists"))?;
|
||||
|
||||
// The community creator becomes a moderator
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
|
@ -115,7 +118,9 @@ impl PerformCrud for CreateCommunity {
|
|||
|
||||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||
if blocking(context.pool(), join).await?.is_err() {
|
||||
return Err(ApiError::err_plain("community_moderator_already_exists").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"community_moderator_already_exists",
|
||||
));
|
||||
}
|
||||
|
||||
// Follow your own community
|
||||
|
@ -127,7 +132,9 @@ impl PerformCrud for CreateCommunity {
|
|||
|
||||
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
|
||||
if blocking(context.pool(), follow).await?.is_err() {
|
||||
return Err(ApiError::err_plain("community_follower_already_exists").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"community_follower_already_exists",
|
||||
));
|
||||
}
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
|
|
|
@ -10,13 +10,14 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
||||
use lemmy_utils::{utils::naive_from_unix, ApiError, ConnectionId, LemmyError};
|
||||
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 DeleteCommunity {
|
||||
type Response = CommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -35,7 +36,7 @@ impl PerformCrud for DeleteCommunity {
|
|||
|
||||
// Make sure deleter is the top mod
|
||||
if local_user_view.person.id != community_mods[0].moderator.id {
|
||||
return Err(ApiError::err_plain("no_community_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_community_edit_allowed"));
|
||||
}
|
||||
|
||||
// Do the delete
|
||||
|
@ -45,7 +46,8 @@ impl PerformCrud for DeleteCommunity {
|
|||
Community::update_deleted(conn, community_id, deleted)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_community"))?;
|
||||
|
||||
// Send apub messages
|
||||
send_apub_delete(
|
||||
|
@ -72,6 +74,7 @@ impl PerformCrud for DeleteCommunity {
|
|||
impl PerformCrud for RemoveCommunity {
|
||||
type Response = CommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -91,7 +94,8 @@ impl PerformCrud for RemoveCommunity {
|
|||
Community::update_removed(conn, community_id, removed)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_community"))?;
|
||||
|
||||
// Mod tables
|
||||
let expires = data.expires.map(naive_from_unix);
|
||||
|
|
|
@ -22,13 +22,14 @@ use lemmy_db_views_actor::{
|
|||
community_moderator_view::CommunityModeratorView,
|
||||
community_view::{CommunityQueryBuilder, CommunityView},
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::GetCommunityUsersOnline, LemmyContext};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for GetCommunity {
|
||||
type Response = GetCommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -36,7 +37,8 @@ impl PerformCrud for GetCommunity {
|
|||
) -> Result<GetCommunityResponse, LemmyError> {
|
||||
let data: &GetCommunity = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -53,7 +55,8 @@ impl PerformCrud for GetCommunity {
|
|||
ObjectId::<ApubCommunity>::new(community_actor_id)
|
||||
.dereference(context, &mut 0)
|
||||
.await
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?
|
||||
.id
|
||||
}
|
||||
};
|
||||
|
@ -62,7 +65,8 @@ impl PerformCrud for GetCommunity {
|
|||
CommunityView::read(conn, community_id, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() && (community_view.community.deleted || community_view.community.removed)
|
||||
|
@ -74,7 +78,8 @@ impl PerformCrud for GetCommunity {
|
|||
CommunityModeratorView::for_community(conn, community_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?;
|
||||
|
||||
let online = context
|
||||
.chat_server()
|
||||
|
@ -97,6 +102,7 @@ impl PerformCrud for GetCommunity {
|
|||
impl PerformCrud for ListCommunities {
|
||||
type Response = ListCommunitiesResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -104,7 +110,8 @@ impl PerformCrud for ListCommunities {
|
|||
) -> Result<ListCommunitiesResponse, LemmyError> {
|
||||
let data: &ListCommunities = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
|
|
@ -14,13 +14,14 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
||||
use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{utils::check_slurs_opt, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for EditCommunity {
|
||||
type Response = CommunityResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -41,7 +42,7 @@ impl PerformCrud for EditCommunity {
|
|||
})
|
||||
.await??;
|
||||
if !mods.contains(&local_user_view.person.id) {
|
||||
return Err(ApiError::err_plain("not_a_moderator").into());
|
||||
return Err(LemmyError::from_message("not_a_moderator"));
|
||||
}
|
||||
|
||||
let community_id = data.community_id;
|
||||
|
@ -70,7 +71,8 @@ impl PerformCrud for EditCommunity {
|
|||
Community::update(conn, community_id, &community_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_community"))?;
|
||||
|
||||
UpdateCommunity::send(
|
||||
updated_community.into(),
|
||||
|
|
|
@ -27,7 +27,6 @@ use lemmy_db_schema::{
|
|||
use lemmy_utils::{
|
||||
request::fetch_site_data,
|
||||
utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -40,6 +39,7 @@ use webmention::{Webmention, WebmentionError};
|
|||
impl PerformCrud for CreatePost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -55,7 +55,7 @@ impl PerformCrud for CreatePost {
|
|||
honeypot_check(&data.honeypot)?;
|
||||
|
||||
if !is_valid_post_title(&data.name) {
|
||||
return Err(ApiError::err_plain("invalid_post_title").into());
|
||||
return Err(LemmyError::from_message("invalid_post_title"));
|
||||
}
|
||||
|
||||
check_community_ban(local_user_view.person.id, data.community_id, context.pool()).await?;
|
||||
|
@ -93,7 +93,7 @@ impl PerformCrud for CreatePost {
|
|||
"couldnt_create_post"
|
||||
};
|
||||
|
||||
return Err(ApiError::err(err_type, e).into());
|
||||
return Err(LemmyError::from(e).with_message(err_type));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,8 @@ impl PerformCrud for CreatePost {
|
|||
Ok(Post::update_ap_id(conn, inserted_post_id, apub_id)?)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_post", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_post"))?;
|
||||
|
||||
// They like their own post by default
|
||||
let person_id = local_user_view.person.id;
|
||||
|
@ -121,7 +122,7 @@ impl PerformCrud for CreatePost {
|
|||
|
||||
let like = move |conn: &'_ _| PostLike::like(conn, &like_form);
|
||||
if blocking(context.pool(), like).await?.is_err() {
|
||||
return Err(ApiError::err_plain("couldnt_like_post").into());
|
||||
return Err(LemmyError::from_message("couldnt_like_post"));
|
||||
}
|
||||
|
||||
// Mark the post as read
|
||||
|
|
|
@ -17,13 +17,14 @@ use lemmy_db_schema::{
|
|||
},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for DeletePost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -38,7 +39,7 @@ impl PerformCrud for DeletePost {
|
|||
|
||||
// Dont delete it if its already been deleted.
|
||||
if orig_post.deleted == data.deleted {
|
||||
return Err(ApiError::err_plain("couldnt_update_post").into());
|
||||
return Err(LemmyError::from_message("couldnt_update_post"));
|
||||
}
|
||||
|
||||
check_community_ban(
|
||||
|
@ -51,7 +52,7 @@ impl PerformCrud for DeletePost {
|
|||
|
||||
// Verify that only the creator can delete
|
||||
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
|
||||
return Err(ApiError::err_plain("no_post_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_post_edit_allowed"));
|
||||
}
|
||||
|
||||
// Update the post
|
||||
|
@ -91,6 +92,7 @@ impl PerformCrud for DeletePost {
|
|||
impl PerformCrud for RemovePost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -26,13 +26,14 @@ use lemmy_db_views_actor::{
|
|||
community_moderator_view::CommunityModeratorView,
|
||||
community_view::CommunityView,
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::GetPostUsersOnline, LemmyContext};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for GetPost {
|
||||
type Response = GetPostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -40,7 +41,8 @@ impl PerformCrud for GetPost {
|
|||
) -> Result<GetPostResponse, LemmyError> {
|
||||
let data: &GetPost = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -54,7 +56,8 @@ impl PerformCrud for GetPost {
|
|||
PostView::read(conn, id, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_post", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_post"))?;
|
||||
|
||||
// Mark the post as read
|
||||
if let Some(person_id) = person_id {
|
||||
|
@ -78,7 +81,8 @@ impl PerformCrud for GetPost {
|
|||
CommunityView::read(conn, community_id, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_community"))?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() {
|
||||
|
@ -123,6 +127,7 @@ impl PerformCrud for GetPost {
|
|||
impl PerformCrud for GetPosts {
|
||||
type Response = GetPostsResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -130,7 +135,8 @@ impl PerformCrud for GetPosts {
|
|||
) -> Result<GetPostsResponse, LemmyError> {
|
||||
let data: &GetPosts = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -175,7 +181,8 @@ impl PerformCrud for GetPosts {
|
|||
.list()
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_get_posts", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_get_posts"))?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() {
|
||||
|
|
|
@ -19,7 +19,6 @@ use lemmy_db_schema::{
|
|||
use lemmy_utils::{
|
||||
request::fetch_site_data,
|
||||
utils::{check_slurs_opt, clean_url_params, is_valid_post_title},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -31,6 +30,7 @@ use crate::PerformCrud;
|
|||
impl PerformCrud for EditPost {
|
||||
type Response = PostResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -46,7 +46,7 @@ impl PerformCrud for EditPost {
|
|||
|
||||
if let Some(name) = &data.name {
|
||||
if !is_valid_post_title(name) {
|
||||
return Err(ApiError::err_plain("invalid_post_title").into());
|
||||
return Err(LemmyError::from_message("invalid_post_title"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ impl PerformCrud for EditPost {
|
|||
|
||||
// Verify that only the creator can edit
|
||||
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
|
||||
return Err(ApiError::err_plain("no_post_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_post_edit_allowed"));
|
||||
}
|
||||
|
||||
// Fetch post links and Pictrs cached image
|
||||
|
@ -103,7 +103,7 @@ impl PerformCrud for EditPost {
|
|||
"couldnt_update_post"
|
||||
};
|
||||
|
||||
return Err(ApiError::err(err_type, e).into());
|
||||
return Err(LemmyError::from(e).with_message(err_type));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::local_user_view::LocalUserView;
|
||||
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{
|
||||
send::{send_email_to_user, send_pm_ws_message},
|
||||
LemmyContext,
|
||||
|
@ -30,6 +30,7 @@ use lemmy_websocket::{
|
|||
impl PerformCrud for CreatePrivateMessage {
|
||||
type Response = PrivateMessageResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -58,7 +59,7 @@ impl PerformCrud for CreatePrivateMessage {
|
|||
{
|
||||
Ok(private_message) => private_message,
|
||||
Err(e) => {
|
||||
return Err(ApiError::err("couldnt_create_private_message", e).into());
|
||||
return Err(LemmyError::from(e).with_message("couldnt_create_private_message"));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -80,7 +81,8 @@ impl PerformCrud for CreatePrivateMessage {
|
|||
},
|
||||
)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_create_private_message", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_create_private_message"))?;
|
||||
|
||||
CreateOrUpdatePrivateMessage::send(
|
||||
updated_private_message.into(),
|
||||
|
|
|
@ -13,13 +13,14 @@ use lemmy_db_schema::{
|
|||
source::private_message::PrivateMessage,
|
||||
traits::{Crud, DeleteableOrRemoveable},
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for DeletePrivateMessage {
|
||||
type Response = PrivateMessageResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -36,7 +37,7 @@ impl PerformCrud for DeletePrivateMessage {
|
|||
})
|
||||
.await??;
|
||||
if local_user_view.person.id != orig_private_message.creator_id {
|
||||
return Err(ApiError::err_plain("no_private_message_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_private_message_edit_allowed"));
|
||||
}
|
||||
|
||||
// Doing the update
|
||||
|
@ -46,7 +47,8 @@ impl PerformCrud for DeletePrivateMessage {
|
|||
PrivateMessage::update_deleted(conn, private_message_id, deleted)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_private_message", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_private_message"))?;
|
||||
|
||||
// Send the apub update
|
||||
if data.deleted {
|
||||
|
|
|
@ -14,6 +14,7 @@ use lemmy_websocket::LemmyContext;
|
|||
impl PerformCrud for GetPrivateMessages {
|
||||
type Response = PrivateMessagesResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -21,7 +22,7 @@ impl PerformCrud for GetPrivateMessages {
|
|||
) -> Result<PrivateMessagesResponse, LemmyError> {
|
||||
let data: &GetPrivateMessages = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt(data.auth.as_ref(), context.pool(), context.secret()).await?;
|
||||
let person_id = local_user_view.person.id;
|
||||
|
||||
let page = data.page;
|
||||
|
|
|
@ -10,13 +10,14 @@ use lemmy_apub::protocol::activities::{
|
|||
CreateOrUpdateType,
|
||||
};
|
||||
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
|
||||
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{utils::remove_slurs, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for EditPrivateMessage {
|
||||
type Response = PrivateMessageResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -33,7 +34,7 @@ impl PerformCrud for EditPrivateMessage {
|
|||
})
|
||||
.await??;
|
||||
if local_user_view.person.id != orig_private_message.creator_id {
|
||||
return Err(ApiError::err_plain("no_private_message_edit_allowed").into());
|
||||
return Err(LemmyError::from_message("no_private_message_edit_allowed"));
|
||||
}
|
||||
|
||||
// Doing the update
|
||||
|
@ -43,7 +44,8 @@ impl PerformCrud for EditPrivateMessage {
|
|||
PrivateMessage::update_content(conn, private_message_id, &content_slurs_removed)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_private_message", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_private_message"))?;
|
||||
|
||||
// Send the apub update
|
||||
CreateOrUpdatePrivateMessage::send(
|
||||
|
|
|
@ -16,7 +16,6 @@ use lemmy_db_schema::{
|
|||
use lemmy_db_views::site_view::SiteView;
|
||||
use lemmy_utils::{
|
||||
utils::{check_slurs, check_slurs_opt},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -26,6 +25,7 @@ use lemmy_websocket::LemmyContext;
|
|||
impl PerformCrud for CreateSite {
|
||||
type Response = SiteResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -35,7 +35,7 @@ impl PerformCrud for CreateSite {
|
|||
|
||||
let read_site = Site::read_simple;
|
||||
if blocking(context.pool(), read_site).await?.is_ok() {
|
||||
return Err(ApiError::err_plain("site_already_exists").into());
|
||||
return Err(LemmyError::from_message("site_already_exists"));
|
||||
};
|
||||
|
||||
let local_user_view =
|
||||
|
@ -72,7 +72,7 @@ impl PerformCrud for CreateSite {
|
|||
|
||||
let create_site = move |conn: &'_ _| Site::create(conn, &site_form);
|
||||
if blocking(context.pool(), create_site).await?.is_err() {
|
||||
return Err(ApiError::err_plain("site_already_exists").into());
|
||||
return Err(LemmyError::from_message("site_already_exists"));
|
||||
}
|
||||
|
||||
let site_view = blocking(context.pool(), SiteView::read).await??;
|
||||
|
|
|
@ -15,7 +15,7 @@ use lemmy_db_views_actor::{
|
|||
person_block_view::PersonBlockView,
|
||||
person_view::PersonViewSafe,
|
||||
};
|
||||
use lemmy_utils::{version, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{version, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::GetUsersOnline, LemmyContext};
|
||||
use tracing::info;
|
||||
|
||||
|
@ -23,6 +23,7 @@ use tracing::info;
|
|||
impl PerformCrud for GetSite {
|
||||
type Response = GetSiteResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -37,9 +38,9 @@ impl PerformCrud for GetSite {
|
|||
if let Some(setup) = context.settings().setup.as_ref() {
|
||||
let register = Register {
|
||||
username: setup.admin_username.to_owned(),
|
||||
email: setup.admin_email.to_owned(),
|
||||
password: setup.admin_password.to_owned(),
|
||||
password_verify: setup.admin_password.to_owned(),
|
||||
email: setup.admin_email.clone().map(|s| s.into()),
|
||||
password: setup.admin_password.clone().into(),
|
||||
password_verify: setup.admin_password.clone().into(),
|
||||
show_nsfw: true,
|
||||
captcha_uuid: None,
|
||||
captcha_answer: None,
|
||||
|
@ -100,36 +101,43 @@ impl PerformCrud for GetSite {
|
|||
.unwrap_or(1);
|
||||
|
||||
// Build the local user
|
||||
let my_user = if let Some(local_user_view) =
|
||||
get_local_user_settings_view_from_jwt_opt(&data.auth, context.pool(), context.secret())
|
||||
.await?
|
||||
let my_user = if let Some(local_user_view) = get_local_user_settings_view_from_jwt_opt(
|
||||
data.auth.as_ref(),
|
||||
context.pool(),
|
||||
context.secret(),
|
||||
)
|
||||
.await?
|
||||
{
|
||||
let person_id = local_user_view.person.id;
|
||||
let follows = blocking(context.pool(), move |conn| {
|
||||
CommunityFollowerView::for_person(conn, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("system_err_login", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("system_err_login"))?;
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_blocks = blocking(context.pool(), move |conn| {
|
||||
CommunityBlockView::for_person(conn, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("system_err_login", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("system_err_login"))?;
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
let person_blocks = blocking(context.pool(), move |conn| {
|
||||
PersonBlockView::for_person(conn, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("system_err_login", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("system_err_login"))?;
|
||||
|
||||
let moderates = blocking(context.pool(), move |conn| {
|
||||
CommunityModeratorView::for_person(conn, person_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("system_err_login", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("system_err_login"))?;
|
||||
|
||||
Some(MyUserInfo {
|
||||
local_user_view,
|
||||
|
@ -142,7 +150,7 @@ impl PerformCrud for GetSite {
|
|||
// If the site is setup, private, and there is no auth, return an error
|
||||
if let Some(site_view) = site_view.to_owned() {
|
||||
if site_view.site.private_instance {
|
||||
return Err(ApiError::err_plain("instance_is_private").into());
|
||||
return Err(LemmyError::from_message("instance_is_private"));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
@ -15,12 +15,14 @@ use lemmy_db_schema::{
|
|||
traits::Crud,
|
||||
};
|
||||
use lemmy_db_views::site_view::SiteView;
|
||||
use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{utils::check_slurs_opt, ConnectionId, LemmyError};
|
||||
use lemmy_websocket::{messages::SendAllMessage, LemmyContext, UserOperationCrud};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for EditSite {
|
||||
type Response = SiteResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -69,7 +71,8 @@ impl PerformCrud for EditSite {
|
|||
let update_site = move |conn: &'_ _| Site::update(conn, 1, &site_form);
|
||||
blocking(context.pool(), update_site)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_site", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_site"))?;
|
||||
|
||||
let site_view = blocking(context.pool(), SiteView::read).await??;
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ use lemmy_utils::{
|
|||
apub::generate_actor_keypair,
|
||||
claims::Claims,
|
||||
utils::{check_slurs, is_valid_actor_name},
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
LemmyError,
|
||||
};
|
||||
|
@ -41,6 +40,7 @@ use lemmy_websocket::{email::send_verification_email, messages::CheckCaptcha, Le
|
|||
impl PerformCrud for Register {
|
||||
type Response = LoginResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -54,7 +54,7 @@ impl PerformCrud for Register {
|
|||
// Make sure site has open registration
|
||||
if let Ok(site) = blocking(context.pool(), Site::read_simple).await? {
|
||||
if !site.open_registration {
|
||||
return Err(ApiError::err_plain("registration_closed").into());
|
||||
return Err(LemmyError::from_message("registration_closed"));
|
||||
}
|
||||
email_verification = site.require_email_verification;
|
||||
require_application = site.require_application;
|
||||
|
@ -64,16 +64,18 @@ impl PerformCrud for Register {
|
|||
honeypot_check(&data.honeypot)?;
|
||||
|
||||
if email_verification && data.email.is_none() {
|
||||
return Err(ApiError::err_plain("email_required").into());
|
||||
return Err(LemmyError::from_message("email_required"));
|
||||
}
|
||||
|
||||
if require_application && data.answer.is_none() {
|
||||
return Err(ApiError::err_plain("registration_application_answer_required").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"registration_application_answer_required",
|
||||
));
|
||||
}
|
||||
|
||||
// Make sure passwords match
|
||||
if data.password != data.password_verify {
|
||||
return Err(ApiError::err_plain("passwords_dont_match").into());
|
||||
return Err(LemmyError::from_message("passwords_dont_match"));
|
||||
}
|
||||
|
||||
// Check if there are admins. False if admins exist
|
||||
|
@ -98,7 +100,7 @@ impl PerformCrud for Register {
|
|||
})
|
||||
.await?;
|
||||
if !check {
|
||||
return Err(ApiError::err_plain("captcha_incorrect").into());
|
||||
return Err(LemmyError::from_message("captcha_incorrect"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +108,7 @@ impl PerformCrud for Register {
|
|||
|
||||
let actor_keypair = generate_actor_keypair()?;
|
||||
if !is_valid_actor_name(&data.username, context.settings().actor_name_max_length) {
|
||||
return Err(ApiError::err_plain("invalid_username").into());
|
||||
return Err(LemmyError::from_message("invalid_username"));
|
||||
}
|
||||
let actor_id = generate_local_apub_endpoint(
|
||||
EndpointType::Person,
|
||||
|
@ -133,13 +135,14 @@ impl PerformCrud for Register {
|
|||
Person::create(conn, &person_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("user_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("user_already_exists"))?;
|
||||
|
||||
// Create the local user
|
||||
let local_user_form = LocalUserForm {
|
||||
person_id: Some(inserted_person.id),
|
||||
email: Some(data.email.to_owned()),
|
||||
password_encrypted: Some(data.password.to_owned()),
|
||||
email: Some(data.email.as_deref().map(|s| s.to_owned())),
|
||||
password_encrypted: Some(data.password.to_string()),
|
||||
show_nsfw: Some(data.show_nsfw),
|
||||
email_verified: Some(!email_verification),
|
||||
..LocalUserForm::default()
|
||||
|
@ -166,7 +169,7 @@ impl PerformCrud for Register {
|
|||
})
|
||||
.await??;
|
||||
|
||||
return Err(ApiError::err(err_type, e).into());
|
||||
return Err(LemmyError::from(e).with_message(err_type));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -231,7 +234,8 @@ impl PerformCrud for Register {
|
|||
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
|
||||
blocking(context.pool(), follow)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_follower_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_follower_already_exists"))?;
|
||||
|
||||
// If its an admin, add them as a mod and follower to main
|
||||
if no_admins {
|
||||
|
@ -243,7 +247,8 @@ impl PerformCrud for Register {
|
|||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||
blocking(context.pool(), join)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("community_moderator_already_exists", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("community_moderator_already_exists"))?;
|
||||
}
|
||||
|
||||
// Log the user in directly if email verification is not required
|
||||
|
@ -269,11 +274,14 @@ impl PerformCrud for Register {
|
|||
}
|
||||
} else {
|
||||
LoginResponse {
|
||||
jwt: Some(Claims::jwt(
|
||||
inserted_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?),
|
||||
jwt: Some(
|
||||
Claims::jwt(
|
||||
inserted_local_user.id.0,
|
||||
&context.secret().jwt_secret,
|
||||
&context.settings().hostname,
|
||||
)?
|
||||
.into(),
|
||||
),
|
||||
verify_email_sent: false,
|
||||
registration_created: false,
|
||||
}
|
||||
|
|
|
@ -3,13 +3,14 @@ use actix_web::web::Data;
|
|||
use bcrypt::verify;
|
||||
use lemmy_api_common::{blocking, get_local_user_view_from_jwt, person::*};
|
||||
use lemmy_db_schema::source::{comment::Comment, person::Person, post::Post};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for DeleteAccount {
|
||||
type Response = LoginResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -17,7 +18,7 @@ impl PerformCrud for DeleteAccount {
|
|||
) -> Result<LoginResponse, LemmyError> {
|
||||
let data: &DeleteAccount = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt(data.auth.as_ref(), context.pool(), context.secret()).await?;
|
||||
|
||||
// Verify the password
|
||||
let valid: bool = verify(
|
||||
|
@ -26,7 +27,7 @@ impl PerformCrud for DeleteAccount {
|
|||
)
|
||||
.unwrap_or(false);
|
||||
if !valid {
|
||||
return Err(ApiError::err_plain("password_incorrect").into());
|
||||
return Err(LemmyError::from_message("password_incorrect"));
|
||||
}
|
||||
|
||||
// Comments
|
||||
|
@ -34,19 +35,22 @@ impl PerformCrud for DeleteAccount {
|
|||
let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, person_id);
|
||||
blocking(context.pool(), permadelete)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_comment", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_comment"))?;
|
||||
|
||||
// Posts
|
||||
let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, person_id);
|
||||
blocking(context.pool(), permadelete)
|
||||
.await?
|
||||
.map_err(|e| ApiError::err("couldnt_update_post", e))?;
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_update_post"))?;
|
||||
|
||||
blocking(context.pool(), move |conn| {
|
||||
Person::delete_account(conn, person_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
// TODO rework this
|
||||
Ok(LoginResponse {
|
||||
jwt: None,
|
||||
verify_email_sent: false,
|
||||
|
|
|
@ -18,13 +18,14 @@ use lemmy_db_views_actor::{
|
|||
community_moderator_view::CommunityModeratorView,
|
||||
person_view::PersonViewSafe,
|
||||
};
|
||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||
use lemmy_utils::{ConnectionId, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for GetPersonDetails {
|
||||
type Response = GetPersonDetailsResponse;
|
||||
|
||||
#[tracing::instrument(skip(self, context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -32,7 +33,8 @@ impl PerformCrud for GetPersonDetails {
|
|||
) -> Result<GetPersonDetailsResponse, LemmyError> {
|
||||
let data: &GetPersonDetails = self;
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt_opt(&data.auth, context.pool(), context.secret()).await?;
|
||||
get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
|
||||
.await?;
|
||||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
|
@ -60,7 +62,8 @@ impl PerformCrud for GetPersonDetails {
|
|||
.dereference(context, &mut 0)
|
||||
.await;
|
||||
person
|
||||
.map_err(|e| ApiError::err("couldnt_find_that_username_or_email", e))?
|
||||
.map_err(LemmyError::from)
|
||||
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?
|
||||
.id
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
impl CreateOrUpdateComment {
|
||||
#[tracing::instrument(skip(comment, actor, kind, context))]
|
||||
pub async fn send(
|
||||
comment: ApubComment,
|
||||
actor: &ApubPerson,
|
||||
|
@ -83,6 +84,7 @@ impl CreateOrUpdateComment {
|
|||
impl ActivityHandler for CreateOrUpdateComment {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -102,6 +104,7 @@ impl ActivityHandler for CreateOrUpdateComment {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -131,6 +134,7 @@ impl ActivityHandler for CreateOrUpdateComment {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for CreateOrUpdateComment {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -11,6 +11,7 @@ use lemmy_websocket::{send::send_local_notifs, LemmyContext};
|
|||
|
||||
pub mod create_or_update;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_notif_recipients(
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
comment: &Comment,
|
||||
|
|
|
@ -32,6 +32,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
impl AddMod {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
community: &ApubCommunity,
|
||||
added_mod: &ApubPerson,
|
||||
|
@ -63,6 +64,7 @@ impl AddMod {
|
|||
impl ActivityHandler for AddMod {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -77,6 +79,7 @@ impl ActivityHandler for AddMod {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -109,6 +112,7 @@ impl ActivityHandler for AddMod {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for AddMod {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -44,6 +44,7 @@ impl AnnounceActivity {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
object: AnnouncableActivities,
|
||||
community: &ApubCommunity,
|
||||
|
@ -85,6 +86,8 @@ impl AnnounceActivity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for AnnounceActivity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -96,6 +99,7 @@ impl ActivityHandler for AnnounceActivity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -52,6 +52,7 @@ impl BlockUserFromCommunity {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
community: &ApubCommunity,
|
||||
target: &ApubPerson,
|
||||
|
@ -70,6 +71,8 @@ impl BlockUserFromCommunity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for BlockUserFromCommunity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -83,6 +86,7 @@ impl ActivityHandler for BlockUserFromCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -119,6 +123,7 @@ impl ActivityHandler for BlockUserFromCommunity {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for BlockUserFromCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -17,6 +17,7 @@ pub mod report;
|
|||
pub mod undo_block_user;
|
||||
pub mod update;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn send_activity_in_community<T: ActorType>(
|
||||
activity: AnnouncableActivities,
|
||||
activity_id: &Url,
|
||||
|
@ -35,6 +36,7 @@ pub(crate) async fn send_activity_in_community<T: ActorType>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community_from_moderators_url(
|
||||
moderators: &Url,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -32,6 +32,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
impl RemoveMod {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
community: &ApubCommunity,
|
||||
removed_mod: &ApubPerson,
|
||||
|
@ -62,6 +63,8 @@ impl RemoveMod {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for RemoveMod {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -76,6 +79,7 @@ impl ActivityHandler for RemoveMod {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -99,6 +103,7 @@ impl ActivityHandler for RemoveMod {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for RemoveMod {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -28,6 +28,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
impl Report {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
object_id: ObjectId<PostOrComment>,
|
||||
actor: &ApubPerson,
|
||||
|
@ -65,6 +66,8 @@ impl Report {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for Report {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -76,6 +79,7 @@ impl ActivityHandler for Report {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -29,6 +29,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
impl UndoBlockUserFromCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
community: &ApubCommunity,
|
||||
target: &ApubPerson,
|
||||
|
@ -60,6 +61,8 @@ impl UndoBlockUserFromCommunity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoBlockUserFromCommunity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -74,6 +77,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -102,6 +106,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UndoBlockUserFromCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -26,6 +26,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
impl UpdateCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
community: ApubCommunity,
|
||||
actor: &ApubPerson,
|
||||
|
@ -53,6 +54,8 @@ impl UpdateCommunity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UpdateCommunity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -73,6 +76,7 @@ impl ActivityHandler for UpdateCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -110,6 +114,7 @@ impl ActivityHandler for UpdateCommunity {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UpdateCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::{
|
|||
protocol::activities::deletion::delete::Delete,
|
||||
};
|
||||
use activitystreams_kinds::{activity::DeleteType, public};
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
|
@ -45,6 +44,8 @@ use url::Url;
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for Delete {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -65,6 +66,7 @@ impl ActivityHandler for Delete {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -112,6 +114,8 @@ impl Delete {
|
|||
unparsed: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(in crate::activities::deletion) async fn send(
|
||||
actor: &ApubPerson,
|
||||
community: &ApubCommunity,
|
||||
|
@ -127,6 +131,7 @@ impl Delete {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(in crate::activities) async fn receive_remove_action(
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
object: &Url,
|
||||
|
@ -139,7 +144,9 @@ pub(in crate::activities) async fn receive_remove_action(
|
|||
match DeletableObjects::read_from_db(object, context).await? {
|
||||
DeletableObjects::Community(community) => {
|
||||
if community.local {
|
||||
return Err(anyhow!("Only local admin can remove community").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"Only local admin can remove community",
|
||||
));
|
||||
}
|
||||
let form = ModRemoveCommunityForm {
|
||||
mod_person_id: actor.id,
|
||||
|
@ -201,6 +208,7 @@ pub(in crate::activities) async fn receive_remove_action(
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for Delete {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -20,6 +20,7 @@ use url::Url;
|
|||
pub mod delete;
|
||||
pub mod undo_delete;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send_apub_delete(
|
||||
actor: &ApubPerson,
|
||||
community: &ApubCommunity,
|
||||
|
@ -36,6 +37,7 @@ pub async fn send_apub_delete(
|
|||
|
||||
// TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
|
||||
// ugly
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send_apub_remove(
|
||||
actor: &ApubPerson,
|
||||
community: &ApubCommunity,
|
||||
|
@ -58,6 +60,7 @@ pub enum DeletableObjects {
|
|||
}
|
||||
|
||||
impl DeletableObjects {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn read_from_db(
|
||||
ap_id: &Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -83,6 +86,7 @@ impl DeletableObjects {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(in crate::activities) async fn verify_delete_activity(
|
||||
object: &Url,
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
|
@ -128,6 +132,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify_delete_activity_post_or_comment(
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
object_id: &Url,
|
||||
|
@ -149,6 +154,7 @@ async fn verify_delete_activity_post_or_comment(
|
|||
/// Write deletion or restoring of an object to the database, and send websocket message.
|
||||
/// TODO: we should do something similar for receive_remove_action(), but its much more complicated
|
||||
/// because of the mod log
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive_delete_action(
|
||||
object: &Url,
|
||||
actor: &ObjectId<ApubPerson>,
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::{
|
|||
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||
};
|
||||
use activitystreams_kinds::{activity::UndoType, public};
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
|
@ -30,6 +29,8 @@ use url::Url;
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoDelete {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -51,6 +52,7 @@ impl ActivityHandler for UndoDelete {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -72,6 +74,7 @@ impl ActivityHandler for UndoDelete {
|
|||
}
|
||||
|
||||
impl UndoDelete {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(in crate::activities::deletion) async fn send(
|
||||
actor: &ApubPerson,
|
||||
community: &ApubCommunity,
|
||||
|
@ -99,6 +102,7 @@ impl UndoDelete {
|
|||
send_activity_in_community(activity, &id, actor, community, vec![], context).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(in crate::activities) async fn receive_undo_remove_action(
|
||||
object: &Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -107,7 +111,9 @@ impl UndoDelete {
|
|||
match DeletableObjects::read_from_db(object, context).await? {
|
||||
DeletableObjects::Community(community) => {
|
||||
if community.local {
|
||||
return Err(anyhow!("Only local admin can restore community").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"Only local admin can restore community",
|
||||
));
|
||||
}
|
||||
let deleted_community = blocking(context.pool(), move |conn| {
|
||||
Community::update_removed(conn, community.id, false)
|
||||
|
@ -136,6 +142,7 @@ impl UndoDelete {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UndoDelete {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -15,6 +15,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
impl AcceptFollowCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
follow: FollowCommunity,
|
||||
context: &LemmyContext,
|
||||
|
@ -45,6 +46,8 @@ impl AcceptFollowCommunity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for AcceptFollowCommunity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -56,6 +59,7 @@ impl ActivityHandler for AcceptFollowCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -40,6 +40,8 @@ impl FollowCommunity {
|
|||
unparsed: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
actor: &ApubPerson,
|
||||
community: &ApubCommunity,
|
||||
|
@ -64,6 +66,8 @@ impl FollowCommunity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for FollowCommunity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -76,6 +80,7 @@ impl ActivityHandler for FollowCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -19,6 +19,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
impl UndoFollowCommunity {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
actor: &ApubPerson,
|
||||
community: &ApubCommunity,
|
||||
|
@ -43,6 +44,8 @@ impl UndoFollowCommunity {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoFollowCommunity {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -55,6 +58,7 @@ impl ActivityHandler for UndoFollowCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
};
|
||||
use activitystreams_kinds::public;
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
activity_queue::send_activity,
|
||||
|
@ -36,6 +35,7 @@ pub mod voting;
|
|||
|
||||
/// Checks that the specified Url actually identifies a Person (by fetching it), and that the person
|
||||
/// doesn't have a site ban.
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify_person(
|
||||
person_id: &ObjectId<ApubPerson>,
|
||||
context: &LemmyContext,
|
||||
|
@ -43,13 +43,15 @@ async fn verify_person(
|
|||
) -> Result<(), LemmyError> {
|
||||
let person = person_id.dereference(context, request_counter).await?;
|
||||
if person.banned {
|
||||
return Err(anyhow!("Person {} is banned", person_id).into());
|
||||
let error = LemmyError::from(anyhow::anyhow!("Person {} is banned", person_id));
|
||||
return Err(error.with_message("banned"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fetches the person and community to verify their type, then checks if person is banned from site
|
||||
/// or community.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn verify_person_in_community(
|
||||
person_id: &ObjectId<ApubPerson>,
|
||||
community: &ApubCommunity,
|
||||
|
@ -58,14 +60,14 @@ pub(crate) async fn verify_person_in_community(
|
|||
) -> Result<(), LemmyError> {
|
||||
let person = person_id.dereference(context, request_counter).await?;
|
||||
if person.banned {
|
||||
return Err(anyhow!("Person is banned from site").into());
|
||||
return Err(LemmyError::from_message("Person is banned from site"));
|
||||
}
|
||||
let person_id = person.id;
|
||||
let community_id = community.id;
|
||||
let is_banned =
|
||||
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
|
||||
if blocking(context.pool(), is_banned).await? {
|
||||
return Err(anyhow!("Person is banned from community").into());
|
||||
return Err(LemmyError::from_message("Person is banned from community"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -80,6 +82,7 @@ fn verify_activity(id: &Url, actor: &Url, settings: &Settings) -> Result<(), Lem
|
|||
/// Verify that the actor is a community mod. This check is only run if the community is local,
|
||||
/// because in case of remote communities, admins can also perform mod actions. As admin status
|
||||
/// is not federated, we cant verify their actions remotely.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn verify_mod_action(
|
||||
actor_id: &ObjectId<ApubPerson>,
|
||||
community: &ApubCommunity,
|
||||
|
@ -98,7 +101,7 @@ pub(crate) async fn verify_mod_action(
|
|||
})
|
||||
.await?;
|
||||
if !is_mod_or_admin {
|
||||
return Err(anyhow!("Not a mod").into());
|
||||
return Err(LemmyError::from_message("Not a mod"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -111,21 +114,23 @@ fn verify_add_remove_moderator_target(
|
|||
community: &ApubCommunity,
|
||||
) -> Result<(), LemmyError> {
|
||||
if target != &generate_moderators_url(&community.actor_id)?.into() {
|
||||
return Err(anyhow!("Unkown target url").into());
|
||||
return Err(LemmyError::from_message("Unkown target url"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn verify_is_public(to: &[Url], cc: &[Url]) -> Result<(), LemmyError> {
|
||||
if ![to, cc].iter().any(|set| set.contains(&public())) {
|
||||
return Err(anyhow!("Object is not public").into());
|
||||
return Err(LemmyError::from_message("Object is not public"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn check_community_deleted_or_removed(community: &Community) -> Result<(), LemmyError> {
|
||||
if community.deleted || community.removed {
|
||||
Err(anyhow!("New post or comment cannot be created in deleted or removed community").into())
|
||||
Err(LemmyError::from_message(
|
||||
"New post or comment cannot be created in deleted or removed community",
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -146,6 +151,7 @@ where
|
|||
Url::parse(&id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn send_lemmy_activity<T: Serialize>(
|
||||
context: &LemmyContext,
|
||||
activity: &T,
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::{
|
|||
protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType},
|
||||
};
|
||||
use activitystreams_kinds::public;
|
||||
use anyhow::anyhow;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
|
@ -47,6 +46,8 @@ impl CreateOrUpdatePost {
|
|||
unparsed: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
post: ApubPost,
|
||||
actor: &ApubPerson,
|
||||
|
@ -70,6 +71,8 @@ impl CreateOrUpdatePost {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for CreateOrUpdatePost {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -92,7 +95,9 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
let is_stickied_or_locked =
|
||||
self.object.stickied == Some(true) || self.object.comments_enabled == Some(false);
|
||||
if community.local && is_stickied_or_locked {
|
||||
return Err(anyhow!("New post cannot be stickied or locked").into());
|
||||
return Err(LemmyError::from_message(
|
||||
"New post cannot be stickied or locked",
|
||||
));
|
||||
}
|
||||
}
|
||||
CreateOrUpdateType::Update => {
|
||||
|
@ -109,6 +114,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -127,6 +133,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for CreateOrUpdatePost {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -18,6 +18,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
impl CreateOrUpdatePrivateMessage {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
private_message: ApubPrivateMessage,
|
||||
actor: &ApubPerson,
|
||||
|
@ -46,9 +47,12 @@ impl CreateOrUpdatePrivateMessage {
|
|||
send_lemmy_activity(context, &create_or_update, &id, actor, inbox, true).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -61,6 +65,7 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -36,6 +36,8 @@ impl DeletePrivateMessage {
|
|||
unparsed: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
actor: &ApubPerson,
|
||||
pm: &ApubPrivateMessage,
|
||||
|
@ -57,6 +59,8 @@ impl DeletePrivateMessage {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for DeletePrivateMessage {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -68,6 +72,7 @@ impl ActivityHandler for DeletePrivateMessage {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -22,6 +22,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||
|
||||
impl UndoDeletePrivateMessage {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
actor: &ApubPerson,
|
||||
pm: &ApubPrivateMessage,
|
||||
|
@ -54,6 +55,8 @@ impl UndoDeletePrivateMessage {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoDeletePrivateMessage {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -67,6 +70,7 @@ impl ActivityHandler for UndoDeletePrivateMessage {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
|||
pub mod undo_vote;
|
||||
pub mod vote;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn vote_comment(
|
||||
vote_type: &VoteType,
|
||||
actor: ApubPerson,
|
||||
|
@ -45,6 +46,7 @@ async fn vote_comment(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn vote_post(
|
||||
vote_type: &VoteType,
|
||||
actor: ApubPerson,
|
||||
|
@ -68,6 +70,7 @@ async fn vote_post(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn undo_vote_comment(
|
||||
actor: ApubPerson,
|
||||
comment: &ApubComment,
|
||||
|
@ -84,6 +87,7 @@ async fn undo_vote_comment(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn undo_vote_post(
|
||||
actor: ApubPerson,
|
||||
post: &ApubPost,
|
||||
|
|
|
@ -28,6 +28,7 @@ use lemmy_utils::LemmyError;
|
|||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
impl UndoVote {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
object: &PostOrComment,
|
||||
actor: &ApubPerson,
|
||||
|
@ -63,6 +64,8 @@ impl UndoVote {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for UndoVote {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -77,6 +80,7 @@ impl ActivityHandler for UndoVote {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -97,6 +101,7 @@ impl ActivityHandler for UndoVote {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for UndoVote {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -46,6 +46,7 @@ impl Vote {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn send(
|
||||
object: &PostOrComment,
|
||||
actor: &ApubPerson,
|
||||
|
@ -69,6 +70,8 @@ impl Vote {
|
|||
#[async_trait::async_trait(?Send)]
|
||||
impl ActivityHandler for Vote {
|
||||
type DataType = LemmyContext;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -81,6 +84,7 @@ impl ActivityHandler for Vote {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive(
|
||||
self,
|
||||
context: &Data<LemmyContext>,
|
||||
|
@ -97,6 +101,7 @@ impl ActivityHandler for Vote {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for Vote {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -88,6 +88,7 @@ pub enum AnnouncableActivities {
|
|||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl GetCommunity for AnnouncableActivities {
|
||||
#[tracing::instrument(skip(self, context))]
|
||||
async fn get_community(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -29,6 +29,7 @@ impl ApubObject for ApubCommunityModerators {
|
|||
None
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
_object_id: Url,
|
||||
data: &Self::DataType,
|
||||
|
@ -46,10 +47,12 @@ impl ApubObject for ApubCommunityModerators {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, _data: &Self::DataType) -> Result<(), LemmyError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
||||
let ordered_items = self
|
||||
.0
|
||||
|
@ -67,6 +70,7 @@ impl ApubObject for ApubCommunityModerators {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
group_moderators: &GroupModerators,
|
||||
expected_domain: &Url,
|
||||
|
@ -77,6 +81,7 @@ impl ApubObject for ApubCommunityModerators {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
apub: Self::ApubType,
|
||||
data: &Self::DataType,
|
||||
|
|
|
@ -33,6 +33,7 @@ impl ApubObject for ApubCommunityOutbox {
|
|||
None
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
_object_id: Url,
|
||||
data: &Self::DataType,
|
||||
|
@ -58,6 +59,7 @@ impl ApubObject for ApubCommunityOutbox {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
|
||||
let mut ordered_items = vec![];
|
||||
for post in self.0 {
|
||||
|
@ -80,6 +82,7 @@ impl ApubObject for ApubCommunityOutbox {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
group_outbox: &GroupOutbox,
|
||||
expected_domain: &Url,
|
||||
|
@ -90,6 +93,7 @@ impl ApubObject for ApubCommunityOutbox {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
apub: Self::ApubType,
|
||||
data: &Self::DataType,
|
||||
|
|
|
@ -33,6 +33,7 @@ impl ApubObject for PostOrComment {
|
|||
}
|
||||
|
||||
// TODO: this can probably be implemented using a single sql query
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
data: &Self::DataType,
|
||||
|
@ -46,6 +47,7 @@ impl ApubObject for PostOrComment {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
|
||||
match self {
|
||||
PostOrComment::Post(p) => p.delete(data).await,
|
||||
|
@ -61,6 +63,7 @@ impl ApubObject for PostOrComment {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
apub: &Self::ApubType,
|
||||
expected_domain: &Url,
|
||||
|
@ -73,6 +76,7 @@ impl ApubObject for PostOrComment {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
apub: PageOrNote,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::{
|
|||
protocol::objects::{group::Group, note::Note, page::Page, person::Person},
|
||||
EndpointType,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use chrono::NaiveDateTime;
|
||||
use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
|
||||
use lemmy_utils::LemmyError;
|
||||
|
@ -19,6 +18,7 @@ use url::Url;
|
|||
/// http://lemmy_beta:8551/u/lemmy_alpha, or @lemmy_beta@lemmy_beta:8551
|
||||
/// http://lemmy_gamma:8561/post/3
|
||||
/// http://lemmy_delta:8571/comment/2
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn search_by_apub_id(
|
||||
query: &str,
|
||||
context: &LemmyContext,
|
||||
|
@ -61,7 +61,7 @@ pub async fn search_by_apub_id(
|
|||
.await?,
|
||||
))
|
||||
}
|
||||
_ => Err(anyhow!("invalid query").into()),
|
||||
_ => Err(LemmyError::from_message("invalid query")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +105,7 @@ impl ApubObject for SearchableObjects {
|
|||
// a single query.
|
||||
// we could skip this and always return an error, but then it would always fetch objects
|
||||
// over http, and not be able to mark objects as deleted that were deleted by remote server.
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -128,6 +129,7 @@ impl ApubObject for SearchableObjects {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
|
||||
match self {
|
||||
SearchableObjects::Person(p) => p.delete(data).await,
|
||||
|
@ -145,6 +147,7 @@ impl ApubObject for SearchableObjects {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
apub: &Self::ApubType,
|
||||
expected_domain: &Url,
|
||||
|
@ -167,6 +170,7 @@ impl ApubObject for SearchableObjects {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
apub: Self::ApubType,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -35,6 +35,7 @@ impl ApubObject for UserOrCommunity {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
data: &Self::DataType,
|
||||
|
@ -48,6 +49,7 @@ impl ApubObject for UserOrCommunity {
|
|||
})
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
|
||||
match self {
|
||||
UserOrCommunity::User(p) => p.delete(data).await,
|
||||
|
@ -63,6 +65,7 @@ impl ApubObject for UserOrCommunity {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
apub: &Self::ApubType,
|
||||
expected_domain: &Url,
|
||||
|
@ -79,6 +82,7 @@ impl ApubObject for UserOrCommunity {
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
apub: Self::ApubType,
|
||||
data: &Self::DataType,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::{generate_local_apub_endpoint, EndpointType};
|
||||
use anyhow::anyhow;
|
||||
use itertools::Itertools;
|
||||
use lemmy_apub_lib::{
|
||||
object_id::ObjectId,
|
||||
|
@ -34,6 +33,7 @@ pub struct WebfingerResponse {
|
|||
///
|
||||
/// TODO: later provide a method in ApubObject to generate the endpoint, so that we dont have to
|
||||
/// pass in EndpointType
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn webfinger_resolve<Kind>(
|
||||
identifier: &str,
|
||||
endpoint_type: EndpointType,
|
||||
|
@ -61,6 +61,7 @@ where
|
|||
|
||||
/// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
||||
/// using webfinger.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn webfinger_resolve_actor<Kind>(
|
||||
identifier: &str,
|
||||
context: &LemmyContext,
|
||||
|
@ -83,7 +84,9 @@ where
|
|||
|
||||
*request_counter += 1;
|
||||
if *request_counter > context.settings().http_fetch_retry_limit {
|
||||
return Err(LemmyError::from(anyhow!("Request retry limit reached")));
|
||||
return Err(LemmyError::from(anyhow::anyhow!(
|
||||
"Request retry limit reached"
|
||||
)));
|
||||
}
|
||||
|
||||
let response = retry(|| context.client().get(&fetch_url).send()).await?;
|
||||
|
@ -114,5 +117,9 @@ where
|
|||
return object.map(|o| o.actor_id().into());
|
||||
}
|
||||
}
|
||||
Err(anyhow!("Failed to resolve actor for {}", identifier).into())
|
||||
let error = LemmyError::from(anyhow::anyhow!(
|
||||
"Failed to resolve actor for {}",
|
||||
identifier
|
||||
));
|
||||
Err(error.with_message("failed_to_resolve"))
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
http::{create_apub_response, create_apub_tombstone_response},
|
||||
objects::comment::ApubComment,
|
||||
};
|
||||
use actix_web::{body::Body, web, web::Path, HttpResponse};
|
||||
use actix_web::{body::AnyBody, web, web::Path, HttpResponse};
|
||||
use diesel::result::Error::NotFound;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::traits::ApubObject;
|
||||
|
@ -17,10 +17,11 @@ pub(crate) struct CommentQuery {
|
|||
}
|
||||
|
||||
/// Return the ActivityPub json representation of a local comment over HTTP.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_apub_comment(
|
||||
info: Path<CommentQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let id = CommentId(info.comment_id.parse::<i32>()?);
|
||||
let comment: ApubComment = blocking(context.pool(), move |conn| Comment::read(conn, id))
|
||||
.await??
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
|||
collections::group_followers::GroupFollowers,
|
||||
},
|
||||
};
|
||||
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
||||
use actix_web::{body::AnyBody, web, web::Payload, HttpRequest, HttpResponse};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
|
||||
use lemmy_db_schema::source::community::Community;
|
||||
|
@ -36,10 +36,11 @@ pub(crate) struct CommunityQuery {
|
|||
}
|
||||
|
||||
/// Return the ActivityPub json representation of a local community over HTTP.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_apub_community_http(
|
||||
info: web::Path<CommunityQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_name(conn, &info.community_name)
|
||||
})
|
||||
|
@ -56,6 +57,7 @@ pub(crate) async fn get_apub_community_http(
|
|||
}
|
||||
|
||||
/// Handler for all incoming receive to community inboxes.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn community_inbox(
|
||||
request: HttpRequest,
|
||||
payload: Payload,
|
||||
|
@ -96,7 +98,7 @@ pub(in crate::http) async fn receive_group_inbox(
|
|||
pub(crate) async fn get_apub_community_followers(
|
||||
info: web::Path<CommunityQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_name(conn, &info.community_name)
|
||||
})
|
||||
|
@ -110,7 +112,7 @@ pub(crate) async fn get_apub_community_followers(
|
|||
pub(crate) async fn get_apub_community_outbox(
|
||||
info: web::Path<CommunityQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let community = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_name(conn, &info.community_name)
|
||||
})
|
||||
|
@ -121,10 +123,11 @@ pub(crate) async fn get_apub_community_outbox(
|
|||
Ok(create_apub_response(&outbox.into_apub(&outbox_data).await?))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_apub_community_moderators(
|
||||
info: web::Path<CommunityQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||
Community::read_from_name(conn, &info.community_name)
|
||||
})
|
||||
|
|
|
@ -7,13 +7,13 @@ use crate::{
|
|||
insert_activity,
|
||||
};
|
||||
use actix_web::{
|
||||
body::Body,
|
||||
body::AnyBody,
|
||||
web,
|
||||
web::{Bytes, BytesMut, Payload},
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
};
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::Context;
|
||||
use futures::StreamExt;
|
||||
use http::StatusCode;
|
||||
use lemmy_api_common::blocking;
|
||||
|
@ -38,6 +38,7 @@ mod person;
|
|||
mod post;
|
||||
pub mod routes;
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn shared_inbox(
|
||||
request: HttpRequest,
|
||||
payload: Payload,
|
||||
|
@ -75,6 +76,7 @@ pub(crate) struct ActivityCommonFields {
|
|||
}
|
||||
|
||||
// TODO: move most of this code to library
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn receive_activity<'a, T>(
|
||||
request: HttpRequest,
|
||||
activity: T,
|
||||
|
@ -117,7 +119,7 @@ where
|
|||
|
||||
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
|
||||
/// headers.
|
||||
fn create_apub_response<T>(data: &T) -> HttpResponse<Body>
|
||||
fn create_apub_response<T>(data: &T) -> HttpResponse<AnyBody>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
|
@ -126,13 +128,13 @@ where
|
|||
.json(WithContext::new(data))
|
||||
}
|
||||
|
||||
fn create_json_apub_response(data: serde_json::Value) -> HttpResponse<Body> {
|
||||
fn create_json_apub_response(data: serde_json::Value) -> HttpResponse<AnyBody> {
|
||||
HttpResponse::Ok()
|
||||
.content_type(APUB_JSON_CONTENT_TYPE)
|
||||
.json(data)
|
||||
}
|
||||
|
||||
fn create_apub_tombstone_response<T>(data: &T) -> HttpResponse<Body>
|
||||
fn create_apub_tombstone_response<T>(data: &T) -> HttpResponse<AnyBody>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
|
@ -149,10 +151,11 @@ pub struct ActivityQuery {
|
|||
}
|
||||
|
||||
/// Return the ActivityPub json representation of a local activity over HTTP.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_activity(
|
||||
info: web::Path<ActivityQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let settings = context.settings();
|
||||
let activity_id = Url::parse(&format!(
|
||||
"{}/activities/{}/{}",
|
||||
|
@ -178,13 +181,11 @@ fn assert_activity_not_local(id: &Url, hostname: &str) -> Result<(), LemmyError>
|
|||
let activity_domain = id.domain().context(location_info!())?;
|
||||
|
||||
if activity_domain == hostname {
|
||||
return Err(
|
||||
anyhow!(
|
||||
"Error: received activity which was sent by local instance: {:?}",
|
||||
id
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
let error = LemmyError::from(anyhow::anyhow!(
|
||||
"Error: received activity which was sent by local instance: {:?}",
|
||||
id
|
||||
));
|
||||
return Err(error.with_message("received_local_activity"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
objects::person::ApubPerson,
|
||||
protocol::collections::person_outbox::PersonOutbox,
|
||||
};
|
||||
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
||||
use actix_web::{body::AnyBody, web, web::Payload, HttpRequest, HttpResponse};
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::traits::ApubObject;
|
||||
use lemmy_db_schema::source::person::Person;
|
||||
|
@ -26,10 +26,11 @@ pub struct PersonQuery {
|
|||
}
|
||||
|
||||
/// Return the ActivityPub json representation of a local person over HTTP.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_apub_person_http(
|
||||
info: web::Path<PersonQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let user_name = info.into_inner().user_name;
|
||||
// TODO: this needs to be able to read deleted persons, so that it can send tombstones
|
||||
let person: ApubPerson = blocking(context.pool(), move |conn| {
|
||||
|
@ -47,6 +48,7 @@ pub(crate) async fn get_apub_person_http(
|
|||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn person_inbox(
|
||||
request: HttpRequest,
|
||||
payload: Payload,
|
||||
|
@ -69,10 +71,11 @@ pub(in crate::http) async fn receive_person_inbox(
|
|||
receive_activity(request, activity, activity_data, context).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_apub_person_outbox(
|
||||
info: web::Path<PersonQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let person = blocking(context.pool(), move |conn| {
|
||||
Person::find_by_name(conn, &info.user_name)
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
http::{create_apub_response, create_apub_tombstone_response},
|
||||
objects::post::ApubPost,
|
||||
};
|
||||
use actix_web::{body::Body, web, HttpResponse};
|
||||
use actix_web::{body::AnyBody, web, HttpResponse};
|
||||
use diesel::result::Error::NotFound;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_apub_lib::traits::ApubObject;
|
||||
|
@ -17,10 +17,11 @@ pub(crate) struct PostQuery {
|
|||
}
|
||||
|
||||
/// Return the ActivityPub json representation of a local post over HTTP.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_apub_post(
|
||||
info: web::Path<PostQuery>,
|
||||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
) -> Result<HttpResponse<AnyBody>, LemmyError> {
|
||||
let id = PostId(info.post_id.parse::<i32>()?);
|
||||
let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, id))
|
||||
.await??
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::fetcher::post_or_comment::PostOrComment;
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::Context;
|
||||
use lemmy_api_common::blocking;
|
||||
use lemmy_db_schema::{newtypes::DbUrl, source::activity::Activity, DbPool};
|
||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||
|
@ -28,6 +28,7 @@ pub mod protocol;
|
|||
///
|
||||
/// `use_strict_allowlist` should be true only when parsing a remote community, or when parsing a
|
||||
/// post/comment in a local community.
|
||||
#[tracing::instrument(skip(settings))]
|
||||
pub(crate) fn check_is_apub_id_valid(
|
||||
apub_id: &Url,
|
||||
use_strict_allowlist: bool,
|
||||
|
@ -40,24 +41,28 @@ pub(crate) fn check_is_apub_id_valid(
|
|||
return if domain == local_instance {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(
|
||||
anyhow!(
|
||||
"Trying to connect with {}, but federation is disabled",
|
||||
domain
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
let error = LemmyError::from(anyhow::anyhow!(
|
||||
"Trying to connect with {}, but federation is disabled",
|
||||
domain
|
||||
));
|
||||
Err(error.with_message("federation_disabled"))
|
||||
};
|
||||
}
|
||||
|
||||
let host = apub_id.host_str().context(location_info!())?;
|
||||
let host_as_ip = host.parse::<IpAddr>();
|
||||
if host == "localhost" || host_as_ip.is_ok() {
|
||||
return Err(anyhow!("invalid hostname {}: {}", host, apub_id).into());
|
||||
let error = LemmyError::from(anyhow::anyhow!("invalid hostname {}: {}", host, apub_id));
|
||||
return Err(error.with_message("invalid_hostname"));
|
||||
}
|
||||
|
||||
if apub_id.scheme() != settings.get_protocol_string() {
|
||||
return Err(anyhow!("invalid apub id scheme {}: {}", apub_id.scheme(), apub_id).into());
|
||||
let error = LemmyError::from(anyhow::anyhow!(
|
||||
"invalid apub id scheme {}: {}",
|
||||
apub_id.scheme(),
|
||||
apub_id
|
||||
));
|
||||
return Err(error.with_message("invalid_scheme"));
|
||||
}
|
||||
|
||||
// TODO: might be good to put the part above in one method, and below in another
|
||||
|
@ -65,7 +70,8 @@ pub(crate) fn check_is_apub_id_valid(
|
|||
// -> no that doesnt make sense, we still need the code below for blocklist and strict allowlist
|
||||
if let Some(blocked) = settings.to_owned().federation.blocked_instances {
|
||||
if blocked.contains(&domain) {
|
||||
return Err(anyhow!("{} is in federation blocklist", domain).into());
|
||||
let error = LemmyError::from(anyhow::anyhow!("{} is in federation blocklist", domain));
|
||||
return Err(error.with_message("federation_blocked"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +84,8 @@ pub(crate) fn check_is_apub_id_valid(
|
|||
allowed.push(local_instance);
|
||||
|
||||
if !allowed.contains(&domain) {
|
||||
return Err(anyhow!("{} not in federation allowlist", domain).into());
|
||||
let error = LemmyError::from(anyhow::anyhow!("{} not in federation allowlist", domain));
|
||||
return Err(error.with_message("federation_not_allowed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +170,7 @@ fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
|||
|
||||
/// Store a sent or received activity in the database, for logging purposes. These records are not
|
||||
/// persistent.
|
||||
#[tracing::instrument(skip(pool))]
|
||||
async fn insert_activity(
|
||||
ap_id: &Url,
|
||||
activity: serde_json::Value,
|
||||
|
|
|
@ -34,6 +34,7 @@ pub struct MentionsAndAddresses {
|
|||
/// This takes a comment, and builds a list of to_addresses, inboxes,
|
||||
/// and mention tags, so they know where to be sent to.
|
||||
/// Addresses are the persons / addresses that go in the cc field.
|
||||
#[tracing::instrument(skip(comment, community_id, context))]
|
||||
pub async fn collect_non_local_mentions(
|
||||
comment: &ApubComment,
|
||||
community_id: ObjectId<ApubCommunity>,
|
||||
|
@ -88,6 +89,7 @@ pub async fn collect_non_local_mentions(
|
|||
|
||||
/// Returns the apub ID of the person this comment is responding to. Meaning, in case this is a
|
||||
/// top-level comment, the creator of the post, otherwise the creator of the parent comment.
|
||||
#[tracing::instrument(skip(pool, comment))]
|
||||
async fn get_comment_parent_creator(
|
||||
pool: &DbPool,
|
||||
comment: &Comment,
|
||||
|
|
|
@ -12,7 +12,6 @@ use crate::{
|
|||
PostOrComment,
|
||||
};
|
||||
use activitystreams_kinds::{object::NoteType, public};
|
||||
use anyhow::anyhow;
|
||||
use chrono::NaiveDateTime;
|
||||
use html2md::parse_html;
|
||||
use lemmy_api_common::blocking;
|
||||
|
@ -65,6 +64,7 @@ impl ApubObject for ApubComment {
|
|||
None
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -78,6 +78,7 @@ impl ApubObject for ApubComment {
|
|||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
if !self.deleted {
|
||||
blocking(context.pool(), move |conn| {
|
||||
|
@ -88,6 +89,7 @@ impl ApubObject for ApubComment {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, context: &LemmyContext) -> Result<Note, LemmyError> {
|
||||
let creator_id = self.creator_id;
|
||||
let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
|
||||
|
@ -136,6 +138,7 @@ impl ApubObject for ApubComment {
|
|||
Ok(Tombstone::new(self.ap_id.clone().into()))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
note: &Note,
|
||||
expected_domain: &Url,
|
||||
|
@ -160,7 +163,7 @@ impl ApubObject for ApubComment {
|
|||
)
|
||||
.await?;
|
||||
if post.locked {
|
||||
return Err(anyhow!("Post is locked").into());
|
||||
return Err(LemmyError::from_message("Post is locked"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -168,6 +171,7 @@ impl ApubObject for ApubComment {
|
|||
/// Converts a `Note` to `Comment`.
|
||||
///
|
||||
/// If the parent community, post and comment(s) are not known locally, these are also fetched.
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
note: Note,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -55,6 +55,7 @@ impl ApubObject for ApubCommunity {
|
|||
Some(self.last_refreshed_at)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -68,6 +69,7 @@ impl ApubObject for ApubCommunity {
|
|||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
blocking(context.pool(), move |conn| {
|
||||
Community::update_deleted(conn, self.id, true)
|
||||
|
@ -76,6 +78,7 @@ impl ApubObject for ApubCommunity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, _context: &LemmyContext) -> Result<Group, LemmyError> {
|
||||
let source = self.description.clone().map(|bio| Source {
|
||||
content: bio,
|
||||
|
@ -115,6 +118,7 @@ impl ApubObject for ApubCommunity {
|
|||
Ok(Tombstone::new(self.actor_id()))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
group: &Group,
|
||||
expected_domain: &Url,
|
||||
|
@ -125,6 +129,7 @@ impl ApubObject for ApubCommunity {
|
|||
}
|
||||
|
||||
/// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
group: Group,
|
||||
context: &LemmyContext,
|
||||
|
@ -181,6 +186,7 @@ impl ActorType for ApubCommunity {
|
|||
|
||||
impl ApubCommunity {
|
||||
/// For a given community, returns the inboxes of all followers.
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub(crate) async fn get_follower_inboxes(
|
||||
&self,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -57,6 +57,7 @@ impl ApubObject for ApubPerson {
|
|||
Some(self.last_refreshed_at)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -70,6 +71,7 @@ impl ApubObject for ApubPerson {
|
|||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
blocking(context.pool(), move |conn| {
|
||||
DbPerson::update_deleted(conn, self.id, true)
|
||||
|
@ -78,6 +80,7 @@ impl ApubObject for ApubPerson {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, _pool: &LemmyContext) -> Result<Person, LemmyError> {
|
||||
let kind = if self.bot_account {
|
||||
UserTypes::Service
|
||||
|
@ -118,6 +121,7 @@ impl ApubObject for ApubPerson {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
person: &Person,
|
||||
expected_domain: &Url,
|
||||
|
@ -135,6 +139,7 @@ impl ApubObject for ApubPerson {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
person: Person,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -60,6 +60,7 @@ impl ApubObject for ApubPost {
|
|||
None
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -73,6 +74,7 @@ impl ApubObject for ApubPost {
|
|||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
if !self.deleted {
|
||||
blocking(context.pool(), move |conn| {
|
||||
|
@ -84,6 +86,7 @@ impl ApubObject for ApubPost {
|
|||
}
|
||||
|
||||
// Turn a Lemmy post into an ActivityPub page that can be sent out over the network.
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, context: &LemmyContext) -> Result<Page, LemmyError> {
|
||||
let creator_id = self.creator_id;
|
||||
let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
|
||||
|
@ -125,6 +128,7 @@ impl ApubObject for ApubPost {
|
|||
Ok(Tombstone::new(self.ap_id.clone().into()))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
page: &Page,
|
||||
expected_domain: &Url,
|
||||
|
@ -146,6 +150,7 @@ impl ApubObject for ApubPost {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
page: Page,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::protocol::{
|
|||
objects::chat_message::{ChatMessage, ChatMessageType},
|
||||
Source,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use chrono::NaiveDateTime;
|
||||
use html2md::parse_html;
|
||||
use lemmy_api_common::blocking;
|
||||
|
@ -53,6 +52,7 @@ impl ApubObject for ApubPrivateMessage {
|
|||
None
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn read_from_apub_id(
|
||||
object_id: Url,
|
||||
context: &LemmyContext,
|
||||
|
@ -71,6 +71,7 @@ impl ApubObject for ApubPrivateMessage {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn into_apub(self, context: &LemmyContext) -> Result<ChatMessage, LemmyError> {
|
||||
let creator_id = self.creator_id;
|
||||
let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
|
||||
|
@ -101,6 +102,7 @@ impl ApubObject for ApubPrivateMessage {
|
|||
unimplemented!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn verify(
|
||||
note: &ChatMessage,
|
||||
expected_domain: &Url,
|
||||
|
@ -114,11 +116,12 @@ impl ApubObject for ApubPrivateMessage {
|
|||
.dereference(context, request_counter)
|
||||
.await?;
|
||||
if person.banned {
|
||||
return Err(anyhow!("Person is banned from site").into());
|
||||
return Err(LemmyError::from_message("Person is banned from site"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn from_apub(
|
||||
note: ChatMessage,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::{
|
|||
objects::person::ApubPerson,
|
||||
protocol::Unparsed,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use lemmy_apub_lib::object_id::ObjectId;
|
||||
use lemmy_utils::LemmyError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -40,7 +39,7 @@ impl TryFrom<i16> for VoteType {
|
|||
match value {
|
||||
1 => Ok(VoteType::Like),
|
||||
-1 => Ok(VoteType::Dislike),
|
||||
_ => Err(anyhow!("invalid vote value").into()),
|
||||
_ => Err(LemmyError::from_message("invalid vote value")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::{
|
|||
protocol::{ImageObject, Source, Unparsed},
|
||||
};
|
||||
use activitystreams_kinds::object::PageType;
|
||||
use anyhow::anyhow;
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use lemmy_apub_lib::{
|
||||
data::Data,
|
||||
|
@ -75,7 +74,7 @@ impl Page {
|
|||
break Ok(c);
|
||||
}
|
||||
} else {
|
||||
return Err(anyhow!("No community found in cc").into());
|
||||
return Err(LemmyError::from_message("No community found in cc"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgC
|
|||
use crate::newtypes::DbUrl;
|
||||
use chrono::NaiveDateTime;
|
||||
use diesel::{Connection, PgConnection};
|
||||
use lemmy_utils::ApiError;
|
||||
use lemmy_utils::LemmyError;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -100,13 +100,13 @@ pub fn diesel_option_overwrite(opt: &Option<String>) -> Option<Option<String>> {
|
|||
|
||||
pub fn diesel_option_overwrite_to_url(
|
||||
opt: &Option<String>,
|
||||
) -> Result<Option<Option<DbUrl>>, ApiError> {
|
||||
) -> Result<Option<Option<DbUrl>>, LemmyError> {
|
||||
match opt.as_ref().map(|s| s.as_str()) {
|
||||
// An empty string is an erase
|
||||
Some("") => Ok(Some(None)),
|
||||
Some(str_url) => match Url::parse(str_url) {
|
||||
Ok(url) => Ok(Some(Some(url.into()))),
|
||||
Err(e) => Err(ApiError::err("invalid_url", e)),
|
||||
Err(e) => Err(LemmyError::from(e).with_message("invalid_url")),
|
||||
},
|
||||
None => Ok(None),
|
||||
}
|
||||
|
|
|
@ -32,3 +32,4 @@ awc = { version = "3.0.0-beta.8", default-features = false }
|
|||
url = { version = "2.2.2", features = ["serde"] }
|
||||
strum = "0.21.0"
|
||||
once_cell = "1.8.0"
|
||||
tracing = "0.1.29"
|
||||
|
|
|
@ -58,6 +58,7 @@ static RSS_NAMESPACE: Lazy<HashMap<String, String>> = Lazy::new(|| {
|
|||
h
|
||||
});
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_all_feed(
|
||||
info: web::Query<Params>,
|
||||
context: web::Data<LemmyContext>,
|
||||
|
@ -66,6 +67,7 @@ async fn get_all_feed(
|
|||
Ok(get_feed_data(&context, ListingType::All, sort_type).await?)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_local_feed(
|
||||
info: web::Query<Params>,
|
||||
context: web::Data<LemmyContext>,
|
||||
|
@ -74,6 +76,7 @@ async fn get_local_feed(
|
|||
Ok(get_feed_data(&context, ListingType::Local, sort_type).await?)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_feed_data(
|
||||
context: &LemmyContext,
|
||||
listing_type: ListingType,
|
||||
|
@ -114,6 +117,7 @@ async fn get_feed_data(
|
|||
)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn get_feed(
|
||||
req: HttpRequest,
|
||||
info: web::Query<Params>,
|
||||
|
@ -167,6 +171,7 @@ fn get_sort_type(info: web::Query<Params>) -> Result<SortType, ParseError> {
|
|||
SortType::from_str(&sort_query)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn get_feed_user(
|
||||
conn: &PgConnection,
|
||||
sort_type: &SortType,
|
||||
|
@ -194,6 +199,7 @@ fn get_feed_user(
|
|||
Ok(channel_builder)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn get_feed_community(
|
||||
conn: &PgConnection,
|
||||
sort_type: &SortType,
|
||||
|
@ -225,6 +231,7 @@ fn get_feed_community(
|
|||
Ok(channel_builder)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn get_feed_front(
|
||||
conn: &PgConnection,
|
||||
jwt_secret: &str,
|
||||
|
@ -260,6 +267,7 @@ fn get_feed_front(
|
|||
Ok(channel_builder)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn get_feed_inbox(
|
||||
conn: &PgConnection,
|
||||
jwt_secret: &str,
|
||||
|
@ -303,6 +311,7 @@ fn get_feed_inbox(
|
|||
Ok(channel_builder)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn create_reply_and_mention_items(
|
||||
replies: Vec<CommentView>,
|
||||
mentions: Vec<PersonMentionView>,
|
||||
|
@ -346,6 +355,7 @@ fn create_reply_and_mention_items(
|
|||
Ok(reply_items)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn build_item(
|
||||
creator_name: &str,
|
||||
published: &NaiveDateTime,
|
||||
|
@ -376,6 +386,7 @@ fn build_item(
|
|||
Ok(i.build().map_err(|e| anyhow!(e))?)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn create_post_items(
|
||||
posts: Vec<PostView>,
|
||||
protocol_and_hostname: &str,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::settings::structs::Settings;
|
||||
use crate::{settings::structs::Settings, LemmyError};
|
||||
use lettre::{
|
||||
message::{header, Mailbox, MultiPart, SinglePart},
|
||||
transport::smtp::{
|
||||
|
@ -20,8 +20,11 @@ pub fn send_email(
|
|||
to_username: &str,
|
||||
html: &str,
|
||||
settings: &Settings,
|
||||
) -> Result<(), String> {
|
||||
let email_config = settings.email.to_owned().ok_or("no_email_setup")?;
|
||||
) -> Result<(), LemmyError> {
|
||||
let email_config = settings
|
||||
.email
|
||||
.to_owned()
|
||||
.ok_or_else(|| LemmyError::from_message("no_email_setup"))?;
|
||||
let domain = settings.hostname.to_owned();
|
||||
|
||||
let (smtp_server, smtp_port) = {
|
||||
|
@ -87,6 +90,6 @@ pub fn send_email(
|
|||
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
Err(e) => Err(LemmyError::from(e).with_message("email_send_failed")),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,13 @@ mod test;
|
|||
pub mod utils;
|
||||
pub mod version;
|
||||
|
||||
mod sensitive;
|
||||
|
||||
pub use sensitive::Sensitive;
|
||||
|
||||
use actix_web::HttpResponse;
|
||||
use http::StatusCode;
|
||||
use std::{fmt, fmt::Display};
|
||||
use thiserror::Error;
|
||||
use tracing::warn;
|
||||
use tracing_error::SpanTrace;
|
||||
|
||||
pub type ConnectionId = usize;
|
||||
|
@ -44,47 +47,71 @@ macro_rules! location_info {
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("{{\"error\":\"{message}\"}}")]
|
||||
pub struct ApiError {
|
||||
message: String,
|
||||
#[derive(serde::Serialize)]
|
||||
struct ApiError {
|
||||
error: &'static str,
|
||||
}
|
||||
|
||||
impl ApiError {
|
||||
pub fn err_plain(msg: &str) -> Self {
|
||||
ApiError {
|
||||
message: msg.to_string(),
|
||||
}
|
||||
}
|
||||
pub fn err<E: Display>(msg: &str, original_error: E) -> Self {
|
||||
warn!("{}", original_error);
|
||||
ApiError {
|
||||
message: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LemmyError {
|
||||
pub message: Option<&'static str>,
|
||||
pub inner: anyhow::Error,
|
||||
pub context: SpanTrace,
|
||||
}
|
||||
|
||||
impl LemmyError {
|
||||
pub fn from_message(message: &'static str) -> Self {
|
||||
let inner = anyhow::anyhow!("{}", message);
|
||||
LemmyError {
|
||||
message: Some(message),
|
||||
inner,
|
||||
context: SpanTrace::capture(),
|
||||
}
|
||||
}
|
||||
pub fn with_message(self, message: &'static str) -> Self {
|
||||
LemmyError {
|
||||
message: Some(message),
|
||||
..self
|
||||
}
|
||||
}
|
||||
pub fn to_json(&self) -> Result<String, Self> {
|
||||
let api_error = match self.message {
|
||||
Some(error) => ApiError { error },
|
||||
None => ApiError { error: "Unknown" },
|
||||
};
|
||||
|
||||
Ok(serde_json::to_string(&api_error)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for LemmyError
|
||||
where
|
||||
T: Into<anyhow::Error>,
|
||||
{
|
||||
fn from(t: T) -> Self {
|
||||
LemmyError {
|
||||
message: None,
|
||||
inner: t.into(),
|
||||
context: SpanTrace::capture(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for LemmyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("LemmyError")
|
||||
.field("message", &self.message)
|
||||
.field("inner", &self.inner)
|
||||
.field("context", &"SpanTrace")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LemmyError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
self.inner.fmt(f)?;
|
||||
if let Some(message) = self.message {
|
||||
write!(f, "{}: ", message)?;
|
||||
}
|
||||
writeln!(f, "{}", self.inner)?;
|
||||
self.context.fmt(f)
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +120,17 @@ impl actix_web::error::ResponseError for LemmyError {
|
|||
fn status_code(&self) -> StatusCode {
|
||||
match self.inner.downcast_ref::<diesel::result::Error>() {
|
||||
Some(diesel::result::Error::NotFound) => StatusCode::NOT_FOUND,
|
||||
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
_ => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
if let Some(message) = &self.message {
|
||||
HttpResponse::build(self.status_code()).json(ApiError { error: message })
|
||||
} else {
|
||||
HttpResponse::build(self.status_code())
|
||||
.content_type("text/plain")
|
||||
.body(self.inner.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{ApiError, IpAddr, LemmyError};
|
||||
use crate::{IpAddr, LemmyError};
|
||||
use std::{collections::HashMap, time::SystemTime};
|
||||
use strum::IntoEnumIterator;
|
||||
use tracing::debug;
|
||||
|
@ -79,18 +79,14 @@ impl RateLimiter {
|
|||
time_passed,
|
||||
rate_limit.allowance
|
||||
);
|
||||
Err(
|
||||
ApiError {
|
||||
message: format!(
|
||||
"Too many requests. type: {}, IP: {}, {} per {} seconds",
|
||||
type_.as_ref(),
|
||||
ip,
|
||||
rate,
|
||||
per
|
||||
),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
let error = LemmyError::from(anyhow::anyhow!(
|
||||
"Too many requests. type: {}, IP: {}, {} per {} seconds",
|
||||
type_.as_ref(),
|
||||
ip,
|
||||
rate,
|
||||
per
|
||||
));
|
||||
Err(error.with_message("too_many_requests"))
|
||||
} else {
|
||||
if !check_only {
|
||||
rate_limit.allowance -= 1.0;
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
use std::{
|
||||
borrow::Borrow,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Sensitive<T>(T);
|
||||
|
||||
impl<T> Sensitive<T> {
|
||||
pub fn new(item: T) -> Self {
|
||||
Sensitive(item)
|
||||
}
|
||||
|
||||
pub fn into_inner(this: Self) -> T {
|
||||
this.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Debug for Sensitive<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Sensitive").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<T> for Sensitive<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Sensitive<String> {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Sensitive<String> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Sensitive<Vec<u8>> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<T> for Sensitive<T> {
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<str> for Sensitive<String> {
|
||||
fn as_mut(&mut self) -> &mut str {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Sensitive<String> {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Sensitive<String> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Sensitive<T> {
|
||||
fn from(t: T) -> Self {
|
||||
Sensitive(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Sensitive<String> {
|
||||
fn from(s: &str) -> Self {
|
||||
Sensitive(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Borrow<T> for Sensitive<T> {
|
||||
fn borrow(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for Sensitive<String> {
|
||||
fn borrow(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{ApiError, IpAddr};
|
||||
use crate::{IpAddr, LemmyError};
|
||||
use actix_web::dev::ConnectionInfo;
|
||||
use chrono::{DateTime, FixedOffset, NaiveDateTime};
|
||||
use itertools::Itertools;
|
||||
|
@ -60,15 +60,19 @@ pub(crate) fn slur_check<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_slurs(text: &str, slur_regex: &Option<Regex>) -> Result<(), ApiError> {
|
||||
pub fn check_slurs(text: &str, slur_regex: &Option<Regex>) -> Result<(), LemmyError> {
|
||||
if let Err(slurs) = slur_check(text, slur_regex) {
|
||||
Err(ApiError::err_plain(&slurs_vec_to_str(slurs)))
|
||||
let error = LemmyError::from(anyhow::anyhow!("{}", slurs_vec_to_str(slurs)));
|
||||
Err(error.with_message("slurs"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_slurs_opt(text: &Option<String>, slur_regex: &Option<Regex>) -> Result<(), ApiError> {
|
||||
pub fn check_slurs_opt(
|
||||
text: &Option<String>,
|
||||
slur_regex: &Option<Regex>,
|
||||
) -> Result<(), LemmyError> {
|
||||
match text {
|
||||
Some(t) => check_slurs(t, slur_regex),
|
||||
None => Ok(()),
|
||||
|
|
|
@ -22,7 +22,6 @@ use lemmy_utils::{
|
|||
location_info,
|
||||
rate_limit::RateLimit,
|
||||
settings::structs::Settings,
|
||||
ApiError,
|
||||
ConnectionId,
|
||||
IpAddr,
|
||||
LemmyError,
|
||||
|
@ -477,7 +476,7 @@ impl ChatServer {
|
|||
let data = &json["data"].to_string();
|
||||
let op = &json["op"]
|
||||
.as_str()
|
||||
.ok_or_else(|| ApiError::err_plain("missing op"))?;
|
||||
.ok_or_else(|| LemmyError::from_message("missing op"))?;
|
||||
|
||||
if let Ok(user_operation_crud) = UserOperationCrud::from_str(op) {
|
||||
let fut = (message_handler_crud)(context, msg.id, user_operation_crud.clone(), data);
|
||||
|
|
|
@ -5,7 +5,7 @@ use lemmy_db_schema::{
|
|||
source::email_verification::{EmailVerification, EmailVerificationForm},
|
||||
traits::Crud,
|
||||
};
|
||||
use lemmy_utils::{email::send_email, utils::generate_random_string, ApiError, LemmyError};
|
||||
use lemmy_utils::{email::send_email, utils::generate_random_string, LemmyError};
|
||||
|
||||
pub async fn send_verification_email(
|
||||
local_user_id: LocalUserId,
|
||||
|
@ -39,8 +39,7 @@ pub async fn send_verification_email(
|
|||
),
|
||||
username, settings.hostname, verify_link
|
||||
);
|
||||
send_email(&subject, new_email, username, &body, &context.settings())
|
||||
.map_err(|e| ApiError::err("email_send_failed", e))?;
|
||||
send_email(&subject, new_email, username, &body, &context.settings())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -76,7 +76,10 @@ impl Handler<StandardMessage> for ChatServer {
|
|||
}
|
||||
Err(e) => {
|
||||
error!("Error during message handling {}", e);
|
||||
Ok(e.to_string())
|
||||
Ok(
|
||||
e.to_json()
|
||||
.unwrap_or_else(|_| String::from(r#"{"error":"failed to serialize json"}"#)),
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue