diff --git a/app/activitypub/routes.py b/app/activitypub/routes.py index 799fb21e..6bd0a8cf 100644 --- a/app/activitypub/routes.py +++ b/app/activitypub/routes.py @@ -203,7 +203,7 @@ def user_profile(actor): "outbox": f"https://{server}/u/{actor}/outbox", "discoverable": user.searchable, "indexable": user.indexable, - "manuallyApprovesFollowers": user.ap_manually_approves_followers, + "manuallyApprovesFollowers": False if not user.ap_manually_approves_followers else user.ap_manually_approves_followers, "publicKey": { "id": f"https://{server}/u/{actor}#main-key", "owner": f"https://{server}/u/{actor}", @@ -666,24 +666,48 @@ def process_inbox_request(request_json, activitypublog_id, ip_address): target_ap_id = request_json['object']['object']['object'] # object object object! post = undo_vote(activity_log, comment, post, target_ap_id, user) activity_log.result = 'success' - elif request_json['object']['type'] == 'Add': + elif request_json['object']['type'] == 'Add' and 'target' in request_json['object']: activity_log.activity_type = request_json['object']['type'] - featured_url = Community.query.filter(Community.ap_public_url == request_json['actor']).first().ap_featured_url - if featured_url: - if 'target' in request_json['object'] and featured_url == request_json['object']['target']: - post = Post.query.filter(Post.ap_id == request_json['object']['object']).first() + target = request_json['object']['target'] + community = Community.query.filter_by(ap_public_url=request_json['actor']).first() + if community: + featured_url = community.ap_featured_url + moderators_url = community.ap_moderators_url + if target == featured_url: + post = Post.query.filter_by(ap_id=request_json['object']['object']).first() if post: post.sticky = True activity_log.result = 'success' - elif request_json['object']['type'] == 'Remove': + if target == moderators_url: + user = find_actor_or_create(request_json['object']['object']) + if user: + existing_membership = CommunityMember.query.filter_by(community_id=community.id, user_id=user.id).first() + if existing_membership: + existing_membership.is_moderator = True + else: + new_membership = CommunityMember(community_id=community.id, user_id=user.id, is_moderator=True) + db.session.add(new_membership) + db.session.commit() + activity_log.result = 'success' + elif request_json['object']['type'] == 'Remove' and 'target' in request_json['object']: activity_log.activity_type = request_json['object']['type'] - featured_url = Community.query.filter(Community.ap_public_url == request_json['actor']).first().ap_featured_url - if featured_url: - if 'target' in request_json['object'] and featured_url == request_json['object']['target']: - post = Post.query.filter(Post.ap_id == request_json['object']['object']).first() + target = request_json['object']['target'] + community = Community.query.filter_by(ap_public_url=request_json['actor']).first() + if community: + featured_url = community.ap_featured_url + moderators_url = community.ap_moderators_url + if target == featured_url: + post = Post.query.filter_by(ap_id=request_json['object']['object']).first() if post: post.sticky = False activity_log.result = 'success' + if target == moderators_url: + user = find_actor_or_create(request_json['object']['object'], create_if_not_found=False) + if user: + existing_membership = CommunityMember.query.filter_by(community_id=community.id, user_id=user.id).first() + if existing_membership: + existing_membership.is_moderator = False + activity_log.result = 'success' else: activity_log.exception_message = 'Invalid type for Announce' diff --git a/app/models.py b/app/models.py index 0ae48c51..8d19bb59 100644 --- a/app/models.py +++ b/app/models.py @@ -488,7 +488,7 @@ class User(UserMixin, db.Model): ap_fetched_at = db.Column(db.DateTime) ap_followers_url = db.Column(db.String(255)) ap_preferred_username = db.Column(db.String(255)) - ap_manually_approves_followers = db.Column(db.Boolean) + ap_manually_approves_followers = db.Column(db.Boolean, default=False) ap_deleted_at = db.Column(db.DateTime) ap_inbox_url = db.Column(db.String(255)) ap_domain = db.Column(db.String(255)) diff --git a/app/post/routes.py b/app/post/routes.py index 14990cbe..8af417ef 100644 --- a/app/post/routes.py +++ b/app/post/routes.py @@ -18,7 +18,7 @@ from app.post.util import post_replies, get_comment_branch, post_reply_count from app.constants import SUBSCRIPTION_MEMBER, POST_TYPE_LINK, POST_TYPE_IMAGE from app.models import Post, PostReply, \ PostReplyVote, PostVote, Notification, utcnow, UserBlock, DomainBlock, InstanceBlock, Report, Site, Community, \ - Topic + Topic, User from app.post import bp from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \ shorten_string, markdown_to_text, gibberish, ap_datetime, return_304, \ @@ -47,6 +47,12 @@ def show_post(post_id: int): mods = community_moderators(community.id) is_moderator = current_user.is_authenticated and any(mod.user_id == current_user.id for mod in mods) + if community.private_mods: + mod_list = [] + else: + mod_user_ids = [mod.user_id for mod in mods] + mod_list = User.query.filter(User.id.in_(mod_user_ids)).all() + # handle top-level comments/replies form = NewReplyForm() if current_user.is_authenticated and current_user.verified and form.validate_on_submit(): @@ -213,7 +219,7 @@ def show_post(post_id: int): breadcrumbs.append(breadcrumb) response = render_template('post/post.html', title=post.title, post=post, is_moderator=is_moderator, community=post.community, - breadcrumbs=breadcrumbs, related_communities=related_communities, + breadcrumbs=breadcrumbs, related_communities=related_communities, mods=mod_list, canonical=post.ap_id, form=form, replies=replies, THREAD_CUTOFF_DEPTH=constants.THREAD_CUTOFF_DEPTH, description=description, og_image=og_image, POST_TYPE_IMAGE=constants.POST_TYPE_IMAGE, POST_TYPE_LINK=constants.POST_TYPE_LINK, POST_TYPE_ARTICLE=constants.POST_TYPE_ARTICLE, @@ -409,9 +415,14 @@ def continue_discussion(post_id, comment_id): abort(404) mods = post.community.moderators() is_moderator = current_user.is_authenticated and any(mod.user_id == current_user.id for mod in mods) + if post.community.private_mods: + mod_list = [] + else: + mod_user_ids = [mod.user_id for mod in mods] + mod_list = User.query.filter(User.id.in_(mod_user_ids)).all() replies = get_comment_branch(post.id, comment.id, 'top') - response = render_template('post/continue_discussion.html', title=_('Discussing %(title)s', title=post.title), post=post, + response = render_template('post/continue_discussion.html', title=_('Discussing %(title)s', title=post.title), post=post, mods=mod_list, is_moderator=is_moderator, comment=comment, replies=replies, markdown_editor=current_user.is_authenticated and current_user.markdown_editor, moderating_communities=moderating_communities(current_user.get_id()), joined_communities=joined_communities(current_user.get_id()), community=post.community, @@ -438,6 +449,11 @@ def add_reply(post_id: int, comment_id: int): in_reply_to = PostReply.query.get_or_404(comment_id) mods = post.community.moderators() is_moderator = current_user.is_authenticated and any(mod.user_id == current_user.id for mod in mods) + if post.community.private_mods: + mod_list = [] + else: + mod_user_ids = [mod.user_id for mod in mods] + mod_list = User.query.filter(User.id.in_(mod_user_ids)).all() if in_reply_to.author.has_blocked_user(current_user.id): flash(_('You cannot reply to %(name)s', name=in_reply_to.author.display_name())) @@ -582,7 +598,7 @@ def add_reply(post_id: int, comment_id: int): form.notify_author.data = True return render_template('post/add_reply.html', title=_('Discussing %(title)s', title=post.title), post=post, is_moderator=is_moderator, form=form, comment=in_reply_to, markdown_editor=current_user.is_authenticated and current_user.markdown_editor, - moderating_communities=moderating_communities(current_user.get_id()), + moderating_communities=moderating_communities(current_user.get_id()), mods=mod_list, joined_communities = joined_communities(current_user.id), inoculation=inoculation[randint(0, len(inoculation) - 1)]) @@ -611,6 +627,14 @@ def post_edit(post_id: int): post = Post.query.get_or_404(post_id) form = CreatePostForm() del form.communities + + mods = post.community.moderators() + if post.community.private_mods: + mod_list = [] + else: + mod_user_ids = [mod.user_id for mod in mods] + mod_list = User.query.filter(User.id.in_(mod_user_ids)).all() + if post.user_id == current_user.id or post.community.is_moderator() or current_user.is_admin(): if g.site.enable_nsfl is False: form.nsfl.render_kw = {'disabled': True} @@ -731,7 +755,7 @@ def post_edit(post_id: int): if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()): form.sticky.render_kw = {'disabled': True} return render_template('post/post_edit.html', title=_('Edit post'), form=form, post=post, - markdown_editor=current_user.markdown_editor, + markdown_editor=current_user.markdown_editor, mods=mod_list, moderating_communities=moderating_communities(current_user.get_id()), joined_communities=joined_communities(current_user.get_id()), inoculation=inoculation[randint(0, len(inoculation) - 1)]