mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 03:11:32 +00:00
Add some communities sub scopes
This commit is contained in:
parent
25f75a0332
commit
d9905824eb
6 changed files with 239 additions and 36 deletions
|
@ -7,7 +7,7 @@ use lemmy_api_common::{
|
|||
utils::check_community_mod_action,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
newtypes::{CommunityId, PersonId},
|
||||
source::{
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
local_user::LocalUser,
|
||||
|
@ -24,9 +24,9 @@ pub async fn add_mod_to_community(
|
|||
data: Json<AddModToCommunity>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
path: Path<CommunityId>,
|
||||
path: Path<(CommunityId, PersonId)>,
|
||||
) -> LemmyResult<Json<AddModToCommunityResponse>> {
|
||||
let community_id = path.into_inner();
|
||||
let (community_id, person_id) = path.into_inner();
|
||||
let community = Community::read(&mut context.pool(), community_id).await?;
|
||||
// Verify that only mods or admins can add mod
|
||||
check_community_mod_action(
|
||||
|
@ -43,7 +43,7 @@ pub async fn add_mod_to_community(
|
|||
&mut context.pool(),
|
||||
community_id,
|
||||
local_user_view.person.id,
|
||||
vec![data.person_id],
|
||||
vec![person_id],
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ pub async fn add_mod_to_community(
|
|||
// Update in local database
|
||||
let community_moderator_form = CommunityModeratorForm {
|
||||
community_id,
|
||||
person_id: data.person_id,
|
||||
person_id,
|
||||
};
|
||||
if data.added {
|
||||
CommunityModerator::join(&mut context.pool(), &community_moderator_form)
|
||||
|
@ -78,7 +78,7 @@ pub async fn add_mod_to_community(
|
|||
// Mod tables
|
||||
let form = ModAddCommunityForm {
|
||||
mod_person_id: local_user_view.person.id,
|
||||
other_person_id: data.person_id,
|
||||
other_person_id: person_id,
|
||||
community_id,
|
||||
removed: Some(!data.added),
|
||||
};
|
||||
|
@ -93,7 +93,7 @@ pub async fn add_mod_to_community(
|
|||
SendActivityData::AddModToCommunity {
|
||||
moderator: local_user_view.person,
|
||||
community_id,
|
||||
target: data.person_id,
|
||||
target: person_id,
|
||||
added: data.added,
|
||||
},
|
||||
&context,
|
||||
|
|
|
@ -9,7 +9,7 @@ use lemmy_api_common::{
|
|||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
newtypes::{CommunityId, PersonId},
|
||||
source::{
|
||||
community::{
|
||||
Community, CommunityFollower, CommunityFollowerForm, CommunityPersonBan,
|
||||
|
@ -32,10 +32,9 @@ pub async fn ban_from_community(
|
|||
data: Json<BanFromCommunity>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
path: Path<CommunityId>,
|
||||
path: Path<(CommunityId, PersonId)>,
|
||||
) -> LemmyResult<Json<BanFromCommunityResponse>> {
|
||||
let community_id = path.into_inner();
|
||||
let banned_person_id = data.person_id;
|
||||
let (community_id, banned_person_id) = path.into_inner();
|
||||
let expires = check_expire_time(data.expires)?;
|
||||
let community = Community::read(&mut context.pool(), community_id).await?;
|
||||
|
||||
|
@ -52,7 +51,7 @@ pub async fn ban_from_community(
|
|||
&mut context.pool(),
|
||||
community_id,
|
||||
local_user_view.person.id,
|
||||
vec![data.person_id],
|
||||
vec![banned_person_id],
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -62,7 +61,7 @@ pub async fn ban_from_community(
|
|||
|
||||
let community_user_ban_form = CommunityPersonBanForm {
|
||||
community_id,
|
||||
person_id: data.person_id,
|
||||
person_id: banned_person_id,
|
||||
expires: Some(expires),
|
||||
};
|
||||
|
||||
|
@ -99,7 +98,7 @@ pub async fn ban_from_community(
|
|||
// Mod tables
|
||||
let form = ModBanFromCommunityForm {
|
||||
mod_person_id: local_user_view.person.id,
|
||||
other_person_id: data.person_id,
|
||||
other_person_id: banned_person_id,
|
||||
community_id,
|
||||
reason: data.reason.clone(),
|
||||
banned: Some(data.ban),
|
||||
|
@ -108,7 +107,7 @@ pub async fn ban_from_community(
|
|||
|
||||
ModBanFromCommunity::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let person_view = PersonView::read(&mut context.pool(), data.person_id, false).await?;
|
||||
let person_view = PersonView::read(&mut context.pool(), banned_person_id, false).await?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::BanFromCommunity {
|
||||
|
|
|
@ -6,7 +6,7 @@ use lemmy_api_common::{
|
|||
utils::{check_community_user_action, is_admin, is_top_mod},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
newtypes::{CommunityId, PersonId},
|
||||
source::{
|
||||
community::{Community, CommunityModerator, CommunityModeratorForm},
|
||||
mod_log::moderator::{ModTransferCommunity, ModTransferCommunityForm},
|
||||
|
@ -27,9 +27,9 @@ pub async fn transfer_community(
|
|||
data: Json<TransferCommunity>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
path: Path<CommunityId>,
|
||||
path: Path<(CommunityId, PersonId)>,
|
||||
) -> LemmyResult<Json<GetCommunityResponse>> {
|
||||
let community_id = path.into_inner();
|
||||
let (community_id, person_id) = path.into_inner();
|
||||
let community = Community::read(&mut context.pool(), community_id).await?;
|
||||
let mut community_mods =
|
||||
CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
|
||||
|
@ -46,7 +46,7 @@ pub async fn transfer_community(
|
|||
// Add the transferee to the top
|
||||
let creator_index = community_mods
|
||||
.iter()
|
||||
.position(|r| r.moderator.id == data.person_id)
|
||||
.position(|r| r.moderator.id == person_id)
|
||||
.context(location_info!())?;
|
||||
let creator_person = community_mods.remove(creator_index);
|
||||
community_mods.insert(0, creator_person);
|
||||
|
@ -70,7 +70,7 @@ pub async fn transfer_community(
|
|||
// Mod tables
|
||||
let form = ModTransferCommunityForm {
|
||||
mod_person_id: local_user_view.person.id,
|
||||
other_person_id: data.person_id,
|
||||
other_person_id: person_id,
|
||||
community_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::convert_published_time;
|
||||
use activitypub_federation::config::Data;
|
||||
use actix_web::web::Json;
|
||||
use actix_web::web::{Json, Path};
|
||||
use lemmy_api_common::{
|
||||
build_response::build_post_response,
|
||||
context::LemmyContext,
|
||||
|
@ -8,15 +8,13 @@ use lemmy_api_common::{
|
|||
request::generate_post_link_metadata,
|
||||
send_activity::SendActivityData,
|
||||
utils::{
|
||||
check_community_user_action,
|
||||
get_url_blocklist,
|
||||
honeypot_check,
|
||||
local_site_to_slur_regex,
|
||||
check_community_user_action, get_url_blocklist, honeypot_check, local_site_to_slur_regex,
|
||||
process_markdown_opt,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
impls::actor_language::validate_post_language,
|
||||
newtypes::CommunityId,
|
||||
source::{
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
|
@ -34,10 +32,7 @@ use lemmy_utils::{
|
|||
utils::{
|
||||
slurs::check_slurs,
|
||||
validation::{
|
||||
is_url_blocked,
|
||||
is_valid_alt_text_field,
|
||||
is_valid_body_field,
|
||||
is_valid_post_title,
|
||||
is_url_blocked, is_valid_alt_text_field, is_valid_body_field, is_valid_post_title,
|
||||
is_valid_url,
|
||||
},
|
||||
},
|
||||
|
@ -46,6 +41,114 @@ use tracing::Instrument;
|
|||
use url::Url;
|
||||
use webmention::{Webmention, WebmentionError};
|
||||
|
||||
#[tracing::instrument(skip(context))]
|
||||
pub async fn create_post_for_community(
|
||||
data: Json<CreatePost>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
path: Path<CommunityId>,
|
||||
) -> LemmyResult<Json<PostResponse>> {
|
||||
let community_id = path.into_inner();
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
|
||||
honeypot_check(&data.honeypot)?;
|
||||
|
||||
let slur_regex = local_site_to_slur_regex(&local_site);
|
||||
check_slurs(&data.name, &slur_regex)?;
|
||||
let url_blocklist = get_url_blocklist(&context).await?;
|
||||
|
||||
let body = process_markdown_opt(&data.body, &slur_regex, &url_blocklist, &context).await?;
|
||||
let url = diesel_url_create(data.url.as_deref())?;
|
||||
let custom_thumbnail = diesel_url_create(data.custom_thumbnail.as_deref())?;
|
||||
|
||||
is_valid_post_title(&data.name)?;
|
||||
|
||||
if let Some(url) = &url {
|
||||
is_url_blocked(url, &url_blocklist)?;
|
||||
is_valid_url(url)?;
|
||||
}
|
||||
|
||||
if let Some(custom_thumbnail) = &custom_thumbnail {
|
||||
is_valid_url(custom_thumbnail)?;
|
||||
}
|
||||
|
||||
if let Some(alt_text) = &data.alt_text {
|
||||
is_valid_alt_text_field(alt_text)?;
|
||||
}
|
||||
|
||||
if let Some(body) = &body {
|
||||
is_valid_body_field(body, true)?;
|
||||
}
|
||||
|
||||
let community = Community::read(&mut context.pool(), community_id).await?;
|
||||
check_community_user_action(&local_user_view.person, &community, &mut context.pool()).await?;
|
||||
|
||||
if community.posting_restricted_to_mods {
|
||||
CommunityModeratorView::check_is_community_moderator(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
local_user_view.local_user.person_id,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let language_id = validate_post_language(
|
||||
&mut context.pool(),
|
||||
data.language_id,
|
||||
community_id,
|
||||
local_user_view.local_user.id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let scheduled_publish_time =
|
||||
convert_published_time(data.scheduled_publish_time, &local_user_view, &context).await?;
|
||||
let post_form = PostInsertForm {
|
||||
url: url.map(Into::into),
|
||||
body,
|
||||
alt_text: data.alt_text.clone(),
|
||||
nsfw: data.nsfw,
|
||||
language_id: Some(language_id),
|
||||
scheduled_publish_time,
|
||||
..PostInsertForm::new(
|
||||
data.name.trim().to_string(),
|
||||
local_user_view.person.id,
|
||||
community_id,
|
||||
)
|
||||
};
|
||||
|
||||
let inserted_post = Post::create(&mut context.pool(), &post_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreatePost)?;
|
||||
|
||||
let federate_post = if scheduled_publish_time.is_none() {
|
||||
send_webmention(inserted_post.clone(), community);
|
||||
|post| Some(SendActivityData::CreatePost(post))
|
||||
} else {
|
||||
|_| None
|
||||
};
|
||||
generate_post_link_metadata(
|
||||
inserted_post.clone(),
|
||||
custom_thumbnail.map(Into::into),
|
||||
federate_post,
|
||||
context.reset_request_count(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// They like their own post by default
|
||||
let person_id = local_user_view.person.id;
|
||||
let post_id = inserted_post.id;
|
||||
let like_form = PostLikeForm::new(post_id, person_id, 1);
|
||||
|
||||
PostLike::like(&mut context.pool(), &like_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntLikePost)?;
|
||||
|
||||
let read_form = PostReadForm::new(post_id, person_id);
|
||||
PostRead::mark_as_read(&mut context.pool(), &read_form).await?;
|
||||
|
||||
build_post_response(&context, community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(context))]
|
||||
pub async fn create_post(
|
||||
data: Json<CreatePost>,
|
||||
|
|
|
@ -4,14 +4,14 @@ use crate::{
|
|||
objects::community::ApubCommunity,
|
||||
};
|
||||
use activitypub_federation::config::Data;
|
||||
use actix_web::web::{Json, Query};
|
||||
use actix_web::web::{Json, Path, Query};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
post::{GetPosts, GetPostsResponse},
|
||||
utils::{check_conflicting_like_filters, check_private_instance},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::PostId,
|
||||
newtypes::{CommunityId, PostId},
|
||||
source::{community::Community, post::PostRead},
|
||||
};
|
||||
use lemmy_db_views::{
|
||||
|
@ -20,6 +20,90 @@ use lemmy_db_views::{
|
|||
};
|
||||
use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult};
|
||||
|
||||
// API v4 TODO This is copy-pasted from list_posts. Refactor when API stabilizied.
|
||||
#[tracing::instrument(skip(context))]
|
||||
pub async fn list_posts_for_community(
|
||||
data: Query<GetPosts>,
|
||||
context: Data<LemmyContext>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
path: Path<CommunityId>,
|
||||
) -> LemmyResult<Json<GetPostsResponse>> {
|
||||
let community_id = Some(path.into_inner());
|
||||
let local_site = SiteView::read_local(&mut context.pool()).await?;
|
||||
|
||||
check_private_instance(&local_user_view, &local_site.local_site)?;
|
||||
|
||||
let page = data.page;
|
||||
let limit = data.limit;
|
||||
|
||||
let saved_only = data.saved_only;
|
||||
let show_hidden = data.show_hidden;
|
||||
let show_read = data.show_read;
|
||||
let show_nsfw = data.show_nsfw;
|
||||
let no_comments_only = data.no_comments_only;
|
||||
|
||||
let liked_only = data.liked_only;
|
||||
let disliked_only = data.disliked_only;
|
||||
check_conflicting_like_filters(liked_only, disliked_only)?;
|
||||
|
||||
let local_user = local_user_view.as_ref().map(|u| &u.local_user);
|
||||
let listing_type = Some(listing_type_with_default(
|
||||
data.type_,
|
||||
local_user,
|
||||
&local_site.local_site,
|
||||
community_id,
|
||||
));
|
||||
|
||||
let sort = Some(post_sort_type_with_default(
|
||||
data.sort,
|
||||
local_user,
|
||||
&local_site.local_site,
|
||||
));
|
||||
|
||||
// parse pagination token
|
||||
let page_after = if let Some(pa) = &data.page_cursor {
|
||||
Some(pa.read(&mut context.pool()).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let posts = PostQuery {
|
||||
local_user,
|
||||
listing_type,
|
||||
sort,
|
||||
community_id,
|
||||
saved_only,
|
||||
liked_only,
|
||||
disliked_only,
|
||||
page,
|
||||
page_after,
|
||||
limit,
|
||||
show_hidden,
|
||||
show_read,
|
||||
show_nsfw,
|
||||
no_comments_only,
|
||||
..Default::default()
|
||||
}
|
||||
.list(&local_site.site, &mut context.pool())
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntGetPosts)?;
|
||||
|
||||
// If in their user settings (or as part of the API request), auto-mark fetched posts as read
|
||||
if let Some(local_user) = local_user {
|
||||
if data
|
||||
.mark_as_read
|
||||
.unwrap_or(local_user.auto_mark_fetched_posts_as_read)
|
||||
{
|
||||
let post_ids = posts.iter().map(|p| p.post.id).collect::<Vec<PostId>>();
|
||||
PostRead::mark_many_as_read(&mut context.pool(), &post_ids, local_user.person_id).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// if this page wasn't empty, then there is a next page after the last post on this page
|
||||
let next_page = posts.last().map(PaginationCursor::after_post);
|
||||
Ok(Json(GetPostsResponse { posts, next_page }))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(context))]
|
||||
pub async fn list_posts(
|
||||
data: Query<GetPosts>,
|
||||
|
|
|
@ -93,7 +93,10 @@ use lemmy_api_crud::{
|
|||
create::create_oauth_provider, delete::delete_oauth_provider, update::update_oauth_provider,
|
||||
},
|
||||
post::{
|
||||
create::create_post, delete::delete_post, read::get_post, remove::remove_post,
|
||||
create::{create_post, create_post_for_community},
|
||||
delete::delete_post,
|
||||
read::get_post,
|
||||
remove::remove_post,
|
||||
update::update_post,
|
||||
},
|
||||
private_message::{
|
||||
|
@ -112,7 +115,7 @@ use lemmy_api_crud::{
|
|||
};
|
||||
use lemmy_apub::api::{
|
||||
list_comments::list_comments,
|
||||
list_posts::list_posts,
|
||||
list_posts::{list_posts, list_posts_for_community},
|
||||
read_community::get_community,
|
||||
read_person::read_person,
|
||||
resolve_object::resolve_object,
|
||||
|
@ -161,9 +164,23 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
.route("/follow", post().to(follow_community))
|
||||
// Mod Actions
|
||||
.route("/remove", post().to(remove_community))
|
||||
.route("/transfer", post().to(transfer_community))
|
||||
.route("/ban_user", post().to(ban_from_community))
|
||||
.route("/mod", post().to(add_mod_to_community))
|
||||
.service(
|
||||
scope("/posts")
|
||||
.route("", get().to(list_posts_for_community))
|
||||
.service(
|
||||
// Handle POST to /post separately to add the post() rate limitter
|
||||
resource("")
|
||||
.guard(guard::Post())
|
||||
.wrap(rate_limit.post())
|
||||
.route(post().to(create_post_for_community)),
|
||||
),
|
||||
)
|
||||
.service(
|
||||
scope("/users/{person_id}")
|
||||
.route("/transfer-moderation", post().to(transfer_community))
|
||||
.route("/ban", post().to(ban_from_community))
|
||||
.route("/appoint-mod", post().to(add_mod_to_community)),
|
||||
)
|
||||
.service(
|
||||
// TODO: Not sure what to do with these
|
||||
scope("/pending_follows")
|
||||
|
|
Loading…
Reference in a new issue