multiple bugfixes

This commit is contained in:
rimu 2024-01-09 20:44:08 +13:00
parent ec4be34d5d
commit 050d1d36d2
14 changed files with 59 additions and 60 deletions

View file

@ -1,3 +1,4 @@
from flask_login import current_user
from app import db, constants, cache, celery
from app.activitypub import bp
@ -144,10 +145,16 @@ def user_profile(actor):
""" Requests to this endpoint can be for a JSON representation of the user, or a HTML rendering of their profile.
The two types of requests are differentiated by the header """
actor = actor.strip()
if '@' in actor:
user: User = User.query.filter_by(ap_id=actor, deleted=False, banned=False).first()
if current_user.is_authenticated and current_user.is_admin():
if '@' in actor:
user: User = User.query.filter_by(ap_id=actor).first()
else:
user: User = User.query.filter_by(user_name=actor, ap_id=None).first()
else:
user: User = User.query.filter_by(user_name=actor, deleted=False, ap_id=None).first()
if '@' in actor:
user: User = User.query.filter_by(ap_id=actor, deleted=False, banned=False).first()
else:
user: User = User.query.filter_by(user_name=actor, deleted=False, ap_id=None).first()
if user is not None:
if request.method == 'HEAD':

View file

@ -59,6 +59,7 @@ def add_local():
db.session.add(membership)
db.session.commit()
flash(_('Your new community has been created.'))
cache.delete_memoized(community_membership, current_user, community)
return redirect('/c/' + community.name)
return render_template('community/add_local.html', title=_('Create community'), form=form)
@ -208,6 +209,9 @@ def subscribe(actor):
if community is not None:
if community_membership(current_user, community) != SUBSCRIPTION_MEMBER and community_membership(current_user, community) != SUBSCRIPTION_PENDING:
banned = CommunityBan.query.filter_by(user_id=current_user.id, community_id=community.id).first()
if banned:
flash(_('You cannot join this community'))
if remote:
# send ActivityPub message to remote community, asking to follow. Accept message will be sent to our shared inbox
join_request = CommunityJoinRequest(user_id=current_user.id, community_id=community.id)
@ -226,15 +230,11 @@ def subscribe(actor):
flash(_('You have joined %(name)s', name=community.title))
else:
flash(_('There was a problem while trying to join.'), 'error')
else: # for local communities, joining is instant
banned = CommunityBan.query.filter_by(user_id=current_user.id, community_id=community.id).first()
if banned:
flash(_('You cannot join this community'))
else:
member = CommunityMember(user_id=current_user.id, community_id=community.id)
db.session.add(member)
db.session.commit()
flash('You joined ' + community.title)
# for local communities, joining is instant
member = CommunityMember(user_id=current_user.id, community_id=community.id)
db.session.add(member)
db.session.commit()
flash('You joined ' + community.title)
referrer = request.headers.get('Referer', None)
cache.delete_memoized(community_membership, current_user, community)
if referrer is not None:
@ -288,7 +288,7 @@ def unsubscribe(actor):
db.session.query(CommunityJoinRequest).filter_by(user_id=current_user.id, community_id=community.id).delete()
db.session.commit()
flash('You are left ' + community.title)
flash('You have left ' + community.title)
cache.delete_memoized(community_membership, current_user, community)
else:
@ -390,7 +390,8 @@ def add_post(actor):
image_url = post.image.source_url
# NB image is a dict while attachment is a list of dicts (usually just one dict in the list)
page['image'] = {'type': 'Image', 'url': image_url}
page['attachment'] = [{'type': 'Link', 'href': post.image.source_url}] # source_url is always a https link, no need for .replace() as done above
if post.type == POST_TYPE_IMAGE:
page['attachment'] = [{'type': 'Link', 'href': post.image.source_url}] # source_url is always a https link, no need for .replace() as done above
if not community.is_local(): # this is a remote community - send the post to the instance that hosts it
success = post_request(community.ap_inbox_url, create, current_user.private_key,
current_user.ap_profile_id + '#main-key')

View file

@ -131,6 +131,9 @@ def actor_to_community(actor) -> Community:
@cache.memoize(timeout=50)
def opengraph_parse(url):
if '?' in url:
url = url.split('?')
url = url[0]
try:
return parse_page(url)
except Exception as ex:
@ -147,6 +150,7 @@ def url_to_thumbnail_file(filename) -> File:
final_place = os.path.join(directory, new_filename + file_extension)
with open(final_place, 'wb') as f:
f.write(response.content)
response.close()
with Image.open(final_place) as img:
img = ImageOps.exif_transpose(img)
img.thumbnail((150, 150))

View file

@ -572,29 +572,12 @@ class User(UserMixin, db.Model):
for file in files:
file.delete_from_disk()
self.delete_dependencies()
db.session.query(Report).filter(Report.reporter_id == self.id).delete()
db.session.query(Report).filter(Report.suspect_user_id == self.id).delete()
db.session.query(ActivityLog).filter(ActivityLog.user_id == self.id).delete()
db.session.query(PostVote).filter(PostVote.user_id == self.id).delete()
db.session.query(PostReplyVote).filter(PostReplyVote.user_id == self.id).delete()
db.session.query(PostReply).filter(PostReply.user_id == self.id).delete()
db.session.query(FilterKeyword).filter(FilterKeyword.user_id == self.id).delete()
db.session.query(Filter).filter(Filter.user_id == self.id).delete()
db.session.query(DomainBlock).filter(DomainBlock.user_id == self.id).delete()
db.session.query(CommunityJoinRequest).filter(CommunityJoinRequest.user_id == self.id).delete()
db.session.query(CommunityMember).filter(CommunityMember.user_id == self.id).delete()
db.session.query(CommunityBlock).filter(CommunityBlock.user_id == self.id).delete()
db.session.query(CommunityBan).filter(CommunityBan.user_id == self.id).delete()
db.session.query(Community).filter(Community.user_id == self.id).delete()
db.session.query(Post).filter(Post.user_id == self.id).delete()
db.session.query(UserNote).filter(UserNote.user_id == self.id).delete()
db.session.query(UserNote).filter(UserNote.target_id == self.id).delete()
db.session.query(UserFollowRequest).filter(UserFollowRequest.follow_id == self.id).delete()
db.session.query(UserFollowRequest).filter(UserFollowRequest.user_id == self.id).delete()
db.session.query(UserBlock).filter(UserBlock.blocked_id == self.id).delete()
db.session.query(UserBlock).filter(UserBlock.blocker_id == self.id).delete()
db.session.execute(text('DELETE FROM user_role WHERE user_id = :user_id'),
{'user_id': self.id})
posts = Post.query.filter_by(user_id=self.id).all()
for post in posts:
post.delete_dependencies()
post.flush_cache()
db.session.delete(post)
db.session.commit()
class ActivityLog(db.Model):

View file

@ -59,7 +59,7 @@
<h3>Moderators</h3>
<ul class="moderator_list">
{% for mod in mods %}
<li><a href="/u/{{ mod.user_name }}">{{ mod.display_name() }}</a></li>
<li><a href="/u/{{ mod.link() }}">{{ mod.display_name() }}</a></li>
{% endfor %}
</ul>
{% endif %}

View file

@ -89,7 +89,7 @@
<h3>Moderators</h3>
<ul class="moderator_list">
{% for mod in mods %}
<li><a href="/u/{{ mod.user_name }}">{{ mod.display_name() }}</a></li>
<li><a href="/u/{{ mod.link() }}">{{ mod.display_name() }}</a></li>
{% endfor %}
</ul>
{% endif %}

View file

@ -174,7 +174,7 @@
<h3>Moderators</h3>
<ul class="moderator_list">
{% for mod in mods %}
<li><a href="/u/{{ mod.user_name }}">{{ mod.display_name() }}</a></li>
<li><a href="/u/{{ mod.link() }}">{{ mod.display_name() }}</a></li>
{% endfor %}
</ul>
{% endif %}

View file

@ -62,7 +62,7 @@
<h3>Moderators</h3>
<ol>
{% for mod in mods %}
<li><a href="/u/{{ mod.user_name }}">{{ mod.display_name() }}</a></li>
<li><a href="/u/{{ mod.link() }}">{{ mod.display_name() }}</a></li>
{% endfor %}
</ol>
{% endif %}

View file

@ -7,7 +7,7 @@
<div class="card mt-5">
<div class="card-body p-6">
<div class="card-title">{{ _('Report comment on "%(post_title)s" by %(reply_name)s',
post_title=post.title, reply_name=post_reply.author.user_name) }}</div>
post_title=post.title, reply_name=post_reply.author.link()) }}</div>
<div class="card-body">
{{ render_form(form) }}
</div>

View file

@ -7,11 +7,11 @@
<nav aria-label="breadcrumb" id="breadcrumb_nav" title="Navigation">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">{{ _('Home') }}</a></li>
<li class="breadcrumb-item"><a href="/u/{{ user.user_name }}">{{ user.display_name() }}</a></li>
<li class="breadcrumb-item"><a href="/u/{{ user.link() }}">{{ user.display_name() }}</a></li>
<li class="breadcrumb-item active">{{ _('Change settings') }}</li>
</ol>
</nav>
<h1 class="mt-2">{{ _('Delete %(username)s', username=user.user_name) }}</h1>
<h1 class="mt-2">{{ _('Delete %(username)s', username=user.link()) }}</h1>
<form method='post'>
<p class="btn-warning">{{ _('You are about to permanently delete the account with the username "<strong>%(username)s</strong>." This means your profile will disappear, pictures will be deleted. Text-based posts will stay but look like they are from someone named "deleted."', username=user.user_name) }}</p>
<p>{{ _('Once you hit delete, nobody can use "%(username)s" as a username again. We are doing this so nobody pretends to be you.', username=user.user_name) }}</p>

View file

@ -7,7 +7,7 @@
<nav aria-label="breadcrumb" id="breadcrumb_nav" title="Navigation">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">{{ _('Home') }}</a></li>
<li class="breadcrumb-item"><a href="/u/{{ user.user_name }}">{{ user.display_name() }}</a></li>
<li class="breadcrumb-item"><a href="/u/{{ user.link() }}">{{ user.display_name() }}</a></li>
<li class="breadcrumb-item active">{{ _('Edit profile') }}</li>
</ol>
</nav>
@ -22,9 +22,9 @@
{{ render_field(form.matrix_user_id) }}
<small class="field_hint">e.g. @something:matrix.org. Include leading @ and use : before server</small>
{{ render_field(form.profile_file) }}
<small class="field_hint">Provide a square image that looks good when small. <strong>Bug: file extension must be lower case</strong>, for some reason</small>
<small class="field_hint">Provide a square image that looks good when small.</small>
{{ render_field(form.banner_file) }}
<small class="field_hint">Provide a wide image - letterbox orientation. <strong>Bug: file extension must be lower case</strong></small>
<small class="field_hint">Provide a wide image - letterbox orientation.</small>
<hr />
{{ render_field(form.bot) }}
{{ render_field(form.submit) }}

View file

@ -7,7 +7,7 @@
<nav aria-label="breadcrumb" id="breadcrumb_nav" title="Navigation">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">{{ _('Home') }}</a></li>
<li class="breadcrumb-item"><a href="/u/{{ user.user_name }}">{{ user.display_name() }}</a></li>
<li class="breadcrumb-item"><a href="/u/{{ user.link() }}">{{ user.display_name() }}</a></li>
<li class="breadcrumb-item active">{{ _('Change settings') }}</li>
</ol>
</nav>

View file

@ -15,14 +15,14 @@
</nav>
</div>
<img class="community_icon_big bump_up rounded-circle" src="{{ user.avatar_image() }}" />
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.ap_id }}</h1>
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}</h1>
{% elif user.avatar_image() != '' %}
<div class="row">
<div class="col-2">
<img class="community_icon_big rounded-circle" src="{{ user.avatar_image() }}" />
</div>
<div class="col-10">
<h1 class="mt-3">{{ user.display_name() if user.is_local() else user.ap_id }}</h1>
<h1 class="mt-3">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}</h1>
</div>
</div>
{% else %}
@ -30,10 +30,10 @@
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/">{{ _('Home') }}</a></li>
<li class="breadcrumb-item"><a href="/people">{{ _('People') }}</a></li>
<li class="breadcrumb-item active">{{ user.user_name|shorten }}</li>
<li class="breadcrumb-item active">{{ user.link()|shorten }}</li>
</ol>
</nav>
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.ap_id }}</h1>
<h1 class="mt-2">{{ user.display_name() if user.is_local() else user.display_name() + ', ' + user.ap_id }}</h1>
{% endif %}
{% if current_user.is_authenticated %}
<div class="profile_action_buttons">
@ -157,20 +157,20 @@
{% if user_access('ban users', current_user.id) %}
{% if user.banned %}
<div class="col-4">
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.user_name }}/unban">{{ _('Unban') }}</a>
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.link() }}/unban">{{ _('Unban') }}</a>
</div>
{% else %}
<div class="col-4">
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.user_name }}/ban">{{ _('Ban') }}</a>
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.link() }}/ban">{{ _('Ban') }}</a>
</div>
{% endif %}
{% endif %}
{% if user_access('manage users', current_user.id) %}
<div class="col-4">
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.user_name }}/delete">{{ _('Delete') }}</a>
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.link() }}/delete">{{ _('Delete') }}</a>
</div>
<div class="col-4">
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.user_name }}/ban_purge">{{ _('Ban + Purge') }}</a>
<a class="w-100 btn btn-primary confirm_first" href="/u/{{ user.link() }}/ban_purge">{{ _('Ban + Purge') }}</a>
</div>
{% endif %}
</div>

View file

@ -28,9 +28,14 @@ def show_people():
def show_profile(user):
if user.deleted or user.banned and current_user.is_anonymous():
if (user.deleted or user.banned) and current_user.is_anonymous:
abort(404)
if user.banned:
flash(_('This user has been banned.'), 'warning')
if user.deleted:
flash(_('This user has been deleted.'), 'warning')
post_page = request.args.get('post_page', 1, type=int)
replies_page = request.args.get('replies_page', 1, type=int)
@ -415,9 +420,9 @@ def send_deletion_requests(user_id):
def ban_purge_profile(actor):
if user_access('manage users', current_user.id):
actor = actor.strip()
user = User.query.filter_by(user_name=actor, deleted=False).first()
user = User.query.filter_by(user_name=actor).first()
if user is None:
user = User.query.filter_by(ap_id=actor, deleted=False).first()
user = User.query.filter_by(ap_id=actor).first()
if user is None:
abort(404)
@ -429,7 +434,6 @@ def ban_purge_profile(actor):
db.session.commit()
user.purge_content()
db.session.delete(user)
db.session.commit()
# todo: empty relevant caches