diff options
Diffstat (limited to 'app/controllers')
24 files changed, 292 insertions, 46 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 26ab6636b..75915b337 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -26,7 +26,10 @@ class AccountsController < ApplicationController end format.json do - render json: @account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' + render json: @account, + serializer: ActivityPub::ActorSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' end end end diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index b37910b36..76553a162 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -9,9 +9,9 @@ class ActivityPub::InboxesController < Api::BaseController if signed_request_account upgrade_account process_payload - head 201 - else head 202 + else + [signature_verification_failure_reason, 401] end end @@ -32,6 +32,7 @@ class ActivityPub::InboxesController < Api::BaseController end Pubsubhubbub::UnsubscribeWorker.perform_async(signed_request_account.id) if signed_request_account.subscribed? + DeliveryFailureTracker.track_inverse_success!(signed_request_account) end def process_payload diff --git a/app/controllers/admin/account_moderation_notes_controller.rb b/app/controllers/admin/account_moderation_notes_controller.rb new file mode 100644 index 000000000..414a875d0 --- /dev/null +++ b/app/controllers/admin/account_moderation_notes_controller.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class Admin::AccountModerationNotesController < Admin::BaseController + def create + @account_moderation_note = current_account.account_moderation_notes.new(resource_params) + if @account_moderation_note.save + @target_account = @account_moderation_note.target_account + redirect_to admin_account_path(@target_account.id), notice: I18n.t('admin.account_moderation_notes.created_msg') + else + @account = @account_moderation_note.target_account + @moderation_notes = @account.targeted_moderation_notes.latest + render template: 'admin/accounts/show' + end + end + + def destroy + @account_moderation_note = AccountModerationNote.find(params[:id]) + @target_account = @account_moderation_note.target_account + @account_moderation_note.destroy + redirect_to admin_account_path(@target_account.id), notice: I18n.t('admin.account_moderation_notes.destroyed_msg') + end + + private + + def resource_params + params.require(:account_moderation_note).permit( + :content, + :target_account_id + ) + end +end diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index 54c659e1b..ffa4dc850 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -9,7 +9,10 @@ module Admin @accounts = filtered_accounts.page(params[:page]) end - def show; end + def show + @account_moderation_note = current_account.account_moderation_notes.new(target_account: @account) + @moderation_notes = @account.targeted_moderation_notes.latest + end def subscribe Pubsubhubbub::SubscribeWorker.perform_async(@account.id) diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb index d70514d9a..ca81f3255 100644 --- a/app/controllers/admin/custom_emojis_controller.rb +++ b/app/controllers/admin/custom_emojis_controller.rb @@ -2,8 +2,10 @@ module Admin class CustomEmojisController < BaseController + before_action :set_custom_emoji, except: [:index, :new, :create] + def index - @custom_emojis = CustomEmoji.local + @custom_emojis = filtered_custom_emojis.page(params[:page]) end def new @@ -21,14 +23,49 @@ module Admin end def destroy - CustomEmoji.find(params[:id]).destroy + @custom_emoji.destroy redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.destroyed_msg') end + def copy + emoji = CustomEmoji.new(domain: nil, shortcode: @custom_emoji.shortcode, image: @custom_emoji.image) + + if emoji.save + redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.copied_msg') + else + redirect_to admin_custom_emojis_path, alert: I18n.t('admin.custom_emojis.copy_failed_msg') + end + end + + def enable + @custom_emoji.update!(disabled: false) + redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.enabled_msg') + end + + def disable + @custom_emoji.update!(disabled: true) + redirect_to admin_custom_emojis_path, notice: I18n.t('admin.custom_emojis.disabled_msg') + end + private + def set_custom_emoji + @custom_emoji = CustomEmoji.find(params[:id]) + end + def resource_params params.require(:custom_emoji).permit(:shortcode, :image) end + + def filtered_custom_emojis + CustomEmojiFilter.new(filter_params).results + end + + def filter_params + params.permit( + :local, + :remote + ) + end end end diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb new file mode 100644 index 000000000..09275d5dc --- /dev/null +++ b/app/controllers/admin/email_domain_blocks_controller.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module Admin + class EmailDomainBlocksController < BaseController + before_action :set_email_domain_block, only: [:show, :destroy] + + def index + @email_domain_blocks = EmailDomainBlock.page(params[:page]) + end + + def new + @email_domain_block = EmailDomainBlock.new + end + + def create + @email_domain_block = EmailDomainBlock.new(resource_params) + + if @email_domain_block.save + redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg') + else + render :new + end + end + + def destroy + @email_domain_block.destroy + redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg') + end + + private + + def set_email_domain_block + @email_domain_block = EmailDomainBlock.find(params[:id]) + end + + def resource_params + params.require(:email_domain_block).permit(:domain) + end + end +end diff --git a/app/controllers/api/salmon_controller.rb b/app/controllers/api/salmon_controller.rb index e9e700b18..143e9d3cd 100644 --- a/app/controllers/api/salmon_controller.rb +++ b/app/controllers/api/salmon_controller.rb @@ -7,9 +7,11 @@ class Api::SalmonController < Api::BaseController def update if verify_payload? process_salmon - head 201 - else head 202 + elsif payload.present? + [signature_verification_failure_reason, 401] + else + head 400 end end diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb index a88cf2021..91a942d75 100644 --- a/app/controllers/api/v1/accounts/relationships_controller.rb +++ b/app/controllers/api/v1/accounts/relationships_controller.rb @@ -7,7 +7,10 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController respond_to :json def index - @accounts = Account.where(id: account_ids).select('id') + accounts = Account.where(id: account_ids).select('id') + # .where doesn't guarantee that our results are in the same order + # we requested them, so return the "right" order to the requestor. + @accounts = accounts.index_by(&:id).values_at(*account_ids) render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships end diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb new file mode 100644 index 000000000..e469c7d21 --- /dev/null +++ b/app/controllers/api/v1/apps/credentials_controller.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class Api::V1::Apps::CredentialsController < Api::BaseController + before_action -> { doorkeeper_authorize! :read } + + respond_to :json + + def show + render json: doorkeeper_token.application, serializer: REST::StatusSerializer::ApplicationSerializer + end +end diff --git a/app/controllers/api/v1/apps_controller.rb b/app/controllers/api/v1/apps_controller.rb index 44a27b20a..e9f7a7291 100644 --- a/app/controllers/api/v1/apps_controller.rb +++ b/app/controllers/api/v1/apps_controller.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class Api::V1::AppsController < Api::BaseController - respond_to :json - def create @app = Doorkeeper::Application.create!(application_options) render json: @app, serializer: REST::ApplicationSerializer diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb index a412e4341..3a6690766 100644 --- a/app/controllers/api/v1/blocks_controller.rb +++ b/app/controllers/api/v1/blocks_controller.rb @@ -15,19 +15,17 @@ class Api::V1::BlocksController < Api::BaseController private def load_accounts - default_accounts.merge(paginated_blocks).to_a - end - - def default_accounts - Account.includes(:blocked_by).references(:blocked_by) + paginated_blocks.map(&:target_account) end def paginated_blocks - Block.where(account: current_account).paginate_by_max_id( - limit_param(DEFAULT_ACCOUNTS_LIMIT), - params[:max_id], - params[:since_id] - ) + @paginated_blocks ||= Block.eager_load(:target_account) + .where(account: current_account) + .paginate_by_max_id( + limit_param(DEFAULT_ACCOUNTS_LIMIT), + params[:max_id], + params[:since_id] + ) end def insert_pagination_headers @@ -41,21 +39,21 @@ class Api::V1::BlocksController < Api::BaseController end def prev_path - unless @accounts.empty? + unless paginated_blocks.empty? api_v1_blocks_url pagination_params(since_id: pagination_since_id) end end def pagination_max_id - @accounts.last.blocked_by_ids.last + paginated_blocks.last.id end def pagination_since_id - @accounts.first.blocked_by_ids.first + paginated_blocks.first.id end def records_continue? - @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) + paginated_blocks.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) end def pagination_params(core_params) diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb index 4dd77fb55..f8cd64455 100644 --- a/app/controllers/api/v1/custom_emojis_controller.rb +++ b/app/controllers/api/v1/custom_emojis_controller.rb @@ -4,6 +4,6 @@ class Api::V1::CustomEmojisController < Api::BaseController respond_to :json def index - render json: CustomEmoji.local, each_serializer: REST::CustomEmojiSerializer + render json: CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer end end diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb index 8a1992fca..9f330f0df 100644 --- a/app/controllers/api/v1/media_controller.rb +++ b/app/controllers/api/v1/media_controller.rb @@ -10,7 +10,7 @@ class Api::V1::MediaController < Api::BaseController respond_to :json def create - @media = current_account.media_attachments.create!(file: media_params[:file]) + @media = current_account.media_attachments.create!(media_params) render json: @media, serializer: REST::MediaAttachmentSerializer rescue Paperclip::Errors::NotIdentifiedByImageMagickError render json: file_type_error, status: 422 @@ -18,10 +18,16 @@ class Api::V1::MediaController < Api::BaseController render json: processing_error, status: 500 end + def update + @media = current_account.media_attachments.where(status_id: nil).find(params[:id]) + @media.update!(media_params) + render json: @media, serializer: REST::MediaAttachmentSerializer + end + private def media_params - params.permit(:file) + params.permit(:file, :description) end def file_type_error diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb index 60ace04d7..aac3c31ff 100644 --- a/app/controllers/auth/registrations_controller.rb +++ b/app/controllers/auth/registrations_controller.rb @@ -6,6 +6,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController before_action :check_enabled_registrations, only: [:new, :create] before_action :configure_sign_up_params, only: [:create] before_action :set_sessions, only: [:edit, :update] + before_action :set_instance_presenter, only: [:new, :update] def destroy not_found @@ -39,6 +40,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController private + def set_instance_presenter + @instance_presenter = InstancePresenter.new + end + def determine_layout %w(edit update).include?(action_name) ? 'admin' : 'auth' end diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index bc3bd2f4b..463a183e4 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -8,6 +8,7 @@ class Auth::SessionsController < Devise::SessionsController skip_before_action :require_no_authentication, only: [:create] skip_before_action :check_suspension, only: [:destroy] prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create] + before_action :set_instance_presenter, only: [:new] def create super do |resource| @@ -84,6 +85,10 @@ class Auth::SessionsController < Devise::SessionsController private + def set_instance_presenter + @instance_presenter = InstancePresenter.new + end + def home_paths(resource) paths = [about_path] if single_user_mode? && resource.is_a?(User) diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 4211283ed..2baafb5bf 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -9,10 +9,15 @@ module SignatureVerification request.headers['Signature'].present? end + def signature_verification_failure_reason + return @signature_verification_failure_reason if defined?(@signature_verification_failure_reason) + end + def signed_request_account return @signed_request_account if defined?(@signed_request_account) unless signed_request? + @signature_verification_failure_reason = 'Request not signed' @signed_request_account = nil return end @@ -27,6 +32,7 @@ module SignatureVerification end if incompatible_signature?(signature_params) + @signature_verification_failure_reason = 'Incompatible request signature' @signed_request_account = nil return end @@ -34,6 +40,7 @@ module SignatureVerification account = account_from_key_id(signature_params['keyId']) if account.nil? + @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}" @signed_request_account = nil return end @@ -44,7 +51,18 @@ module SignatureVerification if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string) @signed_request_account = account @signed_request_account + elsif account.possibly_stale? + account = account.refresh! + + if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string) + @signed_request_account = account + @signed_request_account + else + @signed_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}" + @signed_request_account = nil + end else + @signed_verification_failure_reason = "Verification failed for #{account.username}@#{account.domain} #{account.uri}" @signed_request_account = nil end end @@ -99,7 +117,7 @@ module SignatureVerification ResolveRemoteAccountService.new.call(key_id.gsub(/\Aacct:/, '')) elsif !ActivityPub::TagManager.instance.local_uri?(key_id) account = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account) - account ||= ActivityPub::FetchRemoteKeyService.new.call(key_id) + account ||= ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false) account end end diff --git a/app/controllers/emojis_controller.rb b/app/controllers/emojis_controller.rb new file mode 100644 index 000000000..a82b9340b --- /dev/null +++ b/app/controllers/emojis_controller.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +class EmojisController < ApplicationController + before_action :set_emoji + + def show + respond_to do |format| + format.json do + render json: @emoji, + serializer: ActivityPub::EmojiSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' + end + end + end + + private + + def set_emoji + @emoji = CustomEmoji.local.find(params[:id]) + end +end diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index 8eb4d2822..399e79665 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -10,7 +10,10 @@ class FollowerAccountsController < ApplicationController format.html format.json do - render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' + render json: collection_presenter, + serializer: ActivityPub::CollectionSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' end end end diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 1ca6f0fe7..1e73d4bd4 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -10,7 +10,10 @@ class FollowingAccountsController < ApplicationController format.html format.json do - render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' + render json: collection_presenter, + serializer: ActivityPub::CollectionSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' end end end diff --git a/app/controllers/manifests_controller.rb b/app/controllers/manifests_controller.rb index 832e1eb6f..ac267c229 100644 --- a/app/controllers/manifests_controller.rb +++ b/app/controllers/manifests_controller.rb @@ -1,11 +1,7 @@ # frozen_string_literal: true class ManifestsController < ApplicationController - before_action :set_instance_presenter - - def show; end - - def set_instance_presenter - @instance_presenter = InstancePresenter.new + def show + render json: InstancePresenter.new, serializer: ManifestSerializer end end diff --git a/app/controllers/settings/follower_domains_controller.rb b/app/controllers/settings/follower_domains_controller.rb index 90b48887f..9968504e5 100644 --- a/app/controllers/settings/follower_domains_controller.rb +++ b/app/controllers/settings/follower_domains_controller.rb @@ -9,7 +9,7 @@ class Settings::FollowerDomainsController < ApplicationController def show @account = current_account - @domains = current_account.followers.reorder(nil).group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10) + @domains = current_account.followers.reorder('MIN(follows.id) DESC').group('accounts.domain').select('accounts.domain, count(accounts.id) as accounts_from_domain').page(params[:page]).per(10) end def update diff --git a/app/controllers/settings/notifications_controller.rb b/app/controllers/settings/notifications_controller.rb new file mode 100644 index 000000000..09839f16e --- /dev/null +++ b/app/controllers/settings/notifications_controller.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class Settings::NotificationsController < ApplicationController + layout 'admin' + + before_action :authenticate_user! + + def show; end + + def update + user_settings.update(user_settings_params.to_h) + + if current_user.save + redirect_to settings_notifications_path, notice: I18n.t('generic.changes_saved_msg') + else + render :show + end + end + + private + + def user_settings + UserSettingsDecorator.new(current_user) + end + + def user_settings_params + params.require(:user).permit( + notification_emails: %i(follow follow_request reblog favourite mention digest), + interactions: %i(must_be_follower must_be_following) + ) + end +end diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb index 65206ea96..e8a360fb5 100644 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@ -21,13 +21,19 @@ class StatusesController < ApplicationController end format.json do - render json: @status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' + render json: @status, + serializer: ActivityPub::NoteSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' end end end def activity - render json: @status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' + render json: @status, + serializer: ActivityPub::ActivitySerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' end def embed diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 3001b2ee3..9f3090e37 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -1,24 +1,40 @@ # frozen_string_literal: true class TagsController < ApplicationController - layout 'public' + before_action :set_body_classes + before_action :set_instance_presenter def show - @tag = Tag.find_by!(name: params[:id].downcase) - @statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id]) - @statuses = cache_collection(@statuses, Status) + @tag = Tag.find_by!(name: params[:id].downcase) respond_to do |format| - format.html + format.html do + serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer) + @initial_state_json = serializable_resource.to_json + end format.json do - render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' + @statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id]) + @statuses = cache_collection(@statuses, Status) + + render json: collection_presenter, + serializer: ActivityPub::CollectionSerializer, + adapter: ActivityPub::Adapter, + content_type: 'application/activity+json' end end end private + def set_body_classes + @body_classes = 'tag-body' + end + + def set_instance_presenter + @instance_presenter = InstancePresenter.new + end + def collection_presenter ActivityPub::CollectionPresenter.new( id: tag_url(@tag), @@ -27,4 +43,11 @@ class TagsController < ApplicationController items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) } ) end + + def initial_state_params + { + settings: {}, + token: current_session&.token, + } + end end |