mirror of
https://github.com/LemmyNet/lemmy
synced 2024-11-26 06:20:20 +00:00
commit
9e0fa99c69
177 changed files with 2420 additions and 2495 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -1668,7 +1668,6 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lemmy_api_common",
|
"lemmy_api_common",
|
||||||
"lemmy_apub",
|
"lemmy_apub",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
@ -1697,7 +1696,6 @@ dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"chrono",
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
@ -1732,7 +1730,6 @@ dependencies = [
|
||||||
"lemmy_api_common",
|
"lemmy_api_common",
|
||||||
"lemmy_apub",
|
"lemmy_apub",
|
||||||
"lemmy_apub_lib",
|
"lemmy_apub_lib",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
@ -1776,7 +1773,6 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"lemmy_api_common",
|
"lemmy_api_common",
|
||||||
"lemmy_apub_lib",
|
"lemmy_apub_lib",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
@ -1834,15 +1830,15 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lemmy_db_queries"
|
name = "lemmy_db_schema"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
"chrono",
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
|
"diesel-derive-newtype",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lemmy_db_schema",
|
|
||||||
"lemmy_utils",
|
"lemmy_utils",
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -1855,27 +1851,11 @@ dependencies = [
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lemmy_db_schema"
|
|
||||||
version = "0.13.0"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"diesel",
|
|
||||||
"diesel-derive-newtype",
|
|
||||||
"lemmy_apub_lib",
|
|
||||||
"lemmy_utils",
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lemmy_db_views"
|
name = "lemmy_db_views"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diesel",
|
"diesel",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1888,7 +1868,6 @@ name = "lemmy_db_views_actor"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diesel",
|
"diesel",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -1898,7 +1877,6 @@ name = "lemmy_db_views_moderator"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diesel",
|
"diesel",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -1918,7 +1896,6 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lemmy_api_common",
|
"lemmy_api_common",
|
||||||
"lemmy_apub_lib",
|
"lemmy_apub_lib",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
@ -1954,7 +1931,6 @@ dependencies = [
|
||||||
"lemmy_api_crud",
|
"lemmy_api_crud",
|
||||||
"lemmy_apub",
|
"lemmy_apub",
|
||||||
"lemmy_apub_lib",
|
"lemmy_apub_lib",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
@ -2020,7 +1996,6 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
"lemmy_api_common",
|
"lemmy_api_common",
|
||||||
"lemmy_db_queries",
|
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
|
|
@ -22,7 +22,6 @@ members = [
|
||||||
"crates/apub_lib_derive",
|
"crates/apub_lib_derive",
|
||||||
"crates/apub",
|
"crates/apub",
|
||||||
"crates/utils",
|
"crates/utils",
|
||||||
"crates/db_queries",
|
|
||||||
"crates/db_schema",
|
"crates/db_schema",
|
||||||
"crates/db_views",
|
"crates/db_views",
|
||||||
"crates/db_views_actor",
|
"crates/db_views_actor",
|
||||||
|
@ -38,7 +37,6 @@ lemmy_apub = { version = "=0.13.0", path = "./crates/apub" }
|
||||||
lemmy_apub_lib = { version = "=0.13.0", path = "./crates/apub_lib" }
|
lemmy_apub_lib = { version = "=0.13.0", path = "./crates/apub_lib" }
|
||||||
lemmy_utils = { version = "=0.13.0", path = "./crates/utils" }
|
lemmy_utils = { version = "=0.13.0", path = "./crates/utils" }
|
||||||
lemmy_db_schema = { version = "=0.13.0", path = "./crates/db_schema" }
|
lemmy_db_schema = { version = "=0.13.0", path = "./crates/db_schema" }
|
||||||
lemmy_db_queries = { version = "=0.13.0", path = "./crates/db_queries" }
|
|
||||||
lemmy_db_views = { version = "=0.13.0", path = "./crates/db_views" }
|
lemmy_db_views = { version = "=0.13.0", path = "./crates/db_views" }
|
||||||
lemmy_db_views_moderator = { version = "=0.13.0", path = "./crates/db_views_moderator" }
|
lemmy_db_views_moderator = { version = "=0.13.0", path = "./crates/db_views_moderator" }
|
||||||
lemmy_db_views_actor = { version = "=0.13.0", path = "./crates/db_views_actor" }
|
lemmy_db_views_actor = { version = "=0.13.0", path = "./crates/db_views_actor" }
|
||||||
|
|
|
@ -7,7 +7,7 @@ services:
|
||||||
- "127.0.0.1:8536:8536"
|
- "127.0.0.1:8536:8536"
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- RUST_LOG="warn,lemmy_server=info,lemmy_api=info,lemmy_api_common=info,lemmy_api_crud=info,lemmy_apub=info,lemmy_db_queries=info,lemmy_db_schema=info,lemmy_db_views=info,lemmy_db_views_actor=info,lemmy_db_views_moderator=info,lemmy_routes=info,lemmy_utils=info,lemmy_websocket=info"
|
- RUST_LOG="warn,lemmy_server=info,lemmy_api=info,lemmy_api_common=info,lemmy_api_crud=info,lemmy_apub=info,lemmy_db_schema=info,lemmy_db_views=info,lemmy_db_views_actor=info,lemmy_db_views_moderator=info,lemmy_routes=info,lemmy_utils=info,lemmy_websocket=info"
|
||||||
volumes:
|
volumes:
|
||||||
- ./lemmy.hjson:/config/config.hjson:ro
|
- ./lemmy.hjson:/config/config.hjson:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
@ -3,7 +3,7 @@ set -e
|
||||||
|
|
||||||
export APUB_TESTING_SEND_SYNC=1
|
export APUB_TESTING_SEND_SYNC=1
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
export RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_queries=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
|
export RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
|
||||||
|
|
||||||
for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do
|
for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do
|
||||||
psql "${LEMMY_DATABASE_URL}/lemmy" -c "DROP DATABASE IF EXISTS $INSTANCE"
|
psql "${LEMMY_DATABASE_URL}/lemmy" -c "DROP DATABASE IF EXISTS $INSTANCE"
|
||||||
|
|
|
@ -15,7 +15,6 @@ doctest = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lemmy_apub = { version = "=0.13.0", path = "../apub" }
|
lemmy_apub = { version = "=0.13.0", path = "../apub" }
|
||||||
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
||||||
lemmy_db_queries = { version = "=0.13.0", path = "../db_queries" }
|
|
||||||
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
||||||
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
||||||
lemmy_db_views_moderator = { version = "=0.13.0", path = "../db_views_moderator" }
|
lemmy_db_views_moderator = { version = "=0.13.0", path = "../db_views_moderator" }
|
||||||
|
|
|
@ -15,8 +15,11 @@ use lemmy_apub::{
|
||||||
},
|
},
|
||||||
fetcher::post_or_comment::PostOrComment,
|
fetcher::post_or_comment::PostOrComment,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, Likeable, Saveable};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::{source::comment::*, LocalUserId};
|
newtypes::LocalUserId,
|
||||||
|
source::comment::*,
|
||||||
|
traits::{Likeable, Saveable},
|
||||||
|
};
|
||||||
use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
|
use lemmy_db_views::{comment_view::CommentView, local_user_view::LocalUserView};
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperation};
|
||||||
|
@ -188,7 +191,7 @@ impl Perform for CreateCommentLike {
|
||||||
|
|
||||||
// Only add the like if the score isnt 0
|
// Only add the like if the score isnt 0
|
||||||
let comment = orig_comment.comment;
|
let comment = orig_comment.comment;
|
||||||
let object = PostOrComment::Comment(comment);
|
let object = PostOrComment::Comment(comment.into());
|
||||||
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
|
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
|
||||||
if do_add {
|
if do_add {
|
||||||
let like_form2 = like_form.clone();
|
let like_form2 = like_form.clone();
|
||||||
|
@ -199,7 +202,7 @@ impl Perform for CreateCommentLike {
|
||||||
|
|
||||||
Vote::send(
|
Vote::send(
|
||||||
&object,
|
&object,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
orig_comment.community.id,
|
orig_comment.community.id,
|
||||||
like_form.score.try_into()?,
|
like_form.score.try_into()?,
|
||||||
context,
|
context,
|
||||||
|
@ -209,7 +212,7 @@ impl Perform for CreateCommentLike {
|
||||||
// API doesn't distinguish between Undo/Like and Undo/Dislike
|
// API doesn't distinguish between Undo/Like and Undo/Dislike
|
||||||
UndoVote::send(
|
UndoVote::send(
|
||||||
&object,
|
&object,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
orig_comment.community.id,
|
orig_comment.community.id,
|
||||||
VoteType::Like,
|
VoteType::Like,
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -8,8 +8,7 @@ use lemmy_api_common::{
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
};
|
};
|
||||||
use lemmy_apub::{activities::report::Report, fetcher::object_id::ObjectId};
|
use lemmy_apub::{activities::report::Report, fetcher::object_id::ObjectId};
|
||||||
use lemmy_db_queries::Reportable;
|
use lemmy_db_schema::{source::comment_report::*, traits::Reportable};
|
||||||
use lemmy_db_schema::source::comment_report::*;
|
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
||||||
comment_view::CommentView,
|
comment_view::CommentView,
|
||||||
|
@ -80,8 +79,8 @@ impl Perform for CreateCommentReport {
|
||||||
|
|
||||||
Report::send(
|
Report::send(
|
||||||
ObjectId::new(comment_view.comment.ap_id),
|
ObjectId::new(comment_view.comment.ap_id),
|
||||||
&local_user_view.person,
|
&local_user_view.person.into(),
|
||||||
comment_view.community.id,
|
ObjectId::new(comment_view.community.actor_id),
|
||||||
reason.to_string(),
|
reason.to_string(),
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,8 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
};
|
};
|
||||||
use lemmy_apub::activities::{
|
use lemmy_apub::{
|
||||||
|
activities::{
|
||||||
community::{
|
community::{
|
||||||
add_mod::AddMod,
|
add_mod::AddMod,
|
||||||
block_user::BlockUserFromCommunity,
|
block_user::BlockUserFromCommunity,
|
||||||
|
@ -17,23 +18,35 @@ use lemmy_apub::activities::{
|
||||||
undo_block_user::UndoBlockUserFromCommunity,
|
undo_block_user::UndoBlockUserFromCommunity,
|
||||||
},
|
},
|
||||||
following::{follow::FollowCommunity as FollowCommunityApub, undo::UndoFollowCommunity},
|
following::{follow::FollowCommunity as FollowCommunityApub, undo::UndoFollowCommunity},
|
||||||
|
},
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
source::{comment::Comment_, community::CommunityModerator_, post::Post_},
|
source::{
|
||||||
Bannable,
|
|
||||||
Blockable,
|
|
||||||
Crud,
|
|
||||||
Followable,
|
|
||||||
Joinable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
community::*,
|
community::{
|
||||||
|
Community,
|
||||||
|
CommunityFollower,
|
||||||
|
CommunityFollowerForm,
|
||||||
|
CommunityModerator,
|
||||||
|
CommunityModeratorForm,
|
||||||
|
CommunityPersonBan,
|
||||||
|
CommunityPersonBanForm,
|
||||||
|
},
|
||||||
community_block::{CommunityBlock, CommunityBlockForm},
|
community_block::{CommunityBlock, CommunityBlockForm},
|
||||||
moderator::*,
|
moderator::{
|
||||||
|
ModAddCommunity,
|
||||||
|
ModAddCommunityForm,
|
||||||
|
ModBanFromCommunity,
|
||||||
|
ModBanFromCommunityForm,
|
||||||
|
ModTransferCommunity,
|
||||||
|
ModTransferCommunityForm,
|
||||||
|
},
|
||||||
person::Person,
|
person::Person,
|
||||||
post::Post,
|
post::Post,
|
||||||
site::*,
|
site::Site,
|
||||||
|
},
|
||||||
|
traits::{Bannable, Blockable, Crud, Followable, Joinable},
|
||||||
};
|
};
|
||||||
use lemmy_db_views::comment_view::CommentQueryBuilder;
|
use lemmy_db_views::comment_view::CommentQueryBuilder;
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
|
@ -58,10 +71,11 @@ impl Perform for FollowCommunity {
|
||||||
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
person_id: local_user_view.person.id,
|
person_id: local_user_view.person.id,
|
||||||
|
@ -87,9 +101,11 @@ impl Perform for FollowCommunity {
|
||||||
} else if data.follow {
|
} else if data.follow {
|
||||||
// Dont actually add to the community followers here, because you need
|
// Dont actually add to the community followers here, because you need
|
||||||
// to wait for the accept
|
// to wait for the accept
|
||||||
FollowCommunityApub::send(&local_user_view.person, &community, context).await?;
|
FollowCommunityApub::send(&local_user_view.person.clone().into(), &community, context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
UndoFollowCommunity::send(&local_user_view.person, &community, context).await?;
|
UndoFollowCommunity::send(&local_user_view.person.clone().into(), &community, context)
|
||||||
|
.await?;
|
||||||
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
|
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
|
||||||
blocking(context.pool(), unfollow)
|
blocking(context.pool(), unfollow)
|
||||||
.await?
|
.await?
|
||||||
|
@ -155,7 +171,7 @@ impl Perform for BlockCommunity {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
UndoFollowCommunity::send(&local_user_view.person, &community, context).await?;
|
UndoFollowCommunity::send(&local_user_view.person.into(), &community.into(), context).await?;
|
||||||
} else {
|
} else {
|
||||||
let unblock = move |conn: &'_ _| CommunityBlock::unblock(conn, &community_block_form);
|
let unblock = move |conn: &'_ _| CommunityBlock::unblock(conn, &community_block_form);
|
||||||
blocking(context.pool(), unblock)
|
blocking(context.pool(), unblock)
|
||||||
|
@ -199,14 +215,16 @@ impl Perform for BanFromCommunity {
|
||||||
person_id: data.person_id,
|
person_id: data.person_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let community = blocking(context.pool(), move |conn: &'_ _| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
let banned_person = blocking(context.pool(), move |conn: &'_ _| {
|
.into();
|
||||||
|
let banned_person: ApubPerson = blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Person::read(conn, banned_person_id)
|
Person::read(conn, banned_person_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
if data.ban {
|
if data.ban {
|
||||||
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
||||||
|
@ -226,7 +244,12 @@ impl Perform for BanFromCommunity {
|
||||||
.await?
|
.await?
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
BlockUserFromCommunity::send(&community, &banned_person, &local_user_view.person, context)
|
BlockUserFromCommunity::send(
|
||||||
|
&community,
|
||||||
|
&banned_person,
|
||||||
|
&local_user_view.person.clone().into(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
||||||
|
@ -236,7 +259,7 @@ impl Perform for BanFromCommunity {
|
||||||
UndoBlockUserFromCommunity::send(
|
UndoBlockUserFromCommunity::send(
|
||||||
&community,
|
&community,
|
||||||
&banned_person,
|
&banned_person,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -358,18 +381,32 @@ impl Perform for AddModToCommunity {
|
||||||
|
|
||||||
// Send to federated instances
|
// Send to federated instances
|
||||||
let updated_mod_id = data.person_id;
|
let updated_mod_id = data.person_id;
|
||||||
let updated_mod = blocking(context.pool(), move |conn| {
|
let updated_mod: ApubPerson = blocking(context.pool(), move |conn| {
|
||||||
Person::read(conn, updated_mod_id)
|
Person::read(conn, updated_mod_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
let community = blocking(context.pool(), move |conn| {
|
.into();
|
||||||
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
if data.added {
|
if data.added {
|
||||||
AddMod::send(&community, &updated_mod, &local_user_view.person, context).await?;
|
AddMod::send(
|
||||||
|
&community,
|
||||||
|
&updated_mod,
|
||||||
|
&local_user_view.person.into(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
RemoveMod::send(&community, &updated_mod, &local_user_view.person, context).await?;
|
RemoveMod::send(
|
||||||
|
&community,
|
||||||
|
&updated_mod,
|
||||||
|
&local_user_view.person.into(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: in case a remote mod is added, this returns the old moderators list, it will only get
|
// Note: in case a remote mod is added, this returns the old moderators list, it will only get
|
||||||
|
|
|
@ -191,15 +191,14 @@ pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use lemmy_api_common::check_validator_time;
|
use lemmy_api_common::check_validator_time;
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
source::{local_user::LocalUser_, secret::Secret_},
|
source::{
|
||||||
Crud,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
local_user::{LocalUser, LocalUserForm},
|
local_user::{LocalUser, LocalUserForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
secret::Secret,
|
secret::Secret,
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{claims::Claims, settings::structs::Settings};
|
use lemmy_utils::{claims::Claims, settings::structs::Settings};
|
||||||
|
|
||||||
|
|
|
@ -11,25 +11,10 @@ use lemmy_api_common::{
|
||||||
password_length_check,
|
password_length_check,
|
||||||
person::*,
|
person::*,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
diesel_option_overwrite_to_url,
|
diesel_option_overwrite_to_url,
|
||||||
from_opt_str_to_opt_enum,
|
from_opt_str_to_opt_enum,
|
||||||
source::{
|
|
||||||
comment::Comment_,
|
|
||||||
community::Community_,
|
|
||||||
local_user::LocalUser_,
|
|
||||||
password_reset_request::PasswordResetRequest_,
|
|
||||||
person::Person_,
|
|
||||||
person_mention::PersonMention_,
|
|
||||||
post::Post_,
|
|
||||||
private_message::PrivateMessage_,
|
|
||||||
},
|
|
||||||
Blockable,
|
|
||||||
Crud,
|
|
||||||
SortType,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
naive_now,
|
naive_now,
|
||||||
source::{
|
source::{
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
|
@ -44,6 +29,8 @@ use lemmy_db_schema::{
|
||||||
private_message::PrivateMessage,
|
private_message::PrivateMessage,
|
||||||
site::*,
|
site::*,
|
||||||
},
|
},
|
||||||
|
traits::{Blockable, Crud},
|
||||||
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_report_view::CommentReportView,
|
comment_report_view::CommentReportView,
|
||||||
|
|
|
@ -21,9 +21,12 @@ use lemmy_apub::{
|
||||||
CreateOrUpdateType,
|
CreateOrUpdateType,
|
||||||
},
|
},
|
||||||
fetcher::post_or_comment::PostOrComment,
|
fetcher::post_or_comment::PostOrComment,
|
||||||
|
objects::post::ApubPost,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
source::{moderator::*, post::*},
|
||||||
|
traits::{Crud, Likeable, Saveable},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud, Likeable, Saveable};
|
|
||||||
use lemmy_db_schema::source::{moderator::*, post::*};
|
|
||||||
use lemmy_db_views::post_view::PostView;
|
use lemmy_db_views::post_view::PostView;
|
||||||
use lemmy_utils::{request::fetch_site_metadata, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{request::fetch_site_metadata, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperation};
|
||||||
|
@ -47,7 +50,9 @@ impl Perform for CreatePostLike {
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, post_id))
|
||||||
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
|
check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
|
||||||
check_community_deleted_or_removed(post.community_id, context.pool()).await?;
|
check_community_deleted_or_removed(post.community_id, context.pool()).await?;
|
||||||
|
@ -81,7 +86,7 @@ impl Perform for CreatePostLike {
|
||||||
|
|
||||||
Vote::send(
|
Vote::send(
|
||||||
&object,
|
&object,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
community_id,
|
community_id,
|
||||||
like_form.score.try_into()?,
|
like_form.score.try_into()?,
|
||||||
context,
|
context,
|
||||||
|
@ -91,7 +96,7 @@ impl Perform for CreatePostLike {
|
||||||
// API doesn't distinguish between Undo/Like and Undo/Dislike
|
// API doesn't distinguish between Undo/Like and Undo/Dislike
|
||||||
UndoVote::send(
|
UndoVote::send(
|
||||||
&object,
|
&object,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
community_id,
|
community_id,
|
||||||
VoteType::Like,
|
VoteType::Like,
|
||||||
context,
|
context,
|
||||||
|
@ -148,10 +153,11 @@ impl Perform for LockPost {
|
||||||
// Update the post
|
// Update the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let locked = data.locked;
|
let locked = data.locked;
|
||||||
let updated_post = blocking(context.pool(), move |conn| {
|
let updated_post: ApubPost = blocking(context.pool(), move |conn| {
|
||||||
Post::update_locked(conn, post_id, locked)
|
Post::update_locked(conn, post_id, locked)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModLockPostForm {
|
let form = ModLockPostForm {
|
||||||
|
@ -164,7 +170,7 @@ impl Perform for LockPost {
|
||||||
// apub updates
|
// apub updates
|
||||||
CreateOrUpdatePost::send(
|
CreateOrUpdatePost::send(
|
||||||
&updated_post,
|
&updated_post,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
CreateOrUpdateType::Update,
|
CreateOrUpdateType::Update,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
@ -216,10 +222,11 @@ impl Perform for StickyPost {
|
||||||
// Update the post
|
// Update the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let stickied = data.stickied;
|
let stickied = data.stickied;
|
||||||
let updated_post = blocking(context.pool(), move |conn| {
|
let updated_post: ApubPost = blocking(context.pool(), move |conn| {
|
||||||
Post::update_stickied(conn, post_id, stickied)
|
Post::update_stickied(conn, post_id, stickied)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModStickyPostForm {
|
let form = ModStickyPostForm {
|
||||||
|
@ -236,7 +243,7 @@ impl Perform for StickyPost {
|
||||||
// TODO stickied should pry work like locked for ease of use
|
// TODO stickied should pry work like locked for ease of use
|
||||||
CreateOrUpdatePost::send(
|
CreateOrUpdatePost::send(
|
||||||
&updated_post,
|
&updated_post,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
CreateOrUpdateType::Update,
|
CreateOrUpdateType::Update,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,8 +14,10 @@ use lemmy_api_common::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use lemmy_apub::{activities::report::Report, fetcher::object_id::ObjectId};
|
use lemmy_apub::{activities::report::Report, fetcher::object_id::ObjectId};
|
||||||
use lemmy_db_queries::Reportable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::post_report::{PostReport, PostReportForm};
|
source::post_report::{PostReport, PostReportForm},
|
||||||
|
traits::Reportable,
|
||||||
|
};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
post_report_view::{PostReportQueryBuilder, PostReportView},
|
post_report_view::{PostReportQueryBuilder, PostReportView},
|
||||||
post_view::PostView,
|
post_view::PostView,
|
||||||
|
@ -86,8 +88,8 @@ impl Perform for CreatePostReport {
|
||||||
|
|
||||||
Report::send(
|
Report::send(
|
||||||
ObjectId::new(post_view.post.ap_id),
|
ObjectId::new(post_view.post.ap_id),
|
||||||
&local_user_view.person,
|
&local_user_view.person.into(),
|
||||||
post_view.community.id,
|
ObjectId::new(post_view.community.actor_id),
|
||||||
reason.to_string(),
|
reason.to_string(),
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,8 +5,7 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
person::{MarkPrivateMessageAsRead, PrivateMessageResponse},
|
person::{MarkPrivateMessageAsRead, PrivateMessageResponse},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperation};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperation};
|
||||||
|
|
||||||
|
|
|
@ -15,20 +15,16 @@ use lemmy_apub::{
|
||||||
fetcher::search::{search_by_apub_id, SearchableObjects},
|
fetcher::search::{search_by_apub_id, SearchableObjects},
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
from_opt_str_to_opt_enum,
|
from_opt_str_to_opt_enum,
|
||||||
source::site::Site_,
|
newtypes::PersonId,
|
||||||
Crud,
|
source::{moderator::*, site::Site},
|
||||||
|
traits::{Crud, DeleteableOrRemoveable},
|
||||||
DbPool,
|
DbPool,
|
||||||
DeleteableOrRemoveable,
|
|
||||||
ListingType,
|
ListingType,
|
||||||
SearchType,
|
SearchType,
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
|
||||||
source::{moderator::*, site::Site},
|
|
||||||
PersonId,
|
|
||||||
};
|
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_view::{CommentQueryBuilder, CommentView},
|
comment_view::{CommentQueryBuilder, CommentView},
|
||||||
post_view::{PostQueryBuilder, PostView},
|
post_view::{PostQueryBuilder, PostView},
|
||||||
|
@ -450,7 +446,7 @@ impl Perform for TransferSite {
|
||||||
|
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
let read_site = blocking(context.pool(), Site::read_simple).await??;
|
||||||
|
|
||||||
// Make sure user is the creator
|
// Make sure user is the creator
|
||||||
if read_site.creator_id != local_user_view.person.id {
|
if read_site.creator_id != local_user_view.person.id {
|
||||||
|
|
|
@ -13,7 +13,6 @@ path = "src/lib.rs"
|
||||||
doctest = false
|
doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lemmy_db_queries = { version = "=0.13.0", path = "../db_queries" }
|
|
||||||
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
||||||
lemmy_db_views_moderator = { version = "=0.13.0", path = "../db_views_moderator" }
|
lemmy_db_views_moderator = { version = "=0.13.0", path = "../db_views_moderator" }
|
||||||
lemmy_db_views_actor = { version = "=0.13.0", path = "../db_views_actor" }
|
lemmy_db_views_actor = { version = "=0.13.0", path = "../db_views_actor" }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lemmy_db_schema::{CommentId, CommentReportId, CommunityId, LocalUserId, PostId};
|
use lemmy_db_schema::newtypes::{CommentId, CommentReportId, CommunityId, LocalUserId, PostId};
|
||||||
use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView};
|
use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lemmy_db_schema::{CommunityId, PersonId};
|
use lemmy_db_schema::newtypes::{CommunityId, PersonId};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
|
|
|
@ -6,43 +6,24 @@ pub mod site;
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
use crate::site::FederatedInstances;
|
use crate::site::FederatedInstances;
|
||||||
use diesel::PgConnection;
|
|
||||||
use lemmy_db_queries::{
|
|
||||||
source::{community::Community_, person_block::PersonBlock_, site::Site_},
|
|
||||||
Crud,
|
|
||||||
DbPool,
|
|
||||||
Readable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
newtypes::{CommunityId, LocalUserId, PersonId, PostId},
|
||||||
source::{
|
source::{
|
||||||
comment::Comment,
|
|
||||||
community::Community,
|
community::Community,
|
||||||
person::Person,
|
|
||||||
person_block::PersonBlock,
|
person_block::PersonBlock,
|
||||||
person_mention::{PersonMention, PersonMentionForm},
|
|
||||||
post::{Post, PostRead, PostReadForm},
|
post::{Post, PostRead, PostReadForm},
|
||||||
secret::Secret,
|
secret::Secret,
|
||||||
site::Site,
|
site::Site,
|
||||||
},
|
},
|
||||||
CommunityId,
|
traits::{Crud, Readable},
|
||||||
LocalUserId,
|
DbPool,
|
||||||
PersonId,
|
|
||||||
PostId,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
|
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_person_ban_view::CommunityPersonBanView,
|
community_person_ban_view::CommunityPersonBanView,
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{claims::Claims, settings::structs::FederationConfig, ApiError, LemmyError};
|
||||||
claims::Claims,
|
|
||||||
email::send_email,
|
|
||||||
settings::structs::{FederationConfig, Settings},
|
|
||||||
utils::MentionData,
|
|
||||||
ApiError,
|
|
||||||
LemmyError,
|
|
||||||
};
|
|
||||||
use log::error;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
|
pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
|
||||||
|
@ -61,160 +42,6 @@ where
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_local_notifs(
|
|
||||||
mentions: Vec<MentionData>,
|
|
||||||
comment: Comment,
|
|
||||||
person: Person,
|
|
||||||
post: Post,
|
|
||||||
pool: &DbPool,
|
|
||||||
do_send_email: bool,
|
|
||||||
settings: &Settings,
|
|
||||||
) -> Result<Vec<LocalUserId>, LemmyError> {
|
|
||||||
let settings = settings.to_owned();
|
|
||||||
let ids = blocking(pool, move |conn| {
|
|
||||||
do_send_local_notifs(
|
|
||||||
conn,
|
|
||||||
&mentions,
|
|
||||||
&comment,
|
|
||||||
&person,
|
|
||||||
&post,
|
|
||||||
do_send_email,
|
|
||||||
&settings,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(ids)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_send_local_notifs(
|
|
||||||
conn: &PgConnection,
|
|
||||||
mentions: &[MentionData],
|
|
||||||
comment: &Comment,
|
|
||||||
person: &Person,
|
|
||||||
post: &Post,
|
|
||||||
do_send_email: bool,
|
|
||||||
settings: &Settings,
|
|
||||||
) -> Vec<LocalUserId> {
|
|
||||||
let mut recipient_ids = Vec::new();
|
|
||||||
|
|
||||||
// Send the local mentions
|
|
||||||
for mention in mentions
|
|
||||||
.iter()
|
|
||||||
.filter(|m| m.is_local(&settings.hostname) && m.name.ne(&person.name))
|
|
||||||
.collect::<Vec<&MentionData>>()
|
|
||||||
{
|
|
||||||
if let Ok(mention_user_view) = LocalUserView::read_from_name(conn, &mention.name) {
|
|
||||||
// TODO
|
|
||||||
// At some point, make it so you can't tag the parent creator either
|
|
||||||
// This can cause two notifications, one for reply and the other for mention
|
|
||||||
recipient_ids.push(mention_user_view.local_user.id);
|
|
||||||
|
|
||||||
let user_mention_form = PersonMentionForm {
|
|
||||||
recipient_id: mention_user_view.person.id,
|
|
||||||
comment_id: comment.id,
|
|
||||||
read: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Allow this to fail softly, since comment edits might re-update or replace it
|
|
||||||
// Let the uniqueness handle this fail
|
|
||||||
PersonMention::create(conn, &user_mention_form).ok();
|
|
||||||
|
|
||||||
// Send an email to those local users that have notifications on
|
|
||||||
if do_send_email {
|
|
||||||
send_email_to_user(
|
|
||||||
&mention_user_view,
|
|
||||||
"Mentioned by",
|
|
||||||
"Person Mention",
|
|
||||||
&comment.content,
|
|
||||||
settings,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send notifs to the parent commenter / poster
|
|
||||||
match comment.parent_id {
|
|
||||||
Some(parent_id) => {
|
|
||||||
if let Ok(parent_comment) = Comment::read(conn, parent_id) {
|
|
||||||
// Don't send a notif to yourself
|
|
||||||
if parent_comment.creator_id != person.id {
|
|
||||||
// Get the parent commenter local_user
|
|
||||||
if let Ok(parent_user_view) = LocalUserView::read_person(conn, parent_comment.creator_id)
|
|
||||||
{
|
|
||||||
recipient_ids.push(parent_user_view.local_user.id);
|
|
||||||
|
|
||||||
if do_send_email {
|
|
||||||
send_email_to_user(
|
|
||||||
&parent_user_view,
|
|
||||||
"Reply from",
|
|
||||||
"Comment Reply",
|
|
||||||
&comment.content,
|
|
||||||
settings,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Its a post
|
|
||||||
None => {
|
|
||||||
if post.creator_id != person.id {
|
|
||||||
if let Ok(parent_user_view) = LocalUserView::read_person(conn, post.creator_id) {
|
|
||||||
recipient_ids.push(parent_user_view.local_user.id);
|
|
||||||
|
|
||||||
if do_send_email {
|
|
||||||
send_email_to_user(
|
|
||||||
&parent_user_view,
|
|
||||||
"Reply from",
|
|
||||||
"Post Reply",
|
|
||||||
&comment.content,
|
|
||||||
settings,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
recipient_ids
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_email_to_user(
|
|
||||||
local_user_view: &LocalUserView,
|
|
||||||
subject_text: &str,
|
|
||||||
body_text: &str,
|
|
||||||
comment_content: &str,
|
|
||||||
settings: &Settings,
|
|
||||||
) {
|
|
||||||
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(user_email) = &local_user_view.local_user.email {
|
|
||||||
let subject = &format!(
|
|
||||||
"{} - {} {}",
|
|
||||||
subject_text, settings.hostname, local_user_view.person.name,
|
|
||||||
);
|
|
||||||
let html = &format!(
|
|
||||||
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
|
||||||
body_text,
|
|
||||||
local_user_view.person.name,
|
|
||||||
comment_content,
|
|
||||||
settings.get_protocol_and_hostname()
|
|
||||||
);
|
|
||||||
match send_email(
|
|
||||||
subject,
|
|
||||||
user_email,
|
|
||||||
&local_user_view.person.name,
|
|
||||||
html,
|
|
||||||
settings,
|
|
||||||
) {
|
|
||||||
Ok(_o) => _o,
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn is_mod_or_admin(
|
pub async fn is_mod_or_admin(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
person_id: PersonId,
|
person_id: PersonId,
|
||||||
|
@ -394,7 +221,7 @@ pub async fn check_person_block(
|
||||||
|
|
||||||
pub async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
|
pub async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
|
||||||
if score == -1 {
|
if score == -1 {
|
||||||
let site = blocking(pool, move |conn| Site::read_simple(conn)).await??;
|
let site = blocking(pool, Site::read_simple).await??;
|
||||||
if !site.enable_downvotes {
|
if !site.enable_downvotes {
|
||||||
return Err(ApiError::err_plain("downvotes_disabled").into());
|
return Err(ApiError::err_plain("downvotes_disabled").into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub struct Login {
|
||||||
pub username_or_email: String,
|
pub username_or_email: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
use lemmy_db_schema::{CommunityId, PersonId, PersonMentionId, PrivateMessageId};
|
use lemmy_db_schema::newtypes::{CommunityId, PersonId, PersonMentionId, PrivateMessageId};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Register {
|
pub struct Register {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lemmy_db_schema::{CommunityId, PostId, PostReportId};
|
use lemmy_db_schema::newtypes::{CommunityId, PostId, PostReportId};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_view::CommentView,
|
comment_view::CommentView,
|
||||||
post_report_view::PostReportView,
|
post_report_view::PostReportView,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lemmy_db_schema::{CommunityId, PersonId};
|
use lemmy_db_schema::newtypes::{CommunityId, PersonId};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_view::CommentView,
|
comment_view::CommentView,
|
||||||
local_user_view::LocalUserSettingsView,
|
local_user_view::LocalUserSettingsView,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use lemmy_db_schema::{CommunityId, PostId};
|
use lemmy_db_schema::newtypes::{CommunityId, PostId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
@ -11,7 +11,6 @@ documentation = "https://join-lemmy.org/docs/en/index.html"
|
||||||
lemmy_apub = { version = "=0.13.0", path = "../apub" }
|
lemmy_apub = { version = "=0.13.0", path = "../apub" }
|
||||||
lemmy_apub_lib = { version = "=0.13.0", path = "../apub_lib" }
|
lemmy_apub_lib = { version = "=0.13.0", path = "../apub_lib" }
|
||||||
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
||||||
lemmy_db_queries = { version = "=0.13.0", path = "../db_queries" }
|
|
||||||
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
||||||
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
||||||
lemmy_db_views_moderator = { version = "=0.13.0", path = "../db_views_moderator" }
|
lemmy_db_views_moderator = { version = "=0.13.0", path = "../db_views_moderator" }
|
||||||
|
|
|
@ -9,7 +9,6 @@ use lemmy_api_common::{
|
||||||
comment::*,
|
comment::*,
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
get_post,
|
get_post,
|
||||||
send_local_notifs,
|
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_apub::{
|
||||||
activities::{
|
activities::{
|
||||||
|
@ -21,12 +20,13 @@ use lemmy_apub::{
|
||||||
generate_apub_endpoint,
|
generate_apub_endpoint,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
source::{comment::Comment_, person_mention::PersonMention_},
|
source::{
|
||||||
Crud,
|
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
||||||
Likeable,
|
person_mention::PersonMention,
|
||||||
|
},
|
||||||
|
traits::{Crud, Likeable},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{comment::*, person_mention::PersonMention};
|
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
use lemmy_db_views::comment_view::CommentView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{remove_slurs, scrape_text_for_mentions},
|
utils::{remove_slurs, scrape_text_for_mentions},
|
||||||
|
@ -34,7 +34,11 @@ use lemmy_utils::{
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message, send_local_notifs},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for CreateComment {
|
impl PerformCrud for CreateComment {
|
||||||
|
@ -116,8 +120,8 @@ impl PerformCrud for CreateComment {
|
||||||
.map_err(|e| ApiError::err("couldnt_create_comment", e))?;
|
.map_err(|e| ApiError::err("couldnt_create_comment", e))?;
|
||||||
|
|
||||||
CreateOrUpdateComment::send(
|
CreateOrUpdateComment::send(
|
||||||
&updated_comment,
|
&updated_comment.clone().into(),
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
CreateOrUpdateType::Create,
|
CreateOrUpdateType::Create,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
@ -128,12 +132,11 @@ impl PerformCrud for CreateComment {
|
||||||
let mentions = scrape_text_for_mentions(&comment_form.content);
|
let mentions = scrape_text_for_mentions(&comment_form.content);
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment.clone(),
|
&updated_comment,
|
||||||
local_user_view.person.clone(),
|
&local_user_view.person,
|
||||||
post,
|
&post,
|
||||||
context.pool(),
|
|
||||||
true,
|
true,
|
||||||
&context.settings(),
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -150,10 +153,10 @@ impl PerformCrud for CreateComment {
|
||||||
.await?
|
.await?
|
||||||
.map_err(|e| ApiError::err("couldnt_like_comment", e))?;
|
.map_err(|e| ApiError::err("couldnt_like_comment", e))?;
|
||||||
|
|
||||||
let object = PostOrComment::Comment(updated_comment);
|
let object = PostOrComment::Comment(updated_comment.into());
|
||||||
Vote::send(
|
Vote::send(
|
||||||
&object,
|
&object,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
community_id,
|
community_id,
|
||||||
VoteType::Like,
|
VoteType::Like,
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -6,14 +6,24 @@ use lemmy_api_common::{
|
||||||
comment::*,
|
comment::*,
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
send_local_notifs,
|
|
||||||
};
|
};
|
||||||
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{comment::*, community::Community, moderator::*, post::Post};
|
source::{
|
||||||
|
comment::Comment,
|
||||||
|
community::Community,
|
||||||
|
moderator::{ModRemoveComment, ModRemoveCommentForm},
|
||||||
|
post::Post,
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
use lemmy_db_views::comment_view::CommentView;
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message, send_local_notifs},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for DeleteComment {
|
impl PerformCrud for DeleteComment {
|
||||||
|
@ -60,8 +70,8 @@ impl PerformCrud for DeleteComment {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
send_apub_delete(
|
send_apub_delete(
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
&community,
|
&community.clone().into(),
|
||||||
updated_comment.ap_id.clone().into(),
|
updated_comment.ap_id.clone().into(),
|
||||||
deleted,
|
deleted,
|
||||||
context,
|
context,
|
||||||
|
@ -72,12 +82,11 @@ impl PerformCrud for DeleteComment {
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
vec![],
|
vec![],
|
||||||
updated_comment,
|
&updated_comment,
|
||||||
local_user_view.person.clone(),
|
&local_user_view.person,
|
||||||
post,
|
&post,
|
||||||
context.pool(),
|
|
||||||
false,
|
false,
|
||||||
&context.settings(),
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -154,8 +163,8 @@ impl PerformCrud for RemoveComment {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
send_apub_remove(
|
send_apub_remove(
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
&community,
|
&community.into(),
|
||||||
updated_comment.ap_id.clone().into(),
|
updated_comment.ap_id.clone().into(),
|
||||||
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
||||||
removed,
|
removed,
|
||||||
|
@ -167,12 +176,11 @@ impl PerformCrud for RemoveComment {
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
vec![],
|
vec![],
|
||||||
updated_comment,
|
&updated_comment,
|
||||||
local_user_view.person.clone(),
|
&local_user_view.person.clone(),
|
||||||
post,
|
&post,
|
||||||
context.pool(),
|
|
||||||
false,
|
false,
|
||||||
&context.settings(),
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,12 @@ use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, comment::*, get_local_user_view_from_jwt_opt};
|
use lemmy_api_common::{blocking, comment::*, get_local_user_view_from_jwt_opt};
|
||||||
use lemmy_apub::{build_actor_id_from_shortname, EndpointType};
|
use lemmy_apub::{build_actor_id_from_shortname, EndpointType};
|
||||||
use lemmy_db_queries::{from_opt_str_to_opt_enum, DeleteableOrRemoveable, ListingType, SortType};
|
use lemmy_db_schema::{
|
||||||
|
from_opt_str_to_opt_enum,
|
||||||
|
traits::DeleteableOrRemoveable,
|
||||||
|
ListingType,
|
||||||
|
SortType,
|
||||||
|
};
|
||||||
use lemmy_db_views::comment_view::CommentQueryBuilder;
|
use lemmy_db_views::comment_view::CommentQueryBuilder;
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
|
@ -7,14 +7,12 @@ use lemmy_api_common::{
|
||||||
check_post_deleted_or_removed,
|
check_post_deleted_or_removed,
|
||||||
comment::*,
|
comment::*,
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
send_local_notifs,
|
|
||||||
};
|
};
|
||||||
use lemmy_apub::activities::{
|
use lemmy_apub::activities::{
|
||||||
comment::create_or_update::CreateOrUpdateComment,
|
comment::create_or_update::CreateOrUpdateComment,
|
||||||
CreateOrUpdateType,
|
CreateOrUpdateType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::source::comment::Comment_;
|
use lemmy_db_schema::source::comment::Comment;
|
||||||
use lemmy_db_schema::source::comment::*;
|
|
||||||
use lemmy_db_views::comment_view::CommentView;
|
use lemmy_db_views::comment_view::CommentView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{remove_slurs, scrape_text_for_mentions},
|
utils::{remove_slurs, scrape_text_for_mentions},
|
||||||
|
@ -22,7 +20,11 @@ use lemmy_utils::{
|
||||||
ConnectionId,
|
ConnectionId,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{
|
||||||
|
send::{send_comment_ws_message, send_local_notifs},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for EditComment {
|
impl PerformCrud for EditComment {
|
||||||
|
@ -70,8 +72,8 @@ impl PerformCrud for EditComment {
|
||||||
|
|
||||||
// Send the apub update
|
// Send the apub update
|
||||||
CreateOrUpdateComment::send(
|
CreateOrUpdateComment::send(
|
||||||
&updated_comment,
|
&updated_comment.clone().into(),
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
CreateOrUpdateType::Update,
|
CreateOrUpdateType::Update,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
@ -82,12 +84,11 @@ impl PerformCrud for EditComment {
|
||||||
let mentions = scrape_text_for_mentions(&updated_comment_content);
|
let mentions = scrape_text_for_mentions(&updated_comment_content);
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
&updated_comment,
|
||||||
local_user_view.person.clone(),
|
&local_user_view.person,
|
||||||
orig_comment.post,
|
&orig_comment.post,
|
||||||
context.pool(),
|
|
||||||
false,
|
false,
|
||||||
&context.settings(),
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,12 @@ use lemmy_apub::{
|
||||||
generate_followers_url,
|
generate_followers_url,
|
||||||
generate_inbox_url,
|
generate_inbox_url,
|
||||||
generate_shared_inbox_url,
|
generate_shared_inbox_url,
|
||||||
|
objects::community::ApubCommunity,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{diesel_option_overwrite_to_url, Crud, Followable, Joinable};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
diesel_option_overwrite_to_url,
|
||||||
|
source::{
|
||||||
community::{
|
community::{
|
||||||
Community,
|
Community,
|
||||||
CommunityFollower,
|
CommunityFollower,
|
||||||
|
@ -25,6 +27,8 @@ use lemmy_db_schema::source::{
|
||||||
CommunityModeratorForm,
|
CommunityModeratorForm,
|
||||||
},
|
},
|
||||||
site::Site,
|
site::Site,
|
||||||
|
},
|
||||||
|
traits::{Crud, Followable, Joinable},
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_view::CommunityView;
|
use lemmy_db_views_actor::community_view::CommunityView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
|
@ -68,7 +72,7 @@ impl PerformCrud for CreateCommunity {
|
||||||
&data.name,
|
&data.name,
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?;
|
)?;
|
||||||
let community_actor_id_wrapped = ObjectId::<Community>::new(community_actor_id.clone());
|
let community_actor_id_wrapped = ObjectId::<ApubCommunity>::new(community_actor_id.clone());
|
||||||
let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
|
let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
|
||||||
if community_dupe.is_ok() {
|
if community_dupe.is_ok() {
|
||||||
return Err(ApiError::err_plain("community_already_exists").into());
|
return Err(ApiError::err_plain("community_already_exists").into());
|
||||||
|
|
|
@ -2,10 +2,12 @@ use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin};
|
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt, is_admin};
|
||||||
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
||||||
use lemmy_db_queries::{source::community::Community_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::{
|
||||||
community::*,
|
community::Community,
|
||||||
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
|
moderator::{ModRemoveCommunity, ModRemoveCommunityForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
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, ApiError, ConnectionId, LemmyError};
|
||||||
|
@ -47,8 +49,8 @@ impl PerformCrud for DeleteCommunity {
|
||||||
|
|
||||||
// Send apub messages
|
// Send apub messages
|
||||||
send_apub_delete(
|
send_apub_delete(
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
&updated_community,
|
&updated_community.clone().into(),
|
||||||
updated_community.actor_id.clone().into(),
|
updated_community.actor_id.clone().into(),
|
||||||
deleted,
|
deleted,
|
||||||
context,
|
context,
|
||||||
|
@ -107,8 +109,8 @@ impl PerformCrud for RemoveCommunity {
|
||||||
|
|
||||||
// Apub messages
|
// Apub messages
|
||||||
send_apub_remove(
|
send_apub_remove(
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
&updated_community,
|
&updated_community.clone().into(),
|
||||||
updated_community.actor_id.clone().into(),
|
updated_community.actor_id.clone().into(),
|
||||||
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
||||||
removed,
|
removed,
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
use crate::PerformCrud;
|
use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt_opt};
|
use lemmy_api_common::{blocking, community::*, get_local_user_view_from_jwt_opt};
|
||||||
use lemmy_apub::{build_actor_id_from_shortname, fetcher::object_id::ObjectId, EndpointType};
|
use lemmy_apub::{
|
||||||
use lemmy_db_queries::{from_opt_str_to_opt_enum, DeleteableOrRemoveable, ListingType, SortType};
|
build_actor_id_from_shortname,
|
||||||
use lemmy_db_schema::source::community::*;
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::community::ApubCommunity,
|
||||||
|
EndpointType,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
from_opt_str_to_opt_enum,
|
||||||
|
traits::DeleteableOrRemoveable,
|
||||||
|
ListingType,
|
||||||
|
SortType,
|
||||||
|
};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
community_view::{CommunityQueryBuilder, CommunityView},
|
community_view::{CommunityQueryBuilder, CommunityView},
|
||||||
|
@ -32,7 +41,7 @@ impl PerformCrud for GetCommunity {
|
||||||
let community_actor_id =
|
let community_actor_id =
|
||||||
build_actor_id_from_shortname(EndpointType::Community, &name, &context.settings())?;
|
build_actor_id_from_shortname(EndpointType::Community, &name, &context.settings())?;
|
||||||
|
|
||||||
ObjectId::<Community>::new(community_actor_id)
|
ObjectId::<ApubCommunity>::new(community_actor_id)
|
||||||
.dereference(context, &mut 0)
|
.dereference(context, &mut 0)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ApiError::err("couldnt_find_community", e))?
|
.map_err(|e| ApiError::err("couldnt_find_community", e))?
|
||||||
|
|
|
@ -6,11 +6,12 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
};
|
};
|
||||||
use lemmy_apub::activities::community::update::UpdateCommunity;
|
use lemmy_apub::activities::community::update::UpdateCommunity;
|
||||||
use lemmy_db_queries::{diesel_option_overwrite_to_url, Crud};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
diesel_option_overwrite_to_url,
|
||||||
naive_now,
|
naive_now,
|
||||||
|
newtypes::PersonId,
|
||||||
source::community::{Community, CommunityForm},
|
source::community::{Community, CommunityForm},
|
||||||
PersonId,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
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, ApiError, ConnectionId, LemmyError};
|
||||||
|
@ -70,7 +71,12 @@ impl PerformCrud for EditCommunity {
|
||||||
.await?
|
.await?
|
||||||
.map_err(|e| ApiError::err("couldnt_update_community", e))?;
|
.map_err(|e| ApiError::err("couldnt_update_community", e))?;
|
||||||
|
|
||||||
UpdateCommunity::send(&updated_community, &local_user_view.person, context).await?;
|
UpdateCommunity::send(
|
||||||
|
&updated_community.into(),
|
||||||
|
&local_user_view.person.into(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let op = UserOperationCrud::EditCommunity;
|
let op = UserOperationCrud::EditCommunity;
|
||||||
send_community_ws_message(data.community_id, op, websocket_id, None, context).await
|
send_community_ws_message(data.community_id, op, websocket_id, None, context).await
|
||||||
|
|
|
@ -19,8 +19,10 @@ use lemmy_apub::{
|
||||||
generate_apub_endpoint,
|
generate_apub_endpoint,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud, Likeable};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::post::*;
|
source::post::{Post, PostForm, PostLike, PostLikeForm},
|
||||||
|
traits::{Crud, Likeable},
|
||||||
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title},
|
utils::{check_slurs, check_slurs_opt, clean_url_params, is_valid_post_title},
|
||||||
|
@ -107,8 +109,8 @@ impl PerformCrud for CreatePost {
|
||||||
.map_err(|e| ApiError::err("couldnt_create_post", e))?;
|
.map_err(|e| ApiError::err("couldnt_create_post", e))?;
|
||||||
|
|
||||||
CreateOrUpdatePost::send(
|
CreateOrUpdatePost::send(
|
||||||
&updated_post,
|
&updated_post.clone().into(),
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
CreateOrUpdateType::Create,
|
CreateOrUpdateType::Create,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
@ -144,10 +146,10 @@ impl PerformCrud for CreatePost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let object = PostOrComment::Post(Box::new(updated_post));
|
let object = PostOrComment::Post(Box::new(updated_post.into()));
|
||||||
Vote::send(
|
Vote::send(
|
||||||
&object,
|
&object,
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
inserted_post.community_id,
|
inserted_post.community_id,
|
||||||
VoteType::Like,
|
VoteType::Like,
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -9,8 +9,14 @@ use lemmy_api_common::{
|
||||||
post::*,
|
post::*,
|
||||||
};
|
};
|
||||||
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
use lemmy_apub::activities::deletion::{send_apub_delete, send_apub_remove};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{community::Community, moderator::*, post::*};
|
source::{
|
||||||
|
community::Community,
|
||||||
|
moderator::{ModRemovePost, ModRemovePostForm},
|
||||||
|
post::Post,
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
|
@ -57,8 +63,8 @@ impl PerformCrud for DeletePost {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
send_apub_delete(
|
send_apub_delete(
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
&community,
|
&community.into(),
|
||||||
updated_post.ap_id.into(),
|
updated_post.ap_id.into(),
|
||||||
deleted,
|
deleted,
|
||||||
context,
|
context,
|
||||||
|
@ -133,8 +139,8 @@ impl PerformCrud for RemovePost {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
send_apub_remove(
|
send_apub_remove(
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
&community,
|
&community.into(),
|
||||||
updated_post.ap_id.into(),
|
updated_post.ap_id.into(),
|
||||||
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
data.reason.clone().unwrap_or_else(|| "".to_string()),
|
||||||
removed,
|
removed,
|
||||||
|
|
|
@ -2,7 +2,12 @@ use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, mark_post_as_read, post::*};
|
use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, mark_post_as_read, post::*};
|
||||||
use lemmy_apub::{build_actor_id_from_shortname, EndpointType};
|
use lemmy_apub::{build_actor_id_from_shortname, EndpointType};
|
||||||
use lemmy_db_queries::{from_opt_str_to_opt_enum, DeleteableOrRemoveable, ListingType, SortType};
|
use lemmy_db_schema::{
|
||||||
|
from_opt_str_to_opt_enum,
|
||||||
|
traits::DeleteableOrRemoveable,
|
||||||
|
ListingType,
|
||||||
|
SortType,
|
||||||
|
};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_view::CommentQueryBuilder,
|
comment_view::CommentQueryBuilder,
|
||||||
post_view::{PostQueryBuilder, PostView},
|
post_view::{PostQueryBuilder, PostView},
|
||||||
|
|
|
@ -8,8 +8,11 @@ use lemmy_api_common::{
|
||||||
post::*,
|
post::*,
|
||||||
};
|
};
|
||||||
use lemmy_apub::activities::{post::create_or_update::CreateOrUpdatePost, CreateOrUpdateType};
|
use lemmy_apub::activities::{post::create_or_update::CreateOrUpdatePost, CreateOrUpdateType};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::{naive_now, source::post::*};
|
naive_now,
|
||||||
|
source::post::{Post, PostForm},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
utils::{check_slurs_opt, clean_url_params, is_valid_post_title},
|
utils::{check_slurs_opt, clean_url_params, is_valid_post_title},
|
||||||
|
@ -101,8 +104,8 @@ impl PerformCrud for EditPost {
|
||||||
|
|
||||||
// Send apub update
|
// Send apub update
|
||||||
CreateOrUpdatePost::send(
|
CreateOrUpdatePost::send(
|
||||||
&updated_post,
|
&updated_post.into(),
|
||||||
&local_user_view.person,
|
&local_user_view.person.clone().into(),
|
||||||
CreateOrUpdateType::Update,
|
CreateOrUpdateType::Update,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,6 @@ use lemmy_api_common::{
|
||||||
check_person_block,
|
check_person_block,
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
person::{CreatePrivateMessage, PrivateMessageResponse},
|
person::{CreatePrivateMessage, PrivateMessageResponse},
|
||||||
send_email_to_user,
|
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_apub::{
|
||||||
activities::{
|
activities::{
|
||||||
|
@ -15,11 +14,17 @@ use lemmy_apub::{
|
||||||
generate_apub_endpoint,
|
generate_apub_endpoint,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::private_message::{PrivateMessage, PrivateMessageForm};
|
source::private_message::{PrivateMessage, PrivateMessageForm},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_db_views::local_user_view::LocalUserView;
|
use lemmy_db_views::local_user_view::LocalUserView;
|
||||||
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{
|
||||||
|
send::{send_email_to_user, send_pm_ws_message},
|
||||||
|
LemmyContext,
|
||||||
|
UserOperationCrud,
|
||||||
|
};
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl PerformCrud for CreatePrivateMessage {
|
impl PerformCrud for CreatePrivateMessage {
|
||||||
|
@ -78,8 +83,8 @@ impl PerformCrud for CreatePrivateMessage {
|
||||||
.map_err(|e| ApiError::err("couldnt_create_private_message", e))?;
|
.map_err(|e| ApiError::err("couldnt_create_private_message", e))?;
|
||||||
|
|
||||||
CreateOrUpdatePrivateMessage::send(
|
CreateOrUpdatePrivateMessage::send(
|
||||||
&updated_private_message,
|
&updated_private_message.into(),
|
||||||
&local_user_view.person,
|
&local_user_view.person.into(),
|
||||||
CreateOrUpdateType::Create,
|
CreateOrUpdateType::Create,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,8 +9,10 @@ use lemmy_apub::activities::private_message::{
|
||||||
delete::DeletePrivateMessage as DeletePrivateMessageApub,
|
delete::DeletePrivateMessage as DeletePrivateMessageApub,
|
||||||
undo_delete::UndoDeletePrivateMessage,
|
undo_delete::UndoDeletePrivateMessage,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud, DeleteableOrRemoveable};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
source::private_message::PrivateMessage,
|
||||||
|
traits::{Crud, DeleteableOrRemoveable},
|
||||||
|
};
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
|
@ -49,13 +51,19 @@ impl PerformCrud for DeletePrivateMessage {
|
||||||
// Send the apub update
|
// Send the apub update
|
||||||
if data.deleted {
|
if data.deleted {
|
||||||
DeletePrivateMessageApub::send(
|
DeletePrivateMessageApub::send(
|
||||||
&local_user_view.person,
|
&local_user_view.person.into(),
|
||||||
&updated_private_message.blank_out_deleted_or_removed_info(),
|
&updated_private_message
|
||||||
|
.blank_out_deleted_or_removed_info()
|
||||||
|
.into(),
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
UndoDeletePrivateMessage::send(&local_user_view.person, &updated_private_message, context)
|
UndoDeletePrivateMessage::send(
|
||||||
|
&local_user_view.person.into(),
|
||||||
|
&updated_private_message.into(),
|
||||||
|
context,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
person::{GetPrivateMessages, PrivateMessagesResponse},
|
person::{GetPrivateMessages, PrivateMessagesResponse},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::DeleteableOrRemoveable;
|
use lemmy_db_schema::traits::DeleteableOrRemoveable;
|
||||||
use lemmy_db_views::private_message_view::PrivateMessageQueryBuilder;
|
use lemmy_db_views::private_message_view::PrivateMessageQueryBuilder;
|
||||||
use lemmy_utils::{ConnectionId, LemmyError};
|
use lemmy_utils::{ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
|
@ -9,8 +9,7 @@ use lemmy_apub::activities::{
|
||||||
private_message::create_or_update::CreateOrUpdatePrivateMessage,
|
private_message::create_or_update::CreateOrUpdatePrivateMessage,
|
||||||
CreateOrUpdateType,
|
CreateOrUpdateType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
|
||||||
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::remove_slurs, ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
|
||||||
|
@ -48,8 +47,8 @@ impl PerformCrud for EditPrivateMessage {
|
||||||
|
|
||||||
// Send the apub update
|
// Send the apub update
|
||||||
CreateOrUpdatePrivateMessage::send(
|
CreateOrUpdatePrivateMessage::send(
|
||||||
&updated_private_message,
|
&updated_private_message.into(),
|
||||||
&local_user_view.person,
|
&local_user_view.person.into(),
|
||||||
CreateOrUpdateType::Update,
|
CreateOrUpdateType::Update,
|
||||||
context,
|
context,
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,13 +7,12 @@ use lemmy_api_common::{
|
||||||
site::*,
|
site::*,
|
||||||
site_description_length_check,
|
site_description_length_check,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
diesel_option_overwrite_to_url,
|
diesel_option_overwrite_to_url,
|
||||||
source::site::Site_,
|
source::site::{Site, SiteForm},
|
||||||
Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::site::{Site, *};
|
|
||||||
use lemmy_db_views::site_view::SiteView;
|
use lemmy_db_views::site_view::SiteView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{check_slurs, check_slurs_opt},
|
utils::{check_slurs, check_slurs_opt},
|
||||||
|
@ -34,7 +33,7 @@ impl PerformCrud for CreateSite {
|
||||||
) -> Result<SiteResponse, LemmyError> {
|
) -> Result<SiteResponse, LemmyError> {
|
||||||
let data: &CreateSite = self;
|
let data: &CreateSite = self;
|
||||||
|
|
||||||
let read_site = move |conn: &'_ _| Site::read_simple(conn);
|
let read_site = Site::read_simple;
|
||||||
if blocking(context.pool(), read_site).await?.is_ok() {
|
if blocking(context.pool(), read_site).await?.is_ok() {
|
||||||
return Err(ApiError::err_plain("site_already_exists").into());
|
return Err(ApiError::err_plain("site_already_exists").into());
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,15 +7,12 @@ use lemmy_api_common::{
|
||||||
site::{EditSite, SiteResponse},
|
site::{EditSite, SiteResponse},
|
||||||
site_description_length_check,
|
site_description_length_check,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
diesel_option_overwrite_to_url,
|
diesel_option_overwrite_to_url,
|
||||||
source::site::Site_,
|
|
||||||
Crud,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
naive_now,
|
naive_now,
|
||||||
source::site::{Site, SiteForm},
|
source::site::{Site, SiteForm},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::site_view::SiteView;
|
use lemmy_db_views::site_view::SiteView;
|
||||||
use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{utils::check_slurs_opt, ApiError, ConnectionId, LemmyError};
|
||||||
|
@ -39,7 +36,7 @@ impl PerformCrud for EditSite {
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
let found_site = blocking(context.pool(), Site::read_simple).await??;
|
||||||
|
|
||||||
let sidebar = diesel_option_overwrite(&data.sidebar);
|
let sidebar = diesel_option_overwrite(&data.sidebar);
|
||||||
let description = diesel_option_overwrite(&data.description);
|
let description = diesel_option_overwrite(&data.description);
|
||||||
|
|
|
@ -8,23 +8,25 @@ use lemmy_apub::{
|
||||||
generate_shared_inbox_url,
|
generate_shared_inbox_url,
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
source::{local_user::LocalUser_, site::Site_},
|
newtypes::CommunityId,
|
||||||
Crud,
|
source::{
|
||||||
Followable,
|
community::{
|
||||||
Joinable,
|
Community,
|
||||||
|
CommunityFollower,
|
||||||
|
CommunityFollowerForm,
|
||||||
|
CommunityForm,
|
||||||
|
CommunityModerator,
|
||||||
|
CommunityModeratorForm,
|
||||||
|
},
|
||||||
|
local_user::{LocalUser, LocalUserForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
|
site::Site,
|
||||||
|
},
|
||||||
|
traits::{Crud, Followable, Joinable},
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
|
||||||
source::{
|
|
||||||
community::*,
|
|
||||||
local_user::{LocalUser, LocalUserForm},
|
|
||||||
person::*,
|
|
||||||
site::*,
|
|
||||||
},
|
|
||||||
CommunityId,
|
|
||||||
};
|
|
||||||
use lemmy_db_views_actor::person_view::PersonViewSafe;
|
use lemmy_db_views_actor::person_view::PersonViewSafe;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
apub::generate_actor_keypair,
|
apub::generate_actor_keypair,
|
||||||
|
@ -48,7 +50,7 @@ impl PerformCrud for Register {
|
||||||
let data: &Register = self;
|
let data: &Register = self;
|
||||||
|
|
||||||
// Make sure site has open registration
|
// Make sure site has open registration
|
||||||
if let Ok(site) = blocking(context.pool(), move |conn| Site::read_simple(conn)).await? {
|
if let Ok(site) = blocking(context.pool(), Site::read_simple).await? {
|
||||||
if !site.open_registration {
|
if !site.open_registration {
|
||||||
return Err(ApiError::err_plain("registration_closed").into());
|
return Err(ApiError::err_plain("registration_closed").into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@ use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use bcrypt::verify;
|
use bcrypt::verify;
|
||||||
use lemmy_api_common::{blocking, get_local_user_view_from_jwt, person::*};
|
use lemmy_api_common::{blocking, get_local_user_view_from_jwt, person::*};
|
||||||
use lemmy_db_queries::source::{comment::Comment_, person::Person_, post::Post_};
|
use lemmy_db_schema::source::{comment::Comment, person::Person, post::Post};
|
||||||
use lemmy_db_schema::source::{comment::Comment, person::*, post::Post};
|
|
||||||
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
use lemmy_utils::{ApiError, ConnectionId, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
use crate::PerformCrud;
|
use crate::PerformCrud;
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, person::*};
|
use lemmy_api_common::{blocking, get_local_user_view_from_jwt_opt, person::*};
|
||||||
use lemmy_apub::{build_actor_id_from_shortname, fetcher::object_id::ObjectId, EndpointType};
|
use lemmy_apub::{
|
||||||
use lemmy_db_queries::{from_opt_str_to_opt_enum, SortType};
|
build_actor_id_from_shortname,
|
||||||
use lemmy_db_schema::source::person::*;
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::person::ApubPerson,
|
||||||
|
EndpointType,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType};
|
||||||
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
|
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
|
@ -45,7 +49,7 @@ impl PerformCrud for GetPersonDetails {
|
||||||
let actor_id =
|
let actor_id =
|
||||||
build_actor_id_from_shortname(EndpointType::Person, &name, &context.settings())?;
|
build_actor_id_from_shortname(EndpointType::Person, &name, &context.settings())?;
|
||||||
|
|
||||||
let person = ObjectId::<Person>::new(actor_id)
|
let person = ObjectId::<ApubPerson>::new(actor_id)
|
||||||
.dereference(context, &mut 0)
|
.dereference(context, &mut 0)
|
||||||
.await;
|
.await;
|
||||||
person
|
person
|
||||||
|
|
|
@ -15,7 +15,6 @@ doctest = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
||||||
lemmy_apub_lib = { version = "=0.13.0", path = "../apub_lib" }
|
lemmy_apub_lib = { version = "=0.13.0", path = "../apub_lib" }
|
||||||
lemmy_db_queries = { version = "=0.13.0", path = "../db_queries" }
|
|
||||||
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
||||||
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
lemmy_db_views = { version = "=0.13.0", path = "../db_views" }
|
||||||
lemmy_db_views_actor = { version = "=0.13.0", path = "../db_views_actor" }
|
lemmy_db_views_actor = { version = "=0.13.0", path = "../db_views_actor" }
|
||||||
|
|
|
@ -11,18 +11,24 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
objects::{comment::Note, FromApub, ToApub},
|
objects::{
|
||||||
|
comment::{ApubComment, Note},
|
||||||
|
community::ApubCommunity,
|
||||||
|
person::ApubPerson,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitystreams::{base::AnyBase, link::Mention, primitives::OneOrMany, unparsed::Unparsed};
|
use activitystreams::{base::AnyBase, link::Mention, primitives::OneOrMany, unparsed::Unparsed};
|
||||||
use lemmy_api_common::{blocking, check_post_deleted_or_removed};
|
use lemmy_api_common::{blocking, check_post_deleted_or_removed};
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
data::Data,
|
data::Data,
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
source::{community::Community, post::Post},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -31,7 +37,7 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CreateOrUpdateComment {
|
pub struct CreateOrUpdateComment {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: Note,
|
object: Note,
|
||||||
cc: Vec<Url>,
|
cc: Vec<Url>,
|
||||||
|
@ -47,8 +53,8 @@ pub struct CreateOrUpdateComment {
|
||||||
|
|
||||||
impl CreateOrUpdateComment {
|
impl CreateOrUpdateComment {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
comment: &Comment,
|
comment: &ApubComment,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
kind: CreateOrUpdateType,
|
kind: CreateOrUpdateType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
@ -56,10 +62,11 @@ impl CreateOrUpdateComment {
|
||||||
let post_id = comment.post_id;
|
let post_id = comment.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
let community_id = post.community_id;
|
let community_id = post.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
kind.clone(),
|
kind.clone(),
|
||||||
|
@ -115,7 +122,7 @@ impl ActivityHandler for CreateOrUpdateComment {
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let comment =
|
let comment =
|
||||||
Comment::from_apub(&self.object, context, self.actor.inner(), request_counter).await?;
|
ApubComment::from_apub(&self.object, context, self.actor.inner(), request_counter).await?;
|
||||||
let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
|
let recipients = get_notif_recipients(&self.actor, &comment, context, request_counter).await?;
|
||||||
let notif_type = match self.kind {
|
let notif_type = match self.kind {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
|
CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
|
||||||
|
|
|
@ -1,30 +1,34 @@
|
||||||
use crate::fetcher::object_id::ObjectId;
|
use crate::{
|
||||||
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson},
|
||||||
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
base::BaseExt,
|
base::BaseExt,
|
||||||
link::{LinkExt, Mention},
|
link::{LinkExt, Mention},
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_api_common::{blocking, send_local_notifs};
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{traits::ActorType, webfinger::WebfingerResponse};
|
use lemmy_apub_lib::{traits::ActorType, webfinger::WebfingerResponse};
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{comment::Comment, community::Community, person::Person, post::Post},
|
newtypes::LocalUserId,
|
||||||
LocalUserId,
|
source::{comment::Comment, person::Person, post::Post},
|
||||||
|
traits::Crud,
|
||||||
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::{retry, RecvError},
|
request::{retry, RecvError},
|
||||||
utils::{scrape_text_for_mentions, MentionData},
|
utils::{scrape_text_for_mentions, MentionData},
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::{send::send_local_notifs, LemmyContext};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub mod create_or_update;
|
pub mod create_or_update;
|
||||||
|
|
||||||
async fn get_notif_recipients(
|
async fn get_notif_recipients(
|
||||||
actor: &ObjectId<Person>,
|
actor: &ObjectId<ApubPerson>,
|
||||||
comment: &Comment,
|
comment: &Comment,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
|
@ -39,16 +43,7 @@ async fn get_notif_recipients(
|
||||||
// anyway.
|
// anyway.
|
||||||
// TODO: for compatibility with other projects, it would be much better to read this from cc or tags
|
// TODO: for compatibility with other projects, it would be much better to read this from cc or tags
|
||||||
let mentions = scrape_text_for_mentions(&comment.content);
|
let mentions = scrape_text_for_mentions(&comment.content);
|
||||||
send_local_notifs(
|
send_local_notifs(mentions, comment, &*actor, &post, true, context).await
|
||||||
mentions,
|
|
||||||
comment.clone(),
|
|
||||||
actor,
|
|
||||||
post,
|
|
||||||
context.pool(),
|
|
||||||
true,
|
|
||||||
&context.settings(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MentionsAndAddresses {
|
pub struct MentionsAndAddresses {
|
||||||
|
@ -61,12 +56,12 @@ pub struct MentionsAndAddresses {
|
||||||
/// and mention tags, so they know where to be sent to.
|
/// and mention tags, so they know where to be sent to.
|
||||||
/// Addresses are the persons / addresses that go in the cc field.
|
/// Addresses are the persons / addresses that go in the cc field.
|
||||||
pub async fn collect_non_local_mentions(
|
pub async fn collect_non_local_mentions(
|
||||||
comment: &Comment,
|
comment: &ApubComment,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<MentionsAndAddresses, LemmyError> {
|
) -> Result<MentionsAndAddresses, LemmyError> {
|
||||||
let parent_creator = get_comment_parent_creator(context.pool(), comment).await?;
|
let parent_creator = get_comment_parent_creator(context.pool(), comment).await?;
|
||||||
let mut addressed_ccs = vec![community.actor_id(), parent_creator.actor_id()];
|
let mut addressed_ccs: Vec<Url> = vec![community.actor_id(), parent_creator.actor_id()];
|
||||||
// Note: dont include community inbox here, as we send to it separately with `send_to_community()`
|
// Note: dont include community inbox here, as we send to it separately with `send_to_community()`
|
||||||
let mut inboxes = vec![parent_creator.shared_inbox_or_inbox_url()];
|
let mut inboxes = vec![parent_creator.shared_inbox_or_inbox_url()];
|
||||||
|
|
||||||
|
@ -83,9 +78,9 @@ pub async fn collect_non_local_mentions(
|
||||||
for mention in &mentions {
|
for mention in &mentions {
|
||||||
// TODO should it be fetching it every time?
|
// TODO should it be fetching it every time?
|
||||||
if let Ok(actor_id) = fetch_webfinger_url(mention, context).await {
|
if let Ok(actor_id) = fetch_webfinger_url(mention, context).await {
|
||||||
let actor_id: ObjectId<Person> = ObjectId::new(actor_id);
|
let actor_id: ObjectId<ApubPerson> = ObjectId::new(actor_id);
|
||||||
debug!("mention actor_id: {}", actor_id);
|
debug!("mention actor_id: {}", actor_id);
|
||||||
addressed_ccs.push(actor_id.to_owned().to_string().parse()?);
|
addressed_ccs.push(actor_id.to_string().parse()?);
|
||||||
|
|
||||||
let mention_person = actor_id.dereference(context, &mut 0).await?;
|
let mention_person = actor_id.dereference(context, &mut 0).await?;
|
||||||
inboxes.push(mention_person.shared_inbox_or_inbox_url());
|
inboxes.push(mention_person.shared_inbox_or_inbox_url());
|
||||||
|
@ -112,7 +107,7 @@ pub async fn collect_non_local_mentions(
|
||||||
async fn get_comment_parent_creator(
|
async fn get_comment_parent_creator(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
comment: &Comment,
|
comment: &Comment,
|
||||||
) -> Result<Person, LemmyError> {
|
) -> Result<ApubPerson, LemmyError> {
|
||||||
let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
|
let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
|
||||||
let parent_comment =
|
let parent_comment =
|
||||||
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
|
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
|
||||||
|
@ -122,7 +117,11 @@ async fn get_comment_parent_creator(
|
||||||
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
|
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
|
||||||
parent_post.creator_id
|
parent_post.creator_id
|
||||||
};
|
};
|
||||||
Ok(blocking(pool, move |conn| Person::read(conn, parent_creator_id)).await??)
|
Ok(
|
||||||
|
blocking(pool, move |conn| Person::read(conn, parent_creator_id))
|
||||||
|
.await??
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
/// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::{
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
generate_moderators_url,
|
generate_moderators_url,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::AddType,
|
activity::kind::AddType,
|
||||||
|
@ -23,10 +24,9 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::community::CommunityModerator_, Joinable};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{CommunityModerator, CommunityModeratorForm},
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
traits::Joinable,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -36,11 +36,11 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AddMod {
|
pub struct AddMod {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: ObjectId<Person>,
|
object: ObjectId<ApubPerson>,
|
||||||
target: Url,
|
target: Url,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: AddType,
|
kind: AddType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -52,9 +52,9 @@ pub struct AddMod {
|
||||||
|
|
||||||
impl AddMod {
|
impl AddMod {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
added_mod: &Person,
|
added_mod: &ApubPerson,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
|
@ -90,7 +90,7 @@ impl ActivityHandler for AddMod {
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self, &context.settings())?;
|
verify_activity(self, &context.settings())?;
|
||||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
|
verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_add_remove_moderator_target(&self.target, &self.cc[0])?;
|
verify_add_remove_moderator_target(&self.target, &self.cc[0])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
http::is_activity_already_known,
|
http::is_activity_already_known,
|
||||||
insert_activity,
|
insert_activity,
|
||||||
|
objects::community::ApubCommunity,
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
CommunityType,
|
CommunityType,
|
||||||
};
|
};
|
||||||
|
@ -35,7 +36,6 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::community::Community;
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -62,7 +62,7 @@ pub enum AnnouncableActivities {
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AnnounceActivity {
|
pub struct AnnounceActivity {
|
||||||
actor: ObjectId<Community>,
|
actor: ObjectId<ApubCommunity>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: AnnouncableActivities,
|
object: AnnouncableActivities,
|
||||||
cc: Vec<Url>,
|
cc: Vec<Url>,
|
||||||
|
@ -78,7 +78,7 @@ pub struct AnnounceActivity {
|
||||||
impl AnnounceActivity {
|
impl AnnounceActivity {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
object: AnnouncableActivities,
|
object: AnnouncableActivities,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
additional_inboxes: Vec<Url>,
|
additional_inboxes: Vec<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::BlockType,
|
activity::kind::BlockType,
|
||||||
|
@ -21,16 +22,14 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{Bannable, Followable};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{
|
||||||
community::{
|
|
||||||
Community,
|
|
||||||
CommunityFollower,
|
CommunityFollower,
|
||||||
CommunityFollowerForm,
|
CommunityFollowerForm,
|
||||||
CommunityPersonBan,
|
CommunityPersonBan,
|
||||||
CommunityPersonBanForm,
|
CommunityPersonBanForm,
|
||||||
},
|
},
|
||||||
person::Person,
|
traits::{Bannable, Followable},
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -40,10 +39,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct BlockUserFromCommunity {
|
pub struct BlockUserFromCommunity {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
pub(in crate::activities::community) object: ObjectId<Person>,
|
pub(in crate::activities::community) object: ObjectId<ApubPerson>,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: BlockType,
|
kind: BlockType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -55,9 +54,9 @@ pub struct BlockUserFromCommunity {
|
||||||
|
|
||||||
impl BlockUserFromCommunity {
|
impl BlockUserFromCommunity {
|
||||||
pub(in crate::activities::community) fn new(
|
pub(in crate::activities::community) fn new(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
target: &Person,
|
target: &ApubPerson,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<BlockUserFromCommunity, LemmyError> {
|
) -> Result<BlockUserFromCommunity, LemmyError> {
|
||||||
Ok(BlockUserFromCommunity {
|
Ok(BlockUserFromCommunity {
|
||||||
|
@ -76,9 +75,9 @@ impl BlockUserFromCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
target: &Person,
|
target: &ApubPerson,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let block = BlockUserFromCommunity::new(community, target, actor, context)?;
|
let block = BlockUserFromCommunity::new(community, target, actor, context)?;
|
||||||
|
@ -100,7 +99,7 @@ impl ActivityHandler for BlockUserFromCommunity {
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self, &context.settings())?;
|
verify_activity(self, &context.settings())?;
|
||||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
|
verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,12 @@ use crate::{
|
||||||
activities::community::announce::{AnnouncableActivities, AnnounceActivity},
|
activities::community::announce::{AnnouncableActivities, AnnounceActivity},
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
insert_activity,
|
insert_activity,
|
||||||
|
objects::community::ApubCommunity,
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
CommunityType,
|
CommunityType,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_apub_lib::traits::ActorType;
|
use lemmy_apub_lib::traits::ActorType;
|
||||||
use lemmy_db_schema::source::community::Community;
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -20,7 +20,7 @@ pub mod undo_block_user;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
|
||||||
async fn list_community_follower_inboxes(
|
async fn list_community_follower_inboxes(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
additional_inboxes: Vec<Url>,
|
additional_inboxes: Vec<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<Vec<Url>, LemmyError> {
|
) -> Result<Vec<Url>, LemmyError> {
|
||||||
|
@ -45,7 +45,7 @@ pub(crate) async fn send_to_community<T: ActorType>(
|
||||||
activity: AnnouncableActivities,
|
activity: AnnouncableActivities,
|
||||||
activity_id: &Url,
|
activity_id: &Url,
|
||||||
actor: &T,
|
actor: &T,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
additional_inboxes: Vec<Url>,
|
additional_inboxes: Vec<Url>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::{
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
generate_moderators_url,
|
generate_moderators_url,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::RemoveType,
|
activity::kind::RemoveType,
|
||||||
|
@ -24,10 +25,9 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Joinable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{CommunityModerator, CommunityModeratorForm},
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
traits::Joinable,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -37,10 +37,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RemoveMod {
|
pub struct RemoveMod {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
pub(in crate::activities) object: ObjectId<Person>,
|
pub(in crate::activities) object: ObjectId<ApubPerson>,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: RemoveType,
|
kind: RemoveType,
|
||||||
// if target is set, this is means remove mod from community
|
// if target is set, this is means remove mod from community
|
||||||
|
@ -54,9 +54,9 @@ pub struct RemoveMod {
|
||||||
|
|
||||||
impl RemoveMod {
|
impl RemoveMod {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
removed_mod: &Person,
|
removed_mod: &ApubPerson,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
|
@ -92,7 +92,7 @@ impl ActivityHandler for RemoveMod {
|
||||||
verify_activity(self, &context.settings())?;
|
verify_activity(self, &context.settings())?;
|
||||||
if let Some(target) = &self.target {
|
if let Some(target) = &self.target {
|
||||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
|
verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_add_remove_moderator_target(target, &self.cc[0])?;
|
verify_add_remove_moderator_target(target, &self.cc[0])?;
|
||||||
} else {
|
} else {
|
||||||
verify_delete_activity(
|
verify_delete_activity(
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::UndoType,
|
activity::kind::UndoType,
|
||||||
|
@ -25,10 +26,9 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Bannable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{CommunityPersonBan, CommunityPersonBanForm},
|
||||||
community::{Community, CommunityPersonBan, CommunityPersonBanForm},
|
traits::Bannable,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -38,10 +38,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoBlockUserFromCommunity {
|
pub struct UndoBlockUserFromCommunity {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: BlockUserFromCommunity,
|
object: BlockUserFromCommunity,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -53,9 +53,9 @@ pub struct UndoBlockUserFromCommunity {
|
||||||
|
|
||||||
impl UndoBlockUserFromCommunity {
|
impl UndoBlockUserFromCommunity {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
target: &Person,
|
target: &ApubPerson,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let block = BlockUserFromCommunity::new(community, target, actor, context)?;
|
let block = BlockUserFromCommunity::new(community, target, actor, context)?;
|
||||||
|
@ -91,7 +91,7 @@ impl ActivityHandler for UndoBlockUserFromCommunity {
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self, &context.settings())?;
|
verify_activity(self, &context.settings())?;
|
||||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
|
verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
self.object.verify(context, request_counter).await?;
|
self.object.verify(context, request_counter).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
objects::{community::Group, ToApub},
|
objects::{
|
||||||
|
community::{ApubCommunity, Group},
|
||||||
|
person::ApubPerson,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::UpdateType,
|
activity::kind::UpdateType,
|
||||||
|
@ -19,13 +22,12 @@ use activitystreams::{
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
data::Data,
|
data::Data,
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType, ToApub},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{Community, CommunityForm},
|
||||||
community::{Community, CommunityForm},
|
traits::Crud,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
|
||||||
|
@ -37,11 +39,11 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UpdateCommunity {
|
pub struct UpdateCommunity {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
// TODO: would be nice to use a separate struct here, which only contains the fields updated here
|
// TODO: would be nice to use a separate struct here, which only contains the fields updated here
|
||||||
object: Group,
|
object: Group,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UpdateType,
|
kind: UpdateType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -53,8 +55,8 @@ pub struct UpdateCommunity {
|
||||||
|
|
||||||
impl UpdateCommunity {
|
impl UpdateCommunity {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
|
@ -87,7 +89,7 @@ impl ActivityHandler for UpdateCommunity {
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
verify_activity(self, &context.settings())?;
|
verify_activity(self, &context.settings())?;
|
||||||
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
verify_person_in_community(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
|
verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::DeleteType,
|
activity::kind::DeleteType,
|
||||||
|
@ -26,11 +27,8 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
source::{comment::Comment_, community::Community_, post::Post_},
|
source::{
|
||||||
Crud,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
community::Community,
|
community::Community,
|
||||||
moderator::{
|
moderator::{
|
||||||
|
@ -41,8 +39,9 @@ use lemmy_db_schema::source::{
|
||||||
ModRemovePost,
|
ModRemovePost,
|
||||||
ModRemovePostForm,
|
ModRemovePostForm,
|
||||||
},
|
},
|
||||||
person::Person,
|
|
||||||
post::Post,
|
post::Post,
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{
|
use lemmy_websocket::{
|
||||||
|
@ -66,10 +65,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Delete {
|
pub struct Delete {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
pub(in crate::activities::deletion) object: Url,
|
pub(in crate::activities::deletion) object: Url,
|
||||||
pub(in crate::activities::deletion) cc: [ObjectId<Community>; 1],
|
pub(in crate::activities::deletion) cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: DeleteType,
|
kind: DeleteType,
|
||||||
/// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
|
/// If summary is present, this is a mod action (Remove in Lemmy terms). Otherwise, its a user
|
||||||
|
@ -137,8 +136,8 @@ impl ActivityHandler for Delete {
|
||||||
|
|
||||||
impl Delete {
|
impl Delete {
|
||||||
pub(in crate::activities::deletion) fn new(
|
pub(in crate::activities::deletion) fn new(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
summary: Option<String>,
|
summary: Option<String>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -159,8 +158,8 @@ impl Delete {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub(in crate::activities::deletion) async fn send(
|
pub(in crate::activities::deletion) async fn send(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
summary: Option<String>,
|
summary: Option<String>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -174,7 +173,7 @@ impl Delete {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in crate::activities) async fn receive_remove_action(
|
pub(in crate::activities) async fn receive_remove_action(
|
||||||
actor: &ObjectId<Person>,
|
actor: &ObjectId<ApubPerson>,
|
||||||
object: &Url,
|
object: &Url,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
|
|
@ -5,15 +5,14 @@ use crate::{
|
||||||
verify_person_in_community,
|
verify_person_in_community,
|
||||||
},
|
},
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
||||||
};
|
};
|
||||||
use diesel::PgConnection;
|
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActorType, ApubObject},
|
traits::{ActivityFields, ActorType, ApubObject},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};
|
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{
|
use lemmy_websocket::{
|
||||||
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||||
|
@ -26,8 +25,8 @@ pub mod delete;
|
||||||
pub mod undo_delete;
|
pub mod undo_delete;
|
||||||
|
|
||||||
pub async fn send_apub_delete(
|
pub async fn send_apub_delete(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
deleted: bool,
|
deleted: bool,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -42,8 +41,8 @@ pub async fn send_apub_delete(
|
||||||
// TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
|
// TODO: remove reason is actually optional in lemmy. we set an empty string in that case, but its
|
||||||
// ugly
|
// ugly
|
||||||
pub async fn send_apub_remove(
|
pub async fn send_apub_remove(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
reason: String,
|
reason: String,
|
||||||
removed: bool,
|
removed: bool,
|
||||||
|
@ -57,9 +56,9 @@ pub async fn send_apub_remove(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DeletableObjects {
|
pub enum DeletableObjects {
|
||||||
Community(Box<Community>),
|
Community(Box<ApubCommunity>),
|
||||||
Comment(Box<Comment>),
|
Comment(Box<ApubComment>),
|
||||||
Post(Box<Post>),
|
Post(Box<ApubPost>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeletableObjects {
|
impl DeletableObjects {
|
||||||
|
@ -67,39 +66,23 @@ impl DeletableObjects {
|
||||||
ap_id: &Url,
|
ap_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<DeletableObjects, LemmyError> {
|
) -> Result<DeletableObjects, LemmyError> {
|
||||||
if let Some(c) =
|
if let Some(c) = ApubCommunity::read_from_apub_id(ap_id.clone(), context).await? {
|
||||||
DeletableObjects::read_type_from_db::<Community>(ap_id.clone(), context).await?
|
|
||||||
{
|
|
||||||
return Ok(DeletableObjects::Community(Box::new(c)));
|
return Ok(DeletableObjects::Community(Box::new(c)));
|
||||||
}
|
}
|
||||||
if let Some(p) = DeletableObjects::read_type_from_db::<Post>(ap_id.clone(), context).await? {
|
if let Some(p) = ApubPost::read_from_apub_id(ap_id.clone(), context).await? {
|
||||||
return Ok(DeletableObjects::Post(Box::new(p)));
|
return Ok(DeletableObjects::Post(Box::new(p)));
|
||||||
}
|
}
|
||||||
if let Some(c) = DeletableObjects::read_type_from_db::<Comment>(ap_id.clone(), context).await? {
|
if let Some(c) = ApubComment::read_from_apub_id(ap_id.clone(), context).await? {
|
||||||
return Ok(DeletableObjects::Comment(Box::new(c)));
|
return Ok(DeletableObjects::Comment(Box::new(c)));
|
||||||
}
|
}
|
||||||
Err(diesel::NotFound.into())
|
Err(diesel::NotFound.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: a method like this should be provided by fetcher module
|
|
||||||
async fn read_type_from_db<Type>(
|
|
||||||
ap_id: Url,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<Option<Type>, LemmyError>
|
|
||||||
where
|
|
||||||
Type: ApubObject<DataType = PgConnection> + Send + 'static,
|
|
||||||
{
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
Type::read_from_apub_id(conn, ap_id)
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in crate::activities) async fn verify_delete_activity(
|
pub(in crate::activities) async fn verify_delete_activity(
|
||||||
object: &Url,
|
object: &Url,
|
||||||
activity: &dyn ActivityFields,
|
activity: &dyn ActivityFields,
|
||||||
community_id: &ObjectId<Community>,
|
community_id: &ObjectId<ApubCommunity>,
|
||||||
is_mod_action: bool,
|
is_mod_action: bool,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
|
@ -116,7 +99,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
||||||
// community deletion is always a mod (or admin) action
|
// community deletion is always a mod (or admin) action
|
||||||
verify_mod_action(
|
verify_mod_action(
|
||||||
&actor,
|
&actor,
|
||||||
ObjectId::new(c.actor_id()),
|
&ObjectId::new(c.actor_id()),
|
||||||
context,
|
context,
|
||||||
request_counter,
|
request_counter,
|
||||||
)
|
)
|
||||||
|
@ -125,7 +108,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
||||||
DeletableObjects::Post(p) => {
|
DeletableObjects::Post(p) => {
|
||||||
verify_delete_activity_post_or_comment(
|
verify_delete_activity_post_or_comment(
|
||||||
activity,
|
activity,
|
||||||
&p.ap_id.into(),
|
&p.ap_id.clone().into(),
|
||||||
community_id,
|
community_id,
|
||||||
is_mod_action,
|
is_mod_action,
|
||||||
context,
|
context,
|
||||||
|
@ -136,7 +119,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
||||||
DeletableObjects::Comment(c) => {
|
DeletableObjects::Comment(c) => {
|
||||||
verify_delete_activity_post_or_comment(
|
verify_delete_activity_post_or_comment(
|
||||||
activity,
|
activity,
|
||||||
&c.ap_id.into(),
|
&c.ap_id.clone().into(),
|
||||||
community_id,
|
community_id,
|
||||||
is_mod_action,
|
is_mod_action,
|
||||||
context,
|
context,
|
||||||
|
@ -151,7 +134,7 @@ pub(in crate::activities) async fn verify_delete_activity(
|
||||||
async fn verify_delete_activity_post_or_comment(
|
async fn verify_delete_activity_post_or_comment(
|
||||||
activity: &dyn ActivityFields,
|
activity: &dyn ActivityFields,
|
||||||
object_id: &Url,
|
object_id: &Url,
|
||||||
community_id: &ObjectId<Community>,
|
community_id: &ObjectId<ApubCommunity>,
|
||||||
is_mod_action: bool,
|
is_mod_action: bool,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
|
@ -159,7 +142,7 @@ async fn verify_delete_activity_post_or_comment(
|
||||||
let actor = ObjectId::new(activity.actor().clone());
|
let actor = ObjectId::new(activity.actor().clone());
|
||||||
verify_person_in_community(&actor, community_id, context, request_counter).await?;
|
verify_person_in_community(&actor, community_id, context, request_counter).await?;
|
||||||
if is_mod_action {
|
if is_mod_action {
|
||||||
verify_mod_action(&actor, community_id.clone(), context, request_counter).await?;
|
verify_mod_action(&actor, community_id, context, request_counter).await?;
|
||||||
} else {
|
} else {
|
||||||
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
|
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
|
||||||
verify_domains_match(activity.actor(), object_id)?;
|
verify_domains_match(activity.actor(), object_id)?;
|
||||||
|
@ -178,7 +161,7 @@ struct WebsocketMessages {
|
||||||
/// because of the mod log
|
/// because of the mod log
|
||||||
async fn receive_delete_action(
|
async fn receive_delete_action(
|
||||||
object: &Url,
|
object: &Url,
|
||||||
actor: &ObjectId<Person>,
|
actor: &ObjectId<ApubPerson>,
|
||||||
ws_messages: WebsocketMessages,
|
ws_messages: WebsocketMessages,
|
||||||
deleted: bool,
|
deleted: bool,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::UndoType,
|
activity::kind::UndoType,
|
||||||
|
@ -27,8 +28,7 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::source::{comment::Comment_, community::Community_, post::Post_};
|
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{
|
use lemmy_websocket::{
|
||||||
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
send::{send_comment_ws_message_simple, send_community_ws_message, send_post_ws_message},
|
||||||
|
@ -41,10 +41,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoDelete {
|
pub struct UndoDelete {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: Delete,
|
object: Delete,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -103,8 +103,8 @@ impl ActivityHandler for UndoDelete {
|
||||||
|
|
||||||
impl UndoDelete {
|
impl UndoDelete {
|
||||||
pub(in crate::activities::deletion) async fn send(
|
pub(in crate::activities::deletion) async fn send(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
object_id: Url,
|
object_id: Url,
|
||||||
summary: Option<String>,
|
summary: Option<String>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -21,11 +22,7 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
verify::verify_urls_match,
|
verify::verify_urls_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Followable;
|
use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
community::{Community, CommunityFollower},
|
|
||||||
person::Person,
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -34,8 +31,8 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AcceptFollowCommunity {
|
pub struct AcceptFollowCommunity {
|
||||||
actor: ObjectId<Community>,
|
actor: ObjectId<ApubCommunity>,
|
||||||
to: ObjectId<Person>,
|
to: ObjectId<ApubPerson>,
|
||||||
object: FollowCommunity,
|
object: FollowCommunity,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: AcceptType,
|
kind: AcceptType,
|
||||||
|
@ -70,7 +67,7 @@ impl AcceptFollowCommunity {
|
||||||
context: lemmy_context(),
|
context: lemmy_context(),
|
||||||
unparsed: Default::default(),
|
unparsed: Default::default(),
|
||||||
};
|
};
|
||||||
let inbox = vec![person.inbox_url.into()];
|
let inbox = vec![person.inbox_url()];
|
||||||
send_lemmy_activity(context, &accept, &accept.id, &community, inbox, true).await
|
send_lemmy_activity(context, &accept, &accept.id, &community, inbox, true).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -21,10 +22,9 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
verify::verify_urls_match,
|
verify::verify_urls_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Followable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{CommunityFollower, CommunityFollowerForm},
|
||||||
community::{Community, CommunityFollower, CommunityFollowerForm},
|
traits::Followable,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -34,10 +34,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct FollowCommunity {
|
pub struct FollowCommunity {
|
||||||
pub(in crate::activities::following) actor: ObjectId<Person>,
|
pub(in crate::activities::following) actor: ObjectId<ApubPerson>,
|
||||||
// TODO: is there any reason to put the same community id twice, in to and object?
|
// TODO: is there any reason to put the same community id twice, in to and object?
|
||||||
pub(in crate::activities::following) to: ObjectId<Community>,
|
pub(in crate::activities::following) to: ObjectId<ApubCommunity>,
|
||||||
pub(in crate::activities::following) object: ObjectId<Community>,
|
pub(in crate::activities::following) object: ObjectId<ApubCommunity>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: FollowType,
|
kind: FollowType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -49,8 +49,8 @@ pub struct FollowCommunity {
|
||||||
|
|
||||||
impl FollowCommunity {
|
impl FollowCommunity {
|
||||||
pub(in crate::activities::following) fn new(
|
pub(in crate::activities::following) fn new(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<FollowCommunity, LemmyError> {
|
) -> Result<FollowCommunity, LemmyError> {
|
||||||
Ok(FollowCommunity {
|
Ok(FollowCommunity {
|
||||||
|
@ -67,8 +67,8 @@ impl FollowCommunity {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -21,10 +22,9 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
verify::verify_urls_match,
|
verify::verify_urls_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Followable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{CommunityFollower, CommunityFollowerForm},
|
||||||
community::{Community, CommunityFollower, CommunityFollowerForm},
|
traits::Followable,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -34,8 +34,8 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoFollowCommunity {
|
pub struct UndoFollowCommunity {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: ObjectId<Community>,
|
to: ObjectId<ApubCommunity>,
|
||||||
object: FollowCommunity,
|
object: FollowCommunity,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
|
@ -48,8 +48,8 @@ pub struct UndoFollowCommunity {
|
||||||
|
|
||||||
impl UndoFollowCommunity {
|
impl UndoFollowCommunity {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let object = FollowCommunity::new(actor, community, context)?;
|
let object = FollowCommunity::new(actor, community, context)?;
|
||||||
|
|
|
@ -3,15 +3,17 @@ use crate::{
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
generate_moderators_url,
|
generate_moderators_url,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{traits::ActivityFields, verify::verify_domains_match};
|
use lemmy_apub_lib::{traits::ActivityFields, verify::verify_domains_match};
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person};
|
use lemmy_db_schema::source::community::Community;
|
||||||
use lemmy_db_views_actor::community_view::CommunityView;
|
use lemmy_db_views_actor::community_view::CommunityView;
|
||||||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::ops::Deref;
|
||||||
use strum_macros::ToString;
|
use strum_macros::ToString;
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -35,7 +37,7 @@ pub enum CreateOrUpdateType {
|
||||||
/// Checks that the specified Url actually identifies a Person (by fetching it), and that the person
|
/// Checks that the specified Url actually identifies a Person (by fetching it), and that the person
|
||||||
/// doesn't have a site ban.
|
/// doesn't have a site ban.
|
||||||
async fn verify_person(
|
async fn verify_person(
|
||||||
person_id: &ObjectId<Person>,
|
person_id: &ObjectId<ApubPerson>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
@ -50,7 +52,7 @@ pub(crate) async fn extract_community(
|
||||||
cc: &[Url],
|
cc: &[Url],
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Community, LemmyError> {
|
) -> Result<ApubCommunity, LemmyError> {
|
||||||
let mut cc_iter = cc.iter();
|
let mut cc_iter = cc.iter();
|
||||||
loop {
|
loop {
|
||||||
if let Some(cid) = cc_iter.next() {
|
if let Some(cid) = cc_iter.next() {
|
||||||
|
@ -67,19 +69,19 @@ pub(crate) async fn extract_community(
|
||||||
/// Fetches the person and community to verify their type, then checks if person is banned from site
|
/// Fetches the person and community to verify their type, then checks if person is banned from site
|
||||||
/// or community.
|
/// or community.
|
||||||
pub(crate) async fn verify_person_in_community(
|
pub(crate) async fn verify_person_in_community(
|
||||||
person_id: &ObjectId<Person>,
|
person_id: &ObjectId<ApubPerson>,
|
||||||
community_id: &ObjectId<Community>,
|
community_id: &ObjectId<ApubCommunity>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community = community_id.dereference(context, request_counter).await?;
|
let community = community_id.dereference(context, request_counter).await?;
|
||||||
let person = person_id.dereference(context, request_counter).await?;
|
let person = person_id.dereference(context, request_counter).await?;
|
||||||
check_community_or_site_ban(&person, community.id, context.pool()).await
|
check_community_or_site_ban(person.deref(), community.id, context.pool()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simply check that the url actually refers to a valid group.
|
/// Simply check that the url actually refers to a valid group.
|
||||||
async fn verify_community(
|
async fn verify_community(
|
||||||
community_id: &ObjectId<Community>,
|
community_id: &ObjectId<ApubCommunity>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
@ -97,8 +99,8 @@ fn verify_activity(activity: &dyn ActivityFields, settings: &Settings) -> Result
|
||||||
/// because in case of remote communities, admins can also perform mod actions. As admin status
|
/// because in case of remote communities, admins can also perform mod actions. As admin status
|
||||||
/// is not federated, we cant verify their actions remotely.
|
/// is not federated, we cant verify their actions remotely.
|
||||||
pub(crate) async fn verify_mod_action(
|
pub(crate) async fn verify_mod_action(
|
||||||
actor_id: &ObjectId<Person>,
|
actor_id: &ObjectId<ApubPerson>,
|
||||||
community_id: ObjectId<Community>,
|
community_id: &ObjectId<ApubCommunity>,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
@ -126,7 +128,7 @@ pub(crate) async fn verify_mod_action(
|
||||||
/// /c/community/moderators. Any different values are unsupported.
|
/// /c/community/moderators. Any different values are unsupported.
|
||||||
fn verify_add_remove_moderator_target(
|
fn verify_add_remove_moderator_target(
|
||||||
target: &Url,
|
target: &Url,
|
||||||
community: &ObjectId<Community>,
|
community: &ObjectId<ApubCommunity>,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
if target != &generate_moderators_url(&community.clone().into())?.into_inner() {
|
if target != &generate_moderators_url(&community.clone().into())?.into_inner() {
|
||||||
return Err(anyhow!("Unkown target url").into());
|
return Err(anyhow!("Unkown target url").into());
|
||||||
|
|
|
@ -10,19 +10,22 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
objects::{post::Page, FromApub, ToApub},
|
objects::{
|
||||||
|
community::ApubCommunity,
|
||||||
|
person::ApubPerson,
|
||||||
|
post::{ApubPost, Page},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
|
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
data::Data,
|
data::Data,
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
verify::{verify_domains_match, verify_urls_match},
|
verify::{verify_domains_match, verify_urls_match},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_schema::{source::community::Community, traits::Crud};
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -31,10 +34,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CreateOrUpdatePost {
|
pub struct CreateOrUpdatePost {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: Page,
|
object: Page,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: CreateOrUpdateType,
|
kind: CreateOrUpdateType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -46,16 +49,17 @@ pub struct CreateOrUpdatePost {
|
||||||
|
|
||||||
impl CreateOrUpdatePost {
|
impl CreateOrUpdatePost {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
post: &Post,
|
post: &ApubPost,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
kind: CreateOrUpdateType,
|
kind: CreateOrUpdateType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community_id = post.community_id;
|
let community_id = post.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
kind.clone(),
|
kind.clone(),
|
||||||
|
@ -107,7 +111,7 @@ impl ActivityHandler for CreateOrUpdatePost {
|
||||||
CreateOrUpdateType::Update => {
|
CreateOrUpdateType::Update => {
|
||||||
let is_mod_action = self.object.is_mod_action(context).await?;
|
let is_mod_action = self.object.is_mod_action(context).await?;
|
||||||
if is_mod_action {
|
if is_mod_action {
|
||||||
verify_mod_action(&self.actor, self.cc[0].clone(), context, request_counter).await?;
|
verify_mod_action(&self.actor, &self.cc[0], context, request_counter).await?;
|
||||||
} else {
|
} else {
|
||||||
verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
|
verify_domains_match(self.actor.inner(), self.object.id_unchecked())?;
|
||||||
verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
|
verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
|
||||||
|
@ -124,7 +128,8 @@ impl ActivityHandler for CreateOrUpdatePost {
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let actor = self.actor.dereference(context, request_counter).await?;
|
let actor = self.actor.dereference(context, request_counter).await?;
|
||||||
let post = Post::from_apub(&self.object, context, &actor.actor_id(), request_counter).await?;
|
let post =
|
||||||
|
ApubPost::from_apub(&self.object, context, &actor.actor_id(), request_counter).await?;
|
||||||
|
|
||||||
let notif_type = match self.kind {
|
let notif_type = match self.kind {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
|
CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
|
||||||
|
|
|
@ -2,18 +2,20 @@ use crate::{
|
||||||
activities::{generate_activity_id, verify_activity, verify_person, CreateOrUpdateType},
|
activities::{generate_activity_id, verify_activity, verify_person, CreateOrUpdateType},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
objects::{private_message::Note, FromApub, ToApub},
|
objects::{
|
||||||
|
person::ApubPerson,
|
||||||
|
private_message::{ApubPrivateMessage, Note},
|
||||||
|
},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
};
|
};
|
||||||
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
|
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
data::Data,
|
data::Data,
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType, FromApub, ToApub},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_schema::{source::person::Person, traits::Crud};
|
||||||
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -25,8 +27,8 @@ pub struct CreateOrUpdatePrivateMessage {
|
||||||
#[serde(rename = "@context")]
|
#[serde(rename = "@context")]
|
||||||
pub context: OneOrMany<AnyBase>,
|
pub context: OneOrMany<AnyBase>,
|
||||||
id: Url,
|
id: Url,
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: ObjectId<Person>,
|
to: ObjectId<ApubPerson>,
|
||||||
object: Note,
|
object: Note,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: CreateOrUpdateType,
|
kind: CreateOrUpdateType,
|
||||||
|
@ -36,14 +38,16 @@ pub struct CreateOrUpdatePrivateMessage {
|
||||||
|
|
||||||
impl CreateOrUpdatePrivateMessage {
|
impl CreateOrUpdatePrivateMessage {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
private_message: &PrivateMessage,
|
private_message: &ApubPrivateMessage,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
kind: CreateOrUpdateType,
|
kind: CreateOrUpdateType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let recipient_id = private_message.recipient_id;
|
let recipient_id = private_message.recipient_id;
|
||||||
let recipient =
|
let recipient: ApubPerson =
|
||||||
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
|
||||||
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
kind.clone(),
|
kind.clone(),
|
||||||
|
@ -83,7 +87,8 @@ impl ActivityHandler for CreateOrUpdatePrivateMessage {
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let private_message =
|
let private_message =
|
||||||
PrivateMessage::from_apub(&self.object, context, self.actor.inner(), request_counter).await?;
|
ApubPrivateMessage::from_apub(&self.object, context, self.actor.inner(), request_counter)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let notif_type = match self.kind {
|
let notif_type = match self.kind {
|
||||||
CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
|
CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
||||||
activities::{generate_activity_id, verify_activity, verify_person},
|
activities::{generate_activity_id, verify_activity, verify_person},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{person::ApubPerson, private_message::ApubPrivateMessage},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -16,8 +17,10 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
source::{person::Person, private_message::PrivateMessage},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -26,9 +29,9 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct DeletePrivateMessage {
|
pub struct DeletePrivateMessage {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: ObjectId<Person>,
|
to: ObjectId<ApubPerson>,
|
||||||
pub(in crate::activities::private_message) object: ObjectId<PrivateMessage>,
|
pub(in crate::activities::private_message) object: ObjectId<ApubPrivateMessage>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: DeleteType,
|
kind: DeleteType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -40,7 +43,7 @@ pub struct DeletePrivateMessage {
|
||||||
|
|
||||||
impl DeletePrivateMessage {
|
impl DeletePrivateMessage {
|
||||||
pub(in crate::activities::private_message) fn new(
|
pub(in crate::activities::private_message) fn new(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
pm: &PrivateMessage,
|
pm: &PrivateMessage,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<DeletePrivateMessage, LemmyError> {
|
) -> Result<DeletePrivateMessage, LemmyError> {
|
||||||
|
@ -58,16 +61,18 @@ impl DeletePrivateMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
pm: &PrivateMessage,
|
pm: &ApubPrivateMessage,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let delete = DeletePrivateMessage::new(actor, pm, context)?;
|
let delete = DeletePrivateMessage::new(actor, pm, context)?;
|
||||||
let delete_id = delete.id.clone();
|
let delete_id = delete.id.clone();
|
||||||
|
|
||||||
let recipient_id = pm.recipient_id;
|
let recipient_id = pm.recipient_id;
|
||||||
let recipient =
|
let recipient: ApubPerson =
|
||||||
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
|
||||||
|
.await??
|
||||||
|
.into();
|
||||||
let inbox = vec![recipient.shared_inbox_or_inbox_url()];
|
let inbox = vec![recipient.shared_inbox_or_inbox_url()];
|
||||||
send_lemmy_activity(context, &delete, &delete_id, actor, inbox, true).await
|
send_lemmy_activity(context, &delete, &delete_id, actor, inbox, true).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{person::ApubPerson, private_message::ApubPrivateMessage},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -21,8 +22,10 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
verify::{verify_domains_match, verify_urls_match},
|
verify::{verify_domains_match, verify_urls_match},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
source::{person::Person, private_message::PrivateMessage},
|
||||||
|
traits::Crud,
|
||||||
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -31,8 +34,8 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoDeletePrivateMessage {
|
pub struct UndoDeletePrivateMessage {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: ObjectId<Person>,
|
to: ObjectId<ApubPerson>,
|
||||||
object: DeletePrivateMessage,
|
object: DeletePrivateMessage,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
|
@ -45,13 +48,15 @@ pub struct UndoDeletePrivateMessage {
|
||||||
|
|
||||||
impl UndoDeletePrivateMessage {
|
impl UndoDeletePrivateMessage {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
pm: &PrivateMessage,
|
pm: &ApubPrivateMessage,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let recipient_id = pm.recipient_id;
|
let recipient_id = pm.recipient_id;
|
||||||
let recipient =
|
let recipient: ApubPerson =
|
||||||
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
|
||||||
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
let object = DeletePrivateMessage::new(actor, pm, context)?;
|
let object = DeletePrivateMessage::new(actor, pm, context)?;
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
||||||
activities::{generate_activity_id, verify_activity, verify_person_in_community},
|
activities::{generate_activity_id, verify_activity, verify_person_in_community},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
send_lemmy_activity,
|
send_lemmy_activity,
|
||||||
PostOrComment,
|
PostOrComment,
|
||||||
};
|
};
|
||||||
|
@ -16,15 +17,12 @@ use lemmy_apub_lib::{
|
||||||
data::Data,
|
data::Data,
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{Crud, Reportable};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment_report::{CommentReport, CommentReportForm},
|
comment_report::{CommentReport, CommentReportForm},
|
||||||
community::Community,
|
|
||||||
person::Person,
|
|
||||||
post_report::{PostReport, PostReportForm},
|
post_report::{PostReport, PostReportForm},
|
||||||
},
|
},
|
||||||
CommunityId,
|
traits::Reportable,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::PostReportView};
|
use lemmy_db_views::{comment_report_view::CommentReportView, post_report_view::PostReportView};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
|
@ -35,8 +33,8 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Report {
|
pub struct Report {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [ObjectId<Community>; 1],
|
to: [ObjectId<ApubCommunity>; 1],
|
||||||
object: ObjectId<PostOrComment>,
|
object: ObjectId<PostOrComment>,
|
||||||
summary: String,
|
summary: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
|
@ -51,15 +49,12 @@ pub struct Report {
|
||||||
impl Report {
|
impl Report {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
object_id: ObjectId<PostOrComment>,
|
object_id: ObjectId<PostOrComment>,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community_id: CommunityId,
|
community_id: ObjectId<ApubCommunity>,
|
||||||
reason: String,
|
reason: String,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = community_id.dereference_local(context).await?;
|
||||||
Community::read(conn, community_id)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
let kind = FlagType::Flag;
|
let kind = FlagType::Flag;
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
kind.clone(),
|
kind.clone(),
|
||||||
|
@ -111,10 +106,10 @@ impl ActivityHandler for Report {
|
||||||
let report_form = PostReportForm {
|
let report_form = PostReportForm {
|
||||||
creator_id: actor.id,
|
creator_id: actor.id,
|
||||||
post_id: post.id,
|
post_id: post.id,
|
||||||
original_post_name: post.name,
|
original_post_name: post.name.clone(),
|
||||||
original_post_url: post.url,
|
original_post_url: post.url.clone(),
|
||||||
reason: self.summary,
|
reason: self.summary,
|
||||||
original_post_body: post.body,
|
original_post_body: post.body.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = blocking(context.pool(), move |conn| {
|
let report = blocking(context.pool(), move |conn| {
|
||||||
|
@ -138,7 +133,7 @@ impl ActivityHandler for Report {
|
||||||
let report_form = CommentReportForm {
|
let report_form = CommentReportForm {
|
||||||
creator_id: actor.id,
|
creator_id: actor.id,
|
||||||
comment_id: comment.id,
|
comment_id: comment.id,
|
||||||
original_comment_text: comment.content,
|
original_comment_text: comment.content.clone(),
|
||||||
reason: self.summary,
|
reason: self.summary,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::{
|
||||||
verify_activity,
|
verify_activity,
|
||||||
},
|
},
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::kind::UndoType,
|
activity::kind::UndoType,
|
||||||
|
@ -17,7 +18,6 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler},
|
traits::{ActivityFields, ActivityHandler},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -26,11 +26,11 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoRemovePostCommentOrCommunity {
|
pub struct UndoRemovePostCommentOrCommunity {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
// Note, there is no such thing as Undo/Remove/Mod, so we ignore that
|
// Note, there is no such thing as Undo/Remove/Mod, so we ignore that
|
||||||
object: RemoveMod,
|
object: RemoveMod,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
use crate::activities::voting::vote::VoteType;
|
use crate::{
|
||||||
|
activities::voting::vote::VoteType,
|
||||||
|
objects::{comment::ApubComment, person::ApubPerson, post::ApubPost},
|
||||||
|
};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_db_queries::Likeable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::{
|
||||||
comment::{Comment, CommentLike, CommentLikeForm},
|
comment::{CommentLike, CommentLikeForm},
|
||||||
person::Person,
|
post::{PostLike, PostLikeForm},
|
||||||
post::{Post, PostLike, PostLikeForm},
|
},
|
||||||
|
traits::Likeable,
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::{
|
use lemmy_websocket::{
|
||||||
|
@ -18,8 +22,8 @@ pub mod vote;
|
||||||
|
|
||||||
async fn vote_comment(
|
async fn vote_comment(
|
||||||
vote_type: &VoteType,
|
vote_type: &VoteType,
|
||||||
actor: Person,
|
actor: ApubPerson,
|
||||||
comment: &Comment,
|
comment: &ApubComment,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
|
@ -42,8 +46,8 @@ async fn vote_comment(
|
||||||
|
|
||||||
async fn vote_post(
|
async fn vote_post(
|
||||||
vote_type: &VoteType,
|
vote_type: &VoteType,
|
||||||
actor: Person,
|
actor: ApubPerson,
|
||||||
post: &Post,
|
post: &ApubPost,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
|
@ -64,8 +68,8 @@ async fn vote_post(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn undo_vote_comment(
|
async fn undo_vote_comment(
|
||||||
actor: Person,
|
actor: ApubPerson,
|
||||||
comment: &Comment,
|
comment: &ApubComment,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
|
@ -80,8 +84,8 @@ async fn undo_vote_comment(
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn undo_vote_post(
|
async fn undo_vote_post(
|
||||||
actor: Person,
|
actor: ApubPerson,
|
||||||
post: &Post,
|
post: &ApubPost,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
PostOrComment,
|
PostOrComment,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -27,11 +28,7 @@ use lemmy_apub_lib::{
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
verify::verify_urls_match,
|
verify::verify_urls_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
|
||||||
use lemmy_db_schema::{
|
|
||||||
source::{community::Community, person::Person},
|
|
||||||
CommunityId,
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -41,10 +38,10 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UndoVote {
|
pub struct UndoVote {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
object: Vote,
|
object: Vote,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
kind: UndoType,
|
kind: UndoType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -57,15 +54,16 @@ pub struct UndoVote {
|
||||||
impl UndoVote {
|
impl UndoVote {
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
object: &PostOrComment,
|
object: &PostOrComment,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community_id: CommunityId,
|
community_id: CommunityId,
|
||||||
kind: VoteType,
|
kind: VoteType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
let object = Vote::new(object, actor, &community, kind.clone(), context)?;
|
let object = Vote::new(object, actor, &community, kind.clone(), context)?;
|
||||||
let id = generate_activity_id(
|
let id = generate_activity_id(
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
PostOrComment,
|
PostOrComment,
|
||||||
};
|
};
|
||||||
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
|
use activitystreams::{base::AnyBase, primitives::OneOrMany, unparsed::Unparsed};
|
||||||
|
@ -18,11 +19,7 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler, ActorType},
|
traits::{ActivityFields, ActivityHandler, ActorType},
|
||||||
values::PublicUrl,
|
values::PublicUrl,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
|
||||||
use lemmy_db_schema::{
|
|
||||||
source::{community::Community, person::Person},
|
|
||||||
CommunityId,
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -60,10 +57,10 @@ impl From<&VoteType> for i16 {
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Vote {
|
pub struct Vote {
|
||||||
actor: ObjectId<Person>,
|
actor: ObjectId<ApubPerson>,
|
||||||
to: [PublicUrl; 1],
|
to: [PublicUrl; 1],
|
||||||
pub(in crate::activities::voting) object: ObjectId<PostOrComment>,
|
pub(in crate::activities::voting) object: ObjectId<PostOrComment>,
|
||||||
cc: [ObjectId<Community>; 1],
|
cc: [ObjectId<ApubCommunity>; 1],
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(in crate::activities::voting) kind: VoteType,
|
pub(in crate::activities::voting) kind: VoteType,
|
||||||
id: Url,
|
id: Url,
|
||||||
|
@ -76,8 +73,8 @@ pub struct Vote {
|
||||||
impl Vote {
|
impl Vote {
|
||||||
pub(in crate::activities::voting) fn new(
|
pub(in crate::activities::voting) fn new(
|
||||||
object: &PostOrComment,
|
object: &PostOrComment,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community: &Community,
|
community: &ApubCommunity,
|
||||||
kind: VoteType,
|
kind: VoteType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<Vote, LemmyError> {
|
) -> Result<Vote, LemmyError> {
|
||||||
|
@ -95,7 +92,7 @@ impl Vote {
|
||||||
|
|
||||||
pub async fn send(
|
pub async fn send(
|
||||||
object: &PostOrComment,
|
object: &PostOrComment,
|
||||||
actor: &Person,
|
actor: &ApubPerson,
|
||||||
community_id: CommunityId,
|
community_id: CommunityId,
|
||||||
kind: VoteType,
|
kind: VoteType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -103,7 +100,8 @@ impl Vote {
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
let vote = Vote::new(object, actor, &community, kind, context)?;
|
let vote = Vote::new(object, actor, &community, kind, context)?;
|
||||||
let vote_id = vote.id.clone();
|
let vote_id = vote.id.clone();
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::community::announce::AnnounceActivity,
|
activities::community::announce::AnnounceActivity,
|
||||||
fetcher::{fetch::fetch_remote_object, object_id::ObjectId},
|
fetcher::{fetch::fetch_remote_object, object_id::ObjectId},
|
||||||
objects::community::Group,
|
objects::{community::Group, person::ApubPerson},
|
||||||
};
|
};
|
||||||
use activitystreams::collection::{CollectionExt, OrderedCollection};
|
use activitystreams::collection::{CollectionExt, OrderedCollection};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{data::Data, traits::ActivityHandler};
|
use lemmy_apub_lib::{data::Data, traits::ActivityHandler};
|
||||||
use lemmy_db_queries::Joinable;
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
traits::Joinable,
|
||||||
person::Person,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, LemmyError};
|
||||||
|
@ -46,7 +45,7 @@ pub(crate) async fn update_community_mods(
|
||||||
// Add new mods to database which have been added to moderators collection
|
// Add new mods to database which have been added to moderators collection
|
||||||
for mod_id in new_moderators {
|
for mod_id in new_moderators {
|
||||||
let mod_id = ObjectId::new(mod_id);
|
let mod_id = ObjectId::new(mod_id);
|
||||||
let mod_user: Person = mod_id.dereference(context, request_counter).await?;
|
let mod_user: ApubPerson = mod_id.dereference(context, request_counter).await?;
|
||||||
|
|
||||||
if !current_moderators
|
if !current_moderators
|
||||||
.clone()
|
.clone()
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
use crate::fetcher::post_or_comment::PostOrComment;
|
|
||||||
use lemmy_api_common::blocking;
|
|
||||||
use lemmy_db_queries::source::{
|
|
||||||
comment::Comment_,
|
|
||||||
community::Community_,
|
|
||||||
person::Person_,
|
|
||||||
post::Post_,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::Comment,
|
|
||||||
community::Community,
|
|
||||||
person::Person,
|
|
||||||
post::Post,
|
|
||||||
private_message::PrivateMessage,
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
|
||||||
use lemmy_websocket::LemmyContext;
|
|
||||||
|
|
||||||
// TODO: merge this trait with ApubObject (means that db_schema needs to depend on apub_lib)
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
pub trait DeletableApubObject {
|
|
||||||
// TODO: pass in tombstone with summary field, to decide between remove/delete
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for Community {
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let id = self.id;
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
Community::update_deleted(conn, id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for Person {
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let id = self.id;
|
|
||||||
blocking(context.pool(), move |conn| Person::delete_account(conn, id)).await??;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for Post {
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let id = self.id;
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
Post::update_deleted(conn, id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for Comment {
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
let id = self.id;
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
Comment::update_deleted(conn, id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for PostOrComment {
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
match self {
|
|
||||||
PostOrComment::Comment(c) => {
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
Comment::update_deleted(conn, c.id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
}
|
|
||||||
PostOrComment::Post(p) => {
|
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
Post::update_deleted(conn, p.id, true)
|
|
||||||
})
|
|
||||||
.await??;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for PrivateMessage {
|
|
||||||
async fn delete(self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
// do nothing, because pm can't be fetched over http
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +1,16 @@
|
||||||
pub mod community;
|
pub mod community;
|
||||||
pub mod deletable_apub_object;
|
|
||||||
mod fetch;
|
mod fetch;
|
||||||
pub mod object_id;
|
pub mod object_id;
|
||||||
pub mod post_or_comment;
|
pub mod post_or_comment;
|
||||||
pub mod search;
|
pub mod search;
|
||||||
|
|
||||||
use crate::fetcher::object_id::ObjectId;
|
use crate::{
|
||||||
|
fetcher::object_id::ObjectId,
|
||||||
|
objects::{community::ApubCommunity, person::ApubPerson},
|
||||||
|
};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_apub_lib::traits::ActorType;
|
use lemmy_apub_lib::traits::ActorType;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::naive_now;
|
||||||
naive_now,
|
|
||||||
source::{community::Community, person::Person},
|
|
||||||
};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -29,13 +28,13 @@ pub(crate) async fn get_or_fetch_and_upsert_actor(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
) -> Result<Box<dyn ActorType>, LemmyError> {
|
) -> Result<Box<dyn ActorType>, LemmyError> {
|
||||||
let community_id = ObjectId::<Community>::new(apub_id.clone());
|
let community_id = ObjectId::<ApubCommunity>::new(apub_id.clone());
|
||||||
let community = community_id.dereference(context, recursion_counter).await;
|
let community = community_id.dereference(context, recursion_counter).await;
|
||||||
let actor: Box<dyn ActorType> = match community {
|
let actor: Box<dyn ActorType> = match community {
|
||||||
Ok(c) => Box::new(c),
|
Ok(c) => Box::new(c),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let person_id = ObjectId::new(apub_id);
|
let person_id = ObjectId::new(apub_id);
|
||||||
let person: Person = person_id.dereference(context, recursion_counter).await?;
|
let person: ApubPerson = person_id.dereference(context, recursion_counter).await?;
|
||||||
Box::new(person)
|
Box::new(person)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
use crate::{
|
use crate::fetcher::should_refetch_actor;
|
||||||
fetcher::{deletable_apub_object::DeletableApubObject, should_refetch_actor},
|
|
||||||
objects::FromApub,
|
|
||||||
};
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use diesel::{NotFound, PgConnection};
|
use diesel::NotFound;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_apub_lib::{
|
||||||
use lemmy_apub_lib::{traits::ApubObject, APUB_JSON_CONTENT_TYPE};
|
traits::{ApubObject, FromApub},
|
||||||
use lemmy_db_queries::DbPool;
|
APUB_JSON_CONTENT_TYPE,
|
||||||
use lemmy_db_schema::DbUrl;
|
};
|
||||||
|
use lemmy_db_schema::newtypes::DbUrl;
|
||||||
use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
|
@ -26,12 +24,12 @@ static REQUEST_LIMIT: i32 = 25;
|
||||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug)]
|
||||||
pub struct ObjectId<Kind>(Url, #[serde(skip)] PhantomData<Kind>)
|
pub struct ObjectId<Kind>(Url, #[serde(skip)] PhantomData<Kind>)
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject<DataType = PgConnection> + DeletableApubObject + Send + 'static,
|
Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
|
||||||
for<'de2> <Kind as FromApub>::ApubType: serde::Deserialize<'de2>;
|
for<'de2> <Kind as FromApub>::ApubType: serde::Deserialize<'de2>;
|
||||||
|
|
||||||
impl<Kind> ObjectId<Kind>
|
impl<Kind> ObjectId<Kind>
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject<DataType = PgConnection> + DeletableApubObject + Send + 'static,
|
Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
pub fn new<T>(url: T) -> Self
|
pub fn new<T>(url: T) -> Self
|
||||||
|
@ -51,7 +49,7 @@ where
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Kind, LemmyError> {
|
) -> Result<Kind, LemmyError> {
|
||||||
let db_object = self.dereference_from_db(context.pool()).await?;
|
let db_object = self.dereference_from_db(context).await?;
|
||||||
|
|
||||||
// if its a local object, only fetch it from the database and not over http
|
// if its a local object, only fetch it from the database and not over http
|
||||||
if self.0.domain() == Some(&Settings::get().get_hostname_without_port()?) {
|
if self.0.domain() == Some(&Settings::get().get_hostname_without_port()?) {
|
||||||
|
@ -81,14 +79,14 @@ where
|
||||||
/// Fetch an object from the local db. Instead of falling back to http, this throws an error if
|
/// Fetch an object from the local db. Instead of falling back to http, this throws an error if
|
||||||
/// the object is not found in the database.
|
/// the object is not found in the database.
|
||||||
pub async fn dereference_local(&self, context: &LemmyContext) -> Result<Kind, LemmyError> {
|
pub async fn dereference_local(&self, context: &LemmyContext) -> Result<Kind, LemmyError> {
|
||||||
let object = self.dereference_from_db(context.pool()).await?;
|
let object = self.dereference_from_db(context).await?;
|
||||||
object.ok_or_else(|| anyhow!("object not found in database {}", self).into())
|
object.ok_or_else(|| anyhow!("object not found in database {}", self).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returning none means the object was not found in local db
|
/// returning none means the object was not found in local db
|
||||||
async fn dereference_from_db(&self, pool: &DbPool) -> Result<Option<Kind>, LemmyError> {
|
async fn dereference_from_db(&self, context: &LemmyContext) -> Result<Option<Kind>, LemmyError> {
|
||||||
let id = self.0.clone();
|
let id = self.0.clone();
|
||||||
blocking(pool, move |conn| ApubObject::read_from_apub_id(conn, id)).await?
|
ApubObject::read_from_apub_id(id, context).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn dereference_from_http(
|
async fn dereference_from_http(
|
||||||
|
@ -130,7 +128,7 @@ where
|
||||||
|
|
||||||
impl<Kind> Display for ObjectId<Kind>
|
impl<Kind> Display for ObjectId<Kind>
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject<DataType = PgConnection> + DeletableApubObject + Send + 'static,
|
Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
@ -140,7 +138,7 @@ where
|
||||||
|
|
||||||
impl<Kind> From<ObjectId<Kind>> for Url
|
impl<Kind> From<ObjectId<Kind>> for Url
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject<DataType = PgConnection> + DeletableApubObject + Send + 'static,
|
Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn from(id: ObjectId<Kind>) -> Self {
|
fn from(id: ObjectId<Kind>) -> Self {
|
||||||
|
@ -150,7 +148,7 @@ where
|
||||||
|
|
||||||
impl<Kind> From<ObjectId<Kind>> for DbUrl
|
impl<Kind> From<ObjectId<Kind>> for DbUrl
|
||||||
where
|
where
|
||||||
Kind: FromApub + ApubObject<DataType = PgConnection> + DeletableApubObject + Send + 'static,
|
Kind: FromApub<DataType = LemmyContext> + ApubObject<DataType = LemmyContext> + Send + 'static,
|
||||||
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
for<'de> <Kind as FromApub>::ApubType: serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn from(id: ObjectId<Kind>) -> Self {
|
fn from(id: ObjectId<Kind>) -> Self {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use crate::objects::{comment::Note, post::Page, FromApub};
|
use crate::objects::{
|
||||||
use activitystreams::chrono::NaiveDateTime;
|
comment::{ApubComment, Note},
|
||||||
use diesel::PgConnection;
|
post::{ApubPost, Page},
|
||||||
use lemmy_apub_lib::traits::ApubObject;
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::{Comment, CommentForm},
|
|
||||||
post::{Post, PostForm},
|
|
||||||
};
|
};
|
||||||
|
use activitystreams::chrono::NaiveDateTime;
|
||||||
|
use lemmy_apub_lib::traits::{ApubObject, FromApub};
|
||||||
|
use lemmy_db_schema::source::{comment::CommentForm, post::PostForm};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -13,8 +12,8 @@ use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum PostOrComment {
|
pub enum PostOrComment {
|
||||||
Post(Box<Post>),
|
Post(Box<ApubPost>),
|
||||||
Comment(Comment),
|
Comment(ApubComment),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum PostOrCommentForm {
|
pub enum PostOrCommentForm {
|
||||||
|
@ -31,28 +30,41 @@ pub enum PageOrNote {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubObject for PostOrComment {
|
impl ApubObject for PostOrComment {
|
||||||
type DataType = PgConnection;
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this can probably be implemented using a single sql query
|
// TODO: this can probably be implemented using a single sql query
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError>
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
data: &Self::DataType,
|
||||||
|
) -> Result<Option<Self>, LemmyError>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
let post = Post::read_from_apub_id(conn, object_id.clone())?;
|
let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?;
|
||||||
Ok(match post {
|
Ok(match post {
|
||||||
Some(o) => Some(PostOrComment::Post(Box::new(o))),
|
Some(o) => Some(PostOrComment::Post(Box::new(o))),
|
||||||
None => Comment::read_from_apub_id(conn, object_id)?.map(PostOrComment::Comment),
|
None => ApubComment::read_from_apub_id(object_id, data)
|
||||||
|
.await?
|
||||||
|
.map(PostOrComment::Comment),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
|
||||||
|
match self {
|
||||||
|
PostOrComment::Post(p) => p.delete(data).await,
|
||||||
|
PostOrComment::Comment(c) => c.delete(data).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for PostOrComment {
|
impl FromApub for PostOrComment {
|
||||||
type ApubType = PageOrNote;
|
type ApubType = PageOrNote;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: &PageOrNote,
|
apub: &PageOrNote,
|
||||||
|
@ -65,10 +77,10 @@ impl FromApub for PostOrComment {
|
||||||
{
|
{
|
||||||
Ok(match apub {
|
Ok(match apub {
|
||||||
PageOrNote::Page(p) => PostOrComment::Post(Box::new(
|
PageOrNote::Page(p) => PostOrComment::Post(Box::new(
|
||||||
Post::from_apub(p, context, expected_domain, request_counter).await?,
|
ApubPost::from_apub(p, context, expected_domain, request_counter).await?,
|
||||||
)),
|
)),
|
||||||
PageOrNote::Note(n) => PostOrComment::Comment(
|
PageOrNote::Note(n) => PostOrComment::Comment(
|
||||||
Comment::from_apub(n, context, expected_domain, request_counter).await?,
|
ApubComment::from_apub(n, context, expected_domain, request_counter).await?,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,24 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
fetcher::{deletable_apub_object::DeletableApubObject, object_id::ObjectId},
|
fetcher::object_id::ObjectId,
|
||||||
objects::{comment::Note, community::Group, person::Person as ApubPerson, post::Page, FromApub},
|
objects::{
|
||||||
|
comment::{ApubComment, Note},
|
||||||
|
community::{ApubCommunity, Group},
|
||||||
|
person::{ApubPerson, Person},
|
||||||
|
post::{ApubPost, Page},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use activitystreams::chrono::NaiveDateTime;
|
use activitystreams::chrono::NaiveDateTime;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use diesel::PgConnection;
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
traits::ApubObject,
|
traits::{ApubObject, FromApub},
|
||||||
webfinger::{webfinger_resolve_actor, WebfingerType},
|
webfinger::{webfinger_resolve_actor, WebfingerType},
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_schema::{
|
||||||
source::{community::Community_, person::Person_},
|
source::{community::Community, person::Person as DbPerson},
|
||||||
DbPool,
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -74,10 +77,14 @@ async fn find_local_actor_by_name(
|
||||||
let name: String = name.into();
|
let name: String = name.into();
|
||||||
Ok(match kind {
|
Ok(match kind {
|
||||||
WebfingerType::Group => SearchableObjects::Community(
|
WebfingerType::Group => SearchableObjects::Community(
|
||||||
blocking(pool, move |conn| Community::read_from_name(conn, &name)).await??,
|
blocking(pool, move |conn| Community::read_from_name(conn, &name))
|
||||||
|
.await??
|
||||||
|
.into(),
|
||||||
),
|
),
|
||||||
WebfingerType::Person => SearchableObjects::Person(
|
WebfingerType::Person => SearchableObjects::Person(
|
||||||
blocking(pool, move |conn| Person::find_by_name(conn, &name)).await??,
|
blocking(pool, move |conn| DbPerson::find_by_name(conn, &name))
|
||||||
|
.await??
|
||||||
|
.into(),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -85,23 +92,24 @@ async fn find_local_actor_by_name(
|
||||||
/// The types of ActivityPub objects that can be fetched directly by searching for their ID.
|
/// The types of ActivityPub objects that can be fetched directly by searching for their ID.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SearchableObjects {
|
pub enum SearchableObjects {
|
||||||
Person(Person),
|
Person(ApubPerson),
|
||||||
Community(Community),
|
Community(ApubCommunity),
|
||||||
Post(Post),
|
Post(ApubPost),
|
||||||
Comment(Comment),
|
Comment(ApubComment),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum SearchableApubTypes {
|
pub enum SearchableApubTypes {
|
||||||
Group(Group),
|
Group(Group),
|
||||||
Person(ApubPerson),
|
Person(Person),
|
||||||
Page(Page),
|
Page(Page),
|
||||||
Note(Note),
|
Note(Note),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubObject for SearchableObjects {
|
impl ApubObject for SearchableObjects {
|
||||||
type DataType = PgConnection;
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -117,30 +125,43 @@ impl ApubObject for SearchableObjects {
|
||||||
// a single query.
|
// a single query.
|
||||||
// we could skip this and always return an error, but then it would always fetch objects
|
// 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.
|
// over http, and not be able to mark objects as deleted that were deleted by remote server.
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, LemmyError> {
|
async fn read_from_apub_id(
|
||||||
let c = Community::read_from_apub_id(conn, object_id.clone())?;
|
object_id: Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<Option<Self>, LemmyError> {
|
||||||
|
let c = ApubCommunity::read_from_apub_id(object_id.clone(), context).await?;
|
||||||
if let Some(c) = c {
|
if let Some(c) = c {
|
||||||
return Ok(Some(SearchableObjects::Community(c)));
|
return Ok(Some(SearchableObjects::Community(c)));
|
||||||
}
|
}
|
||||||
let p = Person::read_from_apub_id(conn, object_id.clone())?;
|
let p = ApubPerson::read_from_apub_id(object_id.clone(), context).await?;
|
||||||
if let Some(p) = p {
|
if let Some(p) = p {
|
||||||
return Ok(Some(SearchableObjects::Person(p)));
|
return Ok(Some(SearchableObjects::Person(p)));
|
||||||
}
|
}
|
||||||
let p = Post::read_from_apub_id(conn, object_id.clone())?;
|
let p = ApubPost::read_from_apub_id(object_id.clone(), context).await?;
|
||||||
if let Some(p) = p {
|
if let Some(p) = p {
|
||||||
return Ok(Some(SearchableObjects::Post(p)));
|
return Ok(Some(SearchableObjects::Post(p)));
|
||||||
}
|
}
|
||||||
let c = Comment::read_from_apub_id(conn, object_id)?;
|
let c = ApubComment::read_from_apub_id(object_id, context).await?;
|
||||||
if let Some(c) = c {
|
if let Some(c) = c {
|
||||||
return Ok(Some(SearchableObjects::Comment(c)));
|
return Ok(Some(SearchableObjects::Comment(c)));
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
|
||||||
|
match self {
|
||||||
|
SearchableObjects::Person(p) => p.delete(data).await,
|
||||||
|
SearchableObjects::Community(c) => c.delete(data).await,
|
||||||
|
SearchableObjects::Post(p) => p.delete(data).await,
|
||||||
|
SearchableObjects::Comment(c) => c.delete(data).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for SearchableObjects {
|
impl FromApub for SearchableObjects {
|
||||||
type ApubType = SearchableApubTypes;
|
type ApubType = SearchableApubTypes;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
apub: &Self::ApubType,
|
apub: &Self::ApubType,
|
||||||
|
@ -151,22 +172,10 @@ impl FromApub for SearchableObjects {
|
||||||
use SearchableApubTypes as SAT;
|
use SearchableApubTypes as SAT;
|
||||||
use SearchableObjects as SO;
|
use SearchableObjects as SO;
|
||||||
Ok(match apub {
|
Ok(match apub {
|
||||||
SAT::Group(g) => SO::Community(Community::from_apub(g, context, ed, rc).await?),
|
SAT::Group(g) => SO::Community(ApubCommunity::from_apub(g, context, ed, rc).await?),
|
||||||
SAT::Person(p) => SO::Person(Person::from_apub(p, context, ed, rc).await?),
|
SAT::Person(p) => SO::Person(ApubPerson::from_apub(p, context, ed, rc).await?),
|
||||||
SAT::Page(p) => SO::Post(Post::from_apub(p, context, ed, rc).await?),
|
SAT::Page(p) => SO::Post(ApubPost::from_apub(p, context, ed, rc).await?),
|
||||||
SAT::Note(n) => SO::Comment(Comment::from_apub(n, context, ed, rc).await?),
|
SAT::Note(n) => SO::Comment(ApubComment::from_apub(n, context, ed, rc).await?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
impl DeletableApubObject for SearchableObjects {
|
|
||||||
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
||||||
match self {
|
|
||||||
SearchableObjects::Person(p) => p.delete(context).await,
|
|
||||||
SearchableObjects::Community(c) => c.delete(context).await,
|
|
||||||
SearchableObjects::Post(p) => p.delete(context).await,
|
|
||||||
SearchableObjects::Comment(c) => c.delete(context).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
http::{create_apub_response, create_apub_tombstone_response},
|
http::{create_apub_response, create_apub_tombstone_response},
|
||||||
objects::ToApub,
|
objects::comment::ApubComment,
|
||||||
};
|
};
|
||||||
use actix_web::{body::Body, web, web::Path, HttpResponse};
|
use actix_web::{body::Body, web, web::Path, HttpResponse};
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_apub_lib::traits::ToApub;
|
||||||
use lemmy_db_schema::{source::comment::Comment, CommentId};
|
use lemmy_db_schema::{newtypes::CommentId, source::comment::Comment, traits::Crud};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -22,7 +22,9 @@ pub(crate) async fn get_apub_comment(
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let id = CommentId(info.comment_id.parse::<i32>()?);
|
let id = CommentId(info.comment_id.parse::<i32>()?);
|
||||||
let comment = blocking(context.pool(), move |conn| Comment::read(conn, id)).await??;
|
let comment: ApubComment = blocking(context.pool(), move |conn| Comment::read(conn, id))
|
||||||
|
.await??
|
||||||
|
.into();
|
||||||
if !comment.local {
|
if !comment.local {
|
||||||
return Err(NotFound.into());
|
return Err(NotFound.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
payload_to_string,
|
payload_to_string,
|
||||||
receive_activity,
|
receive_activity,
|
||||||
},
|
},
|
||||||
objects::ToApub,
|
objects::community::ApubCommunity,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
base::{AnyBase, BaseExt},
|
base::{AnyBase, BaseExt},
|
||||||
|
@ -23,8 +23,7 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler};
|
use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub};
|
||||||
use lemmy_db_queries::source::{activity::Activity_, community::Community_};
|
|
||||||
use lemmy_db_schema::source::{activity::Activity, community::Community};
|
use lemmy_db_schema::source::{activity::Activity, community::Community};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_follower_view::CommunityFollowerView,
|
community_follower_view::CommunityFollowerView,
|
||||||
|
@ -45,10 +44,11 @@ pub(crate) async fn get_apub_community_http(
|
||||||
info: web::Path<CommunityQuery>,
|
info: web::Path<CommunityQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read_from_name(conn, &info.community_name)
|
Community::read_from_name(conn, &info.community_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
if !community.deleted {
|
if !community.deleted {
|
||||||
let apub = community.to_apub(context.pool()).await?;
|
let apub = community.to_apub(context.pool()).await?;
|
||||||
|
@ -174,10 +174,11 @@ pub(crate) async fn get_apub_community_moderators(
|
||||||
info: web::Path<CommunityQuery>,
|
info: web::Path<CommunityQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community: ApubCommunity = blocking(context.pool(), move |conn| {
|
||||||
Community::read_from_name(conn, &info.community_name)
|
Community::read_from_name(conn, &info.community_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
// The attributed to, is an ordered vector with the creator actor_ids first,
|
// The attributed to, is an ordered vector with the creator actor_ids first,
|
||||||
// then the rest of the moderators
|
// then the rest of the moderators
|
||||||
|
|
|
@ -24,8 +24,7 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActivityFields, ActivityHandler},
|
traits::{ActivityFields, ActivityHandler},
|
||||||
APUB_JSON_CONTENT_TYPE,
|
APUB_JSON_CONTENT_TYPE,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::activity::Activity_, DbPool};
|
use lemmy_db_schema::{source::activity::Activity, DbPool};
|
||||||
use lemmy_db_schema::source::activity::Activity;
|
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
payload_to_string,
|
payload_to_string,
|
||||||
receive_activity,
|
receive_activity,
|
||||||
},
|
},
|
||||||
objects::ToApub,
|
objects::person::ApubPerson,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
base::BaseExt,
|
base::BaseExt,
|
||||||
|
@ -24,8 +24,7 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler};
|
use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler, ToApub};
|
||||||
use lemmy_db_queries::source::person::Person_;
|
|
||||||
use lemmy_db_schema::source::person::Person;
|
use lemmy_db_schema::source::person::Person;
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -45,10 +44,11 @@ pub(crate) async fn get_apub_person_http(
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let user_name = info.into_inner().user_name;
|
let user_name = info.into_inner().user_name;
|
||||||
// TODO: this needs to be able to read deleted persons, so that it can send tombstones
|
// TODO: this needs to be able to read deleted persons, so that it can send tombstones
|
||||||
let person = blocking(context.pool(), move |conn| {
|
let person: ApubPerson = blocking(context.pool(), move |conn| {
|
||||||
Person::find_by_name(conn, &user_name)
|
Person::find_by_name(conn, &user_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??
|
||||||
|
.into();
|
||||||
|
|
||||||
if !person.deleted {
|
if !person.deleted {
|
||||||
let apub = person.to_apub(context.pool()).await?;
|
let apub = person.to_apub(context.pool()).await?;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
http::{create_apub_response, create_apub_tombstone_response},
|
http::{create_apub_response, create_apub_tombstone_response},
|
||||||
objects::ToApub,
|
objects::post::ApubPost,
|
||||||
};
|
};
|
||||||
use actix_web::{body::Body, web, HttpResponse};
|
use actix_web::{body::Body, web, HttpResponse};
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_apub_lib::traits::ToApub;
|
||||||
use lemmy_db_schema::{source::post::Post, PostId};
|
use lemmy_db_schema::{newtypes::PostId, source::post::Post, traits::Crud};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -22,7 +22,9 @@ pub(crate) async fn get_apub_post(
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let id = PostId(info.post_id.parse::<i32>()?);
|
let id = PostId(info.post_id.parse::<i32>()?);
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, id)).await??;
|
let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, id))
|
||||||
|
.await??
|
||||||
|
.into();
|
||||||
if !post.local {
|
if !post.local {
|
||||||
return Err(NotFound.into());
|
return Err(NotFound.into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,10 @@ use crate::fetcher::post_or_comment::PostOrComment;
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{activity_queue::send_activity, traits::ActorType};
|
use lemmy_apub_lib::{activity_queue::send_activity, traits::ActorType};
|
||||||
use lemmy_db_queries::{source::activity::Activity_, DbPool};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
newtypes::{CommunityId, DbUrl},
|
||||||
source::{activity::Activity, person::Person},
|
source::{activity::Activity, person::Person},
|
||||||
CommunityId,
|
DbPool,
|
||||||
DbUrl,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
|
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
|
||||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
|
|
|
@ -3,11 +3,12 @@ use crate::{
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
migrations::CommentInReplyToMigration,
|
migrations::CommentInReplyToMigration,
|
||||||
objects::{create_tombstone, FromApub, Source, ToApub},
|
objects::{create_tombstone, person::ApubPerson, post::ApubPost, Source},
|
||||||
PostOrComment,
|
PostOrComment,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
base::AnyBase,
|
base::AnyBase,
|
||||||
|
chrono::NaiveDateTime,
|
||||||
object::{kind::NoteType, Tombstone},
|
object::{kind::NoteType, Tombstone},
|
||||||
primitives::OneOrMany,
|
primitives::OneOrMany,
|
||||||
unparsed::Unparsed,
|
unparsed::Unparsed,
|
||||||
|
@ -16,19 +17,20 @@ use anyhow::{anyhow, Context};
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
traits::ActorType,
|
traits::{ApubObject, FromApub, ToApub},
|
||||||
values::{MediaTypeHtml, MediaTypeMarkdown, PublicUrl},
|
values::{MediaTypeHtml, MediaTypeMarkdown, PublicUrl},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, Crud, DbPool};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
newtypes::CommentId,
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::Community,
|
community::Community,
|
||||||
person::Person,
|
person::Person,
|
||||||
post::Post,
|
post::Post,
|
||||||
},
|
},
|
||||||
CommentId,
|
traits::Crud,
|
||||||
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
|
@ -49,7 +51,7 @@ pub struct Note {
|
||||||
context: OneOrMany<AnyBase>,
|
context: OneOrMany<AnyBase>,
|
||||||
r#type: NoteType,
|
r#type: NoteType,
|
||||||
id: Url,
|
id: Url,
|
||||||
pub(crate) attributed_to: ObjectId<Person>,
|
pub(crate) attributed_to: ObjectId<ApubPerson>,
|
||||||
/// Indicates that the object is publicly readable. Unlike [`Post.to`], this one doesn't contain
|
/// Indicates that the object is publicly readable. Unlike [`Post.to`], this one doesn't contain
|
||||||
/// the community ID, as it would be incompatible with Pleroma (and we can get the community from
|
/// the community ID, as it would be incompatible with Pleroma (and we can get the community from
|
||||||
/// the post in [`in_reply_to`]).
|
/// the post in [`in_reply_to`]).
|
||||||
|
@ -77,7 +79,7 @@ impl Note {
|
||||||
&self,
|
&self,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(Post, Option<CommentId>), LemmyError> {
|
) -> Result<(ApubPost, Option<CommentId>), LemmyError> {
|
||||||
match &self.in_reply_to {
|
match &self.in_reply_to {
|
||||||
CommentInReplyToMigration::Old(in_reply_to) => {
|
CommentInReplyToMigration::Old(in_reply_to) => {
|
||||||
// This post, or the parent comment might not yet exist on this server yet, fetch them.
|
// This post, or the parent comment might not yet exist on this server yet, fetch them.
|
||||||
|
@ -89,7 +91,7 @@ impl Note {
|
||||||
// Nested comments will automatically get fetched recursively
|
// Nested comments will automatically get fetched recursively
|
||||||
let parent_id: Option<CommentId> = match in_reply_to.get(1) {
|
let parent_id: Option<CommentId> = match in_reply_to.get(1) {
|
||||||
Some(comment_id) => {
|
Some(comment_id) => {
|
||||||
let comment_id = ObjectId::<Comment>::new(comment_id.clone());
|
let comment_id = ObjectId::<ApubComment>::new(comment_id.clone());
|
||||||
let parent_comment = Box::pin(comment_id.dereference(context, request_counter)).await?;
|
let parent_comment = Box::pin(comment_id.dereference(context, request_counter)).await?;
|
||||||
|
|
||||||
Some(parent_comment.id)
|
Some(parent_comment.id)
|
||||||
|
@ -103,16 +105,16 @@ impl Note {
|
||||||
let parent = Box::pin(in_reply_to.dereference(context, request_counter).await?);
|
let parent = Box::pin(in_reply_to.dereference(context, request_counter).await?);
|
||||||
match parent.deref() {
|
match parent.deref() {
|
||||||
PostOrComment::Post(p) => {
|
PostOrComment::Post(p) => {
|
||||||
// Workaround because I cant figure ut how to get the post out of the box (and we dont
|
// Workaround because I cant figure out how to get the post out of the box (and we dont
|
||||||
// want to stackoverflow in a deep comment hierarchy).
|
// want to stackoverflow in a deep comment hierarchy).
|
||||||
let post_id = p.id;
|
let post_id = p.id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
Ok((post, None))
|
Ok((post.into(), None))
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(c) => {
|
PostOrComment::Comment(c) => {
|
||||||
let post_id = c.post_id;
|
let post_id = c.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
Ok((post, Some(c.id)))
|
Ok((post.into(), Some(c.id)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +139,7 @@ impl Note {
|
||||||
verify_domains_match(self.attributed_to.inner(), &self.id)?;
|
verify_domains_match(self.attributed_to.inner(), &self.id)?;
|
||||||
verify_person_in_community(
|
verify_person_in_community(
|
||||||
&self.attributed_to,
|
&self.attributed_to,
|
||||||
&ObjectId::new(community.actor_id()),
|
&ObjectId::new(community.actor_id),
|
||||||
context,
|
context,
|
||||||
request_counter,
|
request_counter,
|
||||||
)
|
)
|
||||||
|
@ -146,9 +148,57 @@ impl Note {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ApubComment(Comment);
|
||||||
|
|
||||||
|
impl Deref for ApubComment {
|
||||||
|
type Target = Comment;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Comment> for ApubComment {
|
||||||
|
fn from(c: Comment) -> Self {
|
||||||
|
ApubComment { 0: c }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ToApub for Comment {
|
impl ApubObject for ApubComment {
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<Option<Self>, LemmyError> {
|
||||||
|
Ok(
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Comment::read_from_apub_id(conn, object_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Comment::update_deleted(conn, self.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl ToApub for ApubComment {
|
||||||
type ApubType = Note;
|
type ApubType = Note;
|
||||||
|
type TombstoneType = Tombstone;
|
||||||
|
type DataType = DbPool;
|
||||||
|
|
||||||
async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
|
async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
|
||||||
let creator_id = self.creator_id;
|
let creator_id = self.creator_id;
|
||||||
|
@ -199,8 +249,9 @@ impl ToApub for Comment {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for Comment {
|
impl FromApub for ApubComment {
|
||||||
type ApubType = Note;
|
type ApubType = Note;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
/// Converts a `Note` to `Comment`.
|
/// Converts a `Note` to `Comment`.
|
||||||
///
|
///
|
||||||
|
@ -210,7 +261,7 @@ impl FromApub for Comment {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Comment, LemmyError> {
|
) -> Result<ApubComment, LemmyError> {
|
||||||
let ap_id = Some(note.id(expected_domain)?.clone().into());
|
let ap_id = Some(note.id(expected_domain)?.clone().into());
|
||||||
let creator = note
|
let creator = note
|
||||||
.attributed_to
|
.attributed_to
|
||||||
|
@ -237,6 +288,7 @@ impl FromApub for Comment {
|
||||||
ap_id,
|
ap_id,
|
||||||
local: Some(false),
|
local: Some(false),
|
||||||
};
|
};
|
||||||
Ok(blocking(context.pool(), move |conn| Comment::upsert(conn, &form)).await??)
|
let comment = blocking(context.pool(), move |conn| Comment::upsert(conn, &form)).await??;
|
||||||
|
Ok(comment.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,13 @@ use crate::{
|
||||||
fetcher::community::{fetch_community_outbox, update_community_mods},
|
fetcher::community::{fetch_community_outbox, update_community_mods},
|
||||||
generate_moderators_url,
|
generate_moderators_url,
|
||||||
generate_outbox_url,
|
generate_outbox_url,
|
||||||
objects::{create_tombstone, FromApub, ImageObject, Source, ToApub},
|
objects::{create_tombstone, ImageObject, Source},
|
||||||
CommunityType,
|
CommunityType,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
actor::{kind::GroupType, Endpoints},
|
actor::{kind::GroupType, Endpoints},
|
||||||
base::AnyBase,
|
base::AnyBase,
|
||||||
|
chrono::NaiveDateTime,
|
||||||
object::{kind::ImageType, Tombstone},
|
object::{kind::ImageType, Tombstone},
|
||||||
primitives::OneOrMany,
|
primitives::OneOrMany,
|
||||||
unparsed::Unparsed,
|
unparsed::Unparsed,
|
||||||
|
@ -19,14 +20,14 @@ use itertools::Itertools;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
signatures::PublicKey,
|
signatures::PublicKey,
|
||||||
traits::ActorType,
|
traits::{ActorType, ApubObject, FromApub, ToApub},
|
||||||
values::{MediaTypeHtml, MediaTypeMarkdown},
|
values::{MediaTypeHtml, MediaTypeMarkdown},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::community::Community_, DbPool};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::community::{Community, CommunityForm},
|
source::community::{Community, CommunityForm},
|
||||||
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
|
@ -37,6 +38,7 @@ use lemmy_utils::{
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
use std::ops::Deref;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -117,9 +119,83 @@ impl Group {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ApubCommunity(Community);
|
||||||
|
|
||||||
|
impl Deref for ApubCommunity {
|
||||||
|
type Target = Community;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Community> for ApubCommunity {
|
||||||
|
fn from(c: Community) -> Self {
|
||||||
|
ApubCommunity { 0: c }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ToApub for Community {
|
impl ApubObject for ApubCommunity {
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
|
Some(self.last_refreshed_at)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<Option<Self>, LemmyError> {
|
||||||
|
Ok(
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Community::read_from_apub_id(conn, object_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Community::update_deleted(conn, self.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActorType for ApubCommunity {
|
||||||
|
fn is_local(&self) -> bool {
|
||||||
|
self.local
|
||||||
|
}
|
||||||
|
fn actor_id(&self) -> Url {
|
||||||
|
self.actor_id.to_owned().into()
|
||||||
|
}
|
||||||
|
fn name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
fn public_key(&self) -> Option<String> {
|
||||||
|
self.public_key.to_owned()
|
||||||
|
}
|
||||||
|
fn private_key(&self) -> Option<String> {
|
||||||
|
self.private_key.to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inbox_url(&self) -> Url {
|
||||||
|
self.inbox_url.clone().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shared_inbox_url(&self) -> Option<Url> {
|
||||||
|
self.shared_inbox_url.clone().map(|s| s.into_inner())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl ToApub for ApubCommunity {
|
||||||
type ApubType = Group;
|
type ApubType = Group;
|
||||||
|
type TombstoneType = Tombstone;
|
||||||
|
type DataType = DbPool;
|
||||||
|
|
||||||
async fn to_apub(&self, _pool: &DbPool) -> Result<Group, LemmyError> {
|
async fn to_apub(&self, _pool: &DbPool) -> Result<Group, LemmyError> {
|
||||||
let source = self.description.clone().map(|bio| Source {
|
let source = self.description.clone().map(|bio| Source {
|
||||||
|
@ -174,8 +250,9 @@ impl ToApub for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for Community {
|
impl FromApub for ApubCommunity {
|
||||||
type ApubType = Group;
|
type ApubType = Group;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
/// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
|
/// Converts a `Group` to `Community`, inserts it into the database and updates moderators.
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
|
@ -183,7 +260,7 @@ impl FromApub for Community {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Community, LemmyError> {
|
) -> Result<ApubCommunity, LemmyError> {
|
||||||
let form = Group::from_apub_to_form(group, expected_domain, &context.settings()).await?;
|
let form = Group::from_apub_to_form(group, expected_domain, &context.settings()).await?;
|
||||||
|
|
||||||
let community = blocking(context.pool(), move |conn| Community::upsert(conn, &form)).await??;
|
let community = blocking(context.pool(), move |conn| Community::upsert(conn, &form)).await??;
|
||||||
|
@ -192,7 +269,7 @@ impl FromApub for Community {
|
||||||
// TODO: doing this unconditionally might cause infinite loop for some reason
|
// TODO: doing this unconditionally might cause infinite loop for some reason
|
||||||
fetch_community_outbox(context, &group.outbox, request_counter).await?;
|
fetch_community_outbox(context, &group.outbox, request_counter).await?;
|
||||||
|
|
||||||
Ok(community)
|
Ok(community.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,43 +5,14 @@ use activitystreams::{
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_apub_lib::values::MediaTypeMarkdown;
|
use lemmy_apub_lib::values::MediaTypeMarkdown;
|
||||||
use lemmy_db_queries::DbPool;
|
|
||||||
use lemmy_utils::{utils::convert_datetime, LemmyError};
|
use lemmy_utils::{utils::convert_datetime, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub(crate) mod comment;
|
pub mod comment;
|
||||||
pub(crate) mod community;
|
pub mod community;
|
||||||
pub(crate) mod person;
|
pub mod person;
|
||||||
pub(crate) mod post;
|
pub mod post;
|
||||||
pub(crate) mod private_message;
|
pub mod private_message;
|
||||||
|
|
||||||
/// Trait for converting an object or actor into the respective ActivityPub type.
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
pub(crate) trait ToApub {
|
|
||||||
type ApubType;
|
|
||||||
async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
|
|
||||||
fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
|
||||||
pub trait FromApub {
|
|
||||||
type ApubType;
|
|
||||||
/// Converts an object from ActivityPub type to Lemmy internal type.
|
|
||||||
///
|
|
||||||
/// * `apub` The object to read from
|
|
||||||
/// * `context` LemmyContext which holds DB pool, HTTP client etc
|
|
||||||
/// * `expected_domain` Domain where the object was received from. None in case of mod action.
|
|
||||||
/// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case
|
|
||||||
async fn from_apub(
|
|
||||||
apub: &Self::ApubType,
|
|
||||||
context: &LemmyContext,
|
|
||||||
expected_domain: &Url,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<Self, LemmyError>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
|
|
@ -2,27 +2,28 @@ use crate::{
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
generate_outbox_url,
|
generate_outbox_url,
|
||||||
objects::{FromApub, ImageObject, Source, ToApub},
|
objects::{ImageObject, Source},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
actor::Endpoints,
|
actor::Endpoints,
|
||||||
base::AnyBase,
|
base::AnyBase,
|
||||||
chrono::{DateTime, FixedOffset},
|
chrono::NaiveDateTime,
|
||||||
object::{kind::ImageType, Tombstone},
|
object::{kind::ImageType, Tombstone},
|
||||||
primitives::OneOrMany,
|
primitives::OneOrMany,
|
||||||
unparsed::Unparsed,
|
unparsed::Unparsed,
|
||||||
};
|
};
|
||||||
|
use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
signatures::PublicKey,
|
signatures::PublicKey,
|
||||||
traits::ActorType,
|
traits::{ActorType, ApubObject, FromApub, ToApub},
|
||||||
values::{MediaTypeHtml, MediaTypeMarkdown},
|
values::{MediaTypeHtml, MediaTypeMarkdown},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::person::Person_, DbPool};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::person::{Person as DbPerson, PersonForm},
|
source::person::{Person as DbPerson, PersonForm},
|
||||||
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
|
utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
|
||||||
|
@ -31,6 +32,7 @@ use lemmy_utils::{
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
use std::ops::Deref;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
|
||||||
|
@ -79,9 +81,85 @@ impl Person {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ApubPerson(DbPerson);
|
||||||
|
|
||||||
|
impl Deref for ApubPerson {
|
||||||
|
type Target = DbPerson;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DbPerson> for ApubPerson {
|
||||||
|
fn from(p: DbPerson) -> Self {
|
||||||
|
ApubPerson { 0: p }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ToApub for DbPerson {
|
impl ApubObject for ApubPerson {
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
|
Some(self.last_refreshed_at)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<Option<Self>, LemmyError> {
|
||||||
|
Ok(
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
DbPerson::read_from_apub_id(conn, object_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
DbPerson::update_deleted(conn, self.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActorType for ApubPerson {
|
||||||
|
fn is_local(&self) -> bool {
|
||||||
|
self.local
|
||||||
|
}
|
||||||
|
fn actor_id(&self) -> Url {
|
||||||
|
self.actor_id.to_owned().into_inner()
|
||||||
|
}
|
||||||
|
fn name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn public_key(&self) -> Option<String> {
|
||||||
|
self.public_key.to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn private_key(&self) -> Option<String> {
|
||||||
|
self.private_key.to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inbox_url(&self) -> Url {
|
||||||
|
self.inbox_url.clone().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shared_inbox_url(&self) -> Option<Url> {
|
||||||
|
self.shared_inbox_url.clone().map(|s| s.into_inner())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl ToApub for ApubPerson {
|
||||||
type ApubType = Person;
|
type ApubType = Person;
|
||||||
|
type TombstoneType = Tombstone;
|
||||||
|
type DataType = DbPool;
|
||||||
|
|
||||||
async fn to_apub(&self, _pool: &DbPool) -> Result<Person, LemmyError> {
|
async fn to_apub(&self, _pool: &DbPool) -> Result<Person, LemmyError> {
|
||||||
let kind = if self.bot_account {
|
let kind = if self.bot_account {
|
||||||
|
@ -133,15 +211,16 @@ impl ToApub for DbPerson {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for DbPerson {
|
impl FromApub for ApubPerson {
|
||||||
type ApubType = Person;
|
type ApubType = Person;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
person: &Person,
|
person: &Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
_request_counter: &mut i32,
|
_request_counter: &mut i32,
|
||||||
) -> Result<DbPerson, LemmyError> {
|
) -> Result<ApubPerson, LemmyError> {
|
||||||
let actor_id = Some(person.id(expected_domain)?.clone().into());
|
let actor_id = Some(person.id(expected_domain)?.clone().into());
|
||||||
let name = person.preferred_username.clone();
|
let name = person.preferred_username.clone();
|
||||||
let display_name: Option<String> = person.name.clone();
|
let display_name: Option<String> = person.name.clone();
|
||||||
|
@ -184,6 +263,6 @@ impl FromApub for DbPerson {
|
||||||
DbPerson::upsert(conn, &person_form)
|
DbPerson::upsert(conn, &person_form)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
Ok(person)
|
Ok(person.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
activities::{extract_community, verify_person_in_community},
|
activities::{extract_community, verify_person_in_community},
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
objects::{create_tombstone, FromApub, ImageObject, Source, ToApub},
|
objects::{create_tombstone, person::ApubPerson, ImageObject, Source},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
base::AnyBase,
|
base::AnyBase,
|
||||||
|
@ -14,14 +14,13 @@ use activitystreams::{
|
||||||
public,
|
public,
|
||||||
unparsed::Unparsed,
|
unparsed::Unparsed,
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset, NaiveDateTime};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
traits::ActorType,
|
traits::{ActorType, ApubObject, FromApub, ToApub},
|
||||||
values::{MediaTypeHtml, MediaTypeMarkdown},
|
values::{MediaTypeHtml, MediaTypeMarkdown},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::post::Post_, Crud, DbPool};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
self,
|
self,
|
||||||
source::{
|
source::{
|
||||||
|
@ -29,6 +28,8 @@ use lemmy_db_schema::{
|
||||||
person::Person,
|
person::Person,
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
},
|
},
|
||||||
|
traits::Crud,
|
||||||
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::fetch_site_data,
|
request::fetch_site_data,
|
||||||
|
@ -38,6 +39,7 @@ use lemmy_utils::{
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
use std::ops::Deref;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -48,7 +50,7 @@ pub struct Page {
|
||||||
context: OneOrMany<AnyBase>,
|
context: OneOrMany<AnyBase>,
|
||||||
r#type: PageType,
|
r#type: PageType,
|
||||||
id: Url,
|
id: Url,
|
||||||
pub(crate) attributed_to: ObjectId<Person>,
|
pub(crate) attributed_to: ObjectId<ApubPerson>,
|
||||||
to: [Url; 2],
|
to: [Url; 2],
|
||||||
name: String,
|
name: String,
|
||||||
content: Option<String>,
|
content: Option<String>,
|
||||||
|
@ -79,7 +81,7 @@ impl Page {
|
||||||
///
|
///
|
||||||
/// Both stickied and locked need to be false on a newly created post (verified in [[CreatePost]].
|
/// Both stickied and locked need to be false on a newly created post (verified in [[CreatePost]].
|
||||||
pub(crate) async fn is_mod_action(&self, context: &LemmyContext) -> Result<bool, LemmyError> {
|
pub(crate) async fn is_mod_action(&self, context: &LemmyContext) -> Result<bool, LemmyError> {
|
||||||
let old_post = ObjectId::<Post>::new(self.id.clone())
|
let old_post = ObjectId::<ApubPost>::new(self.id.clone())
|
||||||
.dereference_local(context)
|
.dereference_local(context)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -111,9 +113,57 @@ impl Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ApubPost(Post);
|
||||||
|
|
||||||
|
impl Deref for ApubPost {
|
||||||
|
type Target = Post;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Post> for ApubPost {
|
||||||
|
fn from(p: Post) -> Self {
|
||||||
|
ApubPost { 0: p }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ToApub for Post {
|
impl ApubObject for ApubPost {
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<Option<Self>, LemmyError> {
|
||||||
|
Ok(
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Post::read_from_apub_id(conn, object_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
Post::update_deleted(conn, self.id, true)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl ToApub for ApubPost {
|
||||||
type ApubType = Page;
|
type ApubType = Page;
|
||||||
|
type TombstoneType = Tombstone;
|
||||||
|
type DataType = DbPool;
|
||||||
|
|
||||||
// Turn a Lemmy post into an ActivityPub page that can be sent out over the network.
|
// Turn a Lemmy post into an ActivityPub page that can be sent out over the network.
|
||||||
async fn to_apub(&self, pool: &DbPool) -> Result<Page, LemmyError> {
|
async fn to_apub(&self, pool: &DbPool) -> Result<Page, LemmyError> {
|
||||||
|
@ -164,15 +214,16 @@ impl ToApub for Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for Post {
|
impl FromApub for ApubPost {
|
||||||
type ApubType = Page;
|
type ApubType = Page;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
page: &Page,
|
page: &Page,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<Post, LemmyError> {
|
) -> Result<ApubPost, LemmyError> {
|
||||||
// We can't verify the domain in case of mod action, because the mod may be on a different
|
// We can't verify the domain in case of mod action, because the mod may be on a different
|
||||||
// instance from the post author.
|
// instance from the post author.
|
||||||
let ap_id = if page.is_mod_action(context).await? {
|
let ap_id = if page.is_mod_action(context).await? {
|
||||||
|
@ -221,6 +272,7 @@ impl FromApub for Post {
|
||||||
ap_id,
|
ap_id,
|
||||||
local: Some(false),
|
local: Some(false),
|
||||||
};
|
};
|
||||||
Ok(blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??)
|
let post = blocking(context.pool(), move |conn| Post::upsert(conn, &form)).await??;
|
||||||
|
Ok(post.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
context::lemmy_context,
|
context::lemmy_context,
|
||||||
fetcher::object_id::ObjectId,
|
fetcher::object_id::ObjectId,
|
||||||
objects::{create_tombstone, FromApub, Source, ToApub},
|
objects::{create_tombstone, person::ApubPerson, Source},
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
base::AnyBase,
|
base::AnyBase,
|
||||||
|
chrono::NaiveDateTime,
|
||||||
object::{kind::NoteType, Tombstone},
|
object::{kind::NoteType, Tombstone},
|
||||||
primitives::OneOrMany,
|
primitives::OneOrMany,
|
||||||
unparsed::Unparsed,
|
unparsed::Unparsed,
|
||||||
|
@ -13,18 +14,23 @@ use anyhow::anyhow;
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
|
traits::{ApubObject, FromApub, ToApub},
|
||||||
values::{MediaTypeHtml, MediaTypeMarkdown},
|
values::{MediaTypeHtml, MediaTypeMarkdown},
|
||||||
verify::verify_domains_match,
|
verify::verify_domains_match,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{source::private_message::PrivateMessage_, Crud, DbPool};
|
use lemmy_db_schema::{
|
||||||
use lemmy_db_schema::source::{
|
source::{
|
||||||
person::Person,
|
person::Person,
|
||||||
private_message::{PrivateMessage, PrivateMessageForm},
|
private_message::{PrivateMessage, PrivateMessageForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{utils::convert_datetime, LemmyError};
|
use lemmy_utils::{utils::convert_datetime, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
use std::ops::Deref;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
|
@ -35,8 +41,8 @@ pub struct Note {
|
||||||
context: OneOrMany<AnyBase>,
|
context: OneOrMany<AnyBase>,
|
||||||
r#type: NoteType,
|
r#type: NoteType,
|
||||||
id: Url,
|
id: Url,
|
||||||
pub(crate) attributed_to: ObjectId<Person>,
|
pub(crate) attributed_to: ObjectId<ApubPerson>,
|
||||||
to: ObjectId<Person>,
|
to: ObjectId<ApubPerson>,
|
||||||
content: String,
|
content: String,
|
||||||
media_type: MediaTypeHtml,
|
media_type: MediaTypeHtml,
|
||||||
source: Source,
|
source: Source,
|
||||||
|
@ -72,9 +78,54 @@ impl Note {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ApubPrivateMessage(PrivateMessage);
|
||||||
|
|
||||||
|
impl Deref for ApubPrivateMessage {
|
||||||
|
type Target = PrivateMessage;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PrivateMessage> for ApubPrivateMessage {
|
||||||
|
fn from(pm: PrivateMessage) -> Self {
|
||||||
|
ApubPrivateMessage { 0: pm }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ToApub for PrivateMessage {
|
impl ApubObject for ApubPrivateMessage {
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<Option<Self>, LemmyError> {
|
||||||
|
Ok(
|
||||||
|
blocking(context.pool(), move |conn| {
|
||||||
|
PrivateMessage::read_from_apub_id(conn, object_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn delete(self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
|
// do nothing, because pm can't be fetched over http
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl ToApub for ApubPrivateMessage {
|
||||||
type ApubType = Note;
|
type ApubType = Note;
|
||||||
|
type TombstoneType = Tombstone;
|
||||||
|
type DataType = DbPool;
|
||||||
|
|
||||||
async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
|
async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
|
||||||
let creator_id = self.creator_id;
|
let creator_id = self.creator_id;
|
||||||
|
@ -113,15 +164,16 @@ impl ToApub for PrivateMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for PrivateMessage {
|
impl FromApub for ApubPrivateMessage {
|
||||||
type ApubType = Note;
|
type ApubType = Note;
|
||||||
|
type DataType = LemmyContext;
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
note: &Note,
|
note: &Note,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: &Url,
|
expected_domain: &Url,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<PrivateMessage, LemmyError> {
|
) -> Result<ApubPrivateMessage, LemmyError> {
|
||||||
let ap_id = Some(note.id(expected_domain)?.clone().into());
|
let ap_id = Some(note.id(expected_domain)?.clone().into());
|
||||||
let creator = note
|
let creator = note
|
||||||
.attributed_to
|
.attributed_to
|
||||||
|
@ -140,11 +192,10 @@ impl FromApub for PrivateMessage {
|
||||||
ap_id,
|
ap_id,
|
||||||
local: Some(false),
|
local: Some(false),
|
||||||
};
|
};
|
||||||
Ok(
|
let pm = blocking(context.pool(), move |conn| {
|
||||||
blocking(context.pool(), move |conn| {
|
|
||||||
PrivateMessage::upsert(conn, &form)
|
PrivateMessage::upsert(conn, &form)
|
||||||
})
|
})
|
||||||
.await??,
|
.await??;
|
||||||
)
|
Ok(pm.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,21 @@ pub trait ActivityHandler {
|
||||||
) -> Result<(), LemmyError>;
|
) -> Result<(), LemmyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait ApubObject {
|
pub trait ApubObject {
|
||||||
type DataType;
|
type DataType;
|
||||||
/// If this object should be refetched after a certain interval, it should return the last refresh
|
/// If this object should be refetched after a certain interval, it should return the last refresh
|
||||||
/// time here. This is mainly used to update remote actors.
|
/// time here. This is mainly used to update remote actors.
|
||||||
fn last_refreshed_at(&self) -> Option<NaiveDateTime>;
|
fn last_refreshed_at(&self) -> Option<NaiveDateTime>;
|
||||||
/// Try to read the object with given ID from local database. Returns Ok(None) if it doesn't exist.
|
/// Try to read the object with given ID from local database. Returns Ok(None) if it doesn't exist.
|
||||||
fn read_from_apub_id(data: &Self::DataType, object_id: Url) -> Result<Option<Self>, LemmyError>
|
async fn read_from_apub_id(
|
||||||
|
object_id: Url,
|
||||||
|
data: &Self::DataType,
|
||||||
|
) -> Result<Option<Self>, LemmyError>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
/// Marks the object as deleted in local db. Called when a tombstone is received.
|
||||||
|
async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
|
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
|
||||||
|
@ -65,3 +71,35 @@ pub trait ActorType {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for converting an object or actor into the respective ActivityPub type.
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
pub trait ToApub {
|
||||||
|
type ApubType;
|
||||||
|
type TombstoneType;
|
||||||
|
type DataType;
|
||||||
|
|
||||||
|
async fn to_apub(&self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError>;
|
||||||
|
fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
pub trait FromApub {
|
||||||
|
type ApubType;
|
||||||
|
type DataType;
|
||||||
|
|
||||||
|
/// Converts an object from ActivityPub type to Lemmy internal type.
|
||||||
|
///
|
||||||
|
/// * `apub` The object to read from
|
||||||
|
/// * `context` LemmyContext which holds DB pool, HTTP client etc
|
||||||
|
/// * `expected_domain` Domain where the object was received from. None in case of mod action.
|
||||||
|
/// * `mod_action_allowed` True if the object can be a mod activity, ignore `expected_domain` in this case
|
||||||
|
async fn from_apub(
|
||||||
|
apub: &Self::ApubType,
|
||||||
|
data: &Self::DataType,
|
||||||
|
expected_domain: &Url,
|
||||||
|
request_counter: &mut i32,
|
||||||
|
) -> Result<Self, LemmyError>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "lemmy_db_queries"
|
|
||||||
version = "0.13.0"
|
|
||||||
edition = "2018"
|
|
||||||
description = "A link aggregator for the fediverse"
|
|
||||||
license = "AGPL-3.0"
|
|
||||||
homepage = "https://join-lemmy.org/"
|
|
||||||
documentation = "https://join-lemmy.org/docs/en/index.html"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "lemmy_db_queries"
|
|
||||||
path = "src/lib.rs"
|
|
||||||
doctest = false
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
|
||||||
lemmy_db_schema = { version = "=0.13.0", path = "../db_schema" }
|
|
||||||
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
|
|
||||||
diesel_migrations = "1.4.0"
|
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
|
||||||
serde = { version = "1.0.130", features = ["derive"] }
|
|
||||||
serde_json = { version = "1.0.68", features = ["preserve_order"] }
|
|
||||||
strum = "0.21.0"
|
|
||||||
strum_macros = "0.21.1"
|
|
||||||
log = "0.4.14"
|
|
||||||
sha2 = "0.9.8"
|
|
||||||
url = { version = "2.2.2", features = ["serde"] }
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
regex = "1.5.4"
|
|
||||||
bcrypt = "0.10.1"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
serial_test = "0.5.1"
|
|
|
@ -1,348 +0,0 @@
|
||||||
#[macro_use]
|
|
||||||
extern crate diesel;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate strum_macros;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
// this is used in tests
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
#[macro_use]
|
|
||||||
extern crate diesel_migrations;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
extern crate serial_test;
|
|
||||||
|
|
||||||
use diesel::{result::Error, *};
|
|
||||||
use lemmy_db_schema::{CommunityId, DbUrl, PersonId};
|
|
||||||
use lemmy_utils::ApiError;
|
|
||||||
use regex::Regex;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{env, env::VarError};
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
pub mod aggregates;
|
|
||||||
pub mod source;
|
|
||||||
|
|
||||||
pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
|
|
||||||
|
|
||||||
pub trait Crud {
|
|
||||||
type Form;
|
|
||||||
type IdType;
|
|
||||||
fn create(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn read(conn: &PgConnection, id: Self::IdType) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn update(conn: &PgConnection, id: Self::IdType, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn delete(_conn: &PgConnection, _id: Self::IdType) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Followable {
|
|
||||||
type Form;
|
|
||||||
fn follow(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn follow_accepted(
|
|
||||||
conn: &PgConnection,
|
|
||||||
community_id: CommunityId,
|
|
||||||
person_id: PersonId,
|
|
||||||
) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn unfollow(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn has_local_followers(conn: &PgConnection, community_id: CommunityId) -> Result<bool, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Joinable {
|
|
||||||
type Form;
|
|
||||||
fn join(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn leave(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Likeable {
|
|
||||||
type Form;
|
|
||||||
type IdType;
|
|
||||||
fn like(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn remove(
|
|
||||||
conn: &PgConnection,
|
|
||||||
person_id: PersonId,
|
|
||||||
item_id: Self::IdType,
|
|
||||||
) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Bannable {
|
|
||||||
type Form;
|
|
||||||
fn ban(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn unban(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Saveable {
|
|
||||||
type Form;
|
|
||||||
fn save(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn unsave(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Blockable {
|
|
||||||
type Form;
|
|
||||||
fn block(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn unblock(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Readable {
|
|
||||||
type Form;
|
|
||||||
fn mark_as_read(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn mark_as_unread(conn: &PgConnection, form: &Self::Form) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Reportable {
|
|
||||||
type Form;
|
|
||||||
type IdType;
|
|
||||||
fn report(conn: &PgConnection, form: &Self::Form) -> Result<Self, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn resolve(
|
|
||||||
conn: &PgConnection,
|
|
||||||
report_id: Self::IdType,
|
|
||||||
resolver_id: PersonId,
|
|
||||||
) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
fn unresolve(
|
|
||||||
conn: &PgConnection,
|
|
||||||
report_id: Self::IdType,
|
|
||||||
resolver_id: PersonId,
|
|
||||||
) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait DeleteableOrRemoveable {
|
|
||||||
fn blank_out_deleted_or_removed_info(self) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait MaybeOptional<T> {
|
|
||||||
fn get_optional(self) -> Option<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> MaybeOptional<T> for T {
|
|
||||||
fn get_optional(self) -> Option<T> {
|
|
||||||
Some(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> MaybeOptional<T> for Option<T> {
|
|
||||||
fn get_optional(self) -> Option<T> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ToSafe {
|
|
||||||
type SafeColumns;
|
|
||||||
fn safe_columns_tuple() -> Self::SafeColumns;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ToSafeSettings {
|
|
||||||
type SafeSettingsColumns;
|
|
||||||
fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ViewToVec {
|
|
||||||
type DbTuple;
|
|
||||||
fn from_tuple_to_vec(tuple: Vec<Self::DbTuple>) -> Vec<Self>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_database_url_from_env() -> Result<String, VarError> {
|
|
||||||
env::var("LEMMY_DATABASE_URL")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone, Copy)]
|
|
||||||
pub enum SortType {
|
|
||||||
Active,
|
|
||||||
Hot,
|
|
||||||
New,
|
|
||||||
TopDay,
|
|
||||||
TopWeek,
|
|
||||||
TopMonth,
|
|
||||||
TopYear,
|
|
||||||
TopAll,
|
|
||||||
MostComments,
|
|
||||||
NewComments,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone, Copy)]
|
|
||||||
pub enum ListingType {
|
|
||||||
All,
|
|
||||||
Local,
|
|
||||||
Subscribed,
|
|
||||||
Community,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone, Copy)]
|
|
||||||
pub enum SearchType {
|
|
||||||
All,
|
|
||||||
Comments,
|
|
||||||
Posts,
|
|
||||||
Communities,
|
|
||||||
Users,
|
|
||||||
Url,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_opt_str_to_opt_enum<T: std::str::FromStr>(opt: &Option<String>) -> Option<T> {
|
|
||||||
opt.as_ref().map(|t| T::from_str(t).ok()).flatten()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fuzzy_search(q: &str) -> String {
|
|
||||||
let replaced = q.replace(" ", "%");
|
|
||||||
format!("%{}%", replaced)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) {
|
|
||||||
let page = page.unwrap_or(1);
|
|
||||||
let limit = limit.unwrap_or(10);
|
|
||||||
let offset = limit * (page - 1);
|
|
||||||
(limit, offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_email_regex(test: &str) -> bool {
|
|
||||||
EMAIL_REGEX.is_match(test)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn diesel_option_overwrite(opt: &Option<String>) -> Option<Option<String>> {
|
|
||||||
match opt {
|
|
||||||
// An empty string is an erase
|
|
||||||
Some(unwrapped) => {
|
|
||||||
if !unwrapped.eq("") {
|
|
||||||
Some(Some(unwrapped.to_owned()))
|
|
||||||
} else {
|
|
||||||
Some(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn diesel_option_overwrite_to_url(
|
|
||||||
opt: &Option<String>,
|
|
||||||
) -> Result<Option<Option<DbUrl>>, ApiError> {
|
|
||||||
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)),
|
|
||||||
},
|
|
||||||
None => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
embed_migrations!();
|
|
||||||
|
|
||||||
pub fn establish_unpooled_connection() -> PgConnection {
|
|
||||||
let db_url = match get_database_url_from_env() {
|
|
||||||
Ok(url) => url,
|
|
||||||
Err(e) => panic!(
|
|
||||||
"Failed to read database URL from env var LEMMY_DATABASE_URL: {}",
|
|
||||||
e
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let conn =
|
|
||||||
PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
|
|
||||||
embedded_migrations::run(&conn).expect("load migrations");
|
|
||||||
conn
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref EMAIL_REGEX: Regex =
|
|
||||||
Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
|
||||||
.expect("compile email regex");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod functions {
|
|
||||||
use diesel::sql_types::*;
|
|
||||||
|
|
||||||
sql_function! {
|
|
||||||
fn hot_rank(score: BigInt, time: Timestamp) -> Integer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::{fuzzy_search, *};
|
|
||||||
use crate::is_email_regex;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_fuzzy_search() {
|
|
||||||
let test = "This is a fuzzy search";
|
|
||||||
assert_eq!(fuzzy_search(test), "%This%is%a%fuzzy%search%".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_email() {
|
|
||||||
assert!(is_email_regex("gush@gmail.com"));
|
|
||||||
assert!(!is_email_regex("nada_neutho"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_diesel_option_overwrite() {
|
|
||||||
assert_eq!(diesel_option_overwrite(&None), None);
|
|
||||||
assert_eq!(diesel_option_overwrite(&Some("".to_string())), Some(None));
|
|
||||||
assert_eq!(
|
|
||||||
diesel_option_overwrite(&Some("test".to_string())),
|
|
||||||
Some(Some("test".to_string()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_diesel_option_overwrite_to_url() {
|
|
||||||
assert!(matches!(diesel_option_overwrite_to_url(&None), Ok(None)));
|
|
||||||
assert!(matches!(
|
|
||||||
diesel_option_overwrite_to_url(&Some("".to_string())),
|
|
||||||
Ok(Some(None))
|
|
||||||
));
|
|
||||||
assert!(matches!(
|
|
||||||
diesel_option_overwrite_to_url(&Some("invalid_url".to_string())),
|
|
||||||
Err(_)
|
|
||||||
));
|
|
||||||
let example_url = "https://example.com";
|
|
||||||
assert!(matches!(
|
|
||||||
diesel_option_overwrite_to_url(&Some(example_url.to_string())),
|
|
||||||
Ok(Some(Some(url))) if url == Url::parse(example_url).unwrap().into()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
use diesel::{result::Error, *};
|
|
||||||
use lemmy_db_schema::source::secret::Secret;
|
|
||||||
|
|
||||||
pub trait Secret_ {
|
|
||||||
fn init(conn: &PgConnection) -> Result<Secret, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Secret_ for Secret {
|
|
||||||
/// Initialize the Secrets from the DB.
|
|
||||||
/// Warning: You should only call this once.
|
|
||||||
fn init(conn: &PgConnection) -> Result<Secret, Error> {
|
|
||||||
read_secrets(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_secrets(conn: &PgConnection) -> Result<Secret, Error> {
|
|
||||||
use lemmy_db_schema::schema::secret::dsl::*;
|
|
||||||
secret.first::<Secret>(conn)
|
|
||||||
}
|
|
|
@ -12,11 +12,20 @@ doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
lemmy_utils = { version = "=0.13.0", path = "../utils" }
|
||||||
lemmy_apub_lib = { version = "=0.13.0", path = "../apub_lib" }
|
|
||||||
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
|
diesel = { version = "1.4.8", features = ["postgres","chrono","r2d2","serde_json"] }
|
||||||
|
diesel_migrations = "1.4.0"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
serde = { version = "1.0.130", features = ["derive"] }
|
serde = { version = "1.0.130", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.68", features = ["preserve_order"] }
|
serde_json = { version = "1.0.68", features = ["preserve_order"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
url = { version = "2.2.2", features = ["serde"] }
|
url = { version = "2.2.2", features = ["serde"] }
|
||||||
diesel-derive-newtype = "0.1.2"
|
diesel-derive-newtype = "0.1.2"
|
||||||
|
regex = "1.5.4"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
strum = "0.21.0"
|
||||||
|
strum_macros = "0.21.1"
|
||||||
|
sha2 = "0.9.8"
|
||||||
|
bcrypt = "0.10.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serial_test = "0.5.1"
|
|
@ -1,5 +1,5 @@
|
||||||
|
use crate::{newtypes::CommentId, schema::comment_aggregates};
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::{schema::comment_aggregates, CommentId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -28,14 +28,13 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::comment_aggregates::CommentAggregates,
|
aggregates::comment_aggregates::CommentAggregates,
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
source::{
|
||||||
Likeable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
|
},
|
||||||
|
traits::{Crud, Likeable},
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use crate::{newtypes::CommunityId, schema::community_aggregates};
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::{schema::community_aggregates, CommunityId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -32,14 +32,13 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::community_aggregates::CommunityAggregates,
|
aggregates::community_aggregates::CommunityAggregates,
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
source::{
|
||||||
Followable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm},
|
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
|
},
|
||||||
|
traits::{Crud, Followable},
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use crate::{newtypes::PersonId, schema::person_aggregates};
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::{schema::person_aggregates, PersonId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -28,14 +28,13 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::person_aggregates::PersonAggregates,
|
aggregates::person_aggregates::PersonAggregates,
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
source::{
|
||||||
Likeable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm, PostLike, PostLikeForm},
|
post::{Post, PostForm, PostLike, PostLikeForm},
|
||||||
|
},
|
||||||
|
traits::{Crud, Likeable},
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use crate::{newtypes::PostId, schema::post_aggregates};
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::{schema::post_aggregates, PostId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -32,14 +32,13 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::post_aggregates::PostAggregates,
|
aggregates::post_aggregates::PostAggregates,
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
source::{
|
||||||
Likeable,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm, PostLike, PostLikeForm},
|
post::{Post, PostForm, PostLike, PostLikeForm},
|
||||||
|
},
|
||||||
|
traits::{Crud, Likeable},
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use crate::schema::site_aggregates;
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::schema::site_aggregates;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -27,13 +27,17 @@ impl SiteAggregates {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{aggregates::site_aggregates::SiteAggregates, establish_unpooled_connection, Crud};
|
use crate::{
|
||||||
use lemmy_db_schema::source::{
|
aggregates::site_aggregates::SiteAggregates,
|
||||||
|
establish_unpooled_connection,
|
||||||
|
source::{
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
site::{Site, SiteForm},
|
site::{Site, SiteForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::Crud;
|
use crate::{newtypes::DbUrl, source::activity::*, traits::Crud};
|
||||||
use diesel::{dsl::*, result::Error, sql_types::Text, *};
|
use diesel::{dsl::*, result::Error, sql_types::Text, *};
|
||||||
use lemmy_db_schema::{source::activity::*, DbUrl};
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -12,12 +11,12 @@ impl Crud for Activity {
|
||||||
type Form = ActivityForm;
|
type Form = ActivityForm;
|
||||||
type IdType = i32;
|
type IdType = i32;
|
||||||
fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
activity.find(activity_id).first::<Self>(conn)
|
activity.find(activity_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(conn: &PgConnection, new_activity: &ActivityForm) -> Result<Self, Error> {
|
fn create(conn: &PgConnection, new_activity: &ActivityForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
insert_into(activity)
|
insert_into(activity)
|
||||||
.values(new_activity)
|
.values(new_activity)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -28,40 +27,19 @@ impl Crud for Activity {
|
||||||
activity_id: i32,
|
activity_id: i32,
|
||||||
new_activity: &ActivityForm,
|
new_activity: &ActivityForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
diesel::update(activity.find(activity_id))
|
diesel::update(activity.find(activity_id))
|
||||||
.set(new_activity)
|
.set(new_activity)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
fn delete(conn: &PgConnection, activity_id: i32) -> Result<usize, Error> {
|
fn delete(conn: &PgConnection, activity_id: i32) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
diesel::delete(activity.find(activity_id)).execute(conn)
|
diesel::delete(activity.find(activity_id)).execute(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Activity_ {
|
impl Activity {
|
||||||
fn insert<T>(
|
pub fn insert<T>(
|
||||||
conn: &PgConnection,
|
|
||||||
ap_id: DbUrl,
|
|
||||||
data: &T,
|
|
||||||
local: bool,
|
|
||||||
sensitive: bool,
|
|
||||||
) -> Result<Activity, IoError>
|
|
||||||
where
|
|
||||||
T: Serialize + Debug;
|
|
||||||
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error>;
|
|
||||||
fn delete_olds(conn: &PgConnection) -> Result<usize, Error>;
|
|
||||||
|
|
||||||
/// Returns up to 20 activities of type `Announce/Create/Page` from the community
|
|
||||||
fn read_community_outbox(
|
|
||||||
conn: &PgConnection,
|
|
||||||
community_actor_id: &DbUrl,
|
|
||||||
) -> Result<Vec<Value>, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Activity_ for Activity {
|
|
||||||
fn insert<T>(
|
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
ap_id: DbUrl,
|
ap_id: DbUrl,
|
||||||
data: &T,
|
data: &T,
|
||||||
|
@ -88,21 +66,21 @@ impl Activity_ for Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error> {
|
pub fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_olds(conn: &PgConnection) -> Result<usize, Error> {
|
pub fn delete_olds(conn: &PgConnection) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
diesel::delete(activity.filter(published.lt(now - 6.months()))).execute(conn)
|
diesel::delete(activity.filter(published.lt(now - 6.months()))).execute(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_community_outbox(
|
pub fn read_community_outbox(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_actor_id: &DbUrl,
|
community_actor_id: &DbUrl,
|
||||||
) -> Result<Vec<Value>, Error> {
|
) -> Result<Vec<Value>, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use crate::schema::activity::dsl::*;
|
||||||
let res: Vec<Value> = activity
|
let res: Vec<Value> = activity
|
||||||
.select(data)
|
.select(data)
|
||||||
.filter(
|
.filter(
|
||||||
|
@ -122,10 +100,13 @@ impl Activity_ for Activity {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{establish_unpooled_connection, source::activity::Activity_};
|
use crate::{
|
||||||
use lemmy_db_schema::source::{
|
establish_unpooled_connection,
|
||||||
|
newtypes::DbUrl,
|
||||||
|
source::{
|
||||||
activity::{Activity, ActivityForm},
|
activity::{Activity, ActivityForm},
|
||||||
person::{Person, PersonForm},
|
person::{Person, PersonForm},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue