diff --git a/app/activitypub/routes.py b/app/activitypub/routes.py index 80874708..ec87a455 100644 --- a/app/activitypub/routes.py +++ b/app/activitypub/routes.py @@ -228,6 +228,9 @@ def shared_inbox(): activity_log.activity_type = request_json['type'] == 'Create (kbin)' user_ap_id = request_json['object']['attributedTo'] community_ap_id = request_json['to'][0] + if community_ap_id == 'https://www.w3.org/ns/activitystreams#Public': # kbin does this when posting a reply + if 'cc' in request_json['object'] and request_json['object']['cc']: + community_ap_id = request_json['object']['cc'][0] community = find_actor_or_create(community_ap_id) user = find_actor_or_create(user_ap_id) if user and community: @@ -253,12 +256,7 @@ def shared_inbox(): ap_announce_id=None, type=constants.POST_TYPE_ARTICLE ) - if 'source' in request_json['object'] and \ - request_json['object']['source'][ - 'mediaType'] == 'text/markdown': - post.body = request_json['object']['source']['content'] - post.body_html = markdown_to_html(post.body) - elif 'content' in request_json['object']: + if 'content' in request_json['object'] and request_json['object']['content'] is not None: post.body_html = allowlist_html(request_json['object']['content']) post.body = html_to_markdown(post.body_html) if 'attachment' in request_json['object'] and \ @@ -285,6 +283,7 @@ def shared_inbox(): if post is not None: db.session.add(post) community.post_count += 1 + community.last_active = datetime.utcnow() db.session.commit() else: post_id, parent_comment_id, root_id = find_reply_parent(in_reply_to) @@ -307,8 +306,11 @@ def shared_inbox(): post_reply.body = html_to_markdown(post_reply.body_html) if post_reply is not None: + post = Post.query.get(post_id) db.session.add(post_reply) + post.reply_count += 1 community.post_reply_count += 1 + community.last_active = datetime.utcnow() db.session.commit() else: activity_log.exception_message = 'Unacceptable type (kbin): ' + object_type @@ -538,6 +540,19 @@ def shared_inbox(): post.edited_at = datetime.utcnow() db.session.commit() activity_log.result = 'success' + elif request_json['object']['type'] == 'Note': # Editing a reply + reply = PostReply.query.filter_by(ap_id=request_json['object']['id']).first() + if reply: + if 'source' in request_json['object'] and \ + request_json['object']['source']['mediaType'] == 'text/markdown': + reply.body = request_json['object']['source']['content'] + reply.body_html = markdown_to_html(reply.body) + elif 'content' in request_json['object']: + reply.body_html = allowlist_html(request_json['object']['content']) + reply.body = html_to_markdown(reply.body_html) + reply.edited_at = datetime.utcnow() + db.session.commit() + activity_log.result = 'success' elif request_json['type'] == 'Delete': post = Post.query.filter_by(ap_id=request_json['object']['id']).first() if post: diff --git a/app/auth/routes.py b/app/auth/routes.py index 86db576b..092d62ae 100644 --- a/app/auth/routes.py +++ b/app/auth/routes.py @@ -22,7 +22,7 @@ def login(): return redirect(next_page) form = LoginForm() if form.validate_on_submit(): - user = User.query.filter_by(user_name=form.user_name.data).first() + user = User.query.filter_by(user_name=form.user_name.data, ap_id=None).first() if user is None: flash(_('No account exists with that user name address'), 'error') return redirect(url_for('auth.login')) diff --git a/app/community/forms.py b/app/community/forms.py index fdaef6ac..51ba62d9 100644 --- a/app/community/forms.py +++ b/app/community/forms.py @@ -64,7 +64,7 @@ class CreatePost(FlaskForm): if self.link_url.data == '': self.link_url.errors.append(_('URL is required.')) return False - domain = domain_from_url(self.link_url.data) + domain = domain_from_url(self.link_url.data, create=False) if domain and domain.banned: self.link_url.errors.append(_(f"Links to %s are not allowed.".format(domain.name))) return False diff --git a/app/community/routes.py b/app/community/routes.py index 66f398b9..3a55da08 100644 --- a/app/community/routes.py +++ b/app/community/routes.py @@ -205,7 +205,7 @@ def add_post(actor): post.title = form.link_title.data post.url = form.link_url.data post.type = POST_TYPE_LINK - domain = domain_from_url(form.link_url.data, create=True) + domain = domain_from_url(form.link_url.data) domain.post_count += 1 post.domain = domain elif form.type.data == 'image': diff --git a/app/models.py b/app/models.py index 54928c41..e6162a6b 100644 --- a/app/models.py +++ b/app/models.py @@ -124,7 +124,7 @@ user_role = db.Table('user_role', class User(UserMixin, db.Model): query_class = FullTextSearchQuery id = db.Column(db.Integer, primary_key=True) - user_name = db.Column(db.String(255), unique=True, index=True) + user_name = db.Column(db.String(255), index=True) email = db.Column(db.String(255), index=True) password_hash = db.Column(db.String(128)) verified = db.Column(db.Boolean, default=False) diff --git a/app/templates/community/post.html b/app/templates/community/post.html index 4d77cb90..71d4b00d 100644 --- a/app/templates/community/post.html +++ b/app/templates/community/post.html @@ -61,7 +61,7 @@ {{ comment['comment'].author.user_name }} {% endif %} {% if comment['comment'].author.id == post.author.id %}[OP]{% endif %} - {{ moment(comment['comment'].posted_at).fromNow(refresh=True) }} + {{ moment(comment['comment'].posted_at).fromNow(refresh=True) }}{% if comment['comment'].edited_at %}, edited {{ moment(comment['comment'].edited_at).fromNow(refresh=True) }} {% endif %}
{{ comment['comment'].body_html | safe }} diff --git a/app/utils.py b/app/utils.py index cbf51366..85827a8b 100644 --- a/app/utils.py +++ b/app/utils.py @@ -160,7 +160,7 @@ def markdown_to_text(markdown_text) -> str: return markdown_text.replace("# ", '') -def domain_from_url(url: str, create=False) -> Domain: +def domain_from_url(url: str, create=True) -> Domain: parsed_url = urlparse(url) domain = Domain.query.filter_by(name=parsed_url.hostname.lower()).first() if create and domain is None: diff --git a/migrations/versions/84a5cb2a5e5b_remove_unique_on_user.py b/migrations/versions/84a5cb2a5e5b_remove_unique_on_user.py new file mode 100644 index 00000000..05cb60d9 --- /dev/null +++ b/migrations/versions/84a5cb2a5e5b_remove_unique_on_user.py @@ -0,0 +1,34 @@ +"""remove unique on user + +Revision ID: 84a5cb2a5e5b +Revises: 6a9bec0c492e +Create Date: 2023-11-22 19:47:40.609945 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '84a5cb2a5e5b' +down_revision = '6a9bec0c492e' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('user', schema=None) as batch_op: + batch_op.drop_index('ix_user_user_name') + batch_op.create_index(batch_op.f('ix_user_user_name'), ['user_name'], unique=False) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('user', schema=None) as batch_op: + batch_op.drop_index(batch_op.f('ix_user_user_name')) + batch_op.create_index('ix_user_user_name', ['user_name'], unique=False) + + # ### end Alembic commands ###