Merge branch 'master' into glitch-soc/merge-upstream

Conflicts:
- Gemfile.lock
- app/controllers/accounts_controller.rb
- app/controllers/admin/dashboard_controller.rb
- app/controllers/follower_accounts_controller.rb
- app/controllers/following_accounts_controller.rb
- app/controllers/remote_follow_controller.rb
- app/controllers/stream_entries_controller.rb
- app/controllers/tags_controller.rb
- app/javascript/packs/public.js
- app/lib/sanitize_config.rb
- app/models/account.rb
- app/models/form/admin_settings.rb
- app/models/media_attachment.rb
- app/models/stream_entry.rb
- app/models/user.rb
- app/serializers/initial_state_serializer.rb
- app/services/batched_remove_status_service.rb
- app/services/post_status_service.rb
- app/services/process_mentions_service.rb
- app/services/reblog_service.rb
- app/services/remove_status_service.rb
- app/views/admin/settings/edit.html.haml
- config/locales/simple_form.pl.yml
- config/settings.yml
- docker-compose.yml
This commit is contained in:
Thibaut Girka
2019-07-19 18:26:49 +02:00
411 changed files with 3416 additions and 8150 deletions

View File

@ -42,5 +42,7 @@
= mail_to @instance_presenter.site_contact_email, nil, title: @instance_presenter.site_contact_email
.column-3
= render 'application/flashes'
.box-widget
.rich-formatting= @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html')

View File

@ -3,10 +3,10 @@
.moved-account-widget
.moved-account-widget__message
= fa_icon 'suitcase'
= t('accounts.moved_html', name: content_tag(:bdi, content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify)), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), TagManager.instance.url_for(moved_to_account), class: 'mention'))
= t('accounts.moved_html', name: content_tag(:bdi, content_tag(:strong, display_name(account, custom_emojify: true), class: :emojify)), new_profile_link: link_to(content_tag(:strong, safe_join(['@', content_tag(:span, moved_to_account.acct)])), ActivityPub::TagManager.instance.url_for(moved_to_account), class: 'mention'))
.moved-account-widget__card
= link_to TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'me noopener' do
= link_to ActivityPub::TagManager.instance.url_for(moved_to_account), class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'me noopener' do
.detailed-status__display-avatar
.account__avatar-overlay
.account__avatar-overlay-base{ style: "background-image: url('#{moved_to_account.avatar.url(:original)}')" }

View File

@ -7,7 +7,6 @@
- if @account.user&.setting_noindex
%meta{ name: 'robots', content: 'noindex' }/
%link{ rel: 'salmon', href: api_salmon_url(@account.id) }/
%link{ rel: 'alternate', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }/
%link{ rel: 'alternate', type: 'application/rss+xml', href: account_url(@account, format: 'rss') }/
%link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@account) }/
@ -40,12 +39,12 @@
- else
.activity-stream.activity-stream--under-tabs
- if params[:page].to_i.zero?
= render partial: 'stream_entries/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
= render partial: 'statuses/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
- if @newer_url
.entry= link_to_more @newer_url
= render partial: 'stream_entries/status', collection: @statuses, as: :status
= render partial: 'statuses/status', collection: @statuses, as: :status
- if @older_url
.entry= link_to_more @older_url

View File

@ -19,4 +19,4 @@
= table_link_to 'times', t('admin.accounts.reject'), reject_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:reject, account.user)
- else
= table_link_to 'circle', t('admin.accounts.web'), web_path("accounts/#{account.id}")
= table_link_to 'globe', t('admin.accounts.public'), TagManager.instance.url_for(account)
= table_link_to 'globe', t('admin.accounts.public'), ActivityPub::TagManager.instance.url_for(account)

View File

@ -53,6 +53,8 @@
= feature_hint(link_to(t('admin.dashboard.keybase'), edit_admin_settings_path), @keybase_integration)
%li
= feature_hint(link_to(t('admin.dashboard.feature_relay'), admin_relays_path), @relay_enabled)
%li
= feature_hint(link_to(t('admin.dashboard.feature_spam_check'), edit_admin_settings_path), @spam_check_enabled)
.dashboard__widgets__versions
%div

View File

@ -19,7 +19,7 @@
= react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif, media: status.proper.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json }
.detailed-status__meta
= link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener' do
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', target: stream_link_target, rel: 'noopener' do
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
·
- if status.reblog?

View File

@ -78,6 +78,9 @@
.fields-group
= f.input :show_replies_in_public_timelines, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_replies_in_public_timelines.title'), hint: t('admin.settings.show_replies_in_public_timelines.desc_html')
.fields-group
= f.input :spam_check_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.spam_check_enabled.title'), hint: t('admin.settings.spam_check_enabled.desc_html')
%hr.spacer/
.fields-group

View File

@ -1,18 +0,0 @@
%tr
%td
%samp= subscription.account.acct
%td
%samp= subscription.callback_url
%td
- if subscription.confirmed?
%i.fa.fa-check
%td{ style: "color: #{subscription.expired? ? 'red' : 'inherit'};" }
%time.time-ago{ datetime: subscription.expires_at.iso8601, title: l(subscription.expires_at) }
= precede subscription.expired? ? '-' : '' do
= time_ago_in_words(subscription.expires_at)
%td
- if subscription.last_successful_delivery_at?
%time.formatted{ datetime: subscription.last_successful_delivery_at.iso8601, title: l(subscription.last_successful_delivery_at) }
= l subscription.last_successful_delivery_at
- else
%i.fa.fa-times

View File

@ -1,16 +0,0 @@
- content_for :page_title do
= t('admin.subscriptions.title')
.table-wrapper
%table.table
%thead
%tr
%th= t('admin.subscriptions.topic')
%th= t('admin.subscriptions.callback_url')
%th= t('admin.subscriptions.confirmed')
%th= t('admin.subscriptions.expires_in')
%th= t('admin.subscriptions.last_delivery')
%tbody
= render @subscriptions
= paginate @subscriptions

View File

@ -1,4 +1,4 @@
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : ActivityPub::TagManager.instance.url_for(account)
.card.h-card
= link_to account_url, target: '_blank', rel: 'noopener' do

View File

@ -1,4 +1,4 @@
.post-follow-actions
%div= link_to t('authorize_follow.post_follow.web'), web_url("accounts/#{@resource.id}"), class: 'button button--block'
%div= link_to t('authorize_follow.post_follow.return'), TagManager.instance.url_for(@resource), class: 'button button--block'
%div= link_to t('authorize_follow.post_follow.return'), ActivityPub::TagManager.instance.url_for(@resource), class: 'button button--block'
%div= t('authorize_follow.post_follow.close')

View File

@ -7,7 +7,7 @@
.public-layout
.activity-stream.activity-stream--highlighted
= render 'stream_entries/status', status: @status
= render 'statuses/status', status: @status
= simple_form_for @remote_follow, as: :remote_follow, url: remote_interaction_path(@status) do |f|
= render 'shared/error_messages', object: @remote_follow

View File

@ -1,13 +0,0 @@
.account-card
.detailed-status__display-name
%div
= image_tag account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar'
%span.display-name
- account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
= link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
%strong.emojify= display_name(account, custom_emojify: true)
%span @#{account.acct}
- if account.note?
.account__header__content.emojify= Formatter.instance.simplified_format(account)

View File

@ -1,4 +0,0 @@
.post-follow-actions
%div= link_to t('authorize_follow.post_follow.web'), web_url("accounts/#{@account.id}"), class: 'button button--block'
%div= link_to t('authorize_follow.post_follow.return'), TagManager.instance.url_for(@account), class: 'button button--block'
%div= t('authorize_follow.post_follow.close')

View File

@ -1,3 +0,0 @@
.form-container
.flash-message#error_explanation
= t('remote_unfollow.error')

View File

@ -1,10 +0,0 @@
- content_for :page_title do
= t('remote_unfollow.title', acct: @account.acct)
.form-container
.follow-prompt
%h2= t('remote_unfollow.unfollowed')
= render 'application/card', account: @account
= render 'post_follow_actions'

View File

@ -1,6 +1,6 @@
.detailed-status.detailed-status--flex
.p-author.h-card
= link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name u-url', target: stream_link_target, rel: 'noopener' do
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'detailed-status__display-name u-url', target: stream_link_target, rel: 'noopener' do
.detailed-status__display-avatar
- if current_account&.user&.setting_auto_play_gif || autoplay
= image_tag status.account.avatar_original_url, width: 48, height: 48, alt: '', class: 'account__avatar u-photo'
@ -24,23 +24,23 @@
= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay)
- if status.preloadable_poll
= react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
= render partial: 'stream_entries/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay }
= render partial: 'statuses/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay }
- if !status.media_attachments.empty?
- if status.media_attachments.first.audio_or_video?
- video = status.media_attachments.first
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
- else
= react_component :media_gallery, height: 380, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, standalone: true, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, 'reduceMotion': current_account&.user&.setting_reduce_motion, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
- elsif status.preview_card
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
.detailed-status__meta
%data.dt-published{ value: status.created_at.to_time.iso8601 }
= link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
·
- if status.application && @account.user&.setting_show_application

View File

@ -1,11 +1,11 @@
.status
.status__info
= link_to TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener' do
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__relative-time u-url u-uid', target: stream_link_target, rel: 'noopener' do
%time.time-ago{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
%data.dt-published{ value: status.created_at.to_time.iso8601 }
.p-author.h-card
= link_to TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name u-url', target: stream_link_target, rel: 'noopener' do
.status__avatar
%div
- if current_account&.user&.setting_auto_play_gif || autoplay
@ -28,16 +28,16 @@
= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay)
- if status.preloadable_poll
= react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do
= render partial: 'stream_entries/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay }
= render partial: 'statuses/poll', locals: { status: status, poll: status.preloadable_poll, autoplay: autoplay }
- if !status.media_attachments.empty?
- if status.media_attachments.first.audio_or_video?
- video = status.media_attachments.first
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, width: 610, height: 343, inline: true, alt: video.description do
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
- else
= react_component :media_gallery, height: 343, sensitive: !current_account&.user&.show_all_media? && status.sensitive? || current_account&.user&.hide_all_media?, 'autoPlayGif': current_account&.user&.setting_auto_play_gif || autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
= render partial: 'stream_entries/attachment_list', locals: { attachments: status.media_attachments }
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
- elsif status.preview_card
= react_component :card, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
@ -50,9 +50,9 @@
= fa_icon 'reply-all fw'
.status__action-bar__counter__label= obscured_counter status.replies_count
= link_to remote_interaction_path(status, type: :reblog), class: 'status__action-bar-button icon-button modal-button', style: 'font-size: 18px; width: 23.1429px; height: 23.1429px; line-height: 23.15px;' do
- if status.public_visibility? || status.unlisted_visibility?
- if status.distributable?
= fa_icon 'retweet fw'
- elsif status.private_visibility?
- elsif status.private_visibility? || status.limited_visibility?
= fa_icon 'lock fw'
- else
= fa_icon 'envelope fw'

View File

@ -17,9 +17,9 @@
- if status.reply? && include_threads
- if @next_ancestor
.entry{ class: entry_classes }
= link_to_more TagManager.instance.url_for(@next_ancestor)
= link_to_more ActivityPub::TagManager.instance.url_for(@next_ancestor)
= render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }, autoplay: autoplay
= render partial: 'statuses/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }, autoplay: autoplay
.entry{ class: entry_classes }
@ -28,7 +28,7 @@
.status__prepend-icon-wrapper
%i.status__prepend-icon.fa.fa-fw.fa-retweet
%span
= link_to TagManager.instance.url_for(status.account), class: 'status__display-name muted' do
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'status__display-name muted' do
%bdi
%strong.emojify= display_name(status.account, custom_emojify: true)
= t('stream_entries.reblogged')
@ -39,18 +39,18 @@
%span
= t('stream_entries.pinned')
= render (centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status'), status: status.proper, autoplay: autoplay
= render (centered ? 'statuses/detailed_status' : 'statuses/simple_status'), status: status.proper, autoplay: autoplay
- if include_threads
- if @since_descendant_thread_id
.entry{ class: entry_classes }
= link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
- @descendant_threads.each do |thread|
= render partial: 'stream_entries/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }, autoplay: autoplay
= render partial: 'statuses/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }, autoplay: autoplay
- if thread[:next_status]
.entry{ class: entry_classes }
= link_to_more TagManager.instance.url_for(thread[:next_status])
= link_to_more ActivityPub::TagManager.instance.url_for(thread[:next_status])
- if @next_descendant_thread
.entry{ class: entry_classes }
= link_to_more short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)

View File

@ -0,0 +1,3 @@
- cache @status do
.activity-stream.activity-stream--headless
= render 'status', status: @status, centered: true, autoplay: @autoplay

View File

@ -0,0 +1,24 @@
- content_for :page_title do
= t('statuses.title', name: display_name(@account), quote: truncate(@status.spoiler_text.presence || @status.text, length: 50, omission: '…', escape: false))
- content_for :header_tags do
- if @account.user&.setting_noindex
%meta{ name: 'robots', content: 'noindex' }/
%link{ rel: 'alternate', type: 'application/json+oembed', href: api_oembed_url(url: short_account_status_url(@account, @status), format: 'json') }/
%link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@status) }/
= opengraph 'og:site_name', site_title
= opengraph 'og:type', 'article'
= opengraph 'og:title', "#{display_name(@account)} (@#{@account.local_username_and_domain})"
= opengraph 'og:url', short_account_status_url(@account, @status)
= render 'og_description', activity: @status
= render 'og_image', activity: @status, account: @account
.grid
.column-0
.activity-stream.h-entry
= render partial: 'status', locals: { status: @status, include_threads: true }
.column-1
= render 'application/sidebar'

View File

@ -1,3 +0,0 @@
- cache @stream_entry.activity do
.activity-stream.activity-stream--headless
= render "stream_entries/#{@type}", @type.to_sym => @stream_entry.activity, centered: true, autoplay: @autoplay

View File

@ -1,25 +0,0 @@
- content_for :page_title do
= t('statuses.title', name: display_name(@account), quote: truncate(@stream_entry.activity.spoiler_text.presence || @stream_entry.activity.text, length: 50, omission: '…', escape: false))
- content_for :header_tags do
- if @account.user&.setting_noindex
%meta{ name: 'robots', content: 'noindex' }/
%link{ rel: 'alternate', type: 'application/atom+xml', href: account_stream_entry_url(@account, @stream_entry, format: 'atom') }/
%link{ rel: 'alternate', type: 'application/json+oembed', href: api_oembed_url(url: account_stream_entry_url(@account, @stream_entry), format: 'json') }/
%link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@stream_entry.activity) }/
= opengraph 'og:site_name', site_title
= opengraph 'og:type', 'article'
= opengraph 'og:title', "#{display_name(@account)} (@#{@account.local_username_and_domain})"
= opengraph 'og:url', short_account_status_url(@account, @stream_entry.activity)
= render 'stream_entries/og_description', activity: @stream_entry.activity
= render 'stream_entries/og_image', activity: @stream_entry.activity, account: @account
.grid
.column-0
.activity-stream.h-entry
= render partial: "stream_entries/#{@type}", locals: { @type.to_sym => @stream_entry.activity, include_threads: true }
.column-1
= render 'application/sidebar'

View File

@ -4,40 +4,47 @@ doc << Ox::Element.new('XRD').tap do |xrd|
xrd['xmlns'] = 'http://docs.oasis-open.org/ns/xri/xrd-1.0'
xrd << (Ox::Element.new('Subject') << @account.to_webfinger_s)
xrd << (Ox::Element.new('Alias') << short_account_url(@account))
xrd << (Ox::Element.new('Alias') << account_url(@account))
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://webfinger.net/rel/profile-page'
link['type'] = 'text/html'
link['href'] = short_account_url(@account)
end
if @account.instance_actor?
xrd << (Ox::Element.new('Alias') << instance_actor_url)
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://schemas.google.com/g/2010#updates-from'
link['type'] = 'application/atom+xml'
link['href'] = account_url(@account, format: 'atom')
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://webfinger.net/rel/profile-page'
link['type'] = 'text/html'
link['href'] = about_more_url(instance_actor: true)
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'self'
link['type'] = 'application/activity+json'
link['href'] = account_url(@account)
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'self'
link['type'] = 'application/activity+json'
link['href'] = instance_actor_url
end
else
xrd << (Ox::Element.new('Alias') << short_account_url(@account))
xrd << (Ox::Element.new('Alias') << account_url(@account))
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'salmon'
link['href'] = api_salmon_url(@account.id)
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://webfinger.net/rel/profile-page'
link['type'] = 'text/html'
link['href'] = short_account_url(@account)
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'magic-public-key'
link['href'] = "data:application/magic-public-key,#{@account.magic_key}"
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://schemas.google.com/g/2010#updates-from'
link['type'] = 'application/atom+xml'
link['href'] = account_url(@account, format: 'atom')
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://ostatus.org/schema/1.0/subscribe'
link['template'] = "#{authorize_interaction_url}?acct={uri}"
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'self'
link['type'] = 'application/activity+json'
link['href'] = account_url(@account)
end
xrd << Ox::Element.new('Link').tap do |link|
link['rel'] = 'http://ostatus.org/schema/1.0/subscribe'
link['template'] = "#{authorize_interaction_url}?acct={uri}"
end
end
end