diff --git a/.circleci/config.yml b/.circleci/config.yml
index cb45d00e..d332ec13 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -167,7 +167,7 @@ jobs:
- image: circleci/node:8.15.0-stretch
steps:
- *attach_workspace
- - run: ./bin/retry yarn test:jest
+ - run: ./bin/retry yarn test:jest # : todo :
check-i18n:
<<: *defaults
diff --git a/.eslintrc.js b/.eslintrc.js
index f2113e44..e5b812a1 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -5,7 +5,6 @@ module.exports = {
browser: true,
node: true,
es6: true,
- jest: true,
},
globals: {
@@ -199,8 +198,6 @@ module.exports = {
{
devDependencies: [
'config/webpack/**',
- 'app/javascript/gabsocial/test_setup.js',
- 'app/javascript/**/__tests__/**',
],
},
],
diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb
index 37c49e92..7cf6068f 100644
--- a/app/controllers/about_controller.rb
+++ b/app/controllers/about_controller.rb
@@ -13,19 +13,11 @@ class AboutController < ApplicationController
end
end
- def more; end
- def terms; end
- def privacy; end
- def investors; end
- def dmca; end
- def sales; end
-
private
def new_user
User.new.tap do |user|
user.build_account
- user.build_invite_request
end
end
diff --git a/app/controllers/account_follow_controller.rb b/app/controllers/account_follow_controller.rb
deleted file mode 100644
index 185a355f..00000000
--- a/app/controllers/account_follow_controller.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AccountFollowController < ApplicationController
- include AccountControllerConcern
-
- before_action :authenticate_user!
-
- def create
- FollowService.new.call(current_user.account, @account.acct)
- redirect_to account_path(@account)
- end
-end
diff --git a/app/controllers/account_unfollow_controller.rb b/app/controllers/account_unfollow_controller.rb
deleted file mode 100644
index 378ec86d..00000000
--- a/app/controllers/account_unfollow_controller.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class AccountUnfollowController < ApplicationController
- include AccountControllerConcern
-
- before_action :authenticate_user!
-
- def create
- UnfollowService.new.call(current_user.account, @account)
- redirect_to account_path(@account)
- end
-end
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
deleted file mode 100644
index a5a17f28..00000000
--- a/app/controllers/accounts_controller.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-# frozen_string_literal: true
-
-class AccountsController < ReactController
- PAGE_SIZE = 20
-
- include AccountControllerConcern
-
- before_action :set_cache_headers
-
- def show
- respond_to do |format|
- format.html do
- mark_cacheable! unless user_signed_in?
- return process(:react)
- end
-
- format.atom do
- mark_cacheable!
-
- @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id])
- render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? }))
- end
-
- format.rss do
- mark_cacheable!
-
- @statuses = cache_collection(default_statuses.without_reblogs.without_replies.limit(PAGE_SIZE), Status)
- render xml: RSS::AccountSerializer.render(@account, @statuses)
- end
-
- format.json do
- mark_cacheable!
-
- render_cached_json(['activitypub', 'actor', @account], content_type: 'application/activity+json') do
- ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
- end
- end
- end
- end
-
- private
-
- def show_pinned_statuses?
- [replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
- end
-
- def filtered_statuses
- default_statuses.tap do |statuses|
- statuses.merge!(hashtag_scope) if tag_requested?
- statuses.merge!(only_media_scope) if media_requested?
- statuses.merge!(no_replies_scope) unless replies_requested?
- statuses.merge!(only_replies_scope) unless comments_only_requested?
- end
- end
-
- def default_statuses
- @account.statuses.where(visibility: [:public, :unlisted])
- end
-
- def only_media_scope
- Status.where(id: account_media_status_ids)
- end
-
- def account_media_status_ids
- @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
- end
-
- def no_replies_scope
- Status.without_replies
- end
-
- def only_replies_scope
- Status.only_replies
- end
-
- def hashtag_scope
- tag = Tag.find_normalized(params[:tag])
-
- if tag
- Status.tagged_with(tag.id)
- else
- Status.none
- end
- end
-
- def username_param
- params[:username]
- end
-
- def older_url
- pagination_url(max_id: @statuses.last.id)
- end
-
- def newer_url
- pagination_url(min_id: @statuses.first.id)
- end
-
- def pagination_url(max_id: nil, min_id: nil)
- if tag_requested?
- short_account_tag_url(@account, params[:tag], max_id: max_id, min_id: min_id)
- elsif media_requested?
- short_account_media_url(@account, max_id: max_id, min_id: min_id)
- elsif replies_requested?
- short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
- elsif comments_only_requested?
- short_account_comments_only_url(@account, max_id: max_id, min_id: min_id)
- else
- short_account_url(@account, max_id: max_id, min_id: min_id)
- end
- end
-
- def media_requested?
- request.path.ends_with?('/media')
- end
-
- def replies_requested?
- request.path.ends_with?('/with_replies')
- end
-
- def comments_only_requested?
- request.path.ends_with?('/comments_only')
- end
-
- def tag_requested?
- request.path.ends_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
- end
-
- def filtered_status_page(params)
- if params[:min_id].present?
- filtered_statuses.paginate_by_min_id(PAGE_SIZE, params[:min_id]).reverse
- else
- filtered_statuses.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id]).to_a
- end
- end
-end
diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb
index 9e17d789..a48806a6 100644
--- a/app/controllers/admin/accounts_controller.rb
+++ b/app/controllers/admin/accounts_controller.rb
@@ -2,8 +2,8 @@
module Admin
class AccountsController < BaseController
- before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :remove_avatar, :remove_header, :enable, :unsilence, :unsuspend, :memorialize, :approve, :reject, :verify, :unverify, :add_donor_badge, :remove_donor_badge, :add_investor_badge, :remove_investor_badge, :edit_pro, :save_pro, :edit, :update]
- before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
+ before_action :set_account, only: [:show, :redownload, :remove_avatar, :remove_header, :enable, :unsilence, :unsuspend, :memorialize, :approve, :reject, :verify, :unverify, :add_donor_badge, :remove_donor_badge, :add_investor_badge, :remove_investor_badge, :edit_pro, :save_pro, :edit, :update]
+ before_action :require_remote_account!, only: [:redownload]
before_action :require_local_account!, only: [:enable, :memorialize, :approve, :reject]
def index
@@ -19,18 +19,6 @@ module Admin
@warnings = @account.targeted_account_warnings.latest.custom
end
- def subscribe
- authorize @account, :subscribe?
- Pubsubhubbub::SubscribeWorker.perform_async(@account.id)
- redirect_to admin_account_path(@account.id)
- end
-
- def unsubscribe
- authorize @account, :unsubscribe?
- Pubsubhubbub::UnsubscribeWorker.perform_async(@account.id)
- redirect_to admin_account_path(@account.id)
- end
-
def memorialize
authorize @account, :memorialize?
@account.memorialize!
@@ -134,9 +122,6 @@ module Admin
def redownload
authorize @account, :redownload?
- @account.update!(last_webfingered_at: nil)
- ResolveAccountService.new.call(@account)
-
redirect_to admin_account_path(@account.id)
end
diff --git a/app/controllers/admin/custom_emojis_controller.rb b/app/controllers/admin/custom_emojis_controller.rb
index f7769916..051f4146 100644
--- a/app/controllers/admin/custom_emojis_controller.rb
+++ b/app/controllers/admin/custom_emojis_controller.rb
@@ -51,23 +51,6 @@ module Admin
redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
end
- def copy
- authorize @custom_emoji, :copy?
-
- emoji = CustomEmoji.find_or_initialize_by(domain: nil,
- shortcode: @custom_emoji.shortcode)
- emoji.image = @custom_emoji.image
-
- if emoji.save
- log_action :create, emoji
- flash[:notice] = I18n.t('admin.custom_emojis.copied_msg')
- else
- flash[:alert] = I18n.t('admin.custom_emojis.copy_failed_msg')
- end
-
- redirect_to admin_custom_emojis_path(page: params[:page], **@filter_params)
- end
-
def enable
authorize @custom_emoji, :enable?
@custom_emoji.update!(disabled: false)
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index 44f20213..fd7c9d6f 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -8,11 +8,7 @@ module Admin
@registrations_week = Redis.current.get("activity:accounts:local:#{current_week}") || 0
@logins_week = Redis.current.pfcount("activity:logins:#{current_week}")
@interactions_week = Redis.current.get("activity:interactions:#{current_week}") || 0
- @relay_enabled = Relay.enabled.exists?
@single_user_mode = Rails.configuration.x.single_user_mode
- @registrations_enabled = Setting.registrations_mode != 'none'
- @deletions_enabled = Setting.open_deletion
- @invites_enabled = Setting.min_invite_role == 'user'
@search_enabled = Chewy.enabled?
@version = GabSocial::Version.to_s
@database_version = ActiveRecord::Base.connection.execute('SELECT VERSION()').first['version'].match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1]
@@ -27,9 +23,6 @@ module Admin
@saml_enabled = ENV['SAML_ENABLED'] == 'true'
@pam_enabled = ENV['PAM_ENABLED'] == 'true'
@hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
- @trending_hashtags = TrendingTags.get(7)
- @profile_directory = Setting.profile_directory
- @timeline_preview = Setting.timeline_preview
end
private
diff --git a/app/controllers/admin/domain_blocks_controller.rb b/app/controllers/admin/domain_blocks_controller.rb
deleted file mode 100644
index 71597763..00000000
--- a/app/controllers/admin/domain_blocks_controller.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class DomainBlocksController < BaseController
- before_action :set_domain_block, only: [:show, :destroy]
-
- def new
- authorize :domain_block, :create?
- @domain_block = DomainBlock.new(domain: params[:_domain])
- end
-
- def create
- authorize :domain_block, :create?
-
- @domain_block = DomainBlock.new(resource_params)
- existing_domain_block = resource_params[:domain].present? ? DomainBlock.find_by(domain: resource_params[:domain]) : nil
-
- if existing_domain_block.present? && !@domain_block.stricter_than?(existing_domain_block)
- @domain_block.save
- flash[:alert] = I18n.t('admin.domain_blocks.existing_domain_block_html', name: existing_domain_block.domain, unblock_url: admin_domain_block_path(existing_domain_block)).html_safe # rubocop:disable Rails/OutputSafety
- @domain_block.errors[:domain].clear
- render :new
- else
- if existing_domain_block.present?
- @domain_block = existing_domain_block
- @domain_block.update(resource_params)
- end
- if @domain_block.save
- DomainBlockWorker.perform_async(@domain_block.id)
- log_action :create, @domain_block
- redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.created_msg')
- else
- render :new
- end
- end
- end
-
- def show
- authorize @domain_block, :show?
- end
-
- def destroy
- authorize @domain_block, :destroy?
- UnblockDomainService.new.call(@domain_block)
- log_action :destroy, @domain_block
- redirect_to admin_instances_path(limited: '1'), notice: I18n.t('admin.domain_blocks.destroyed_msg')
- end
-
- private
-
- def set_domain_block
- @domain_block = DomainBlock.find(params[:id])
- end
-
- def resource_params
- params.require(:domain_block).permit(:domain, :severity, :reject_media, :reject_reports)
- end
- end
-end
diff --git a/app/controllers/admin/instances_controller.rb b/app/controllers/admin/instances_controller.rb
deleted file mode 100644
index 6dd659a3..00000000
--- a/app/controllers/admin/instances_controller.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class InstancesController < BaseController
- def index
- authorize :instance, :index?
-
- @instances = ordered_instances
- end
-
- def show
- authorize :instance, :show?
-
- @instance = Instance.new(Account.by_domain_accounts.find_by(domain: params[:id]) || DomainBlock.find_by!(domain: params[:id]))
- @following_count = Follow.where(account: Account.where(domain: params[:id])).count
- @followers_count = Follow.where(target_account: Account.where(domain: params[:id])).count
- @reports_count = Report.where(target_account: Account.where(domain: params[:id])).count
- @blocks_count = Block.where(target_account: Account.where(domain: params[:id])).count
- @available = DeliveryFailureTracker.available?(Account.select(:shared_inbox_url).where(domain: params[:id]).first&.shared_inbox_url)
- @media_storage = MediaAttachment.where(account: Account.where(domain: params[:id])).sum(:file_file_size)
- @domain_block = DomainBlock.find_by(domain: params[:id])
- end
-
- private
-
- def filtered_instances
- InstanceFilter.new(filter_params).results
- end
-
- def paginated_instances
- filtered_instances.page(params[:page])
- end
-
- helper_method :paginated_instances
-
- def ordered_instances
- paginated_instances.map { |resource| Instance.new(resource) }
- end
-
- def filter_params
- params.permit(:limited, :by_domain)
- end
- end
-end
diff --git a/app/controllers/admin/invites_controller.rb b/app/controllers/admin/invites_controller.rb
deleted file mode 100644
index 44a8eec7..00000000
--- a/app/controllers/admin/invites_controller.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class InvitesController < BaseController
- def index
- authorize :invite, :index?
-
- @invites = filtered_invites.includes(user: :account).page(params[:page])
- @invite = Invite.new
- end
-
- def create
- authorize :invite, :create?
-
- @invite = Invite.new(resource_params)
- @invite.user = current_user
-
- if @invite.save
- redirect_to admin_invites_path
- else
- @invites = Invite.page(params[:page])
- render :index
- end
- end
-
- def destroy
- @invite = Invite.find(params[:id])
- authorize @invite, :destroy?
- @invite.expire!
- redirect_to admin_invites_path
- end
-
- def deactivate_all
- authorize :invite, :deactivate_all?
- Invite.available.in_batches.update_all(expires_at: Time.now.utc)
- redirect_to admin_invites_path
- end
-
- private
-
- def resource_params
- params.require(:invite).permit(:max_uses, :expires_in)
- end
-
- def filtered_invites
- InviteFilter.new(filter_params).results
- end
-
- def filter_params
- params.permit(:available, :expired)
- end
- end
-end
diff --git a/app/controllers/admin/pending_accounts_controller.rb b/app/controllers/admin/pending_accounts_controller.rb
deleted file mode 100644
index b62a9bc8..00000000
--- a/app/controllers/admin/pending_accounts_controller.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class PendingAccountsController < BaseController
- before_action :set_accounts, only: :index
-
- def index
- @form = Form::AccountBatch.new
- end
-
- def batch
- @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
- @form.save
- rescue ActionController::ParameterMissing
- flash[:alert] = I18n.t('admin.accounts.no_account_selected')
- ensure
- redirect_to admin_pending_accounts_path(current_params)
- end
-
- def approve_all
- Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'approve').save
- redirect_to admin_pending_accounts_path(current_params)
- end
-
- def reject_all
- Form::AccountBatch.new(current_account: current_account, account_ids: User.pending.pluck(:account_id), action: 'reject').save
- redirect_to admin_pending_accounts_path(current_params)
- end
-
- private
-
- def set_accounts
- @accounts = Account.joins(:user).merge(User.pending.recent).includes(user: :invite_request).page(params[:page])
- end
-
- def form_account_batch_params
- params.require(:form_account_batch).permit(:action, account_ids: [])
- end
-
- def action_from_button
- if params[:approve]
- 'approve'
- elsif params[:reject]
- 'reject'
- end
- end
-
- def current_params
- params.slice(:page).permit(:page)
- end
- end
-end
diff --git a/app/controllers/admin/relays_controller.rb b/app/controllers/admin/relays_controller.rb
deleted file mode 100644
index 1b02d3c3..00000000
--- a/app/controllers/admin/relays_controller.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class RelaysController < BaseController
- before_action :set_relay, except: [:index, :new, :create]
-
- def index
- authorize :relay, :update?
- @relays = Relay.all
- end
-
- def new
- authorize :relay, :update?
- @relay = Relay.new(inbox_url: Relay::PRESET_RELAY)
- end
-
- def create
- authorize :relay, :update?
-
- @relay = Relay.new(resource_params)
-
- if @relay.save
- @relay.enable!
- redirect_to admin_relays_path
- else
- render action: :new
- end
- end
-
- def destroy
- authorize :relay, :update?
- @relay.destroy
- redirect_to admin_relays_path
- end
-
- def enable
- authorize :relay, :update?
- @relay.enable!
- redirect_to admin_relays_path
- end
-
- def disable
- authorize :relay, :update?
- @relay.disable!
- redirect_to admin_relays_path
- end
-
- private
-
- def set_relay
- @relay = Relay.find(params[:id])
- end
-
- def resource_params
- params.require(:relay).permit(:inbox_url)
- end
- end
-end
diff --git a/app/controllers/admin/subscriptions_controller.rb b/app/controllers/admin/subscriptions_controller.rb
deleted file mode 100644
index 40500ef4..00000000
--- a/app/controllers/admin/subscriptions_controller.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class SubscriptionsController < BaseController
- def index
- authorize :subscription, :index?
- @subscriptions = ordered_subscriptions.page(requested_page)
- end
-
- private
-
- def ordered_subscriptions
- Subscription.order(id: :desc).includes(:account)
- end
-
- def requested_page
- params[:page].to_i
- end
- end
-end
diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb
deleted file mode 100644
index e9f4f2cf..00000000
--- a/app/controllers/admin/tags_controller.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class TagsController < BaseController
- before_action :set_tags, only: :index
- before_action :set_tag, except: :index
- before_action :set_filter_params
-
- def index
- authorize :tag, :index?
- end
-
- def hide
- authorize @tag, :hide?
- @tag.account_tag_stat.update!(hidden: true)
- redirect_to admin_tags_path(@filter_params)
- end
-
- def unhide
- authorize @tag, :unhide?
- @tag.account_tag_stat.update!(hidden: false)
- redirect_to admin_tags_path(@filter_params)
- end
-
- private
-
- def set_tags
- @tags = Tag.discoverable
- @tags.merge!(Tag.hidden) if filter_params[:hidden]
- end
-
- def set_tag
- @tag = Tag.find(params[:id])
- end
-
- def set_filter_params
- @filter_params = filter_params.to_hash.symbolize_keys
- end
-
- def filter_params
- params.permit(:hidden)
- end
- end
-end
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index e8b2872c..260909cc 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class Api::BaseController < ApplicationController
- DEFAULT_STATUSES_LIMIT = 20
+ DEFAULT_STATUSES_LIMIT = 18
DEFAULT_ACCOUNTS_LIMIT = 40
include RateLimitHeaders
@@ -77,8 +77,6 @@ class Api::BaseController < ApplicationController
# : todo : when figure out email/catpcha, put this back
# elsif !current_user.confirmed?
# render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
- elsif !current_user.approved?
- render json: { error: 'Your login is currently pending approval' }, status: 403
else
set_user_activity
end
diff --git a/app/controllers/api/oembed_controller.rb b/app/controllers/api/oembed_controller.rb
index 37a163cd..72b75f91 100644
--- a/app/controllers/api/oembed_controller.rb
+++ b/app/controllers/api/oembed_controller.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class Api::OEmbedController < Api::BaseController
- respond_to :json
def show
@status = status_finder.status
diff --git a/app/controllers/api/proofs_controller.rb b/app/controllers/api/proofs_controller.rb
index a84ad201..5720e27b 100644
--- a/app/controllers/api/proofs_controller.rb
+++ b/app/controllers/api/proofs_controller.rb
@@ -3,7 +3,6 @@
class Api::ProofsController < Api::BaseController
before_action :set_account
before_action :set_provider
- before_action :check_account_approval
before_action :check_account_suspension
def index
@@ -20,10 +19,6 @@ class Api::ProofsController < Api::BaseController
@account = Account.find_local!(params[:username])
end
- def check_account_approval
- not_found if @account.user_pending?
- end
-
def check_account_suspension
gone if @account.suspended?
end
diff --git a/app/controllers/api/push_controller.rb b/app/controllers/api/push_controller.rb
deleted file mode 100644
index e04d1912..00000000
--- a/app/controllers/api/push_controller.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-class Api::PushController < Api::BaseController
- include SignatureVerification
-
- def update
- response, status = process_push_request
- render plain: response, status: status
- end
-
- private
-
- def process_push_request
- case hub_mode
- when 'subscribe'
- Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds, verified_domain)
- when 'unsubscribe'
- Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback)
- else
- ["Unknown mode: #{hub_mode}", 422]
- end
- end
-
- def hub_mode
- params['hub.mode']
- end
-
- def hub_topic
- params['hub.topic']
- end
-
- def hub_callback
- params['hub.callback']
- end
-
- def hub_lease_seconds
- params['hub.lease_seconds']
- end
-
- def hub_secret
- params['hub.secret']
- end
-
- def account_from_topic
- if hub_topic.present? && local_domain? && account_feed_path?
- Account.find_local(hub_topic_params[:username])
- end
- end
-
- def hub_topic_params
- @_hub_topic_params ||= Rails.application.routes.recognize_path(hub_topic_uri.path)
- end
-
- def hub_topic_uri
- @_hub_topic_uri ||= Addressable::URI.parse(hub_topic).normalize
- end
-
- def local_domain?
- TagManager.instance.web_domain?(hub_topic_domain)
- end
-
- def verified_domain
- return signed_request_account.domain if signed_request_account
- end
-
- def hub_topic_domain
- hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '')
- end
-
- def account_feed_path?
- hub_topic_params[:controller] == 'accounts' && hub_topic_params[:action] == 'show' && hub_topic_params[:format] == 'atom'
- end
-end
diff --git a/app/controllers/api/salmon_controller.rb b/app/controllers/api/salmon_controller.rb
deleted file mode 100644
index ac5f3268..00000000
--- a/app/controllers/api/salmon_controller.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class Api::SalmonController < Api::BaseController
- include SignatureVerification
-
- before_action :set_account
- respond_to :txt
-
- def update
- if verify_payload?
- process_salmon
- head 202
- elsif payload.present?
- render plain: signature_verification_failure_reason, status: 401
- else
- head 400
- end
- end
-
- private
-
- def set_account
- @account = Account.find(params[:id])
- end
-
- def payload
- @_payload ||= request.body.read
- end
-
- def verify_payload?
- payload.present? && VerifySalmonService.new.call(payload)
- end
-
- def process_salmon
- SalmonWorker.perform_async(@account.id, payload.force_encoding('UTF-8'))
- end
-end
diff --git a/app/controllers/api/subscriptions_controller.rb b/app/controllers/api/subscriptions_controller.rb
deleted file mode 100644
index 89007f3d..00000000
--- a/app/controllers/api/subscriptions_controller.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-class Api::SubscriptionsController < Api::BaseController
- before_action :set_account
- respond_to :txt
-
- def show
- if subscription.valid?(params['hub.topic'])
- @account.update(subscription_expires_at: future_expires)
- render plain: encoded_challenge, status: 200
- else
- head 404
- end
- end
-
- def update
- if subscription.verify(body, request.headers['HTTP_X_HUB_SIGNATURE'])
- ProcessingWorker.perform_async(@account.id, body.force_encoding('UTF-8'))
- end
-
- head 200
- end
-
- private
-
- def subscription
- @_subscription ||= @account.subscription(
- api_subscription_url(@account.id)
- )
- end
-
- def body
- @_body ||= request.body.read
- end
-
- def encoded_challenge
- HTMLEntities.new.encode(params['hub.challenge'])
- end
-
- def future_expires
- Time.now.utc + lease_seconds_or_default
- end
-
- def lease_seconds_or_default
- (params['hub.lease_seconds'] || 1.day).to_i.seconds
- end
-
- def set_account
- @account = Account.find(params[:id])
- end
-end
diff --git a/app/controllers/api/v1/account_by_username_controller.rb b/app/controllers/api/v1/account_by_username_controller.rb
index 5246f800..63a34353 100644
--- a/app/controllers/api/v1/account_by_username_controller.rb
+++ b/app/controllers/api/v1/account_by_username_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::AccountByUsernameController < EmptyController
before_action :check_account_suspension
before_action :check_account_local
- respond_to :json
-
def show
render json: @account, serializer: REST::AccountSerializer
end
diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb
index 4659fdb5..0fb7d3ca 100644
--- a/app/controllers/api/v1/accounts/credentials_controller.rb
+++ b/app/controllers/api/v1/accounts/credentials_controller.rb
@@ -14,7 +14,6 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
@account = current_account
UpdateAccountService.new.call(@account, account_params, raise_error: true)
UserSettingsDecorator.new(current_user).update(user_settings_params) if user_settings_params
- ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index 2dabb839..c85db5f7 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
before_action :set_account
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index 44e89804..6d0247e3 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
before_action :set_account
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
@@ -25,6 +23,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
end
def hide_results?
+ # : todo : where tf is this?
(@account.user_hides_network? && current_account.id != @account.id) || (current_account && @account.blocking?(current_account))
end
diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
deleted file mode 100644
index dee28977..00000000
--- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::Accounts::IdentityProofsController < Api::BaseController
- before_action :set_account
-
- respond_to :json
-
- def index
- @proofs = @account.identity_proofs.active
- render json: @proofs, each_serializer: REST::IdentityProofSerializer
- end
-
- private
-
- def set_account
- @account = Account.find(params[:account_id])
- end
-end
diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb
index 72392453..ccb751f8 100644
--- a/app/controllers/api/v1/accounts/lists_controller.rb
+++ b/app/controllers/api/v1/accounts/lists_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::ListsController < Api::BaseController
before_action :require_user!
before_action :set_account
- respond_to :json
-
def index
@lists = @account.lists.where(account: current_account)
render json: @lists, each_serializer: REST::ListSerializer
diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb
deleted file mode 100644
index 0a0239c4..00000000
--- a/app/controllers/api/v1/accounts/pins_controller.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::Accounts::PinsController < Api::BaseController
- include Authorization
-
- before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
- before_action :require_user!
- before_action :set_account
-
- respond_to :json
-
- def create
- AccountPin.create!(account: current_account, target_account: @account)
- render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
- end
-
- def destroy
- pin = AccountPin.find_by(account: current_account, target_account: @account)
- pin&.destroy!
- render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
- end
-
- private
-
- def set_account
- @account = Account.find(params[:account_id])
- end
-
- def relationships_presenter
- AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
- end
-end
diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb
index ab8a0461..1d3992a2 100644
--- a/app/controllers/api/v1/accounts/relationships_controller.rb
+++ b/app/controllers/api/v1/accounts/relationships_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:follows' }
before_action :require_user!
- respond_to :json
-
def index
accounts = Account.where(id: account_ids).select('id')
# .where doesn't guarantee that our results are in the same order
diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb
deleted file mode 100644
index 4217b527..00000000
--- a/app/controllers/api/v1/accounts/search_controller.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::Accounts::SearchController < Api::BaseController
- before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
- before_action :require_user!
-
- respond_to :json
-
- def show
- @accounts = account_search
- render json: @accounts, each_serializer: REST::AccountSerializer
- end
-
- private
-
- def account_search
- AccountSearchService.new.call(
- params[:q],
- current_account,
- limit: limit_param(DEFAULT_ACCOUNTS_LIMIT),
- resolve: truthy_param?(:resolve),
- following: truthy_param?(:following),
- offset: params[:offset]
- )
- end
-end
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 76b857a4..b4563d28 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -5,11 +5,12 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
before_action :set_account
after_action :insert_pagination_headers
- respond_to :json
-
def index
@statuses = load_statuses
- render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
+ render json: @statuses,
+ each_serializer: REST::StatusSerializer,
+ account_id: params[:account_id],
+ relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
private
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index b0c62778..09ae8701 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -10,9 +10,6 @@ class Api::V1::AccountsController < Api::BaseController
before_action :require_user!, except: [:show, :create]
before_action :set_account, except: [:create]
before_action :check_account_suspension, only: [:show]
- before_action :check_enabled_registrations, only: [:create]
-
- respond_to :json
def show
render json: @account, serializer: REST::AccountSerializer
@@ -78,12 +75,4 @@ class Api::V1::AccountsController < Api::BaseController
def account_params
params.permit(:username, :email, :password, :agreement, :locale)
end
-
- def check_enabled_registrations
- forbidden if single_user_mode? || !allowed_registrations?
- end
-
- def allowed_registrations?
- Setting.registrations_mode != 'none'
- end
end
diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb
index 8b63d049..0475b2d4 100644
--- a/app/controllers/api/v1/apps/credentials_controller.rb
+++ b/app/controllers/api/v1/apps/credentials_controller.rb
@@ -3,8 +3,6 @@
class Api::V1::Apps::CredentialsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
- respond_to :json
-
def show
render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key)
end
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index 4cff04ca..a2baeef9 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::BlocksController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb
index b3ef2fd9..f6aed818 100644
--- a/app/controllers/api/v1/bookmarks_controller.rb
+++ b/app/controllers/api/v1/bookmarks_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::BookmarksController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@statuses = []
if current_account.is_pro
diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb
deleted file mode 100644
index b19f27eb..00000000
--- a/app/controllers/api/v1/conversations_controller.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::ConversationsController < Api::BaseController
- LIMIT = 20
-
- before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :index
- before_action -> { doorkeeper_authorize! :write, :'write:conversations' }, except: :index
- before_action :require_user!
- before_action :set_conversation, except: :index
- after_action :insert_pagination_headers, only: :index
-
- respond_to :json
-
- def index
- @conversations = paginated_conversations
- render json: @conversations, each_serializer: REST::ConversationSerializer
- end
-
- def read
- @conversation.update!(unread: false)
- render json: @conversation, serializer: REST::ConversationSerializer
- end
-
- def destroy
- @conversation.destroy!
- render_empty
- end
-
- private
-
- def set_conversation
- @conversation = AccountConversation.where(account: current_account).find(params[:id])
- end
-
- def paginated_conversations
- AccountConversation.where(account: current_account)
- .paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
- end
-
- def insert_pagination_headers
- set_pagination_headers(next_path, prev_path)
- end
-
- def next_path
- if records_continue?
- api_v1_conversations_url pagination_params(max_id: pagination_max_id)
- end
- end
-
- def prev_path
- unless @conversations.empty?
- api_v1_conversations_url pagination_params(min_id: pagination_since_id)
- end
- end
-
- def pagination_max_id
- @conversations.last.last_status_id
- end
-
- def pagination_since_id
- @conversations.first.last_status_id
- end
-
- def records_continue?
- @conversations.size == limit_param(LIMIT)
- end
-
- def pagination_params(core_params)
- params.slice(:limit).permit(:limit).merge(core_params)
- end
-end
diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb
index 3589d1e3..ef9d6f96 100644
--- a/app/controllers/api/v1/custom_emojis_controller.rb
+++ b/app/controllers/api/v1/custom_emojis_controller.rb
@@ -1,8 +1,10 @@
# frozen_string_literal: true
class Api::V1::CustomEmojisController < EmptyController
+
def index
- data = ActiveModelSerializers::SerializableResource.new(CustomEmoji.local.where(disabled: false), each_serializer: REST::CustomEmojiSerializer)
+ data = ActiveModelSerializers::SerializableResource.new(CustomEmoji.local, each_serializer: REST::CustomEmojiSerializer)
render json: data.to_json, content_type: 'application/json'
end
+
end
diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb
deleted file mode 100644
index af9e7a20..00000000
--- a/app/controllers/api/v1/domain_blocks_controller.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::DomainBlocksController < Api::BaseController
- BLOCK_LIMIT = 100
-
- before_action -> { doorkeeper_authorize! :follow, :'read:blocks' }, only: :show
- before_action -> { doorkeeper_authorize! :follow, :'write:blocks' }, except: :show
- before_action :require_user!
- after_action :insert_pagination_headers, only: :show
-
- respond_to :json
-
- def show
- @blocks = load_domain_blocks
- render json: @blocks.map(&:domain)
- end
-
- def create
- current_account.block_domain!(domain_block_params[:domain])
- AfterAccountDomainBlockWorker.perform_async(current_account.id, domain_block_params[:domain])
- render_empty
- end
-
- def destroy
- current_account.unblock_domain!(domain_block_params[:domain])
- render_empty
- end
-
- private
-
- def load_domain_blocks
- account_domain_blocks.paginate_by_max_id(
- limit_param(BLOCK_LIMIT),
- params[:max_id],
- params[:since_id]
- )
- end
-
- def account_domain_blocks
- current_account.domain_blocks
- end
-
- def insert_pagination_headers
- set_pagination_headers(next_path, prev_path)
- end
-
- def next_path
- if records_continue?
- api_v1_domain_blocks_url pagination_params(max_id: pagination_max_id)
- end
- end
-
- def prev_path
- unless @blocks.empty?
- api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id)
- end
- end
-
- def pagination_max_id
- @blocks.last.id
- end
-
- def pagination_since_id
- @blocks.first.id
- end
-
- def records_continue?
- @blocks.size == limit_param(BLOCK_LIMIT)
- end
-
- def pagination_params(core_params)
- params.slice(:limit).permit(:limit).merge(core_params)
- end
-
- def domain_block_params
- params.permit(:domain)
- end
-end
diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb
deleted file mode 100644
index 2770c7ae..00000000
--- a/app/controllers/api/v1/endorsements_controller.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::EndorsementsController < Api::BaseController
- before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
- before_action :require_user!
- after_action :insert_pagination_headers
-
- respond_to :json
-
- def index
- @accounts = load_accounts
- render json: @accounts, each_serializer: REST::AccountSerializer
- end
-
- private
-
- def load_accounts
- if unlimited?
- endorsed_accounts.all
- else
- endorsed_accounts.paginate_by_max_id(
- limit_param(DEFAULT_ACCOUNTS_LIMIT),
- params[:max_id],
- params[:since_id]
- )
- end
- end
-
- def endorsed_accounts
- current_account.endorsed_accounts.includes(:account_stat)
- end
-
- def insert_pagination_headers
- set_pagination_headers(next_path, prev_path)
- end
-
- def next_path
- return if unlimited?
-
- if records_continue?
- api_v1_endorsements_url pagination_params(max_id: pagination_max_id)
- end
- end
-
- def prev_path
- return if unlimited?
-
- unless @accounts.empty?
- api_v1_endorsements_url pagination_params(since_id: pagination_since_id)
- end
- end
-
- def pagination_max_id
- @accounts.last.id
- end
-
- def pagination_since_id
- @accounts.first.id
- end
-
- def records_continue?
- @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
- end
-
- def pagination_params(core_params)
- params.slice(:limit).permit(:limit).merge(core_params)
- end
-
- def unlimited?
- params[:limit] == '0'
- end
-end
diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb
index db827f9d..3e242905 100644
--- a/app/controllers/api/v1/favourites_controller.rb
+++ b/app/controllers/api/v1/favourites_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::FavouritesController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb
index e5ebaff4..b0ace3af 100644
--- a/app/controllers/api/v1/filters_controller.rb
+++ b/app/controllers/api/v1/filters_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::FiltersController < Api::BaseController
before_action :set_filters, only: :index
before_action :set_filter, only: [:show, :update, :destroy]
- respond_to :json
-
def index
render json: @filters, each_serializer: REST::FilterSerializer
end
diff --git a/app/controllers/api/v1/follows_controller.rb b/app/controllers/api/v1/follows_controller.rb
index 5420c053..5eaf06b3 100644
--- a/app/controllers/api/v1/follows_controller.rb
+++ b/app/controllers/api/v1/follows_controller.rb
@@ -4,18 +4,11 @@ class Api::V1::FollowsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow, :'write:follows' }
before_action :require_user!
- respond_to :json
-
def create
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
- if @account.nil?
- username, domain = target_uri.split('@')
- @account = Account.find_remote!(username, domain)
- end
-
render json: @account, serializer: REST::AccountSerializer
end
diff --git a/app/controllers/api/v1/gab_trends_controller.rb b/app/controllers/api/v1/gab_trends_controller.rb
deleted file mode 100644
index 166403bb..00000000
--- a/app/controllers/api/v1/gab_trends_controller.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::GabTrendsController < EmptyController
- def index
- if Rails.env != 'development'
- render json: nil
- end
-
- type = params[:type]
- if type == 'feed'
- body = Redis.current.get("gabtrends:feed")
-
- if body.nil? || body.empty?
- Request.new(:get, "https://trends.gab.com/trend-feed/json").perform do |res|
- Rails.logger.debug "GabTrendsController: #{type} endpoint res code: #{res.code.to_s}"
- if res.code == 200
- body = res.body_with_limit
- Redis.current.set("gabtrends:feed", body)
- Redis.current.expire("gabtrends:feed", 1.hour.seconds)
- render json: body
- else
- render json: nil
- end
- end
- else
- render json: body
- end
- elsif type == 'partner'
- body = Redis.current.get("gabtrends:partner")
-
- if body.nil? || body.empty?
- Request.new(:get, "https://trends.gab.com/partner").perform do |res|
- Rails.logger.debug "GabTrendsController: #{type} endpoint res code: #{res.code.to_s}"
- if res.code == 200
- body = res.body_with_limit
- Redis.current.set("gabtrends:partner", body)
- Redis.current.expire("gabtrends:partner", 1.minute.seconds)
- render json: body
- else
- render json: nil
- end
- end
- else
- render json: body
- end
- elsif type == 'news'
- body = Redis.current.get("gabtrends:news")
-
- if body.nil? || body.empty?
- Request.new(:get, "https://news.gab.com/feed/json").perform do |res|
- Rails.logger.debug "GabTrendsController: #{type} endpoint res code: #{res.code.to_s}"
- if res.code == 200
- body = res.body_with_limit
- Redis.current.set("gabtrends:news", body)
- Redis.current.expire("gabtrends:news", 1.minute.seconds)
- render json: body
- else
- render json: nil
- end
- end
- else
- render json: body
- end
- elsif type == 'rss'
- body = Redis.current.get("gabtrends:feeds")
-
- if body.nil? || body.empty?
- Request.new(:get, "https://trends.gab.com/feed/#{params[:feedId]}?fmt=json&p=#{params[:page]}").perform do |res|
- Rails.logger.debug "GabTrendsController: #{type} endpoint res code: #{res.code.to_s}"
- if res.code == 200
- body = res.body_with_limit
- Redis.current.set("gabtrends:news", body)
- Redis.current.expire("gabtrends:news", 1.minute.seconds)
- render json: body
- else
- render json: nil
- end
- end
- else
- render json: body
- end
- else
- raise GabSocial::NotPermittedError
- end
-
- rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, HTTP::Error
- Rails.logger.debug "Error fetching gabtrends feed: #{type}"
- render json: nil
- end
-
-end
diff --git a/app/controllers/api/v1/groups/password_controller.rb b/app/controllers/api/v1/groups/password_controller.rb
index d0804077..ba8ed772 100644
--- a/app/controllers/api/v1/groups/password_controller.rb
+++ b/app/controllers/api/v1/groups/password_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Groups::PasswordController < Api::BaseController
before_action :require_user!
before_action :set_group
- respond_to :json
-
def create
authorize @group, :join?
diff --git a/app/controllers/api/v1/groups/pins_controller.rb b/app/controllers/api/v1/groups/pins_controller.rb
index ce66e0bc..051897f3 100644
--- a/app/controllers/api/v1/groups/pins_controller.rb
+++ b/app/controllers/api/v1/groups/pins_controller.rb
@@ -8,8 +8,6 @@ class Api::V1::Groups::PinsController < Api::BaseController
before_action :set_group
before_action :set_status
- respond_to :json
-
def create
authorize @group, :update?
@@ -17,6 +15,10 @@ class Api::V1::Groups::PinsController < Api::BaseController
render json: @status, serializer: REST::StatusSerializer
end
+ def show
+ # is status pinned by user of group?
+ end
+
def destroy
authorize @group, :update?
diff --git a/app/controllers/api/v1/groups/relationships_controller.rb b/app/controllers/api/v1/groups/relationships_controller.rb
index 884c5916..3bbad6aa 100644
--- a/app/controllers/api/v1/groups/relationships_controller.rb
+++ b/app/controllers/api/v1/groups/relationships_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Groups::RelationshipsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:groups' }
before_action :require_user!
- respond_to :json
-
def index
groups = Group.where(id: group_ids, is_archived: false).select('id')
# .where doesn't guarantee that our results are in the same order
diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb
index 659ddf90..8ad3c602 100644
--- a/app/controllers/api/v1/media_controller.rb
+++ b/app/controllers/api/v1/media_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::MediaController < Api::BaseController
include ObfuscateFilename
obfuscate_filename :file
- respond_to :json
-
def create
@media = current_account.media_attachments.create!(account: current_account, file: media_params[:file], description: media_params[:description], focus: media_params[:focus])
render json: @media, serializer: REST::MediaAttachmentSerializer
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index df6c8e86..65439fe9 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::MutesController < Api::BaseController
before_action :require_user!
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index a3152942..727f693b 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -1,14 +1,12 @@
# frozen_string_literal: true
class Api::V1::NotificationsController < Api::BaseController
- before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, except: [:clear, :dismiss, :mark_read]
- before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: [:clear, :dismiss, :mark_read]
+ before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, except: [:clear, :mark_read]
+ before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: [:clear, :mark_read]
before_action :require_user!
before_action :set_filter_params
after_action :insert_pagination_headers, only: :index
- respond_to :json
-
DEFAULT_NOTIFICATIONS_LIMIT = 20
def index
@@ -26,11 +24,6 @@ class Api::V1::NotificationsController < Api::BaseController
render_empty
end
- def dismiss
- current_account.notifications.find_by!(id: params[:id]).destroy!
- render_empty
- end
-
def mark_read
current_account.notifications.find(params[:id]).mark_read!
render_empty
diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb
index aac094c1..b4e4a68b 100644
--- a/app/controllers/api/v1/polls/votes_controller.rb
+++ b/app/controllers/api/v1/polls/votes_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Polls::VotesController < Api::BaseController
before_action :require_user!
before_action :set_poll
- respond_to :json
-
def create
VoteService.new.call(current_account, @poll, vote_params[:choices])
render json: @poll, serializer: REST::PollSerializer
diff --git a/app/controllers/api/v1/polls_controller.rb b/app/controllers/api/v1/polls_controller.rb
index 4f4a6858..f5a1dc38 100644
--- a/app/controllers/api/v1/polls_controller.rb
+++ b/app/controllers/api/v1/polls_controller.rb
@@ -3,11 +3,8 @@
class Api::V1::PollsController < Api::BaseController
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, only: :show
- respond_to :json
-
def show
@poll = Poll.attached.find(params[:id])
- ActivityPub::FetchRemotePollService.new.call(@poll, current_account) if user_signed_in? && @poll.possibly_stale?
render json: @poll, serializer: REST::PollSerializer, include_results: true
end
end
diff --git a/app/controllers/api/v1/preferences_controller.rb b/app/controllers/api/v1/preferences_controller.rb
index 077d39f5..1640a822 100644
--- a/app/controllers/api/v1/preferences_controller.rb
+++ b/app/controllers/api/v1/preferences_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::PreferencesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
before_action :require_user!
- respond_to :json
-
def index
render json: current_account, serializer: REST::PreferencesSerializer
end
diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb
deleted file mode 100644
index 1b658f87..00000000
--- a/app/controllers/api/v1/push/subscriptions_controller.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::Push::SubscriptionsController < Api::BaseController
- before_action -> { doorkeeper_authorize! :push }
- before_action :require_user!
- before_action :set_web_push_subscription
-
- def create
- @web_subscription&.destroy!
-
- @web_subscription = ::Web::PushSubscription.create!(
- endpoint: subscription_params[:endpoint],
- key_p256dh: subscription_params[:keys][:p256dh],
- key_auth: subscription_params[:keys][:auth],
- data: data_params,
- user_id: current_user.id,
- access_token_id: doorkeeper_token.id
- )
-
- render json: @web_subscription, serializer: REST::WebPushSubscriptionSerializer
- end
-
- def show
- raise ActiveRecord::RecordNotFound if @web_subscription.nil?
-
- render json: @web_subscription, serializer: REST::WebPushSubscriptionSerializer
- end
-
- def update
- raise ActiveRecord::RecordNotFound if @web_subscription.nil?
-
- @web_subscription.update!(data: data_params)
-
- render json: @web_subscription, serializer: REST::WebPushSubscriptionSerializer
- end
-
- def destroy
- @web_subscription&.destroy!
- render_empty
- end
-
- private
-
- def set_web_push_subscription
- @web_subscription = ::Web::PushSubscription.find_by(access_token_id: doorkeeper_token.id)
- end
-
- def subscription_params
- params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh])
- end
-
- def data_params
- return {} if params[:data].blank?
- params.require(:data).permit(alerts: [:follow, :favourite, :reblog, :mention, :poll])
- end
-end
diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb
index e182a9c6..4b477a0f 100644
--- a/app/controllers/api/v1/reports_controller.rb
+++ b/app/controllers/api/v1/reports_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::ReportsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create]
before_action :require_user!
- respond_to :json
-
def create
@report = ReportService.new.call(
current_account,
diff --git a/app/controllers/api/v1/search_controller.rb b/app/controllers/api/v1/search_controller.rb
index daa7ba81..bb81ed9f 100644
--- a/app/controllers/api/v1/search_controller.rb
+++ b/app/controllers/api/v1/search_controller.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
-class Api::V1::SearchController < Api::BaseController
- RESULTS_LIMIT = 100
-
- respond_to :json
+class Api::V1::SearchController < EmptyController
+ RESULTS_LIMIT = 25
def index
@search = Search.new(search_results)
diff --git a/app/controllers/api/v1/shop_controller.rb b/app/controllers/api/v1/shop_controller.rb
deleted file mode 100644
index 32984e53..00000000
--- a/app/controllers/api/v1/shop_controller.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::ShopController < EmptyController
- def index
- if Rails.env != 'development'
- render json: nil
- end
-
- type = params[:type]
- if type == 'featured_products'
- body = Redis.current.get("gabstore:featuredproducts")
-
- if body.nil? || body.empty?
- Request.new(:get, "https://shop.dissenter.com/product/group/json").perform do |res|
- Rails.logger.debug "ShopController dissenter products endpoint res code: #{res.code.to_s}"
- if res.code == 200
- body = res.body_with_limit
- Redis.current.set("gabstore:featuredproducts", body)
- Redis.current.expire("gabstore:featuredproducts", 15.minutes.seconds)
- render json: body
- else
- render json: nil
- end
- end
- else
- render json: body
- end
- else
- raise GabSocial::NotPermittedError
- end
- rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, HTTP::Error
- Rails.logger.debug "Error fetching dissenter shop: #{type}"
- render json: nil
- end
-
-end
diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb
index 6dbb74c7..8a5625ed 100644
--- a/app/controllers/api/v1/statuses/bookmarks_controller.rb
+++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' }
before_action :require_user!
- respond_to :json
-
def create
if current_user.account.is_pro
@status = bookmarked_status
@@ -17,6 +15,10 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
end
end
+ def show
+ # is status bookmarked by user?
+ end
+
def destroy
if current_user.account.is_pro
@status = requested_status
diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb
index 2ee4beb7..4f52942f 100644
--- a/app/controllers/api/v1/statuses/favourites_controller.rb
+++ b/app/controllers/api/v1/statuses/favourites_controller.rb
@@ -6,11 +6,10 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:favourites' }
before_action :require_user!
- respond_to :json
-
def create
@status = favourited_status
- render json: @status, serializer: REST::StatusSerializer
+ puts "tilly -- status: " + @status.inspect
+ render json: @status, serializer: REST::StatusStatSerializer
end
def destroy
@@ -19,7 +18,7 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
- render json: @status, serializer: REST::StatusSerializer, unfavourite: true, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
+ render json: @status, serializer: REST::StatusStatSerializer, unfavourite: true, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
end
private
diff --git a/app/controllers/api/v1/statuses/mutes_controller.rb b/app/controllers/api/v1/statuses/mutes_controller.rb
deleted file mode 100644
index 3a1c49d6..00000000
--- a/app/controllers/api/v1/statuses/mutes_controller.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::Statuses::MutesController < Api::BaseController
- include Authorization
-
- before_action -> { doorkeeper_authorize! :write, :'write:mutes' }
- before_action :require_user!
- before_action :set_status
- before_action :set_conversation
-
- respond_to :json
-
- def create
- current_account.mute_conversation!(@conversation)
- @mutes_map = { @conversation.id => true }
-
- render json: @status, serializer: REST::StatusSerializer
- end
-
- def destroy
- current_account.unmute_conversation!(@conversation)
- @mutes_map = { @conversation.id => false }
-
- render json: @status, serializer: REST::StatusSerializer
- end
-
- private
-
- def set_status
- @status = Status.find(params[:status_id])
- authorize @status, :show?
- rescue GabSocial::NotPermittedError
- # Reraise in order to get a 404 instead of a 403 error code
- raise ActiveRecord::RecordNotFound
- end
-
- def set_conversation
- @conversation = @status.conversation
- raise GabSocial::ValidationError if @conversation.nil?
- end
-end
diff --git a/app/controllers/api/v1/statuses/pins_controller.rb b/app/controllers/api/v1/statuses/pins_controller.rb
index f9f135d8..fba194da 100644
--- a/app/controllers/api/v1/statuses/pins_controller.rb
+++ b/app/controllers/api/v1/statuses/pins_controller.rb
@@ -7,13 +7,15 @@ class Api::V1::Statuses::PinsController < Api::BaseController
before_action :require_user!
before_action :set_status
- respond_to :json
-
def create
StatusPin.create!(account: current_account, status: @status)
render json: @status, serializer: REST::StatusSerializer
end
+ def show
+ # is status pinned by user?
+ end
+
def destroy
pin = StatusPin.find_by(account: current_account, status: @status)
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index 7a267bf4..f897650d 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -1,14 +1,12 @@
# frozen_string_literal: true
-class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
+class Api::V1::Statuses::RepostedByAccountsController < Api::BaseController
include Authorization
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
before_action :set_status
after_action :insert_pagination_headers
- respond_to :json
-
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
@@ -38,13 +36,13 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
def next_path
if records_continue?
- api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id)
+ api_v1_status_reposted_by_index_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
- api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id)
+ api_v1_status_reposted_by_index_url pagination_params(since_id: pagination_since_id)
end
end
diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb
index bb5b6a4a..fe492fd0 100644
--- a/app/controllers/api/v1/statuses/reblogs_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogs_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
before_action :require_user!
- respond_to :json
-
def create
if !current_user.account.local? || !status_for_reblog.local
return render json: { error: 'Invalid action' }, status: 422
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index 5f42befd..a84b5d30 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -3,13 +3,12 @@
class Api::V1::StatusesController < Api::BaseController
include Authorization
+ # : todo : disable all oauth everything
before_action -> { authorize_if_got_token! :read, :'read:statuses' }, except: [:create, :update, :destroy]
before_action -> { doorkeeper_authorize! :write, :'write:statuses' }, only: [:create, :update, :destroy]
before_action :require_user!, except: [:show, :comments, :context, :card]
before_action :set_status, only: [:show, :comments, :context, :card, :update, :revisions]
- respond_to :json
-
# This API was originally unlimited, pagination cannot be introduced without
# breaking backwards-compatibility. Arbitrarily high number to cover most
# conversations as quasi-unlimited, it would be too much work to render more
@@ -126,7 +125,6 @@ class Api::V1::StatusesController < Api::BaseController
media_ids: [],
poll: [
:multiple,
- :hide_totals,
:expires_in,
options: [],
],
diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb
index 66b812e7..da918610 100644
--- a/app/controllers/api/v1/streaming_controller.rb
+++ b/app/controllers/api/v1/streaming_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::V1::StreamingController < Api::BaseController
- respond_to :json
-
def index
if Rails.configuration.x.streaming_api_base_url != request.host
uri = URI.parse(request.url)
diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb
index 7f0eda60..6ebec322 100644
--- a/app/controllers/api/v1/suggestions_controller.rb
+++ b/app/controllers/api/v1/suggestions_controller.rb
@@ -6,13 +6,11 @@ class Api::V1::SuggestionsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
- respond_to :json
-
def index
type = params[:type]
if type == 'related'
- count = truthy_param?(:unlimited) ? 80 : 10
+ count = truthy_param?(:unlimited) ? PotentialFriendshipTracker::MAX_ITEMS : 10
@accounts = PotentialFriendshipTracker.get(current_account.id, limit: count)
render json: @accounts, each_serializer: REST::AccountSerializer
elsif type == 'verified'
diff --git a/app/controllers/api/v1/timelines/explore_controller.rb b/app/controllers/api/v1/timelines/explore_controller.rb
index 00b89b7e..a4fe635d 100644
--- a/app/controllers/api/v1/timelines/explore_controller.rb
+++ b/app/controllers/api/v1/timelines/explore_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Api::V1::Timelines::ExploreController < Api::BaseController
+class Api::V1::Timelines::ExploreController < EmptyController
before_action :set_sort_type
before_action :set_statuses
@@ -45,110 +45,7 @@ class Api::V1::Timelines::ExploreController < Api::BaseController
end
def explore_statuses
- statuses = nil
-
- date_limit = 30.days.ago
- top_order = 'status_stats.favourites_count DESC, status_stats.reblogs_count DESC, status_stats.replies_count DESC'
-
- if @sort_type == 'hot'
- # : todo :
- # unique groups
- # unique users
- date_limit = 8.hours.ago
- elsif @sort_type == 'top_today'
- date_limit = 24.hours.ago
- elsif @sort_type == 'top_weekly'
- date_limit = 7.days.ago
- elsif @sort_type == 'top_monthly'
- date_limit = 30.days.ago
- elsif @sort_type == 'top_yearly'
- date_limit = 1.year.ago
- end
-
- if current_account
- if @sort_type == 'newest'
- statuses = Status.with_public_visibility.where(
- reply: false
- ).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif @sort_type == 'recent'
- statuses = Status.with_public_visibility.where(
- reply: false
- ).joins(:status_stat).where(
- 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0'
- ).order('status_stats.updated_at DESC').paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time', 'hot'].include? @sort_type
- if @sort_type == 'top_all_time'
- statuses = Status.unscoped.with_public_visibility.where(
- reply: false
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif @sort_type == 'hot'
- statuses = Status.unscoped.with_public_visibility.where(
- reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- else
- statuses = Status.unscoped.with_public_visibility.where(
- reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- end
- end
- else
- if @sort_type == 'newest'
- statuses = Status.with_public_visibility.where(
- reply: false
- ).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- )
- elsif @sort_type == 'recent'
- statuses = Status.with_public_visibility.where(
- reply: false
- ).joins(:status_stat).where(
- 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0'
- ).order('status_stats.updated_at DESC').paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- )
- elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time', 'hot'].include? @sort_type
- if @sort_type == 'top_all_time'
- statuses = Status.unscoped.with_public_visibility.where(
- reply: false
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- )
- else
- statuses = Status.unscoped.with_public_visibility.where(
- reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id)
- )
- end
- end
- end
-
- statuses
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id])
end
def insert_pagination_headers
diff --git a/app/controllers/api/v1/timelines/group_collection_controller.rb b/app/controllers/api/v1/timelines/group_collection_controller.rb
index b08d0c90..780638b7 100644
--- a/app/controllers/api/v1/timelines/group_collection_controller.rb
+++ b/app/controllers/api/v1/timelines/group_collection_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Api::V1::Timelines::GroupCollectionController < Api::BaseController
+class Api::V1::Timelines::GroupCollectionController < EmptyController
before_action :set_collection_type
before_action :set_sort_type
before_action :set_statuses
@@ -61,8 +61,6 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController
end
def group_collection_statuses
- statuses = nil
-
@groupIds = []
if @collection_type == 'featured'
@groupIds = FetchGroupsService.new.call("featured")
@@ -72,98 +70,7 @@ class Api::V1::Timelines::GroupCollectionController < Api::BaseController
return []
end
- date_limit = 30.days.ago
- top_order = 'status_stats.favourites_count DESC, status_stats.reblogs_count DESC, status_stats.replies_count DESC'
-
- if @sort_type == 'hot'
- # : todo :
- # unique groups
- # unique users
- date_limit = 8.hours.ago
- elsif @sort_type == 'top_today'
- date_limit = 24.hours.ago
- elsif @sort_type == 'top_weekly'
- date_limit = 7.days.ago
- elsif @sort_type == 'top_monthly'
- date_limit = 30.days.ago
- elsif @sort_type == 'top_yearly'
- date_limit = 1.year.ago
- end
-
- if current_account
- if @sort_type == 'newest'
- statuses = Status.where(
- group: @groupIds, reply: false
- ).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif @sort_type == 'recent'
- statuses = Status.where(
- group: @groupIds, reply: false
- ).joins(:status_stat).where(
- 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0'
- ).order('status_stats.updated_at DESC').paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time', 'hot'].include? @sort_type
- if @sort_type == 'top_all_time'
- statuses = Status.unscoped.where(
- group: @groupIds, reply: false
- ).joins(:status_stat).order(top_order)
- .paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- else
- statuses = Status.unscoped.where(
- group: @groupIds, reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- end
- end
- else
- if @sort_type == 'newest'
- statuses = Status.where(
- group: @groupIds, reply: false
- ).paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
- elsif @sort_type == 'recent'
- statuses = Status.where(
- group: @groupIds, reply: false
- ).joins(:status_stat).where(
- 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0'
- ).order('status_stats.updated_at DESC').paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time', 'hot'].include? @sort_type
- if @sort_type == 'top_all_time'
- statuses = Status.unscoped.where(
- group: @groupIds, reply: false
- ).joins(:status_stat).order(top_order)
- .paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- else
- statuses = Status.unscoped.where(
- group: @groupIds, reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- end
- end
- end
-
- statuses
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id], @groupIds)
end
def insert_pagination_headers
diff --git a/app/controllers/api/v1/timelines/group_controller.rb b/app/controllers/api/v1/timelines/group_controller.rb
index e9c870a2..01e0a31b 100644
--- a/app/controllers/api/v1/timelines/group_controller.rb
+++ b/app/controllers/api/v1/timelines/group_controller.rb
@@ -13,6 +13,7 @@ class Api::V1::Timelines::GroupController < Api::BaseController
if current_user
render json: @statuses,
each_serializer: REST::StatusSerializer,
+ group_id: params[:id],
relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id, group_id: @group.id)
else
render json: @statuses, each_serializer: REST::StatusSerializer
@@ -50,103 +51,7 @@ class Api::V1::Timelines::GroupController < Api::BaseController
end
def group_statuses
- statuses = nil
-
- date_limit = 30.days.ago
- top_order = 'status_stats.favourites_count DESC, status_stats.reblogs_count DESC, status_stats.replies_count DESC'
-
- if @sort_type == 'hot'
- # : todo :
- # unique groups
- # unique users
- date_limit = 8.hours.ago
- elsif @sort_type == 'top_today'
- date_limit = 24.hours.ago
- elsif @sort_type == 'top_weekly'
- date_limit = 7.days.ago
- elsif @sort_type == 'top_monthly'
- date_limit = 30.days.ago
- elsif @sort_type == 'top_yearly'
- date_limit = 1.year.ago
- end
-
- if current_account
- if @sort_type == 'newest'
- statuses = Status.where(
- group: @group, reply: false
- ).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif @sort_type == 'recent'
- statuses = Status.where(
- group: @group, reply: false
- ).joins(:status_stat).where(
- 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0'
- ).order('status_stats.updated_at DESC').paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time', 'hot'].include? @sort_type
- if @sort_type == 'top_all_time'
- statuses = Status.unscoped.where(
- group: @group, reply: false
- ).joins(:status_stat).order(top_order)
- .paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- else
- statuses = Status.unscoped.where(
- group: @group, reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- ).reject { |status| FeedManager.instance.filter?(:home, status, current_account.id) }
- end
- end
- else
- if @sort_type == 'newest'
- statuses = Status.where(
- group: @group, reply: false
- ).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- elsif @sort_type == 'recent'
- statuses = Status.where(
- group: @group, reply: false
- ).joins(:status_stat).where(
- 'status_stats.replies_count > 0 OR status_stats.reblogs_count > 0 OR status_stats.favourites_count > 0'
- ).order('status_stats.updated_at DESC').paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- elsif ['top_today', 'top_weekly', 'top_monthly', 'top_yearly', 'top_all_time', 'hot'].include? @sort_type
- if @sort_type == 'top_all_time'
- statuses = Status.unscoped.where(
- group: @group, reply: false
- ).joins(:status_stat).order(top_order)
- .paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- else
- statuses = Status.unscoped.where(
- group: @group, reply: false
- ).where(
- 'statuses.created_at > ?', date_limit
- ).joins(:status_stat).order(top_order).paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
- end
- end
- end
-
- statuses
+ SortingQueryBuilder.new.call(@sort_type, params[:max_id], @group)
end
def insert_pagination_headers
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb
index 748799a6..28fb06a5 100644
--- a/app/controllers/api/v1/timelines/home_controller.rb
+++ b/app/controllers/api/v1/timelines/home_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Timelines::HomeController < Api::BaseController
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
- respond_to :json
-
def show
@statuses = load_statuses
render json: @statuses,
diff --git a/app/controllers/api/v1/timelines/preview_card_controller.rb b/app/controllers/api/v1/timelines/preview_card_controller.rb
index 8f0d15c2..4734ea2a 100644
--- a/app/controllers/api/v1/timelines/preview_card_controller.rb
+++ b/app/controllers/api/v1/timelines/preview_card_controller.rb
@@ -10,6 +10,7 @@ class Api::V1::Timelines::PreviewCardController < Api::BaseController
def show
render json: @statuses,
each_serializer: REST::StatusSerializer,
+ preview_card_id: params[:id],
relationships: StatusRelationshipsPresenter.new(@statuses, current_user.account_id)
end
diff --git a/app/controllers/api/v1/timelines/pro_controller.rb b/app/controllers/api/v1/timelines/pro_controller.rb
index 89abc4f1..97691a88 100644
--- a/app/controllers/api/v1/timelines/pro_controller.rb
+++ b/app/controllers/api/v1/timelines/pro_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Timelines::ProController < Api::BaseController
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
- respond_to :json
-
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
deleted file mode 100644
index a6d1e8ee..00000000
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-class Api::V1::Timelines::PublicController < Api::BaseController
- before_action :require_user!, only: [:show]
- before_action :require_admin!
- after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
-
- respond_to :json
-
- def show
- @statuses = load_statuses
- render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
- end
-
- private
-
- def load_statuses
- cached_public_statuses
- end
-
- def cached_public_statuses
- cache_collection public_statuses, Status
- end
-
- def public_statuses
- statuses = public_timeline_statuses.paginate_by_id(
- limit_param(DEFAULT_STATUSES_LIMIT),
- params_slice(:max_id, :since_id, :min_id)
- )
-
- if truthy_param?(:only_media)
- # `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids.
- status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id)
- statuses.where(id: status_ids)
- else
- statuses
- end
- end
-
- def public_timeline_statuses
- Status.as_public_timeline(current_account)
- end
-
- def insert_pagination_headers
- set_pagination_headers(next_path, prev_path)
- end
-
- def pagination_params(core_params)
- params.slice(:limit, :only_media).permit(:limit, :only_media).merge(core_params)
- end
-
- def next_path
- api_v1_timelines_public_url pagination_params(max_id: pagination_max_id)
- end
-
- def prev_path
- api_v1_timelines_public_url pagination_params(min_id: pagination_since_id)
- end
-
- def pagination_max_id
- @statuses.last.id
- end
-
- def pagination_since_id
- @statuses.first.id
- end
-end
diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb
index 777be45f..4e89a112 100644
--- a/app/controllers/api/v1/timelines/tag_controller.rb
+++ b/app/controllers/api/v1/timelines/tag_controller.rb
@@ -5,11 +5,11 @@ class Api::V1::Timelines::TagController < Api::BaseController
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
- respond_to :json
-
def show
@statuses = tagged_statuses
- render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
+ render json: @statuses,
+ each_serializer: REST::StatusSerializer,
+ relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
private
diff --git a/app/controllers/api/web/embeds_controller.rb b/app/controllers/api/web/embeds_controller.rb
index a62b1af4..9f58ff8f 100644
--- a/app/controllers/api/web/embeds_controller.rb
+++ b/app/controllers/api/web/embeds_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::EmbedsController < Api::Web::BaseController
- respond_to :json
-
def create
status = StatusFinder.new(params[:url]).status
render json: status, serializer: OEmbedSerializer, width: 400
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb
index d8153e08..07c4aa56 100644
--- a/app/controllers/api/web/push_subscriptions_controller.rb
+++ b/app/controllers/api/web/push_subscriptions_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
- respond_to :json
-
before_action :require_user!
def create
diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb
index e3178bf4..3d65e46e 100644
--- a/app/controllers/api/web/settings_controller.rb
+++ b/app/controllers/api/web/settings_controller.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::SettingsController < Api::Web::BaseController
- respond_to :json
-
before_action :require_user!
def update
diff --git a/app/controllers/auth/omniauth_callbacks_controller.rb b/app/controllers/auth/omniauth_callbacks_controller.rb
deleted file mode 100644
index bbf63bed..00000000
--- a/app/controllers/auth/omniauth_callbacks_controller.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
- skip_before_action :verify_authenticity_token
-
- def self.provides_callback_for(provider)
- provider_id = provider.to_s.chomp '_oauth2'
-
- define_method provider do
- @user = User.find_for_oauth(request.env['omniauth.auth'], current_user)
-
- if @user.persisted?
- sign_in_and_redirect @user, event: :authentication
- set_flash_message(:notice, :success, kind: provider_id.capitalize) if is_navigational_format?
- else
- session["devise.#{provider}_data"] = request.env['omniauth.auth']
- redirect_to new_user_registration_url
- end
- end
- end
-
- Devise.omniauth_configs.each_key do |provider|
- provides_callback_for provider
- end
-
- def after_sign_in_path_for(resource)
- if resource.email_verified?
- root_path
- else
- finish_signup_path
- end
- end
-end
diff --git a/app/controllers/auth/registrations_controller.rb b/app/controllers/auth/registrations_controller.rb
index b1f322f1..ccd9b473 100644
--- a/app/controllers/auth/registrations_controller.rb
+++ b/app/controllers/auth/registrations_controller.rb
@@ -3,9 +3,7 @@
class Auth::RegistrationsController < Devise::RegistrationsController
layout :determine_layout
- before_action :set_invite, only: [:new, :create]
before_action :set_challenge, only: [:new]
- 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, :create, :update]
@@ -41,7 +39,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
super(hash)
resource.locale = I18n.locale
- resource.invite_code = params[:invite_code] if resource.invite_code.blank?
resource.agreement = true
resource.current_sign_in_ip = request.remote_ip
@@ -50,7 +47,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up) do |u|
- u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code)
+ u.permit({ account_attributes: [:username] }, :email, :password, :password_confirmation)
end
end
@@ -58,16 +55,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
new_user_session_path
end
- def after_sign_in_path_for(_resource)
- set_invite
-
- if @invite&.autofollow?
- short_account_path(@invite.user.account)
- else
- super
- end
- end
-
def after_inactive_sign_up_path_for(_resource)
new_user_session_path
end
@@ -76,22 +63,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
edit_user_registration_path
end
- def check_enabled_registrations
- redirect_to root_path if single_user_mode? || !allowed_registrations?
- end
-
- def allowed_registrations?
- Setting.registrations_mode != 'none' || @invite&.valid_for_use?
- end
-
- def invite_code
- if params[:user]
- params[:user][:invite_code]
- else
- params[:invite_code]
- end
- end
-
private
def set_instance_presenter
@@ -102,11 +73,6 @@ class Auth::RegistrationsController < Devise::RegistrationsController
@body_classes = %w(edit update).include?(action_name) ? 'admin' : ''
end
- def set_invite
- invite = invite_code.present? ? Invite.find_by(code: invite_code) : nil
- @invite = invite&.valid_for_use? ? invite : nil
- end
-
def set_challenge
@challenge_add_1 = rand(0...9)
@challenge_add_2 = rand(0...9)
diff --git a/app/controllers/authorize_interactions_controller.rb b/app/controllers/authorize_interactions_controller.rb
deleted file mode 100644
index 5c308260..00000000
--- a/app/controllers/authorize_interactions_controller.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-class AuthorizeInteractionsController < ApplicationController
- include Authorization
-
- layout 'modal'
-
- before_action :authenticate_user!
- before_action :set_body_classes
- before_action :set_resource
-
- def show
- if @resource.is_a?(Account)
- render :show
- elsif @resource.is_a?(Status)
- redirect_to web_url("statuses/#{@resource.id}")
- else
- render :error
- end
- end
-
- def create
- if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource)
- render :success
- else
- render :error
- end
- rescue ActiveRecord::RecordNotFound, GabSocial::NotPermittedError
- render :error
- end
-
- private
-
- def set_resource
- @resource = located_resource || render(:error)
- authorize(@resource, :show?) if @resource.is_a?(Status)
- end
-
- def located_resource
- if uri_param_is_url?
- ResolveURLService.new.call(uri_param)
- else
- account_from_remote_follow
- end
- end
-
- def account_from_remote_follow
- ResolveAccountService.new.call(uri_param)
- end
-
- def uri_param_is_url?
- parsed_uri.path && %w(http https).include?(parsed_uri.scheme)
- end
-
- def parsed_uri
- Addressable::URI.parse(uri_param).normalize
- end
-
- def uri_param
- params[:uri] || params.fetch(:acct, '').gsub(/\Aacct:/, '')
- end
-
- def set_body_classes
- @body_classes = 'modal-layout'
- end
-end
diff --git a/app/controllers/concerns/account_controller_concern.rb b/app/controllers/concerns/account_controller_concern.rb
index d17560d1..5b93831a 100644
--- a/app/controllers/concerns/account_controller_concern.rb
+++ b/app/controllers/concerns/account_controller_concern.rb
@@ -7,10 +7,8 @@ module AccountControllerConcern
included do
before_action :set_account
- before_action :check_account_approval
before_action :check_account_suspension
before_action :set_instance_presenter
- before_action :set_link_headers
end
private
@@ -23,51 +21,10 @@ module AccountControllerConcern
@instance_presenter = InstancePresenter.new
end
- def set_link_headers
- return if !@account.local? # TODO: Handle remote users
-
- response.headers['Link'] = LinkHeader.new(
- [
- webfinger_account_link,
- atom_account_url_link,
- actor_url_link,
- ]
- )
- end
-
def username_param
params[:account_username]
end
- def webfinger_account_link
- [
- webfinger_account_url,
- [%w(rel lrdd), %w(type application/xrd+xml)],
- ]
- end
-
- def atom_account_url_link
- [
- account_url(@account, format: 'atom'),
- [%w(rel alternate), %w(type application/atom+xml)],
- ]
- end
-
- def actor_url_link
- [
- ActivityPub::TagManager.instance.uri_for(@account),
- [%w(rel alternate), %w(type application/activity+json)],
- ]
- end
-
- def webfinger_account_url
- webfinger_url(resource: @account.to_webfinger_s)
- end
-
- def check_account_approval
- not_found if @account.user_pending?
- end
-
def check_account_suspension
if @account.suspended?
skip_session!
diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb
index 90a57197..fb2166ff 100644
--- a/app/controllers/concerns/signature_verification.rb
+++ b/app/controllers/concerns/signature_verification.rb
@@ -43,7 +43,7 @@ module SignatureVerification
return
end
- account = account_from_key_id(signature_params['keyId'])
+ account = nil
if account.nil?
@signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
@@ -56,7 +56,7 @@ module SignatureVerification
return account unless verify_signature(account, signature, compare_signed_string).nil?
- account = stoplight_wrap_request { account.possibly_stale? ? account.refresh! : account_refresh_key(account) }
+ account = nil
if account.nil?
@signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
@@ -122,27 +122,4 @@ module SignatureVerification
signature_params['signature'].blank?
end
- def account_from_key_id(key_id)
- if key_id.start_with?('acct:')
- stoplight_wrap_request { ResolveAccountService.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 ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false) }
- account
- end
- end
-
- def stoplight_wrap_request(&block)
- Stoplight("source:#{request.remote_ip}", &block)
- .with_fallback { nil }
- .with_threshold(1)
- .with_cool_off_time(5.minutes.seconds)
- .with_error_handler { |error, handle| error.is_a?(HTTP::Error) ? handle.call(error) : raise(error) }
- .run
- end
-
- def account_refresh_key(account)
- return if account.local? || !account.activitypub?
- ActivityPub::FetchRemoteAccountService.new.call(account.uri, only_key: true)
- end
end
diff --git a/app/controllers/directories_controller.rb b/app/controllers/directories_controller.rb
deleted file mode 100644
index 59490767..00000000
--- a/app/controllers/directories_controller.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class DirectoriesController < ApplicationController
- layout 'public'
-
- before_action :check_enabled
- before_action :set_instance_presenter
- before_action :set_tag, only: :show
- before_action :set_tags
- before_action :set_accounts
-
- def index
- render :index
- end
-
- def show
- render :index
- end
-
- private
-
- def check_enabled
- return not_found unless Setting.profile_directory
- end
-
- def set_tag
- @tag = Tag.discoverable.find_by!(name: params[:id].downcase)
- end
-
- def set_tags
- @tags = Tag.discoverable.limit(30).reject { |tag| tag.cached_sample_accounts.empty? }
- end
-
- def set_accounts
- @accounts = Account.discoverable.by_recent_status.page(params[:page]).per(40).tap do |query|
- query.merge!(Account.tagged_with(@tag.id)) if @tag
- end
- end
-
- def set_instance_presenter
- @instance_presenter = InstancePresenter.new
- end
-end
diff --git a/app/controllers/downloads_controller.rb b/app/controllers/downloads_controller.rb
deleted file mode 100644
index 946c7ded..00000000
--- a/app/controllers/downloads_controller.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-class DownloadsController < ApplicationController
- layout 'public'
-
- before_action :check_enabled
-
-end
\ No newline at end of file
diff --git a/app/controllers/emojis_controller.rb b/app/controllers/emojis_controller.rb
deleted file mode 100644
index 5d306e60..00000000
--- a/app/controllers/emojis_controller.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class EmojisController < ApplicationController
- before_action :set_emoji
- before_action :set_cache_headers
-
- def show
- respond_to do |format|
- format.json do
- skip_session!
-
- render_cached_json(['activitypub', 'emoji', @emoji], content_type: 'application/activity+json') do
- ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter)
- end
- 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
deleted file mode 100644
index ff7c6b5b..00000000
--- a/app/controllers/follower_accounts_controller.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class FollowerAccountsController < ApplicationController
- include AccountControllerConcern
-
- before_action :set_cache_headers
-
- def index
- respond_to do |format|
- format.html do
- mark_cacheable! unless user_signed_in?
-
- next if @account.user_hides_network?
-
- follows
- @relationships = AccountRelationshipsPresenter.new(follows.map(&:account_id), current_user.account_id) if user_signed_in?
- end
-
- format.json do
- raise GabSocial::NotPermittedError if params[:page].present? && @account.user_hides_network?
-
- if params[:page].blank?
- skip_session!
- expires_in 3.minutes, public: true
- end
-
- render json: collection_presenter,
- serializer: ActivityPub::CollectionSerializer,
- adapter: ActivityPub::Adapter,
- content_type: 'application/activity+json'
- end
- end
- end
-
- private
-
- def follows
- @follows ||= Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
- end
-
- def page_url(page)
- account_followers_url(@account, page: page) unless page.nil?
- end
-
- def collection_presenter
- if params[:page].present?
- ActivityPub::CollectionPresenter.new(
- id: account_followers_url(@account, page: params.fetch(:page, 1)),
- type: :ordered,
- size: @account.followers_count,
- items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) },
- part_of: account_followers_url(@account),
- next: page_url(follows.next_page),
- prev: page_url(follows.prev_page)
- )
- else
- ActivityPub::CollectionPresenter.new(
- id: account_followers_url(@account),
- type: :ordered,
- size: @account.followers_count,
- first: page_url(1)
- )
- end
- end
-end
diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb
deleted file mode 100644
index 6dcf4eff..00000000
--- a/app/controllers/following_accounts_controller.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class FollowingAccountsController < ApplicationController
- include AccountControllerConcern
-
- before_action :set_cache_headers
-
- def index
- respond_to do |format|
- format.html do
- mark_cacheable! unless user_signed_in?
-
- next if @account.user_hides_network?
-
- follows
- @relationships = AccountRelationshipsPresenter.new(follows.map(&:target_account_id), current_user.account_id) if user_signed_in?
- end
-
- format.json do
- raise GabSocial::NotPermittedError if params[:page].present? && @account.user_hides_network?
-
- if params[:page].blank?
- skip_session!
- expires_in 3.minutes, public: true
- end
-
- render json: collection_presenter,
- serializer: ActivityPub::CollectionSerializer,
- adapter: ActivityPub::Adapter,
- content_type: 'application/activity+json'
- end
- end
- end
-
- private
-
- def follows
- @follows ||= Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
- end
-
- def page_url(page)
- account_following_index_url(@account, page: page) unless page.nil?
- end
-
- def collection_presenter
- if params[:page].present?
- ActivityPub::CollectionPresenter.new(
- id: account_following_index_url(@account, page: params.fetch(:page, 1)),
- type: :ordered,
- size: @account.following_count,
- items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.target_account) },
- part_of: account_following_index_url(@account),
- next: page_url(follows.next_page),
- prev: page_url(follows.prev_page)
- )
- else
- ActivityPub::CollectionPresenter.new(
- id: account_following_index_url(@account),
- type: :ordered,
- size: @account.following_count,
- first: page_url(1)
- )
- end
- end
-end
diff --git a/app/controllers/intents_controller.rb b/app/controllers/intents_controller.rb
deleted file mode 100644
index 9f41cf48..00000000
--- a/app/controllers/intents_controller.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-class IntentsController < ApplicationController
- before_action :check_uri
- rescue_from Addressable::URI::InvalidURIError, with: :handle_invalid_uri
-
- def show
- if uri.scheme == 'web+mastodon'
- case uri.host
- when 'follow'
- return redirect_to authorize_interaction_path(uri: uri.query_values['uri'].gsub(/\Aacct:/, ''))
- when 'share'
- return redirect_to share_path(text: uri.query_values['text'])
- end
- end
-
- not_found
- end
-
- private
-
- def check_uri
- not_found if uri.blank?
- end
-
- def handle_invalid_uri
- not_found
- end
-
- def uri
- @uri ||= Addressable::URI.parse(params[:uri])
- end
-end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
deleted file mode 100644
index fdb3a096..00000000
--- a/app/controllers/invites_controller.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-class InvitesController < ApplicationController
- include Authorization
-
- layout 'admin'
-
- before_action :authenticate_user!
- before_action :set_body_classes
-
- def index
- authorize :invite, :create?
-
- @invites = invites
- @invite = Invite.new
- end
-
- def create
- authorize :invite, :create?
-
- @invite = Invite.new(resource_params)
- @invite.user = current_user
-
- if @invite.save
- redirect_to invites_path
- else
- @invites = invites
- render :index
- end
- end
-
- def destroy
- @invite = invites.find(params[:id])
- authorize @invite, :destroy?
- @invite.expire!
- redirect_to invites_path
- end
-
- private
-
- def invites
- Invite.where(user: current_user).order(id: :desc)
- end
-
- def resource_params
- params.require(:invite).permit(:max_uses, :expires_in, :autofollow)
- end
-
- def set_body_classes
- @body_classes = 'admin'
- end
-end
diff --git a/app/controllers/manifests_controller.rb b/app/controllers/manifests_controller.rb
index 2b8ab280..09985129 100644
--- a/app/controllers/manifests_controller.rb
+++ b/app/controllers/manifests_controller.rb
@@ -5,4 +5,5 @@ class ManifestsController < EmptyController
def show
render json: InstancePresenter.new, serializer: ManifestSerializer
end
+
end
diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb
deleted file mode 100644
index 86a7d3e0..00000000
--- a/app/controllers/media_controller.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class MediaController < ApplicationController
- include Authorization
-
- skip_before_action :store_current_location
-
- before_action :set_media_attachment
- before_action :verify_permitted_status!
-
- content_security_policy only: :player do |p|
- p.frame_ancestors(false)
- end
-
- def show
- redirect_to @media_attachment.file.url(:original)
- end
-
- def player
- @body_classes = 'player'
- response.headers['X-Frame-Options'] = 'ALLOWALL'
- raise ActiveRecord::RecordNotFound unless @media_attachment.video? || @media_attachment.gifv?
- end
-
- private
-
- def set_media_attachment
- @media_attachment = MediaAttachment.attached.find_by!(shortcode: params[:id] || params[:medium_id])
- end
-
- def verify_permitted_status!
- authorize @media_attachment.status, :show?
- rescue GabSocial::NotPermittedError
- # Reraise in order to get a 404 instead of a 403 error code
- raise ActiveRecord::RecordNotFound
- end
-end
diff --git a/app/controllers/public_timelines_controller.rb b/app/controllers/public_timelines_controller.rb
deleted file mode 100644
index 53d4472d..00000000
--- a/app/controllers/public_timelines_controller.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class PublicTimelinesController < ApplicationController
- layout 'public'
-
- before_action :check_enabled
- before_action :set_body_classes
- before_action :set_instance_presenter
-
- def show
- respond_to do |format|
- format.html do
- @initial_state_json = ActiveModelSerializers::SerializableResource.new(
- InitialStatePresenter.new(settings: { known_fediverse: Setting.show_known_fediverse_at_about_page }, token: current_session&.token),
- serializer: InitialStateSerializer
- ).to_json
- end
- end
- end
-
- private
-
- def check_enabled
- raise ActiveRecord::RecordNotFound unless Setting.timeline_preview
- end
-
- def set_body_classes
- @body_classes = 'with-modals'
- end
-
- def set_instance_presenter
- @instance_presenter = InstancePresenter.new
- end
-end
diff --git a/app/controllers/react_controller.rb b/app/controllers/react_controller.rb
index 5295afcc..cb7d4822 100644
--- a/app/controllers/react_controller.rb
+++ b/app/controllers/react_controller.rb
@@ -52,7 +52,7 @@ class ReactController < ApplicationController
end
def find_route_matches
- request.path.match(/\A\/(home|news|suggestions|links|messages|shortcuts|group|groups|list|lists|notifications|tags|compose|follow_requests|admin|account|settings|filters|timeline|blocks|domain_blocks|mutes)/)
+ request.path.match(/\A\/(home|news|suggestions|links|messages|shortcuts|group|groups|list|lists|notifications|tags|compose|follow_requests|admin|account|settings|filters|timeline|blocks|mutes)/)
end
def find_public_route_matches
diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb
deleted file mode 100644
index e6705c32..00000000
--- a/app/controllers/relationships_controller.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-class RelationshipsController < ApplicationController
- layout 'admin'
-
- before_action :authenticate_user!
- before_action :set_accounts, only: :show
- before_action :set_body_classes
-
- helper_method :following_relationship?, :followed_by_relationship?, :mutual_relationship?
-
- def show
- @form = Form::AccountBatch.new
- end
-
- def update
- @form = Form::AccountBatch.new(form_account_batch_params.merge(current_account: current_account, action: action_from_button))
- @form.save
- rescue ActionController::ParameterMissing
- # Do nothing
- ensure
- redirect_to relationships_path(current_params)
- end
-
- private
-
- def set_accounts
- @accounts = relationships_scope.page(params[:page]).per(40)
- end
-
- def relationships_scope
- scope = begin
- if following_relationship?
- current_account.following.eager_load(:account_stat).reorder(nil)
- else
- current_account.followers.eager_load(:account_stat).reorder(nil)
- end
- end
-
- scope.merge!(Follow.recent) if params[:order].blank? || params[:order] == 'recent'
- scope.merge!(Account.by_recent_status) if params[:order] == 'active'
- scope.merge!(mutual_relationship_scope) if mutual_relationship?
- scope.merge!(moved_account_scope) if params[:status] == 'moved'
- scope.merge!(primary_account_scope) if params[:status] == 'primary'
- scope.merge!(by_domain_scope) if params[:by_domain].present?
- scope.merge!(dormant_account_scope) if params[:activity] == 'dormant'
-
- scope
- end
-
- def mutual_relationship_scope
- Account.where(id: current_account.following)
- end
-
- def moved_account_scope
- Account.where.not(moved_to_account_id: nil)
- end
-
- def primary_account_scope
- Account.where(moved_to_account_id: nil)
- end
-
- def dormant_account_scope
- AccountStat.where(last_status_at: nil).or(AccountStat.where(AccountStat.arel_table[:last_status_at].lt(1.month.ago)))
- end
-
- def by_domain_scope
- Account.where(domain: params[:by_domain])
- end
-
- def form_account_batch_params
- params.require(:form_account_batch).permit(:action, account_ids: [])
- end
-
- def following_relationship?
- params[:relationship].blank? || params[:relationship] == 'following'
- end
-
- def mutual_relationship?
- params[:relationship] == 'mutual'
- end
-
- def followed_by_relationship?
- params[:relationship] == 'followed_by'
- end
-
- def current_params
- params.slice(:page, :status, :relationship, :by_domain, :activity, :order).permit(:page, :status, :relationship, :by_domain, :activity, :order)
- end
-
- def action_from_button
- if params[:unfollow]
- 'unfollow'
- elsif params[:remove_from_followers]
- 'remove_from_followers'
- elsif params[:block_domains]
- 'block_domains'
- end
- end
-
- def set_body_classes
- @body_classes = 'admin'
- end
-end
diff --git a/app/controllers/remote_follow_controller.rb b/app/controllers/remote_follow_controller.rb
deleted file mode 100644
index 8ba331cd..00000000
--- a/app/controllers/remote_follow_controller.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteFollowController < ApplicationController
- layout 'modal'
-
- before_action :set_account
- before_action :gone, if: :suspended_account?
- before_action :set_body_classes
-
- def new
- @remote_follow = RemoteFollow.new(session_params)
- end
-
- def create
- @remote_follow = RemoteFollow.new(resource_params)
-
- if @remote_follow.valid?
- session[:remote_follow] = @remote_follow.acct
- redirect_to @remote_follow.subscribe_address_for(@account)
- else
- render :new
- end
- end
-
- private
-
- def resource_params
- params.require(:remote_follow).permit(:acct)
- end
-
- def session_params
- { acct: session[:remote_follow] }
- end
-
- def set_account
- @account = Account.find_local!(params[:account_username])
- end
-
- def suspended_account?
- @account.suspended?
- end
-
- def set_body_classes
- @body_classes = 'modal-layout'
- @hide_header = true
- end
-end
diff --git a/app/controllers/remote_interaction_controller.rb b/app/controllers/remote_interaction_controller.rb
deleted file mode 100644
index 2cb19333..00000000
--- a/app/controllers/remote_interaction_controller.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteInteractionController < ApplicationController
- include Authorization
-
- layout 'modal'
-
- before_action :set_interaction_type
- before_action :set_status
- before_action :set_body_classes
-
- def new
- @remote_follow = RemoteFollow.new(session_params)
- end
-
- def create
- @remote_follow = RemoteFollow.new(resource_params)
-
- if @remote_follow.valid?
- session[:remote_follow] = @remote_follow.acct
- redirect_to @remote_follow.interact_address_for(@status)
- else
- render :new
- end
- end
-
- private
-
- def resource_params
- params.require(:remote_follow).permit(:acct)
- end
-
- def session_params
- { acct: session[:remote_follow] }
- end
-
- def set_status
- @status = Status.find(params[:id])
- authorize @status, :show?
- rescue GabSocial::NotPermittedError
- # Reraise in order to get a 404
- raise ActiveRecord::RecordNotFound
- end
-
- def set_body_classes
- @body_classes = 'modal-layout'
- @hide_header = true
- end
-
- def set_interaction_type
- @interaction_type = %w(reply reblog favourite).include?(params[:type]) ? params[:type] : 'reply'
- end
-end
diff --git a/app/controllers/remote_unfollows_controller.rb b/app/controllers/remote_unfollows_controller.rb
deleted file mode 100644
index 494218da..00000000
--- a/app/controllers/remote_unfollows_controller.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteUnfollowsController < ApplicationController
- layout 'modal'
-
- before_action :authenticate_user!
- before_action :set_body_classes
-
- def create
- @account = unfollow_attempt.try(:target_account)
-
- if @account.nil?
- render :error
- else
- render :success
- end
- rescue ActiveRecord::RecordNotFound, GabSocial::NotPermittedError
- render :error
- end
-
- private
-
- def unfollow_attempt
- username, domain = acct_without_prefix.split('@')
- UnfollowService.new.call(current_account, Account.find_remote!(username, domain))
- end
-
- def acct_without_prefix
- acct_params.gsub(/\Aacct:/, '')
- end
-
- def acct_params
- params.fetch(:acct, '')
- end
-
- def set_body_classes
- @body_classes = 'modal-layout'
- end
-end
diff --git a/app/controllers/settings/deletes_controller.rb b/app/controllers/settings/deletes_controller.rb
index dd19aadf..709efaf1 100644
--- a/app/controllers/settings/deletes_controller.rb
+++ b/app/controllers/settings/deletes_controller.rb
@@ -3,7 +3,6 @@
class Settings::DeletesController < Settings::BaseController
layout 'admin'
- before_action :check_enabled_deletion
before_action :authenticate_user!
def show
@@ -22,10 +21,6 @@ class Settings::DeletesController < Settings::BaseController
private
- def check_enabled_deletion
- redirect_to root_path unless Setting.open_deletion
- end
-
def delete_params
params.require(:form_delete_confirmation).permit(:password)
end
diff --git a/app/controllers/settings/exports/blocked_domains_controller.rb b/app/controllers/settings/exports/blocked_domains_controller.rb
deleted file mode 100644
index 6676ce34..00000000
--- a/app/controllers/settings/exports/blocked_domains_controller.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module Settings
- module Exports
- class BlockedDomainsController < ApplicationController
- include ExportControllerConcern
-
- def index
- send_export_file
- end
-
- private
-
- def export_data
- @export.to_blocked_domains_csv
- end
- end
- end
-end
diff --git a/app/controllers/settings/identity_proofs_controller.rb b/app/controllers/settings/identity_proofs_controller.rb
deleted file mode 100644
index e22b4d9b..00000000
--- a/app/controllers/settings/identity_proofs_controller.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-class Settings::IdentityProofsController < Settings::BaseController
- layout 'admin'
-
- before_action :authenticate_user!
- before_action :check_required_params, only: :new
-
- def index
- @proofs = AccountIdentityProof.where(account: current_account).order(provider: :asc, provider_username: :asc)
- @proofs.each(&:refresh!)
- end
-
- def new
- @proof = current_account.identity_proofs.new(
- token: params[:token],
- provider: params[:provider],
- provider_username: params[:provider_username]
- )
-
- if current_account.username.casecmp(params[:username]).zero?
- render layout: 'auth'
- else
- flash[:alert] = I18n.t('identity_proofs.errors.wrong_user', proving: params[:username], current: current_account.username)
- redirect_to settings_identity_proofs_path
- end
- end
-
- def create
- @proof = current_account.identity_proofs.where(provider: resource_params[:provider], provider_username: resource_params[:provider_username]).first_or_initialize(resource_params)
- @proof.token = resource_params[:token]
-
- if @proof.save
- PostStatusService.new.call(current_user.account, text: post_params[:status_text]) if publish_proof?
- redirect_to @proof.on_success_path(params[:user_agent])
- else
- flash[:alert] = I18n.t('identity_proofs.errors.failed', provider: @proof.provider.capitalize)
- redirect_to settings_identity_proofs_path
- end
- end
-
- private
-
- def check_required_params
- redirect_to settings_identity_proofs_path unless [:provider, :provider_username, :username, :token].all? { |k| params[k].present? }
- end
-
- def resource_params
- params.require(:account_identity_proof).permit(:provider, :provider_username, :token)
- end
-
- def publish_proof?
- ActiveModel::Type::Boolean.new.cast(post_params[:post_status])
- end
-
- def post_params
- params.require(:account_identity_proof).permit(:post_status, :status_text)
- end
-
- def set_body_classes
- @body_classes = ''
- end
-end
diff --git a/app/controllers/settings/imports_controller.rb b/app/controllers/settings/imports_controller.rb
deleted file mode 100644
index 38f2e39c..00000000
--- a/app/controllers/settings/imports_controller.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class Settings::ImportsController < Settings::BaseController
- layout 'admin'
-
- before_action :authenticate_user!
- before_action :set_account
-
- def show
- @import = Import.new
- end
-
- def create
- @import = Import.new(import_params)
- @import.account = @account
-
- if @import.save
- ImportWorker.perform_async(@import.id)
- redirect_to settings_import_path, notice: I18n.t('imports.success')
- else
- render :show
- end
- end
-
- private
-
- def set_account
- @account = current_user.account
- end
-
- def import_params
- params.require(:import).permit(:data, :type)
- end
-end
diff --git a/app/controllers/settings/migrations_controller.rb b/app/controllers/settings/migrations_controller.rb
deleted file mode 100644
index 59eb4877..00000000
--- a/app/controllers/settings/migrations_controller.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class Settings::MigrationsController < Settings::BaseController
- layout 'admin'
-
- before_action :authenticate_user!
-
- def show
- @migration = Form::Migration.new(account: current_account.moved_to_account)
- end
-
- def update
- @migration = Form::Migration.new(resource_params)
-
- if @migration.valid? && migration_account_changed?
- current_account.update!(moved_to_account: @migration.account)
- ActivityPub::UpdateDistributionWorker.perform_async(current_account.id)
- redirect_to settings_migration_path, notice: I18n.t('migrations.updated_msg')
- else
- render :show
- end
- end
-
- private
-
- def resource_params
- params.require(:migration).permit(:acct)
- end
-
- def migration_account_changed?
- current_account.moved_to_account_id != @migration.account&.id &&
- current_account.id != @migration.account&.id
- end
-end
diff --git a/app/controllers/settings/notifications_controller.rb b/app/controllers/settings/notifications_controller.rb
index b1e527e4..6464c7eb 100644
--- a/app/controllers/settings/notifications_controller.rb
+++ b/app/controllers/settings/notifications_controller.rb
@@ -25,7 +25,7 @@ class Settings::NotificationsController < Settings::BaseController
def user_settings_params
params.require(:user).permit(
- notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account emails_from_gabcom),
+ notification_emails: %i(follow follow_request reblog favourite mention digest report emails_from_gabcom),
interactions: %i(must_be_follower must_be_following must_be_following_dm)
)
end
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index cb1de69d..4ce457e3 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -47,9 +47,8 @@ class Settings::PreferencesController < Settings::BaseController
:setting_theme,
:setting_hide_network,
:setting_aggregate_reblogs,
- :setting_show_application,
:setting_group_in_home_feed,
- notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account emails_from_gabcom),
+ notification_emails: %i(follow follow_request reblog favourite mention digest report emails_from_gabcom),
interactions: %i(must_be_follower must_be_following)
)
end
diff --git a/app/controllers/settings/profiles_controller.rb b/app/controllers/settings/profiles_controller.rb
index 32714955..0312017b 100644
--- a/app/controllers/settings/profiles_controller.rb
+++ b/app/controllers/settings/profiles_controller.rb
@@ -22,7 +22,6 @@ class Settings::ProfilesController < Settings::BaseController
redirect_to settings_profile_path
else
if UpdateAccountService.new.call(@account, account_params)
- ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg')
else
@account.build_fields
diff --git a/app/controllers/shares_controller.rb b/app/controllers/shares_controller.rb
deleted file mode 100644
index af605b98..00000000
--- a/app/controllers/shares_controller.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class SharesController < ApplicationController
- layout 'modal'
-
- before_action :authenticate_user!
- before_action :set_body_classes
-
- def show
- serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
- @initial_state_json = serializable_resource.to_json
- end
-
- private
-
- def initial_state_params
- text = [params[:title], params[:text], params[:url]].compact.join(' ')
-
- {
- settings: Web::Setting.find_by(user: current_user)&.data || {},
- push_subscription: current_account.user.web_push_subscription(current_session),
- current_account: current_account,
- token: current_session.token,
- admin: Account.find_local(Setting.site_contact_username.strip.gsub(/\A@/, '')),
- text: text,
- }
- end
-
- def set_body_classes
- @body_classes = 'modal-layout compose-standalone'
- end
-end
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
deleted file mode 100644
index dbb4bd08..00000000
--- a/app/controllers/statuses_controller.rb
+++ /dev/null
@@ -1,230 +0,0 @@
-# frozen_string_literal: true
-
-class StatusesController < ReactController
- include SignatureAuthentication
- include Authorization
-
- ANCESTORS_LIMIT = 40
- DESCENDANTS_LIMIT = 60
- DESCENDANTS_DEPTH_LIMIT = 20
-
- before_action :set_account
- before_action :set_status
- before_action :set_instance_presenter
- before_action :set_link_headers
- before_action :check_account_suspension
- before_action :redirect_to_original, only: [:show]
- before_action :set_referrer_policy_header, only: [:show]
- before_action :set_cache_headers
- before_action :set_replies, only: [:replies]
-
- content_security_policy only: :embed do |p|
- p.frame_ancestors(false)
- end
-
- def show
- respond_to do |format|
- format.html do
- unless user_signed_in?
- skip_session!
- expires_in 10.seconds, public: true
- end
-
- return process(:react)
- end
-
- format.json do
- mark_cacheable! unless @stream_entry.hidden?
-
- render_cached_json(['activitypub', 'note', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
- ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
- end
- end
- end
- end
-
- def activity
- skip_session!
-
- render_cached_json(['activitypub', 'activity', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
- ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter)
- end
- end
-
- def embed
- raise ActiveRecord::RecordNotFound if @status.hidden?
-
- skip_session!
- expires_in 180, public: true
- response.headers['X-Frame-Options'] = 'ALLOWALL'
- @autoplay = ActiveModel::Type::Boolean.new.cast(params[:autoplay])
-
- render 'stream_entries/embed', layout: 'embedded'
- end
-
- def replies
- skip_session!
-
- render json: replies_collection_presenter,
- serializer: ActivityPub::CollectionSerializer,
- adapter: ActivityPub::Adapter,
- content_type: 'application/activity+json',
- skip_activities: true
- end
-
- private
-
- def replies_collection_presenter
- page = ActivityPub::CollectionPresenter.new(
- id: replies_account_status_url(@account, @status, page_params),
- type: :unordered,
- part_of: replies_account_status_url(@account, @status),
- next: next_page,
- items: @replies.map { |status| status.local ? status : status.id }
- )
- if page_requested?
- page
- else
- ActivityPub::CollectionPresenter.new(
- id: replies_account_status_url(@account, @status),
- type: :unordered,
- first: page
- )
- end
- end
-
- def create_descendant_thread(starting_depth, statuses)
- depth = starting_depth + statuses.size
- if depth < DESCENDANTS_DEPTH_LIMIT
- { statuses: statuses, starting_depth: starting_depth }
- else
- next_status = statuses.pop
- { statuses: statuses, starting_depth: starting_depth, next_status: next_status }
- end
- end
-
- def set_account
- @account = Account.find_acct!(params[:account_username])
- end
-
- def set_ancestors
- @ancestors = @status.reply? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT, current_account), Status) : []
- @next_ancestor = @ancestors.size < ANCESTORS_LIMIT ? nil : @ancestors.shift
- end
-
- def set_descendants
- @max_descendant_thread_id = params[:max_descendant_thread_id]&.to_i
- @since_descendant_thread_id = params[:since_descendant_thread_id]&.to_i
-
- descendants = cache_collection(
- @status.descendants(
- DESCENDANTS_LIMIT,
- current_account,
- @max_descendant_thread_id,
- @since_descendant_thread_id,
- DESCENDANTS_DEPTH_LIMIT
- ),
- Status
- )
-
- @descendant_threads = []
-
- if descendants.present?
- statuses = [descendants.first]
- starting_depth = 0
-
- descendants.drop(1).each_with_index do |descendant, index|
- if descendants[index].id == descendant.in_reply_to_id
- statuses << descendant
- else
- @descendant_threads << create_descendant_thread(starting_depth, statuses)
-
- # The thread is broken, assume it's a reply to the root status
- starting_depth = 0
-
- # ... unless we can find its ancestor in one of the already-processed threads
- @descendant_threads.reverse_each do |descendant_thread|
- statuses = descendant_thread[:statuses]
-
- index = statuses.find_index do |thread_status|
- thread_status.id == descendant.in_reply_to_id
- end
-
- if index.present?
- starting_depth = descendant_thread[:starting_depth] + index + 1
- break
- end
- end
-
- statuses = [descendant]
- end
- end
-
- @descendant_threads << create_descendant_thread(starting_depth, statuses)
- end
-
- @max_descendant_thread_id = @descendant_threads.pop[:statuses].first.id if descendants.size >= DESCENDANTS_LIMIT
- end
-
- def set_link_headers
- return if !@account.local? # TODO: Handle remote accounts
-
- response.headers['Link'] = LinkHeader.new(
- [
- [account_stream_entry_url(@account, @status.stream_entry, format: 'atom'), [%w(rel alternate), %w(type application/atom+xml)]],
- [ActivityPub::TagManager.instance.uri_for(@status), [%w(rel alternate), %w(type application/activity+json)]],
- ]
- )
- end
-
- def set_status
- @status = @account.statuses.find(params[:id])
- @stream_entry = @status.stream_entry
- @type = @stream_entry&.activity_type&.downcase
-
- authorize @status, :show?
- rescue GabSocial::NotPermittedError
- # Reraise in order to get a 404
- raise ActiveRecord::RecordNotFound
- end
-
- def set_instance_presenter
- @instance_presenter = InstancePresenter.new
- end
-
- def check_account_suspension
- gone if @account.suspended?
- end
-
- def redirect_to_original
- redirect_to ::TagManager.instance.url_for(@status.reblog) if @status.reblog?
- end
-
- def set_referrer_policy_header
- return if @status.public_visibility? || @status.unlisted_visibility?
- response.headers['Referrer-Policy'] = 'origin'
- end
-
- def page_requested?
- params[:page] == 'true'
- end
-
- def set_replies
- @replies = page_params[:other_accounts] ? Status.where.not(account_id: @account.id) : @account.statuses
- @replies = @replies.where(in_reply_to_id: @status.id, visibility: [:public, :unlisted])
- @replies = @replies.paginate_by_min_id(DESCENDANTS_LIMIT, params[:min_id])
- end
-
- def next_page
- last_reply = @replies.last
- return if last_reply.nil?
- same_account = last_reply.account_id == @account.id
- return unless same_account || @replies.size == DESCENDANTS_LIMIT
- same_account = false unless @replies.size == DESCENDANTS_LIMIT
- replies_account_status_url(@account, @status, page: true, min_id: last_reply.id, other_accounts: !same_account)
- end
-
- def page_params
- { page: true, other_accounts: params[:other_accounts], min_id: params[:min_id] }.compact
- end
-end
diff --git a/app/controllers/stream_entries_controller.rb b/app/controllers/stream_entries_controller.rb
deleted file mode 100644
index e4003adc..00000000
--- a/app/controllers/stream_entries_controller.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-class StreamEntriesController < ApplicationController
- include Authorization
- include SignatureVerification
-
- layout 'public'
-
- before_action :set_account
- before_action :set_stream_entry
- before_action :set_link_headers
- before_action :check_account_suspension
- before_action :set_cache_headers
-
- def show
- respond_to do |format|
- format.html do
- unless user_signed_in?
- skip_session!
- expires_in 5.minutes, public: true
- end
-
- redirect_to short_account_status_url(params[:account_username], @stream_entry.activity) if @type == 'status'
- end
-
- format.atom do
- unless @stream_entry.hidden?
- skip_session!
- expires_in 3.minutes, public: true
- end
-
- render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.entry(@stream_entry, true))
- end
- end
- end
-
- def embed
- redirect_to embed_short_account_status_url(@account, @stream_entry.activity), status: 301
- end
-
- private
-
- def set_account
- @account = Account.find_local!(params[:account_username])
- end
-
- def set_link_headers
- response.headers['Link'] = LinkHeader.new(
- [
- [account_stream_entry_url(@account, @stream_entry, format: 'atom'), [%w(rel alternate), %w(type application/atom+xml)]],
- [ActivityPub::TagManager.instance.uri_for(@stream_entry.activity), [%w(rel alternate), %w(type application/activity+json)]],
- ]
- )
- end
-
- def set_stream_entry
- @stream_entry = @account.stream_entries.where(activity_type: 'Status').find(params[:id])
- @type = @stream_entry.activity_type.downcase
-
- raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
- authorize @stream_entry.activity, :show? if @stream_entry.hidden?
- rescue GabSocial::NotPermittedError
- # Reraise in order to get a 404
- raise ActiveRecord::RecordNotFound
- end
-
- def check_account_suspension
- gone if @account.suspended?
- end
-end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
deleted file mode 100644
index 02df87c6..00000000
--- a/app/controllers/tags_controller.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-class TagsController < ApplicationController
- PAGE_SIZE = 20
-
- layout 'public'
-
- before_action :set_body_classes
- before_action :set_instance_presenter
-
- def show
- @tag = Tag.find_normalized!(params[:id])
-
- respond_to do |format|
- format.html do
- @initial_state_json = ActiveModelSerializers::SerializableResource.new(
- InitialStatePresenter.new(settings: {}, token: current_session&.token),
- serializer: InitialStateSerializer
- ).to_json
- end
-
- format.rss do
- @statuses = HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none)).limit(PAGE_SIZE)
- @statuses = cache_collection(@statuses, Status)
-
- render xml: RSS::TagSerializer.render(@tag, @statuses)
- end
-
- format.json do
- @statuses = HashtagQueryService.new.call(@tag, params.slice(:any, :all, :none), current_account).paginate_by_max_id(PAGE_SIZE, 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 = 'with-modals'
- end
-
- def set_instance_presenter
- @instance_presenter = InstancePresenter.new
- end
-
- def collection_presenter
- ActivityPub::CollectionPresenter.new(
- id: tag_url(@tag, params.slice(:any, :all, :none)),
- type: :ordered,
- size: @tag.statuses.count,
- items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
- )
- end
-end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 5a636508..86a5a0d4 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -19,28 +19,8 @@ module ApplicationHelper
!user_signed_in? && !single_user_mode?
end
- def open_registrations?
- Setting.registrations_mode == 'open'
- end
-
- def approved_registrations?
- Setting.registrations_mode == 'approved'
- end
-
- def closed_registrations?
- Setting.registrations_mode == 'none'
- end
-
def available_sign_up_path
- if closed_registrations?
- 'https://gab.com/hosting#getting-started'
- else
- new_user_registration_path
- end
- end
-
- def open_deletion?
- Setting.open_deletion
+ new_user_registration_path
end
def locale_direction
diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb
index df60b7dd..8e17bda2 100644
--- a/app/helpers/home_helper.rb
+++ b/app/helpers/home_helper.rb
@@ -65,13 +65,4 @@ module HomeHelper
end
end
- def sign_up_message
- if closed_registrations?
- t('auth.registration_closed', instance: site_hostname)
- elsif open_registrations?
- t('auth.register')
- elsif approved_registrations?
- t('auth.apply_for_account')
- end
- end
end
diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/statuses_helper.rb
similarity index 91%
rename from app/helpers/stream_entries_helper.rb
rename to app/helpers/statuses_helper.rb
index d1700151..948a9be0 100644
--- a/app/helpers/stream_entries_helper.rb
+++ b/app/helpers/statuses_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module StreamEntriesHelper
+module StatusesHelper
EMBEDDED_CONTROLLER = 'statuses'
EMBEDDED_ACTION = 'embed'
@@ -41,16 +41,6 @@ module StreamEntriesHelper
def account_badge(account, all: false)
if account.bot?
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
- elsif (Setting.show_staff_badge && account.user_staff?) || all
- content_tag(:div, class: 'roles') do
- if all && !account.user_staff?
- content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role')
- elsif account.user_admin?
- content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
- elsif account.user_moderator?
- content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
- end
- end
end
end
diff --git a/app/javascript/gabsocial/actions/accounts.js b/app/javascript/gabsocial/actions/accounts.js
index eb0ae3f5..38c1d563 100644
--- a/app/javascript/gabsocial/actions/accounts.js
+++ b/app/javascript/gabsocial/actions/accounts.js
@@ -36,14 +36,6 @@ export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
-export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
-export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS';
-export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
-
-export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
-export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
-export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
-
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
@@ -772,72 +764,3 @@ export function rejectFollowRequestFail(id, error) {
};
};
-export function pinAccount(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(pinAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => {
- dispatch(pinAccountSuccess(response.data));
- }).catch(error => {
- dispatch(pinAccountFail(error));
- });
- };
-};
-
-export function unpinAccount(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unpinAccountRequest(id));
-
- api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => {
- dispatch(unpinAccountSuccess(response.data));
- }).catch(error => {
- dispatch(unpinAccountFail(error));
- });
- };
-};
-
-export function pinAccountRequest(id) {
- return {
- type: ACCOUNT_PIN_REQUEST,
- id,
- };
-};
-
-export function pinAccountSuccess(relationship) {
- return {
- type: ACCOUNT_PIN_SUCCESS,
- relationship,
- };
-};
-
-export function pinAccountFail(error) {
- return {
- type: ACCOUNT_PIN_FAIL,
- error,
- };
-};
-
-export function unpinAccountRequest(id) {
- return {
- type: ACCOUNT_UNPIN_REQUEST,
- id,
- };
-};
-
-export function unpinAccountSuccess(relationship) {
- return {
- type: ACCOUNT_UNPIN_SUCCESS,
- relationship,
- };
-};
-
-export function unpinAccountFail(error) {
- return {
- type: ACCOUNT_UNPIN_FAIL,
- error,
- };
-};
diff --git a/app/javascript/gabsocial/actions/blocks.js b/app/javascript/gabsocial/actions/blocks.js
index f241eef7..279f505f 100644
--- a/app/javascript/gabsocial/actions/blocks.js
+++ b/app/javascript/gabsocial/actions/blocks.js
@@ -11,79 +11,69 @@ export const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST'
export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS'
export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL'
-export function fetchBlocks() {
- return (dispatch, getState) => {
- if (!me) return
+/**
+ *
+ */
+export const fetchBlocks = () => (dispatch, getState) => {
+ if (!me) return
- dispatch(fetchBlocksRequest())
+ dispatch(fetchBlocksRequest())
- api(getState).get('/api/v1/blocks').then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
- dispatch(importFetchedAccounts(response.data))
- dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null))
- dispatch(fetchRelationships(response.data.map(item => item.id)))
- }).catch(error => dispatch(fetchBlocksFail(error)))
- }
+ api(getState).get('/api/v1/blocks').then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(fetchBlocksFail(error)))
}
-export function fetchBlocksRequest() {
- return {
- type: BLOCKS_FETCH_REQUEST,
- }
+export const fetchBlocksRequest = () => ({
+ type: BLOCKS_FETCH_REQUEST,
+})
+
+export const fetchBlocksSuccess = (accounts, next) => ({
+ type: BLOCKS_FETCH_SUCCESS,
+ accounts,
+ next,
+})
+
+export const fetchBlocksFail = (error) => ({
+ type: BLOCKS_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const expandBlocks = () => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'blocks', me, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'blocks', me, 'isLoading'])
+
+ if (url === null || isLoading) return
+
+ dispatch(expandBlocksRequest())
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandBlocksSuccess(response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(expandBlocksFail(error)))
}
-export function fetchBlocksSuccess(accounts, next) {
- return {
- type: BLOCKS_FETCH_SUCCESS,
- accounts,
- next,
- }
-}
+export const expandBlocksRequest = () => ({
+ type: BLOCKS_EXPAND_REQUEST,
+})
-export function fetchBlocksFail(error) {
- return {
- type: BLOCKS_FETCH_FAIL,
- error,
- }
-}
+export const expandBlocksSuccess = (accounts, next) => ({
+ type: BLOCKS_EXPAND_SUCCESS,
+ accounts,
+ next,
+})
-export function expandBlocks() {
- return (dispatch, getState) => {
- if (!me) return
-
- const url = getState().getIn(['user_lists', 'blocks', me, 'next'])
- const isLoading = getState().getIn(['user_lists', 'blocks', me, 'isLoading'])
-
- if (url === null || isLoading) return
-
- dispatch(expandBlocksRequest())
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
- dispatch(importFetchedAccounts(response.data))
- dispatch(expandBlocksSuccess(response.data, next ? next.uri : null))
- dispatch(fetchRelationships(response.data.map(item => item.id)))
- }).catch(error => dispatch(expandBlocksFail(error)))
- }
-}
-
-export function expandBlocksRequest() {
- return {
- type: BLOCKS_EXPAND_REQUEST,
- }
-}
-
-export function expandBlocksSuccess(accounts, next) {
- return {
- type: BLOCKS_EXPAND_SUCCESS,
- accounts,
- next,
- }
-}
-
-export function expandBlocksFail(error) {
- return {
- type: BLOCKS_EXPAND_FAIL,
- error,
- }
-}
+export const expandBlocksFail = (error) => ({
+ type: BLOCKS_EXPAND_FAIL,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/bookmarks.js b/app/javascript/gabsocial/actions/bookmarks.js
index 6bbce6dd..3c41d2ff 100644
--- a/app/javascript/gabsocial/actions/bookmarks.js
+++ b/app/javascript/gabsocial/actions/bookmarks.js
@@ -10,89 +10,79 @@ export const BOOKMARKED_STATUSES_EXPAND_REQUEST = 'BOOKMARKED_STATUSES_EXPAND_RE
export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = 'BOOKMARKED_STATUSES_EXPAND_SUCCESS'
export const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL'
-export function fetchBookmarkedStatuses() {
- return (dispatch, getState) => {
- if (!me) return
+/**
+ *
+ */
+export const fetchBookmarkedStatuses = () => (dispatch, getState) => {
+ if (!me) return
- if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
- return
- }
-
- dispatch(fetchBookmarkedStatusesRequest())
-
- api(getState).get('/api/v1/bookmarks').then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
- dispatch(importFetchedStatuses(response.data))
- dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null))
- }).catch(error => {
- dispatch(fetchBookmarkedStatusesFail(error))
- })
+ if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
+ return
}
+
+ dispatch(fetchBookmarkedStatusesRequest())
+
+ api(getState).get('/api/v1/bookmarks').then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedStatuses(response.data))
+ dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null))
+ }).catch(error => {
+ dispatch(fetchBookmarkedStatusesFail(error))
+ })
}
-export function fetchBookmarkedStatusesRequest() {
- return {
- type: BOOKMARKED_STATUSES_FETCH_REQUEST,
- skipLoading: true,
+const fetchBookmarkedStatusesRequest = () => ({
+ type: BOOKMARKED_STATUSES_FETCH_REQUEST,
+ skipLoading: true,
+})
+
+const fetchBookmarkedStatusesSuccess = (statuses, next) => ({
+ type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
+ statuses,
+ next,
+ skipLoading: true,
+})
+
+const fetchBookmarkedStatusesFail = (error) => ({
+ type: BOOKMARKED_STATUSES_FETCH_FAIL,
+ error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const expandBookmarkedStatuses = () => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null)
+
+ if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
+ return
}
+
+ dispatch(expandBookmarkedStatusesRequest())
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedStatuses(response.data))
+ dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null))
+ }).catch(error => {
+ dispatch(expandBookmarkedStatusesFail(error))
+ })
}
-export function fetchBookmarkedStatusesSuccess(statuses, next) {
- return {
- type: BOOKMARKED_STATUSES_FETCH_SUCCESS,
- statuses,
- next,
- skipLoading: true,
- }
-}
+const expandBookmarkedStatusesRequest = () => ({
+ type: BOOKMARKED_STATUSES_EXPAND_REQUEST,
+})
-export function fetchBookmarkedStatusesFail(error) {
- return {
- type: BOOKMARKED_STATUSES_FETCH_FAIL,
- error,
- skipLoading: true,
- }
-}
+const expandBookmarkedStatusesSuccess = (statuses, next) => ({
+ type: BOOKMARKED_STATUSES_EXPAND_SUCCESS,
+ statuses,
+ next,
+})
-export function expandBookmarkedStatuses() {
- return (dispatch, getState) => {
- if (!me) return
-
- const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null)
-
- if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
- return
- }
-
- dispatch(expandBookmarkedStatusesRequest())
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
- dispatch(importFetchedStatuses(response.data))
- dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null))
- }).catch(error => {
- dispatch(expandBookmarkedStatusesFail(error))
- })
- }
-}
-
-export function expandBookmarkedStatusesRequest() {
- return {
- type: BOOKMARKED_STATUSES_EXPAND_REQUEST,
- }
-}
-
-export function expandBookmarkedStatusesSuccess(statuses, next) {
- return {
- type: BOOKMARKED_STATUSES_EXPAND_SUCCESS,
- statuses,
- next,
- }
-}
-
-export function expandBookmarkedStatusesFail(error) {
- return {
- type: BOOKMARKED_STATUSES_EXPAND_FAIL,
- error,
- }
-}
+const expandBookmarkedStatusesFail = (error) => ({
+ type: BOOKMARKED_STATUSES_EXPAND_FAIL,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/bundles.js b/app/javascript/gabsocial/actions/bundles.js
index ecc9c8f7..97fc24de 100644
--- a/app/javascript/gabsocial/actions/bundles.js
+++ b/app/javascript/gabsocial/actions/bundles.js
@@ -1,25 +1,19 @@
-export const BUNDLE_FETCH_REQUEST = 'BUNDLE_FETCH_REQUEST';
-export const BUNDLE_FETCH_SUCCESS = 'BUNDLE_FETCH_SUCCESS';
-export const BUNDLE_FETCH_FAIL = 'BUNDLE_FETCH_FAIL';
+export const BUNDLE_FETCH_REQUEST = 'BUNDLE_FETCH_REQUEST'
+export const BUNDLE_FETCH_SUCCESS = 'BUNDLE_FETCH_SUCCESS'
+export const BUNDLE_FETCH_FAIL = 'BUNDLE_FETCH_FAIL'
-export function fetchBundleRequest(skipLoading) {
- return {
- type: BUNDLE_FETCH_REQUEST,
- skipLoading,
- };
-}
+export const fetchBundleRequest = (skipLoading) => ({
+ type: BUNDLE_FETCH_REQUEST,
+ skipLoading,
+})
-export function fetchBundleSuccess(skipLoading) {
- return {
- type: BUNDLE_FETCH_SUCCESS,
- skipLoading,
- };
-}
+export const fetchBundleSuccess = (skipLoading) => ({
+ type: BUNDLE_FETCH_SUCCESS,
+ skipLoading,
+})
-export function fetchBundleFail(error, skipLoading) {
- return {
- type: BUNDLE_FETCH_FAIL,
- error,
- skipLoading,
- };
-}
+export const fetchBundleFail = (error, skipLoading) => ({
+ type: BUNDLE_FETCH_FAIL,
+ error,
+ skipLoading,
+})
diff --git a/app/javascript/gabsocial/actions/compose.js b/app/javascript/gabsocial/actions/compose.js
index d1a81375..fe9e4d80 100644
--- a/app/javascript/gabsocial/actions/compose.js
+++ b/app/javascript/gabsocial/actions/compose.js
@@ -1,23 +1,23 @@
-import api from '../api';
+import api from '../api'
import { FormattedMessage } from 'react-intl'
-import { CancelToken, isCancel } from 'axios';
+import { CancelToken, isCancel } from 'axios'
import throttle from 'lodash.throttle'
import moment from 'moment-mini'
import { isMobile } from '../utils/is_mobile'
-import { search as emojiSearch } from '../components/emoji/emoji_mart_search_light';
+import { search as emojiSearch } from '../components/emoji/emoji_mart_search_light'
import { urlRegex } from '../features/ui/util/url_regex'
-import { tagHistory } from '../settings';
+import { tagHistory } from '../settings'
import { joinGroup } from './groups'
-import { useEmoji } from './emojis';
-import resizeImage from '../utils/resize_image';
-import { importFetchedAccounts } from './importer';
+import { useEmoji } from './emojis'
+import resizeImage from '../utils/resize_image'
+import { importFetchedAccounts } from './importer'
import {
updateTimelineQueue,
updateTimeline,
} from './timelines'
-// import { showAlert, showAlertForError } from './alerts';
-import { defineMessages } from 'react-intl';
-import { openModal, closeModal } from './modal';
+// import { showAlert, showAlertForError } from './alerts'
+import { defineMessages } from 'react-intl'
+import { openModal, closeModal } from './modal'
import {
STATUS_EXPIRATION_OPTION_5_MINUTES,
STATUS_EXPIRATION_OPTION_60_MINUTES,
@@ -26,57 +26,58 @@ import {
STATUS_EXPIRATION_OPTION_3_DAYS,
STATUS_EXPIRATION_OPTION_7_DAYS,
} from '../constants'
-import { me } from '../initial_state';
+import { me } from '../initial_state'
import { makeGetStatus } from '../selectors'
-let cancelFetchComposeSuggestionsAccounts;
+let cancelFetchComposeSuggestionsAccounts
-export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
-export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
-export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS';
-export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
-export const COMPOSE_REPLY = 'COMPOSE_REPLY';
-export const COMPOSE_QUOTE = 'COMPOSE_QUOTE';
-export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
-export const COMPOSE_MENTION = 'COMPOSE_MENTION';
-export const COMPOSE_RESET = 'COMPOSE_RESET';
-export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
-export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
-export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
-export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
-export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
+export const COMPOSE_CHANGE = 'COMPOSE_CHANGE'
+export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST'
+export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS'
+export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL'
+export const COMPOSE_REPLY = 'COMPOSE_REPLY'
+export const COMPOSE_QUOTE = 'COMPOSE_QUOTE'
+export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL'
+export const COMPOSE_MENTION = 'COMPOSE_MENTION'
+export const COMPOSE_RESET = 'COMPOSE_RESET'
-export const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR';
-export const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY';
-export const COMPOSE_SUGGESTION_SELECT = 'COMPOSE_SUGGESTION_SELECT';
-export const COMPOSE_SUGGESTION_TAGS_UPDATE = 'COMPOSE_SUGGESTION_TAGS_UPDATE';
+export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST'
+export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS'
+export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL'
+export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS'
+export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO'
-export const COMPOSE_TAG_HISTORY_UPDATE = 'COMPOSE_TAG_HISTORY_UPDATE';
+export const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR'
+export const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY'
+export const COMPOSE_SUGGESTION_SELECT = 'COMPOSE_SUGGESTION_SELECT'
+export const COMPOSE_SUGGESTION_TAGS_UPDATE = 'COMPOSE_SUGGESTION_TAGS_UPDATE'
-export const COMPOSE_MOUNT = 'COMPOSE_MOUNT';
-export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
+export const COMPOSE_TAG_HISTORY_UPDATE = 'COMPOSE_TAG_HISTORY_UPDATE'
-export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
-export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
-export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
-export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
-export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE';
-export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE';
+export const COMPOSE_MOUNT = 'COMPOSE_MOUNT'
+export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT'
-export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
+export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE'
+export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE'
+export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE'
+export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE'
+export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE'
+export const COMPOSE_COMPOSING_CHANGE = 'COMPOSE_COMPOSING_CHANGE'
-export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST';
-export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS';
-export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL';
+export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT'
-export const COMPOSE_POLL_ADD = 'COMPOSE_POLL_ADD';
-export const COMPOSE_POLL_REMOVE = 'COMPOSE_POLL_REMOVE';
-export const COMPOSE_POLL_OPTION_ADD = 'COMPOSE_POLL_OPTION_ADD';
-export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE';
-export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE';
-export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE';
+export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST'
+export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS'
+export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL'
-export const COMPOSE_SCHEDULED_AT_CHANGE = 'COMPOSE_SCHEDULED_AT_CHANGE';
+export const COMPOSE_POLL_ADD = 'COMPOSE_POLL_ADD'
+export const COMPOSE_POLL_REMOVE = 'COMPOSE_POLL_REMOVE'
+export const COMPOSE_POLL_OPTION_ADD = 'COMPOSE_POLL_OPTION_ADD'
+export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE'
+export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE'
+export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE'
+
+export const COMPOSE_SCHEDULED_AT_CHANGE = 'COMPOSE_SCHEDULED_AT_CHANGE'
export const COMPOSE_EXPIRES_AT_CHANGE = 'COMPOSE_EXPIRES_AT_CHANGE'
@@ -87,15 +88,15 @@ export const COMPOSE_CLEAR = 'COMPOSE_CLEAR'
const messages = defineMessages({
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
-});
+})
-const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1);
+const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1)
export const ensureComposeIsVisible = (getState, routerHistory) => {
if (!getState().getIn(['compose', 'mounted']) && window.innerWidth < COMPOSE_PANEL_BREAKPOINT) {
- routerHistory.push('/posts/new');
+ routerHistory.push('/posts/new')
}
-};
+}
export function changeCompose(text, markdown, replyId, isStandalone, caretPosition) {
return function (dispatch, getState) {
@@ -566,13 +567,11 @@ export function readyComposeSuggestionsEmojis(token, emojis) {
};
};
-export function readyComposeSuggestionsAccounts(token, accounts) {
- return {
- type: COMPOSE_SUGGESTIONS_READY,
- token,
- accounts,
- };
-};
+export const readyComposeSuggestionsAccounts = (token, accounts) => ({
+ type: COMPOSE_SUGGESTIONS_READY,
+ token,
+ accounts,
+})
export function selectComposeSuggestion(position, token, suggestion, path) {
return (dispatch, getState) => {
@@ -730,31 +729,35 @@ export function removePollOption(index) {
};
};
-export function changePollSettings(expiresIn, isMultiple) {
- return {
- type: COMPOSE_POLL_SETTINGS_CHANGE,
- expiresIn,
- isMultiple,
- };
-};
+/**
+ *
+ */
+export const changePollSettings = (expiresIn, isMultiple) => ({
+ type: COMPOSE_POLL_SETTINGS_CHANGE,
+ expiresIn,
+ isMultiple,
+})
-export function changeScheduledAt(date) {
- return {
- type: COMPOSE_SCHEDULED_AT_CHANGE,
- date,
- };
-};
+/**
+ *
+ */
+export const changeScheduledAt = (date) => ({
+ type: COMPOSE_SCHEDULED_AT_CHANGE,
+ date,
+})
-export function changeExpiresAt(value) {
- return {
- type: COMPOSE_EXPIRES_AT_CHANGE,
- value,
- }
-}
+/**
+ *
+ */
+export const changeExpiresAt = (value) => ({
+ type: COMPOSE_EXPIRES_AT_CHANGE,
+ value,
+})
-export function changeRichTextEditorControlsVisibility(open) {
- return {
- type: COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY,
- open,
- }
-}
\ No newline at end of file
+/**
+ *
+ */
+export const changeRichTextEditorControlsVisibility = (open) => ({
+ type: COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY,
+ open,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/conversations.js b/app/javascript/gabsocial/actions/conversations.js
deleted file mode 100644
index b0c3af2f..00000000
--- a/app/javascript/gabsocial/actions/conversations.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import api, { getLinks } from '../api';
-import {
- importFetchedAccounts,
- importFetchedStatuses,
- importFetchedStatus,
-} from './importer';
-import { me } from '../initial_state';
-
-export const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT';
-export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT';
-
-export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST';
-export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS';
-export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL';
-export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE';
-
-export const CONVERSATIONS_READ = 'CONVERSATIONS_READ';
-
-export const mountConversations = () => ({
- type: CONVERSATIONS_MOUNT,
-});
-
-export const unmountConversations = () => ({
- type: CONVERSATIONS_UNMOUNT,
-});
-
-export const markConversationRead = conversationId => (dispatch, getState) => {
- if (!me) return;
-
- dispatch({
- type: CONVERSATIONS_READ,
- id: conversationId,
- });
-
- api(getState).post(`/api/v1/conversations/${conversationId}/read`);
-};
-
-export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
- if (!me) return;
-
- dispatch(expandConversationsRequest());
-
- const params = { max_id: maxId };
-
- if (!maxId) {
- params.since_id = getState().getIn(['conversations', 'items', 0, 'last_status']);
- }
-
- const isLoadingRecent = !!params.since_id;
-
- api(getState).get('/api/v1/conversations', { params })
- .then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data.reduce((aggr, item) => aggr.concat(item.accounts), [])));
- dispatch(importFetchedStatuses(response.data.map(item => item.last_status).filter(x => !!x)));
- dispatch(expandConversationsSuccess(response.data, next ? next.uri : null, isLoadingRecent));
- })
- .catch(err => dispatch(expandConversationsFail(err)));
-};
-
-export const expandConversationsRequest = () => ({
- type: CONVERSATIONS_FETCH_REQUEST,
-});
-
-export const expandConversationsSuccess = (conversations, next, isLoadingRecent) => ({
- type: CONVERSATIONS_FETCH_SUCCESS,
- conversations,
- next,
- isLoadingRecent,
-});
-
-export const expandConversationsFail = error => ({
- type: CONVERSATIONS_FETCH_FAIL,
- error,
-});
-
-export const updateConversations = conversation => dispatch => {
- dispatch(importFetchedAccounts(conversation.accounts));
-
- if (conversation.last_status) {
- dispatch(importFetchedStatus(conversation.last_status));
- }
-
- dispatch({
- type: CONVERSATIONS_UPDATE,
- conversation,
- });
-};
diff --git a/app/javascript/gabsocial/actions/custom_emojis.js b/app/javascript/gabsocial/actions/custom_emojis.js
index 7b7d0091..486e271e 100644
--- a/app/javascript/gabsocial/actions/custom_emojis.js
+++ b/app/javascript/gabsocial/actions/custom_emojis.js
@@ -1,40 +1,32 @@
-import api from '../api';
+import api from '../api'
-export const CUSTOM_EMOJIS_FETCH_REQUEST = 'CUSTOM_EMOJIS_FETCH_REQUEST';
-export const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS';
-export const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL';
+export const CUSTOM_EMOJIS_FETCH_REQUEST = 'CUSTOM_EMOJIS_FETCH_REQUEST'
+export const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS'
+export const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL'
-export function fetchCustomEmojis() {
- return (dispatch, getState) => {
- dispatch(fetchCustomEmojisRequest());
+export const fetchCustomEmojis = () => (dispatch, getState) => {
+ dispatch(fetchCustomEmojisRequest())
- api(getState).get('/api/v1/custom_emojis').then(response => {
- dispatch(fetchCustomEmojisSuccess(response.data));
- }).catch(error => {
- dispatch(fetchCustomEmojisFail(error));
- });
- };
-};
+ api(getState).get('/api/v1/custom_emojis').then((response) => {
+ dispatch(fetchCustomEmojisSuccess(response.data))
+ }).catch((error) => {
+ dispatch(fetchCustomEmojisFail(error))
+ })
+}
-export function fetchCustomEmojisRequest() {
- return {
- type: CUSTOM_EMOJIS_FETCH_REQUEST,
- skipLoading: true,
- };
-};
+const fetchCustomEmojisRequest = () => ({
+ type: CUSTOM_EMOJIS_FETCH_REQUEST,
+ skipLoading: true,
+})
-export function fetchCustomEmojisSuccess(custom_emojis) {
- return {
- type: CUSTOM_EMOJIS_FETCH_SUCCESS,
- custom_emojis,
- skipLoading: true,
- };
-};
+const fetchCustomEmojisSuccess = (custom_emojis) => ({
+ type: CUSTOM_EMOJIS_FETCH_SUCCESS,
+ custom_emojis,
+ skipLoading: true,
+})
-export function fetchCustomEmojisFail(error) {
- return {
- type: CUSTOM_EMOJIS_FETCH_FAIL,
- error,
- skipLoading: true,
- };
-};
+const fetchCustomEmojisFail = (error) => ({
+ type: CUSTOM_EMOJIS_FETCH_FAIL,
+ error,
+ skipLoading: true,
+})
diff --git a/app/javascript/gabsocial/actions/emojis.js b/app/javascript/gabsocial/actions/emojis.js
index 7cd9d4b7..2a2e019b 100644
--- a/app/javascript/gabsocial/actions/emojis.js
+++ b/app/javascript/gabsocial/actions/emojis.js
@@ -1,14 +1,12 @@
-import { saveSettings } from './settings';
+import { saveSettings } from './settings'
-export const EMOJI_USE = 'EMOJI_USE';
+export const EMOJI_USE = 'EMOJI_USE'
-export function useEmoji(emoji) {
- return dispatch => {
- dispatch({
- type: EMOJI_USE,
- emoji,
- });
+export const useEmoji = (emoji) => (dispatch) => {
+ dispatch({
+ type: EMOJI_USE,
+ emoji,
+ });
- dispatch(saveSettings());
- };
-};
+ dispatch(saveSettings())
+}
diff --git a/app/javascript/gabsocial/actions/favorites.js b/app/javascript/gabsocial/actions/favorites.js
index f94830b7..a1648cbd 100644
--- a/app/javascript/gabsocial/actions/favorites.js
+++ b/app/javascript/gabsocial/actions/favorites.js
@@ -10,89 +10,79 @@ export const FAVORITED_STATUSES_EXPAND_REQUEST = 'FAVORITED_STATUSES_EXPAND_REQU
export const FAVORITED_STATUSES_EXPAND_SUCCESS = 'FAVORITED_STATUSES_EXPAND_SUCCESS'
export const FAVORITED_STATUSES_EXPAND_FAIL = 'FAVORITED_STATUSES_EXPAND_FAIL'
-export function fetchFavoritedStatuses() {
- return (dispatch, getState) => {
- if (!me) return
+/**
+ *
+ */
+export const fetchFavoritedStatuses = () => (dispatch, getState) => {
+ if (!me) return
- if (getState().getIn(['status_lists', 'favorites', 'isLoading'])) {
- return
- }
-
- dispatch(fetchFavoritedStatusesRequest())
-
- api(getState).get('/api/v1/favourites').then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
- dispatch(importFetchedStatuses(response.data))
- dispatch(fetchFavoritedStatusesSuccess(response.data, next ? next.uri : null))
- }).catch(error => {
- dispatch(fetchFavoritedStatusesFail(error))
- })
+ if (getState().getIn(['status_lists', 'favorites', 'isLoading'])) {
+ return
}
+
+ dispatch(fetchFavoritedStatusesRequest())
+
+ api(getState).get('/api/v1/favourites').then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedStatuses(response.data))
+ dispatch(fetchFavoritedStatusesSuccess(response.data, next ? next.uri : null))
+ }).catch(error => {
+ dispatch(fetchFavoritedStatusesFail(error))
+ })
}
-export function fetchFavoritedStatusesRequest() {
- return {
- type: FAVORITED_STATUSES_FETCH_REQUEST,
- skipLoading: true,
+const fetchFavoritedStatusesRequest = () => ({
+ type: FAVORITED_STATUSES_FETCH_REQUEST,
+ skipLoading: true,
+})
+
+const fetchFavoritedStatusesSuccess = (statuses, next) => ({
+ type: FAVORITED_STATUSES_FETCH_SUCCESS,
+ statuses,
+ next,
+ skipLoading: true,
+})
+
+const fetchFavoritedStatusesFail = (error) => ({
+ type: FAVORITED_STATUSES_FETCH_FAIL,
+ error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const expandFavoritedStatuses = () => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['status_lists', 'favorites', 'next'], null)
+
+ if (url === null || getState().getIn(['status_lists', 'favorites', 'isLoading'])) {
+ return
}
+
+ dispatch(expandFavoritedStatusesRequest())
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedStatuses(response.data))
+ dispatch(expandFavoritedStatusesSuccess(response.data, next ? next.uri : null))
+ }).catch(error => {
+ dispatch(expandFavoritedStatusesFail(error))
+ })
}
-export function fetchFavoritedStatusesSuccess(statuses, next) {
- return {
- type: FAVORITED_STATUSES_FETCH_SUCCESS,
- statuses,
- next,
- skipLoading: true,
- }
-}
+const expandFavoritedStatusesRequest = () => ({
+ type: FAVORITED_STATUSES_EXPAND_REQUEST,
+})
-export function fetchFavoritedStatusesFail(error) {
- return {
- type: FAVORITED_STATUSES_FETCH_FAIL,
- error,
- skipLoading: true,
- }
-}
+const expandFavoritedStatusesSuccess = (statuses, next) => ({
+ type: FAVORITED_STATUSES_EXPAND_SUCCESS,
+ statuses,
+ next,
+})
-export function expandFavoritedStatuses() {
- return (dispatch, getState) => {
- if (!me) return
-
- const url = getState().getIn(['status_lists', 'favorites', 'next'], null)
-
- if (url === null || getState().getIn(['status_lists', 'favorites', 'isLoading'])) {
- return
- }
-
- dispatch(expandFavoritedStatusesRequest())
-
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next')
- dispatch(importFetchedStatuses(response.data))
- dispatch(expandFavoritedStatusesSuccess(response.data, next ? next.uri : null))
- }).catch(error => {
- dispatch(expandFavoritedStatusesFail(error))
- })
- }
-}
-
-export function expandFavoritedStatusesRequest() {
- return {
- type: FAVORITED_STATUSES_EXPAND_REQUEST,
- }
-}
-
-export function expandFavoritedStatusesSuccess(statuses, next) {
- return {
- type: FAVORITED_STATUSES_EXPAND_SUCCESS,
- statuses,
- next,
- }
-}
-
-export function expandFavoritedStatusesFail(error) {
- return {
- type: FAVORITED_STATUSES_EXPAND_FAIL,
- error,
- }
-}
+const expandFavoritedStatusesFail = (error) => ({
+ type: FAVORITED_STATUSES_EXPAND_FAIL,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/filters.js b/app/javascript/gabsocial/actions/filters.js
index 20274141..01559de0 100644
--- a/app/javascript/gabsocial/actions/filters.js
+++ b/app/javascript/gabsocial/actions/filters.js
@@ -1,29 +1,40 @@
-import api from '../api';
-import { me } from '../initial_state';
+import api from '../api'
+import { me } from '../initial_state'
-export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
-export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
-export const FILTERS_FETCH_FAIL = 'FILTERS_FETCH_FAIL';
+export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST'
+export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS'
+export const FILTERS_FETCH_FAIL = 'FILTERS_FETCH_FAIL'
+/**
+ *
+ */
export const fetchFilters = () => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch({
- type: FILTERS_FETCH_REQUEST,
- skipLoading: true,
- });
+ dispatch(fetchFiltersRequest())
- api(getState)
- .get('/api/v1/filters')
- .then(({ data }) => dispatch({
- type: FILTERS_FETCH_SUCCESS,
- filters: data,
- skipLoading: true,
- }))
- .catch(err => dispatch({
- type: FILTERS_FETCH_FAIL,
- err,
- skipLoading: true,
- skipAlert: true,
- }));
-};
+ api(getState).get('/api/v1/filters').then(({ data }) => {
+ dispatch(fetchFiltersSuccess(data))
+ }).catch((err) => {
+ dispatch(fetchFiltersFail(err))
+ })
+}
+
+
+const fetchFiltersRequest = () => ({
+ type: FILTERS_FETCH_REQUEST,
+ skipLoading: true,
+})
+
+const fetchFiltersSuccess = (filters) => ({
+ type: FILTERS_FETCH_SUCCESS,
+ filters,
+ skipLoading: true,
+})
+
+const fetchFiltersFail = (err) => ({
+ type: FILTERS_FETCH_FAIL,
+ err,
+ skipLoading: true,
+ skipAlert: true,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/group_categories.js b/app/javascript/gabsocial/actions/group_categories.js
index 242bc8fb..0861e4d7 100644
--- a/app/javascript/gabsocial/actions/group_categories.js
+++ b/app/javascript/gabsocial/actions/group_categories.js
@@ -4,6 +4,9 @@ export const GROUP_CATEGORIES_FETCH_REQUEST = 'GROUP_CATEGORIES_FETCH_REQUEST'
export const GROUP_CATEGORIES_FETCH_SUCCESS = 'GROUP_CATEGORIES_FETCH_SUCCESS'
export const GROUP_CATEGORIES_FETCH_FAIL = 'GROUP_CATEGORIES_FETCH_FAIL'
+/**
+ *
+ */
export const fetchGroupCategories = () => (dispatch, getState) => {
dispatch(fetchGroupCategoriesRequest())
@@ -12,16 +15,16 @@ export const fetchGroupCategories = () => (dispatch, getState) => {
.catch(err => dispatch(fetchGroupCategoriesFail(err)))
}
-export const fetchGroupCategoriesRequest = () => ({
+const fetchGroupCategoriesRequest = () => ({
type: GROUP_CATEGORIES_FETCH_REQUEST,
})
-export const fetchGroupCategoriesSuccess = (categories) => ({
+const fetchGroupCategoriesSuccess = (categories) => ({
type: GROUP_CATEGORIES_FETCH_SUCCESS,
categories,
})
-export const fetchGroupCategoriesFail = (error) => ({
+const fetchGroupCategoriesFail = (error) => ({
type: GROUP_CATEGORIES_FETCH_FAIL,
error,
})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/group_editor.js b/app/javascript/gabsocial/actions/group_editor.js
index d3a34459..cf4c80bd 100644
--- a/app/javascript/gabsocial/actions/group_editor.js
+++ b/app/javascript/gabsocial/actions/group_editor.js
@@ -22,6 +22,9 @@ export const GROUP_EDITOR_IS_VISIBLE_CHANGE = 'GROUP_EDITOR_IS_VISIBLE_CHANGE'
export const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET'
export const GROUP_EDITOR_SETUP = 'GROUP_EDITOR_SETUP'
+/**
+ *
+ */
export const submit = (routerHistory) => (dispatch, getState) => {
if (!me) return
@@ -50,16 +53,19 @@ export const submit = (routerHistory) => (dispatch, getState) => {
}
if (groupId === null) {
- dispatch(create(options, routerHistory))
+ dispatch(createGroup(options, routerHistory))
} else {
- dispatch(update(groupId, options, routerHistory))
+ dispatch(updateGroup(groupId, options, routerHistory))
}
}
-const create = (options, routerHistory) => (dispatch, getState) => {
+/**
+ *
+ */
+const createGroup = (options, routerHistory) => (dispatch, getState) => {
if (!me) return
- dispatch(createRequest())
+ dispatch(createGroupRequest())
const formData = new FormData()
formData.append('title', options.title)
@@ -81,28 +87,31 @@ const create = (options, routerHistory) => (dispatch, getState) => {
'Content-Type': 'multipart/form-data'
}
}).then(({ data }) => {
- dispatch(createSuccess(data))
+ dispatch(createGroupSuccess(data))
routerHistory.push(`/groups/${data.id}`)
- }).catch(err => dispatch(createFail(err)))
+ }).catch((err) => dispatch(createGroupFail(err)))
}
-export const createRequest = (id) => ({
+const createGroupRequest = (id) => ({
type: GROUP_CREATE_REQUEST,
id,
})
-export const createSuccess = (group) => ({
+const createSuccess = (group) => ({
type: GROUP_CREATE_SUCCESS,
group,
})
-export const createFail = (error) => ({
+const createFail = (error) => ({
type: GROUP_CREATE_FAIL,
error,
})
-const update = (groupId, options, routerHistory) => (dispatch, getState) => {
+/**
+ *
+ */
+const updateGroup = (groupId, options, routerHistory) => (dispatch, getState) => {
if (!me) return
dispatch(updateRequest())
@@ -130,26 +139,29 @@ const update = (groupId, options, routerHistory) => (dispatch, getState) => {
'Content-Type': 'multipart/form-data'
}
}).then(({ data }) => {
- dispatch(updateSuccess(data))
+ dispatch(updateGroupSuccess(data))
routerHistory.push(`/groups/${data.id}`)
- }).catch(err => dispatch(updateFail(err)))
+ }).catch((err) => dispatch(updateGroupFail(err)))
}
-export const updateRequest = (id) => ({
+const updateGroupRequest = (id) => ({
type: GROUP_UPDATE_REQUEST,
id,
})
-export const updateSuccess = (group) => ({
+const updateGroupSuccess = (group) => ({
type: GROUP_UPDATE_SUCCESS,
group,
})
-export const updateFail = (error) => ({
+const updateGroupFail = (error) => ({
type: GROUP_UPDATE_FAIL,
error,
})
+/**
+ *
+ */
export const resetEditor = () => ({
type: GROUP_EDITOR_RESET
})
diff --git a/app/javascript/gabsocial/actions/groups.js b/app/javascript/gabsocial/actions/groups.js
index 9ddb5526..1f9d5590 100644
--- a/app/javascript/gabsocial/actions/groups.js
+++ b/app/javascript/gabsocial/actions/groups.js
@@ -107,6 +107,11 @@ export const importGroup = (group) => (dispatch) => {
dispatch(fetchGroupSuccess(group))
}
+export const importGroups = (groups) => (dispatch) => {
+ if (!Array.isArray(groups)) return
+ groups.map((group) => dispatch(fetchGroupSuccess(group)))
+}
+
export const fetchGroup = (id) => (dispatch, getState) => {
dispatch(fetchGroupRelationships([id]));
diff --git a/app/javascript/gabsocial/actions/height_cache.js b/app/javascript/gabsocial/actions/height_cache.js
index 4c752993..c8df2cc1 100644
--- a/app/javascript/gabsocial/actions/height_cache.js
+++ b/app/javascript/gabsocial/actions/height_cache.js
@@ -1,17 +1,13 @@
-export const HEIGHT_CACHE_SET = 'HEIGHT_CACHE_SET';
-export const HEIGHT_CACHE_CLEAR = 'HEIGHT_CACHE_CLEAR';
+export const HEIGHT_CACHE_SET = 'HEIGHT_CACHE_SET'
+export const HEIGHT_CACHE_CLEAR = 'HEIGHT_CACHE_CLEAR'
-export function setHeight (key, id, height) {
- return {
- type: HEIGHT_CACHE_SET,
- key,
- id,
- height,
- };
-};
+export const setHeight = (key, id, height) => ({
+ type: HEIGHT_CACHE_SET,
+ key,
+ id,
+ height,
+})
-export function clearHeight () {
- return {
- type: HEIGHT_CACHE_CLEAR,
- };
-};
+export const clearHeight = () => ({
+ type: HEIGHT_CACHE_CLEAR,
+})
diff --git a/app/javascript/gabsocial/actions/importer/index.js b/app/javascript/gabsocial/actions/importer/index.js
index 5dea143a..b9c1630f 100644
--- a/app/javascript/gabsocial/actions/importer/index.js
+++ b/app/javascript/gabsocial/actions/importer/index.js
@@ -1,12 +1,18 @@
-import { normalizeAccount, normalizeStatus, normalizePoll } from './normalizer';
+import isObject from 'lodash.isobject'
+import {
+ normalizeAccount,
+ normalizeStatus,
+ normalizePoll,
+} from './normalizer'
import { fetchContext } from '../statuses'
+import { importGroups } from '../groups'
-export const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT';
-export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT';
-export const STATUS_IMPORT = 'STATUS_IMPORT';
-export const STATUSES_IMPORT = 'STATUSES_IMPORT';
-export const POLLS_IMPORT = 'POLLS_IMPORT';
-export const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP';
+export const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT'
+export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT'
+export const STATUS_IMPORT = 'STATUS_IMPORT'
+export const STATUSES_IMPORT = 'STATUSES_IMPORT'
+export const POLLS_IMPORT = 'POLLS_IMPORT'
+export const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'
function pushUnique(array, object) {
if (array.every(element => element.id !== object.id)) {
@@ -14,34 +20,39 @@ function pushUnique(array, object) {
}
}
-export function importAccount(account) {
- return { type: ACCOUNT_IMPORT, account };
-}
+export const importAccount = (account) => ({
+ type: ACCOUNT_IMPORT,
+ account,
+})
-export function importAccounts(accounts) {
- return { type: ACCOUNTS_IMPORT, accounts };
-}
+export const importAccounts = (accounts) => ({
+ type: ACCOUNTS_IMPORT,
+ accounts,
+})
-export function importStatus(status) {
- return { type: STATUS_IMPORT, status };
-}
+export const importStatus = (status) => ({
+ type: STATUS_IMPORT,
+ status,
+})
-export function importStatuses(statuses) {
- return { type: STATUSES_IMPORT, statuses };
-}
+export const importStatuses = (statuses) => ({
+ type: STATUSES_IMPORT,
+ statuses,
+})
-export function importPolls(polls) {
- return { type: POLLS_IMPORT, polls };
-}
+export const importPolls = (polls) => ({
+ type: POLLS_IMPORT,
+ polls,
+})
-export function importFetchedAccount(account) {
+export const importFetchedAccount = (account) => {
return importFetchedAccounts([account]);
}
-export function importFetchedAccounts(accounts) {
+export const importFetchedAccounts = (accounts) => {
const normalAccounts = [];
- function processAccount(account) {
+ const processAccount = (account) => {
pushUnique(normalAccounts, normalizeAccount(account));
if (account.moved) {
@@ -54,47 +65,48 @@ export function importFetchedAccounts(accounts) {
return importAccounts(normalAccounts);
}
-export function importFetchedStatus(status) {
+export const importFetchedStatus = (status) => {
return importFetchedStatuses([status]);
}
-export function importFetchedStatuses(statuses) {
- return (dispatch, getState) => {
- const accounts = [];
- const normalStatuses = [];
- const polls = [];
+export const importFetchedStatuses = (statuses) => (dispatch, getState) => {
+ const accounts = []
+ const normalStatuses = []
+ const polls = []
+ const groups = []
- function processStatus(status) {
- pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id])));
- pushUnique(accounts, status.account);
+ const processStatus = (status) => {
+ pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id])))
- if (status.reblog && status.reblog.id) {
- processStatus(status.reblog);
- }
-
- if (status.quote && status.quote.id) {
- processStatus(status.quote);
- }
-
- if (status.poll && status.poll.id) {
- pushUnique(polls, normalizePoll(status.poll));
- }
+ if (isObject(status.account)) pushUnique(accounts, status.account)
+ if (isObject(status.group)) pushUnique(groups, status.group)
+
+ if (status.reblog && status.reblog.id) {
+ processStatus(status.reblog)
}
- statuses.forEach(processStatus);
+ if (status.quote && status.quote.id) {
+ processStatus(status.quote)
+ }
- dispatch(importPolls(polls));
- dispatch(importFetchedAccounts(accounts));
- dispatch(importStatuses(normalStatuses));
- };
+ if (status.poll && status.poll.id) {
+ pushUnique(polls, normalizePoll(status.poll))
+ }
+ }
+
+ statuses.forEach(processStatus)
+
+ dispatch(importPolls(polls))
+ dispatch(importFetchedAccounts(accounts))
+ dispatch(importStatuses(normalStatuses))
+ dispatch(importGroups(groups))
}
-export function importFetchedPoll(poll) {
- return dispatch => {
- dispatch(importPolls([normalizePoll(poll)]));
- };
+export const importFetchedPoll = (poll) => (dispatch) => {
+ dispatch(importPolls([normalizePoll(poll)]))
}
-export function importErrorWhileFetchingAccountByUsername(username) {
- return { type: ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP, username };
-};
+export const importErrorWhileFetchingAccountByUsername = (username) => ({
+ type: ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP,
+ username
+})
diff --git a/app/javascript/gabsocial/actions/importer/normalizer.js b/app/javascript/gabsocial/actions/importer/normalizer.js
index 46f487e7..69c3c26d 100644
--- a/app/javascript/gabsocial/actions/importer/normalizer.js
+++ b/app/javascript/gabsocial/actions/importer/normalizer.js
@@ -39,7 +39,7 @@ export function normalizeAccount(account) {
export function normalizeStatus(status, normalOldStatus) {
const normalStatus = { ...status };
- normalStatus.account = status.account.id;
+ normalStatus.account = status.account_id || status.account.id;
if (status.reblog && status.reblog.id) {
normalStatus.reblog = status.reblog.id;
@@ -53,6 +53,10 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.poll = status.poll.id;
}
+ if (!!status.group || !!status.group_id) {
+ normalStatus.group = status.group_id || status.group.id;
+ }
+
// Only calculate these values when status first encountered
// Otherwise keep the ones already in the reducer
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
diff --git a/app/javascript/gabsocial/actions/interactions.js b/app/javascript/gabsocial/actions/interactions.js
index 6d3d5f95..657ee262 100644
--- a/app/javascript/gabsocial/actions/interactions.js
+++ b/app/javascript/gabsocial/actions/interactions.js
@@ -1,34 +1,35 @@
-import api from '../api';
-import { importFetchedAccounts, importFetchedStatus } from './importer';
-import { me } from '../initial_state';
+import api from '../api'
+import { importFetchedAccounts, importFetchedStatus } from './importer'
+import { updateStatusStats } from './statuses'
+import { me } from '../initial_state'
-export const REPOST_REQUEST = 'REPOST_REQUEST';
-export const REPOST_SUCCESS = 'REPOST_SUCCESS';
-export const REPOST_FAIL = 'REPOST_FAIL';
+export const REPOST_REQUEST = 'REPOST_REQUEST'
+export const REPOST_SUCCESS = 'REPOST_SUCCESS'
+export const REPOST_FAIL = 'REPOST_FAIL'
-export const FAVORITE_REQUEST = 'FAVORITE_REQUEST';
-export const FAVORITE_SUCCESS = 'FAVORITE_SUCCESS';
-export const FAVORITE_FAIL = 'FAVORITE_FAIL';
+export const FAVORITE_REQUEST = 'FAVORITE_REQUEST'
+export const FAVORITE_SUCCESS = 'FAVORITE_SUCCESS'
+export const FAVORITE_FAIL = 'FAVORITE_FAIL'
-export const UNREPOST_REQUEST = 'UNREPOST_REQUEST';
-export const UNREPOST_SUCCESS = 'UNREPOST_SUCCESS';
-export const UNREPOST_FAIL = 'UNREPOST_FAIL';
+export const UNREPOST_REQUEST = 'UNREPOST_REQUEST'
+export const UNREPOST_SUCCESS = 'UNREPOST_SUCCESS'
+export const UNREPOST_FAIL = 'UNREPOST_FAIL'
-export const UNFAVORITE_REQUEST = 'UNFAVORITE_REQUEST';
-export const UNFAVORITE_SUCCESS = 'UNFAVORITE_SUCCESS';
-export const UNFAVORITE_FAIL = 'UNFAVORITE_FAIL';
+export const UNFAVORITE_REQUEST = 'UNFAVORITE_REQUEST'
+export const UNFAVORITE_SUCCESS = 'UNFAVORITE_SUCCESS'
+export const UNFAVORITE_FAIL = 'UNFAVORITE_FAIL'
-export const REPOSTS_FETCH_REQUEST = 'REPOSTS_FETCH_REQUEST';
-export const REPOSTS_FETCH_SUCCESS = 'REPOSTS_FETCH_SUCCESS';
-export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL';
+export const REPOSTS_FETCH_REQUEST = 'REPOSTS_FETCH_REQUEST'
+export const REPOSTS_FETCH_SUCCESS = 'REPOSTS_FETCH_SUCCESS'
+export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL'
-export const PIN_REQUEST = 'PIN_REQUEST';
-export const PIN_SUCCESS = 'PIN_SUCCESS';
-export const PIN_FAIL = 'PIN_FAIL';
+export const PIN_REQUEST = 'PIN_REQUEST'
+export const PIN_SUCCESS = 'PIN_SUCCESS'
+export const PIN_FAIL = 'PIN_FAIL'
-export const UNPIN_REQUEST = 'UNPIN_REQUEST';
-export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
-export const UNPIN_FAIL = 'UNPIN_FAIL';
+export const UNPIN_REQUEST = 'UNPIN_REQUEST'
+export const UNPIN_SUCCESS = 'UNPIN_SUCCESS'
+export const UNPIN_FAIL = 'UNPIN_FAIL'
export const BOOKMARK_REQUEST = 'BOOKMARK_REQUEST'
export const BOOKMARK_SUCCESS = 'BOOKMARK_SUCCESS'
@@ -38,392 +39,342 @@ export const UNBOOKMARK_REQUEST = 'UNBOOKMARK_REQUEST'
export const UNBOOKMARK_SUCCESS = 'UNBOOKMARK_SUCCESS'
export const UNBOOKMARK_FAIL = 'UNBOOKMARK_FAIL'
-export const LIKES_FETCH_REQUEST = 'LIKES_FETCH_REQUEST';
-export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS';
-export const LIKES_FETCH_FAIL = 'LIKES_FETCH_FAIL';
+export const LIKES_FETCH_REQUEST = 'LIKES_FETCH_REQUEST'
+export const LIKES_FETCH_SUCCESS = 'LIKES_FETCH_SUCCESS'
+export const LIKES_FETCH_FAIL = 'LIKES_FETCH_FAIL'
-export function repost(status) {
- return function (dispatch, getState) {
- if (!me) return;
+/**
+ *
+ */
+export const repost = (status) => (dispatch, getState) => {
+ if (!me) return
- dispatch(repostRequest(status));
+ dispatch(repostRequest(status))
- api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then(function (response) {
- // The reblog API method returns a new status wrapped around the original. In this case we are only
- // interested in how the original is modified, hence passing it skipping the wrapper
- dispatch(importFetchedStatus(response.data.reblog));
- dispatch(repostSuccess(status));
- }).catch(function (error) {
- dispatch(repostFail(status, error));
- });
- };
-};
-
-export function unrepost(status) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unrepostRequest(status));
-
- api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
- dispatch(importFetchedStatus(response.data));
- dispatch(unrepostSuccess(status));
- }).catch(error => {
- dispatch(unrepostFail(status, error));
- });
- };
-};
-
-export function repostRequest(status) {
- return {
- type: REPOST_REQUEST,
- status: status,
- skipLoading: true,
- };
-};
-
-export function repostSuccess(status) {
- return {
- type: REPOST_SUCCESS,
- status: status,
- skipLoading: true,
- };
-};
-
-export function repostFail(status, error) {
- return {
- type: REPOST_FAIL,
- status: status,
- error: error,
- skipLoading: true,
- };
-};
-
-export function unrepostRequest(status) {
- return {
- type: UNREPOST_REQUEST,
- status: status,
- skipLoading: true,
- };
-};
-
-export function unrepostSuccess(status) {
- return {
- type: UNREPOST_SUCCESS,
- status: status,
- skipLoading: true,
- };
-};
-
-export function unrepostFail(status, error) {
- return {
- type: UNREPOST_FAIL,
- status: status,
- error: error,
- skipLoading: true,
- };
-};
-
-export function favorite(status) {
- return function (dispatch, getState) {
- if (!me) return;
-
- dispatch(favoriteRequest(status));
-
- api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
- dispatch(importFetchedStatus(response.data));
- dispatch(favoriteSuccess(status));
- }).catch(function (error) {
- dispatch(favoriteFail(status, error));
- });
- };
-};
-
-export function unfavorite(status) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unfavoriteRequest(status));
-
- api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
- dispatch(importFetchedStatus(response.data));
- dispatch(unfavoriteSuccess(status));
- }).catch(error => {
- dispatch(unfavoriteFail(status, error));
- });
- };
-};
-
-export function favoriteRequest(status) {
- return {
- type: FAVORITE_REQUEST,
- status: status,
- skipLoading: true,
- };
-};
-
-export function favoriteSuccess(status) {
- return {
- type: FAVORITE_SUCCESS,
- status: status,
- skipLoading: true,
- };
-};
-
-export function favoriteFail(status, error) {
- return {
- type: FAVORITE_FAIL,
- status: status,
- error: error,
- skipLoading: true,
- };
-};
-
-export function unfavoriteRequest(status) {
- return {
- type: UNFAVORITE_REQUEST,
- status: status,
- skipLoading: true,
- };
-};
-
-export function unfavoriteSuccess(status) {
- return {
- type: UNFAVORITE_SUCCESS,
- status: status,
- skipLoading: true,
- };
-};
-
-export function unfavoriteFail(status, error) {
- return {
- type: UNFAVORITE_FAIL,
- status: status,
- error: error,
- skipLoading: true,
- };
-};
-
-export function fetchReposts(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(fetchRepostsRequest(id));
-
- api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchRepostsSuccess(id, response.data));
- }).catch(error => {
- dispatch(fetchRepostsFail(id, error));
- });
- };
-};
-
-export function fetchRepostsRequest(id) {
- return {
- type: REPOSTS_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchRepostsSuccess(id, accounts) {
- return {
- type: REPOSTS_FETCH_SUCCESS,
- id,
- accounts,
- };
-};
-
-export function fetchRepostsFail(id, error) {
- return {
- type: REPOSTS_FETCH_FAIL,
- error,
- };
-};
-
-export function pin(status) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(pinRequest(status));
-
- api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
- dispatch(importFetchedStatus(response.data));
- dispatch(pinSuccess(status));
- }).catch(error => {
- dispatch(pinFail(status, error));
- });
- };
-};
-
-export function pinRequest(status) {
- return {
- type: PIN_REQUEST,
- status,
- skipLoading: true,
- };
-};
-
-export function pinSuccess(status) {
- return {
- type: PIN_SUCCESS,
- status,
- skipLoading: true,
- };
-};
-
-export function pinFail(status, error) {
- return {
- type: PIN_FAIL,
- status,
- error,
- skipLoading: true,
- };
-};
-
-export function unpin (status) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unpinRequest(status));
-
- api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
- dispatch(importFetchedStatus(response.data));
- dispatch(unpinSuccess(status));
- }).catch(error => {
- dispatch(unpinFail(status, error));
- });
- };
-};
-
-export function unpinRequest(status) {
- return {
- type: UNPIN_REQUEST,
- status,
- skipLoading: true,
- };
-};
-
-export function unpinSuccess(status) {
- return {
- type: UNPIN_SUCCESS,
- status,
- skipLoading: true,
- };
-};
-
-export function unpinFail(status, error) {
- return {
- type: UNPIN_FAIL,
- status,
- error,
- skipLoading: true,
- };
-};
-
-export function fetchLikes(id) {
- return (dispatch, getState) => {
- dispatch(fetchLikesRequest(id));
-
- api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchLikesSuccess(id, response.data));
- }).catch(error => {
- dispatch(fetchLikesFail(id, error));
- });
- };
-};
-
-export function fetchLikesRequest(id) {
- return {
- type: LIKES_FETCH_REQUEST,
- id,
- };
-};
-
-export function fetchLikesSuccess(id, accounts) {
- return {
- type: LIKES_FETCH_SUCCESS,
- id,
- accounts,
- };
-};
-
-export function fetchLikesFail(id, error) {
- return {
- type: LIKES_FETCH_FAIL,
- error,
- };
-};
-
-export function bookmark(status) {
- return function (dispatch, getState) {
- dispatch(bookmarkRequest(status));
-
- api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function (response) {
- dispatch(importFetchedStatus(response.data));
- dispatch(bookmarkSuccess(status, response.data));
- }).catch(function (error) {
- dispatch(bookmarkFail(status, error))
- })
- }
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then((response) => {
+ // The reblog API method returns a new status wrapped around the original. In this case we are only
+ // interested in how the original is modified, hence passing it skipping the wrapper
+ dispatch(importFetchedStatus(response.data.reblog))
+ dispatch(repostSuccess(status))
+ }).catch((error) => {
+ dispatch(repostFail(status, error))
+ })
}
-export function unbookmark(status) {
- return (dispatch, getState) => {
- dispatch(unbookmarkRequest(status))
+export const repostRequest = (status) => ({
+ type: REPOST_REQUEST,
+ status: status,
+ skipLoading: true,
+})
- api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
- dispatch(importFetchedStatus(response.data))
- dispatch(unbookmarkSuccess(status, response.data))
- }).catch(error => {
- dispatch(unbookmarkFail(status, error))
- })
- }
+export const repostSuccess = (status) => ({
+ type: REPOST_SUCCESS,
+ status: status,
+ skipLoading: true,
+})
+
+export const repostFail = (status, error) => ({
+ type: REPOST_FAIL,
+ status: status,
+ error: error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const unrepost = (status) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(unrepostRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(unrepostSuccess(status))
+ }).catch((error) => {
+ dispatch(unrepostFail(status, error))
+ })
}
-export function bookmarkRequest(status) {
- return {
- type: BOOKMARK_REQUEST,
- status: status,
- }
+export const unrepostRequest = (status) => ({
+ type: UNREPOST_REQUEST,
+ status: status,
+ skipLoading: true,
+})
+
+export const unrepostSuccess = (status) => ({
+ type: UNREPOST_SUCCESS,
+ status: status,
+ skipLoading: true,
+})
+
+export const unrepostFail = (status, error) => ({
+ type: UNREPOST_FAIL,
+ status: status,
+ error: error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const favorite = (status) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(favoriteRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then((response) => {
+ dispatch(updateStatusStats(response.data))
+ dispatch(favoriteSuccess(status))
+ }).catch((error) => {
+ dispatch(favoriteFail(status, error))
+ })
}
-export function bookmarkSuccess(status, response) {
- return {
- type: BOOKMARK_SUCCESS,
- status: status,
- response: response,
- }
+export const favoriteRequest = (status) => ({
+ type: FAVORITE_REQUEST,
+ status: status,
+ skipLoading: true,
+})
+
+export const favoriteSuccess = (status) => ({
+ type: FAVORITE_SUCCESS,
+ status: status,
+ skipLoading: true,
+})
+
+export const favoriteFail = (status, error) => ({
+ type: FAVORITE_FAIL,
+ status: status,
+ error: error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const unfavorite = (status) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(unfavoriteRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(unfavoriteSuccess(status))
+ }).catch((error) => {
+ dispatch(unfavoriteFail(status, error))
+ })
}
-export function bookmarkFail(status, error) {
- return {
- type: BOOKMARK_FAIL,
- status: status,
- error: error,
- }
+export const unfavoriteRequest = (status) => ({
+ type: UNFAVORITE_REQUEST,
+ status: status,
+ skipLoading: true,
+})
+
+export const unfavoriteSuccess = (status) => ({
+ type: UNFAVORITE_SUCCESS,
+ status: status,
+ skipLoading: true,
+})
+
+export const unfavoriteFail = (status, error) => ({
+ type: UNFAVORITE_FAIL,
+ status: status,
+ error: error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const fetchReposts = (id) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(fetchRepostsRequest(id))
+
+ api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then((response) => {
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchRepostsSuccess(id, response.data))
+ }).catch((error) => {
+ dispatch(fetchRepostsFail(id, error))
+ })
}
-export function unbookmarkRequest(status) {
- return {
- type: UNBOOKMARK_REQUEST,
- status: status,
- }
+export const fetchRepostsRequest = (id) => ({
+ type: REPOSTS_FETCH_REQUEST,
+ id,
+})
+
+export const fetchRepostsSuccess = (id, accounts) => ({
+ type: REPOSTS_FETCH_SUCCESS,
+ id,
+ accounts,
+})
+
+export const fetchRepostsFail = (id, error) => ({
+ type: REPOSTS_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const pin = (status) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(pinRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(pinSuccess(status))
+ }).catch((error) => {
+ dispatch(pinFail(status, error))
+ })
}
-export function unbookmarkSuccess(status, response) {
- return {
- type: UNBOOKMARK_SUCCESS,
- status: status,
- response: response,
- }
+export const pinRequest = (status) => ({
+ type: PIN_REQUEST,
+ status,
+ skipLoading: true,
+})
+
+export const pinSuccess = (status) => ({
+ type: PIN_SUCCESS,
+ status,
+ skipLoading: true,
+})
+
+export const pinFail = (status, error) => ({
+ type: PIN_FAIL,
+ status,
+ error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const unpin = (status) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(unpinRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(unpinSuccess(status))
+ }).catch((error) => {
+ dispatch(unpinFail(status, error))
+ })
}
-export function unbookmarkFail(status, error) {
- return {
- type: UNBOOKMARK_FAIL,
- status: status,
- error: error,
- }
-}
\ No newline at end of file
+export const unpinRequest = (status) => ({
+ type: UNPIN_REQUEST,
+ status,
+ skipLoading: true,
+})
+
+export const unpinSuccess = (status) => ({
+ type: UNPIN_SUCCESS,
+ status,
+ skipLoading: true,
+})
+
+export const unpinFail = (status, error) => ({
+ type: UNPIN_FAIL,
+ status,
+ error,
+ skipLoading: true,
+})
+
+/**
+ *
+ */
+export const fetchLikes = (id) => (dispatch, getState) => {
+ dispatch(fetchLikesRequest(id))
+
+ api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then((response) => {
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchLikesSuccess(id, response.data))
+ }).catch((error) => {
+ dispatch(fetchLikesFail(id, error))
+ })
+}
+
+export const fetchLikesRequest = (id) => ({
+ type: LIKES_FETCH_REQUEST,
+ id,
+})
+
+export const fetchLikesSuccess = (id, accounts) => ({
+ type: LIKES_FETCH_SUCCESS,
+ id,
+ accounts,
+})
+
+export const fetchLikesFail = (id, error) => ({
+ type: LIKES_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const bookmark = (status) => (dispatch, getState) => {
+ dispatch(bookmarkRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(bookmarkSuccess(status, response.data))
+ }).catch((error) => {
+ dispatch(bookmarkFail(status, error))
+ })
+}
+
+export const bookmarkRequest = (status) => ({
+ type: BOOKMARK_REQUEST,
+ status: status,
+})
+
+export const bookmarkSuccess = (status, response) => ({
+ type: BOOKMARK_SUCCESS,
+ status: status,
+ response: response,
+})
+
+export const bookmarkFail = (status, error) => ({
+ type: BOOKMARK_FAIL,
+ status: status,
+ error: error,
+})
+
+/**
+ *
+ */
+export const unbookmark = (status) => (dispatch, getState) => {
+ dispatch(unbookmarkRequest(status))
+
+ api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then((response) => {
+ dispatch(importFetchedStatus(response.data))
+ dispatch(unbookmarkSuccess(status, response.data))
+ }).catch((error) => {
+ dispatch(unbookmarkFail(status, error))
+ })
+}
+
+export const unbookmarkRequest = (status) => ({
+ type: UNBOOKMARK_REQUEST,
+ status: status,
+})
+
+export const unbookmarkSuccess = (status, response) => ({
+ type: UNBOOKMARK_SUCCESS,
+ status: status,
+ response: response,
+})
+
+export const unbookmarkFail = (status, error) => ({
+ type: UNBOOKMARK_FAIL,
+ status: status,
+ error: error,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/links.js b/app/javascript/gabsocial/actions/links.js
index f6d72447..fabc73a2 100644
--- a/app/javascript/gabsocial/actions/links.js
+++ b/app/javascript/gabsocial/actions/links.js
@@ -10,6 +10,17 @@ export const POPULAR_LINKS_FETCH_FAIL = 'POPULAR_LINKS_FETCH_FAIL'
export const IMPORT_LINK_CARDS = 'IMPORT_LINK_CARDS'
+/**
+ *
+ */
+export const importLinkCards = (cards) => ({
+ type: IMPORT_LINK_CARDS,
+ cards,
+})
+
+/**
+ *
+ */
export const fetchLinkCard = (cardId) => (dispatch, getState) => {
//If card exists, don't refetch
const card = getState().getIn(['links', 'items', `${cardId}`])
@@ -39,11 +50,9 @@ export const fetchLinkCardFail = (error, cardId) => ({
cardId,
})
-export const importLinkCards = (cards) => ({
- type: IMPORT_LINK_CARDS,
- cards,
-})
-
+/**
+ *
+ */
export const fetchPopularLinks = () => (dispatch, getState) => {
const isFetched = getState().getIn(['links', 'popular', 'isFetched'], false)
if (isFetched) return
@@ -56,16 +65,16 @@ export const fetchPopularLinks = () => (dispatch, getState) => {
.catch((err) => dispatch(fetchPopularLinksFail(err)))
}
-export const fetchPopularLinksRequest = () => ({
+const fetchPopularLinksRequest = () => ({
type: POPULAR_LINKS_FETCH_REQUEST,
})
-export const fetchPopularLinksSuccess = (cards) => ({
+const fetchPopularLinksSuccess = (cards) => ({
type: POPULAR_LINKS_FETCH_SUCCESS,
cards,
})
-export const fetchPopularLinksFail = (error) => ({
+const fetchPopularLinksFail = (error) => ({
type: POPULAR_LINKS_FETCH_FAIL,
error,
})
diff --git a/app/javascript/gabsocial/actions/lists.js b/app/javascript/gabsocial/actions/lists.js
index e6c2af9c..27d77873 100644
--- a/app/javascript/gabsocial/actions/lists.js
+++ b/app/javascript/gabsocial/actions/lists.js
@@ -1,88 +1,92 @@
-import api from '../api';
-import { importFetchedAccounts } from './importer';
-// import { showAlertForError } from './alerts';
+import api from '../api'
+import { importFetchedAccounts } from './importer'
+// import { showAlertForError } from './alerts'
import { me } from '../initial_state'
-export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST';
-export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS';
-export const LIST_FETCH_FAIL = 'LIST_FETCH_FAIL';
+export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST'
+export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS'
+export const LIST_FETCH_FAIL = 'LIST_FETCH_FAIL'
-export const LISTS_FETCH_REQUEST = 'LISTS_FETCH_REQUEST';
-export const LISTS_FETCH_SUCCESS = 'LISTS_FETCH_SUCCESS';
-export const LISTS_FETCH_FAIL = 'LISTS_FETCH_FAIL';
+export const LISTS_FETCH_REQUEST = 'LISTS_FETCH_REQUEST'
+export const LISTS_FETCH_SUCCESS = 'LISTS_FETCH_SUCCESS'
+export const LISTS_FETCH_FAIL = 'LISTS_FETCH_FAIL'
-export const LIST_EDITOR_TITLE_CHANGE = 'LIST_EDITOR_TITLE_CHANGE';
-export const LIST_EDITOR_RESET = 'LIST_EDITOR_RESET';
-export const LIST_EDITOR_SETUP = 'LIST_EDITOR_SETUP';
+export const LIST_EDITOR_TITLE_CHANGE = 'LIST_EDITOR_TITLE_CHANGE'
+export const LIST_EDITOR_RESET = 'LIST_EDITOR_RESET'
+export const LIST_EDITOR_SETUP = 'LIST_EDITOR_SETUP'
-export const LIST_CREATE_REQUEST = 'LIST_CREATE_REQUEST';
-export const LIST_CREATE_SUCCESS = 'LIST_CREATE_SUCCESS';
-export const LIST_CREATE_FAIL = 'LIST_CREATE_FAIL';
+export const LIST_CREATE_REQUEST = 'LIST_CREATE_REQUEST'
+export const LIST_CREATE_SUCCESS = 'LIST_CREATE_SUCCESS'
+export const LIST_CREATE_FAIL = 'LIST_CREATE_FAIL'
-export const LIST_UPDATE_REQUEST = 'LIST_UPDATE_REQUEST';
-export const LIST_UPDATE_SUCCESS = 'LIST_UPDATE_SUCCESS';
-export const LIST_UPDATE_FAIL = 'LIST_UPDATE_FAIL';
+export const LIST_UPDATE_REQUEST = 'LIST_UPDATE_REQUEST'
+export const LIST_UPDATE_SUCCESS = 'LIST_UPDATE_SUCCESS'
+export const LIST_UPDATE_FAIL = 'LIST_UPDATE_FAIL'
-export const LIST_DELETE_REQUEST = 'LIST_DELETE_REQUEST';
-export const LIST_DELETE_SUCCESS = 'LIST_DELETE_SUCCESS';
-export const LIST_DELETE_FAIL = 'LIST_DELETE_FAIL';
+export const LIST_DELETE_REQUEST = 'LIST_DELETE_REQUEST'
+export const LIST_DELETE_SUCCESS = 'LIST_DELETE_SUCCESS'
+export const LIST_DELETE_FAIL = 'LIST_DELETE_FAIL'
-export const LIST_ACCOUNTS_FETCH_REQUEST = 'LIST_ACCOUNTS_FETCH_REQUEST';
-export const LIST_ACCOUNTS_FETCH_SUCCESS = 'LIST_ACCOUNTS_FETCH_SUCCESS';
-export const LIST_ACCOUNTS_FETCH_FAIL = 'LIST_ACCOUNTS_FETCH_FAIL';
+export const LIST_ACCOUNTS_FETCH_REQUEST = 'LIST_ACCOUNTS_FETCH_REQUEST'
+export const LIST_ACCOUNTS_FETCH_SUCCESS = 'LIST_ACCOUNTS_FETCH_SUCCESS'
+export const LIST_ACCOUNTS_FETCH_FAIL = 'LIST_ACCOUNTS_FETCH_FAIL'
-export const LIST_EDITOR_SUGGESTIONS_CHANGE = 'LIST_EDITOR_SUGGESTIONS_CHANGE';
-export const LIST_EDITOR_SUGGESTIONS_READY = 'LIST_EDITOR_SUGGESTIONS_READY';
-export const LIST_EDITOR_SUGGESTIONS_CLEAR = 'LIST_EDITOR_SUGGESTIONS_CLEAR';
+export const LIST_EDITOR_SUGGESTIONS_CHANGE = 'LIST_EDITOR_SUGGESTIONS_CHANGE'
+export const LIST_EDITOR_SUGGESTIONS_READY = 'LIST_EDITOR_SUGGESTIONS_READY'
+export const LIST_EDITOR_SUGGESTIONS_CLEAR = 'LIST_EDITOR_SUGGESTIONS_CLEAR'
-export const LIST_EDITOR_ADD_REQUEST = 'LIST_EDITOR_ADD_REQUEST';
-export const LIST_EDITOR_ADD_SUCCESS = 'LIST_EDITOR_ADD_SUCCESS';
-export const LIST_EDITOR_ADD_FAIL = 'LIST_EDITOR_ADD_FAIL';
+export const LIST_EDITOR_ADD_REQUEST = 'LIST_EDITOR_ADD_REQUEST'
+export const LIST_EDITOR_ADD_SUCCESS = 'LIST_EDITOR_ADD_SUCCESS'
+export const LIST_EDITOR_ADD_FAIL = 'LIST_EDITOR_ADD_FAIL'
-export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST';
-export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS';
-export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL';
+export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST'
+export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS'
+export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL'
-export const LIST_ADDER_RESET = 'LIST_ADDER_RESET';
-export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP';
+export const LIST_ADDER_RESET = 'LIST_ADDER_RESET'
+export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP'
-export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST';
-export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS';
-export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL';
+export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST'
+export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS'
+export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL'
-export const fetchList = id => (dispatch, getState) => {
- if (!me) return;
+/**
+ *
+ */
+export const fetchList = (id) => (dispatch, getState) => {
+ if (!me) return
- if (getState().getIn(['lists', id])) {
- return;
- }
+ if (getState().getIn(['lists', id])) return
- dispatch(fetchListRequest(id));
+ dispatch(fetchListRequest(id))
api(getState).get(`/api/v1/lists/${id}`)
.then(({ data }) => dispatch(fetchListSuccess(data)))
- .catch(err => dispatch(fetchListFail(id, err)));
-};
+ .catch((err) => dispatch(fetchListFail(id, err)))
+}
-export const fetchListRequest = id => ({
+const fetchListRequest = id => ({
type: LIST_FETCH_REQUEST,
id,
-});
+})
-export const fetchListSuccess = list => ({
+const fetchListSuccess = list => ({
type: LIST_FETCH_SUCCESS,
list,
-});
+})
-export const fetchListFail = (id, error) => ({
+const fetchListFail = (id, error) => ({
type: LIST_FETCH_FAIL,
id,
error,
-});
+})
+/**
+ *
+ */
export const fetchLists = () => (dispatch, getState) => {
return new Promise((resolve, reject) => {
- dispatch(fetchListsRequest());
+ dispatch(fetchListsRequest())
if (!me) return reject()
api(getState).get('/api/v1/lists').then(({ data }) => {
dispatch(fetchListsSuccess(data))
@@ -90,307 +94,367 @@ export const fetchLists = () => (dispatch, getState) => {
}).catch((err) => {
dispatch(fetchListsFail(err))
return reject()
- });
+ })
})
-};
+}
-export const fetchListsRequest = () => ({
+const fetchListsRequest = () => ({
type: LISTS_FETCH_REQUEST,
-});
+})
-export const fetchListsSuccess = (lists) => ({
+const fetchListsSuccess = (lists) => ({
type: LISTS_FETCH_SUCCESS,
lists,
-});
+})
-export const fetchListsFail = (error) => ({
+const fetchListsFail = (error) => ({
type: LISTS_FETCH_FAIL,
error,
-});
+})
+/**
+ *
+ */
export const submitListEditor = (shouldReset) => (dispatch, getState) => {
- const listId = getState().getIn(['listEditor', 'listId']);
- const title = getState().getIn(['listEditor', 'title']);
+ const listId = getState().getIn(['listEditor', 'listId'])
+ const title = getState().getIn(['listEditor', 'title'])
if (listId === null) {
- dispatch(createList(title, shouldReset));
+ dispatch(createList(title, shouldReset))
} else {
- dispatch(updateList(listId, title, shouldReset));
+ dispatch(updateList(listId, title, shouldReset))
}
-};
+}
+/**
+ *
+ */
export const setupListEditor = (listId) => (dispatch, getState) => {
dispatch({
type: LIST_EDITOR_SETUP,
list: getState().getIn(['lists', listId]),
- });
+ })
- dispatch(fetchListAccounts(listId));
-};
+ dispatch(fetchListAccounts(listId))
+}
+/**
+ *
+ */
export const changeListEditorTitle = (value) => ({
type: LIST_EDITOR_TITLE_CHANGE,
value,
-});
+})
+/**
+ *
+ */
export const createList = (title, shouldReset) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(createListRequest());
+ dispatch(createListRequest())
api(getState).post('/api/v1/lists', { title }).then(({ data }) => {
- dispatch(createListSuccess(data));
+ dispatch(createListSuccess(data))
if (shouldReset) {
- dispatch(resetListEditor());
+ dispatch(resetListEditor())
}
- }).catch(err => dispatch(createListFail(err)));
-};
+ }).catch((err) => dispatch(createListFail(err)))
+}
export const createListRequest = () => ({
type: LIST_CREATE_REQUEST,
-});
+})
export const createListSuccess = (list) => ({
type: LIST_CREATE_SUCCESS,
list,
-});
+})
export const createListFail = (error) => ({
type: LIST_CREATE_FAIL,
error,
-});
+})
+/**
+ *
+ */
export const updateList = (id, title, shouldReset) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(updateListRequest(id));
+ dispatch(updateListRequest(id))
api(getState).put(`/api/v1/lists/${id}`, { title }).then(({ data }) => {
- dispatch(updateListSuccess(data));
+ dispatch(updateListSuccess(data))
if (shouldReset) {
- dispatch(resetListEditor());
+ dispatch(resetListEditor())
}
- }).catch(err => dispatch(updateListFail(id, err)));
-};
+ }).catch((err) => dispatch(updateListFail(id, err)))
+}
export const updateListRequest = id => ({
type: LIST_UPDATE_REQUEST,
id,
-});
+})
export const updateListSuccess = list => ({
type: LIST_UPDATE_SUCCESS,
list,
-});
+})
export const updateListFail = (id, error) => ({
type: LIST_UPDATE_FAIL,
id,
error,
-});
+})
export const resetListEditor = () => ({
type: LIST_EDITOR_RESET,
-});
+})
+/**
+ *
+ */
export const deleteList = (id) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(deleteListRequest(id));
+ dispatch(deleteListRequest(id))
api(getState).delete(`/api/v1/lists/${id}`)
.then(() => dispatch(deleteListSuccess(id)))
- .catch(err => dispatch(deleteListFail(id, err)));
-};
+ .catch((err) => dispatch(deleteListFail(id, err)))
+}
export const deleteListRequest = (id) => ({
type: LIST_DELETE_REQUEST,
id,
-});
+})
export const deleteListSuccess = (id) => ({
type: LIST_DELETE_SUCCESS,
id,
-});
+})
export const deleteListFail = (id, error) => ({
type: LIST_DELETE_FAIL,
id,
error,
-});
+})
+/**
+ *
+ */
export const fetchListAccounts = (listId) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(fetchListAccountsRequest(listId));
+ dispatch(fetchListAccountsRequest(listId))
api(getState).get(`/api/v1/lists/${listId}/accounts`, { params: { limit: 0 } }).then(({ data }) => {
- dispatch(importFetchedAccounts(data));
- dispatch(fetchListAccountsSuccess(listId, data));
- }).catch(err => dispatch(fetchListAccountsFail(listId, err)));
-};
+ dispatch(importFetchedAccounts(data))
+ dispatch(fetchListAccountsSuccess(listId, data))
+ }).catch((err) => dispatch(fetchListAccountsFail(listId, err)))
+}
export const fetchListAccountsRequest = (id) => ({
type: LIST_ACCOUNTS_FETCH_REQUEST,
id,
-});
+})
export const fetchListAccountsSuccess = (id, accounts, next) => ({
type: LIST_ACCOUNTS_FETCH_SUCCESS,
id,
accounts,
next,
-});
+})
export const fetchListAccountsFail = (id, error) => ({
type: LIST_ACCOUNTS_FETCH_FAIL,
id,
error,
-});
+})
+/**
+ *
+ */
export const fetchListSuggestions = (q) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
const params = {
q,
resolve: false,
limit: 25,
- };
+ }
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
- dispatch(importFetchedAccounts(data));
- dispatch(fetchListSuggestionsReady(q, data));
+ dispatch(importFetchedAccounts(data))
+ dispatch(fetchListSuggestionsReady(q, data))
})
- // }).catch(error => dispatch(showAlertForError(error)));
-};
+ // }).catch(error => dispatch(showAlertForError(error)))
+}
+/**
+ *
+ */
export const fetchListSuggestionsReady = (query, accounts) => ({
type: LIST_EDITOR_SUGGESTIONS_READY,
query,
accounts,
-});
+})
+/**
+ *
+ */
export const clearListSuggestions = () => ({
type: LIST_EDITOR_SUGGESTIONS_CLEAR,
-});
+})
+/**
+ *
+ */
export const changeListSuggestions = (value) => ({
type: LIST_EDITOR_SUGGESTIONS_CHANGE,
value,
-});
+})
+/**
+ *
+ */
export const addToListEditor = accountId => (dispatch, getState) => {
- dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId));
-};
+ dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId))
+}
+/**
+ *
+ */
export const addToList = (listId, accountId) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(addToListRequest(listId, accountId));
+ dispatch(addToListRequest(listId, accountId))
api(getState).post(`/api/v1/lists/${listId}/accounts`, { account_ids: [accountId] })
.then(() => dispatch(addToListSuccess(listId, accountId)))
- .catch(err => dispatch(addToListFail(listId, accountId, err)));
-};
+ .catch((err) => dispatch(addToListFail(listId, accountId, err)))
+}
-export const addToListRequest = (listId, accountId) => ({
+const addToListRequest = (listId, accountId) => ({
type: LIST_EDITOR_ADD_REQUEST,
listId,
accountId,
-});
+})
-export const addToListSuccess = (listId, accountId) => ({
+const addToListSuccess = (listId, accountId) => ({
type: LIST_EDITOR_ADD_SUCCESS,
listId,
accountId,
-});
+})
-export const addToListFail = (listId, accountId, error) => ({
+const addToListFail = (listId, accountId, error) => ({
type: LIST_EDITOR_ADD_FAIL,
listId,
accountId,
error,
-});
+})
+/**
+ *
+ */
export const removeFromListEditor = accountId => (dispatch, getState) => {
- dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId));
-};
+ dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId))
+}
+/**
+ *
+ */
export const removeFromList = (listId, accountId) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(removeFromListRequest(listId, accountId));
+ dispatch(removeFromListRequest(listId, accountId))
api(getState).delete(`/api/v1/lists/${listId}/accounts`, { params: { account_ids: [accountId] } })
.then(() => dispatch(removeFromListSuccess(listId, accountId)))
- .catch(err => dispatch(removeFromListFail(listId, accountId, err)));
-};
+ .catch((err) => dispatch(removeFromListFail(listId, accountId, err)))
+}
-export const removeFromListRequest = (listId, accountId) => ({
+const removeFromListRequest = (listId, accountId) => ({
type: LIST_EDITOR_REMOVE_REQUEST,
listId,
accountId,
-});
+})
-export const removeFromListSuccess = (listId, accountId) => ({
+const removeFromListSuccess = (listId, accountId) => ({
type: LIST_EDITOR_REMOVE_SUCCESS,
listId,
accountId,
-});
+})
-export const removeFromListFail = (listId, accountId, error) => ({
+const removeFromListFail = (listId, accountId, error) => ({
type: LIST_EDITOR_REMOVE_FAIL,
listId,
accountId,
error,
-});
+})
+/**
+ *
+ */
export const resetListAdder = () => ({
type: LIST_ADDER_RESET,
-});
+})
+/**
+ *
+ */
export const setupListAdder = accountId => (dispatch, getState) => {
dispatch({
type: LIST_ADDER_SETUP,
account: getState().getIn(['accounts', accountId]),
- });
- dispatch(fetchLists());
- dispatch(fetchAccountLists(accountId));
-};
+ })
+ dispatch(fetchLists())
+ dispatch(fetchAccountLists(accountId))
+}
+/**
+ *
+ */
export const fetchAccountLists = (accountId) => (dispatch, getState) => {
- if (!me) return;
+ if (!me) return
- dispatch(fetchAccountListsRequest(accountId));
+ dispatch(fetchAccountListsRequest(accountId))
api(getState).get(`/api/v1/accounts/${accountId}/lists`)
.then(({ data }) => dispatch(fetchAccountListsSuccess(accountId, data)))
- .catch(err => dispatch(fetchAccountListsFail(accountId, err)));
-};
+ .catch((err) => dispatch(fetchAccountListsFail(accountId, err)))
+}
-export const fetchAccountListsRequest = (id) => ({
+const fetchAccountListsRequest = (id) => ({
type:LIST_ADDER_LISTS_FETCH_REQUEST,
id,
-});
+})
-export const fetchAccountListsSuccess = (id, lists) => ({
+const fetchAccountListsSuccess = (id, lists) => ({
type: LIST_ADDER_LISTS_FETCH_SUCCESS,
id,
lists,
-});
+})
-export const fetchAccountListsFail = (id, err) => ({
+const fetchAccountListsFail = (id, err) => ({
type: LIST_ADDER_LISTS_FETCH_FAIL,
id,
err,
-});
+})
+/**
+ *
+ */
export const addToListAdder = (listId) => (dispatch, getState) => {
- dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])));
-};
+ dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])))
+}
+/**
+ *
+ */
export const removeFromListAdder = (listId) => (dispatch, getState) => {
- dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])));
-};
+ dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])))
+}
diff --git a/app/javascript/gabsocial/actions/modal.js b/app/javascript/gabsocial/actions/modal.js
index e664baa7..836a43cb 100644
--- a/app/javascript/gabsocial/actions/modal.js
+++ b/app/javascript/gabsocial/actions/modal.js
@@ -1,16 +1,12 @@
export const MODAL_OPEN = 'MODAL_OPEN'
export const MODAL_CLOSE = 'MODAL_CLOSE'
-export function openModal(type, props) {
- return {
- type: MODAL_OPEN,
- modalType: type,
- modalProps: props,
- }
-}
+export const openModal = (type, props) => ({
+ type: MODAL_OPEN,
+ modalType: type,
+ modalProps: props,
+})
-export function closeModal() {
- return {
- type: MODAL_CLOSE,
- }
-}
+export const closeModal = () => ({
+ type: MODAL_CLOSE,
+})
diff --git a/app/javascript/gabsocial/actions/mutes.js b/app/javascript/gabsocial/actions/mutes.js
index 31276a77..8e1d3c1f 100644
--- a/app/javascript/gabsocial/actions/mutes.js
+++ b/app/javascript/gabsocial/actions/mutes.js
@@ -1,103 +1,95 @@
-import api, { getLinks } from '../api';
-import { fetchRelationships } from './accounts';
-import { importFetchedAccounts } from './importer';
-import { openModal } from './modal';
-import { me } from '../initial_state';
+import api, { getLinks } from '../api'
+import { fetchRelationships } from './accounts'
+import { importFetchedAccounts } from './importer'
+import { openModal } from './modal'
+import { me } from '../initial_state'
+import { MODAL_MUTE } from '../constants'
-export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
-export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS';
-export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL';
+export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST'
+export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS'
+export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL'
-export const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST';
-export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
-export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
+export const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST'
+export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS'
+export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL'
-export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
+export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL'
-export function fetchMutes() {
- return (dispatch, getState) => {
- if (!me) return;
+/**
+ *
+ */
+export const fetchMutes = () => (dispatch, getState) => {
+ if (!me) return
- dispatch(fetchMutesRequest());
+ dispatch(fetchMutesRequest())
- api(getState).get('/api/v1/mutes').then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
- dispatch(importFetchedAccounts(response.data));
- dispatch(fetchMutesSuccess(response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => dispatch(fetchMutesFail(error)));
- };
-};
+ api(getState).get('/api/v1/mutes').then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchMutesSuccess(response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => dispatch(fetchMutesFail(error)))
+}
-export function fetchMutesRequest() {
- return {
- type: MUTES_FETCH_REQUEST,
- };
-};
+const fetchMutesRequest = () => ({
+ type: MUTES_FETCH_REQUEST,
+})
-export function fetchMutesSuccess(accounts, next) {
- return {
- type: MUTES_FETCH_SUCCESS,
- accounts,
- next,
- };
-};
+const fetchMutesSuccess = (accounts, next) => ({
+ type: MUTES_FETCH_SUCCESS,
+ accounts,
+ next,
+})
-export function fetchMutesFail(error) {
- return {
- type: MUTES_FETCH_FAIL,
- error,
- };
-};
+const fetchMutesFail = (error) => ({
+ type: MUTES_FETCH_FAIL,
+ error,
+})
-export function expandMutes() {
- return (dispatch, getState) => {
- if (!me) return;
-
- const url = getState().getIn(['user_lists', 'mutes', me, 'next']);
- const isLoading = getState().getIn(['user_lists', 'mutes', me, 'isLoading']);
+/**
+ *
+ */
+export const expandMutes = () => (dispatch, getState) => {
+ if (!me) return
+
+ const url = getState().getIn(['user_lists', 'mutes', me, 'next'])
+ const isLoading = getState().getIn(['user_lists', 'mutes', me, 'isLoading'])
- if (url === null || isLoading) return
+ if (url === null || isLoading) return
- dispatch(expandMutesRequest());
+ dispatch(expandMutesRequest())
- api(getState).get(url).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
- dispatch(importFetchedAccounts(response.data));
- dispatch(expandMutesSuccess(response.data, next ? next.uri : null));
- dispatch(fetchRelationships(response.data.map(item => item.id)));
- }).catch(error => dispatch(expandMutesFail(error)));
- };
-};
+ api(getState).get(url).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(expandMutesSuccess(response.data, next ? next.uri : null))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch((error) => dispatch(expandMutesFail(error)))
+}
-export function expandMutesRequest() {
- return {
- type: MUTES_EXPAND_REQUEST,
- };
-};
+const expandMutesRequest = () => ({
+ type: MUTES_EXPAND_REQUEST,
+})
-export function expandMutesSuccess(accounts, next) {
- return {
- type: MUTES_EXPAND_SUCCESS,
- accounts,
- next,
- };
-};
+const expandMutesSuccess = (accounts, next) => ({
+ type: MUTES_EXPAND_SUCCESS,
+ accounts,
+ next,
+})
-export function expandMutesFail(error) {
- return {
- type: MUTES_EXPAND_FAIL,
- error,
- };
-};
+export const expandMutesFail = (error) => ({
+ type: MUTES_EXPAND_FAIL,
+ error,
+})
-export function initMuteModal(account) {
- return dispatch => {
- dispatch({
- type: MUTES_INIT_MODAL,
- account,
- });
+/**
+ *
+ */
+export const initMuteModal = (account) => (dispatch) => {
+ dispatch({
+ type: MUTES_INIT_MODAL,
+ account,
+ })
- dispatch(openModal('MUTE'));
- };
+ dispatch(openModal(MODAL_MUTE))
}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/news.js b/app/javascript/gabsocial/actions/news.js
index 352a5093..dcdd860b 100644
--- a/app/javascript/gabsocial/actions/news.js
+++ b/app/javascript/gabsocial/actions/news.js
@@ -30,7 +30,6 @@ export const fetchGabTrends = () => (dispatch, getState) => {
dispatch(fetchGabTrendsRequest())
const url = 'https://trends.gab.com/partner'
- // api(getState).get(`/api/v1/gab_trends?type=partner`).then((response) => {
axios.get(url).then((response) => {
dispatch(fetchGabTrendsSuccess(response.data))
}).catch((error) => {
@@ -65,7 +64,6 @@ export const expandGabTrendsFeed = (feedId) => (dispatch, getState) => {
dispatch(expandGabTrendsFeedRequest(feedId))
const url = `https://trends.gab.com/feed/${feedId}?fmt=json&p=${page}`
- // api(getState).get(`/api/v1/gab_trends?type=rss&page=${page}&feedId=${feedId}`).then((response) => {
axios.get(url).then((response) => {
dispatch(expandGabTrendsFeedSuccess(response.data.rssFeedItems, feedId, response.data.pagination.p))
}).catch((error) => {
@@ -102,8 +100,7 @@ export const fetchGabNews = () => (dispatch, getState) => {
dispatch(fetchGabNewsRequest())
const url = 'https://news.gab.com/feed/?feed=json'
- // api(getState).get(`/api/v1/gab_trends?type=news`).then((response) => {
- axios.get(url).then((response) => {
+ axios.get(url).then((response) => {
dispatch(fetchGabNewsSuccess(response.data.items))
}).catch((error) => {
dispatch(fetchGabNewsFail(error))
diff --git a/app/javascript/gabsocial/actions/notifications.js b/app/javascript/gabsocial/actions/notifications.js
index 738a5d4b..99f584b3 100644
--- a/app/javascript/gabsocial/actions/notifications.js
+++ b/app/javascript/gabsocial/actions/notifications.js
@@ -1,278 +1,283 @@
-import api, { getLinks } from '../api';
-import IntlMessageFormat from 'intl-messageformat';
-import { fetchRelationships } from './accounts';
+import api, { getLinks } from '../api'
+import IntlMessageFormat from 'intl-messageformat'
+import { fetchRelationships } from './accounts'
import {
importFetchedAccount,
importFetchedAccounts,
importFetchedStatus,
importFetchedStatuses,
-} from './importer';
-import { defineMessages } from 'react-intl';
-import { List as ImmutableList } from 'immutable';
-import { unescapeHTML } from '../utils/html';
-import { getFilters, regexFromFilters } from '../selectors';
-import { me } from '../initial_state';
+} from './importer'
+import { defineMessages } from 'react-intl'
+import { List as ImmutableList } from 'immutable'
+import { unescapeHTML } from '../utils/html'
+import { getFilters, regexFromFilters } from '../selectors'
+import { me } from '../initial_state'
import { NOTIFICATION_FILTERS } from '../constants'
-export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE';
-export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
-export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE';
-export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE';
+export const NOTIFICATIONS_INITIALIZE = 'NOTIFICATIONS_INITIALIZE'
+export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'
+export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE'
+export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE'
-export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
-export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
-export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
+export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST'
+export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS'
+export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL'
-export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
+export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET'
-export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
-export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
-export const NOTIFICATIONS_MARK_READ = 'NOTIFICATIONS_MARK_READ';
+export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR'
+export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP'
+export const NOTIFICATIONS_MARK_READ = 'NOTIFICATIONS_MARK_READ'
export const MAX_QUEUED_NOTIFICATIONS = 40
defineMessages({
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
group: { id: 'notifications.group', defaultMessage: '{count} notifications' },
-});
+})
const fetchRelatedRelationships = (dispatch, notifications) => {
- const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
+ const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id)
if (accountIds.length > 0) {
- dispatch(fetchRelationships(accountIds));
+ dispatch(fetchRelationships(accountIds))
}
}
-export function initializeNotifications() {
- return {
- type: NOTIFICATIONS_INITIALIZE,
- }
-}
-
-export function updateNotifications(notification, intlMessages, intlLocale) {
- return (dispatch, getState) => {
- const showInColumn = getState().getIn(['notifications', 'filter', notification.type], true);
-
- if (showInColumn) {
- dispatch(importFetchedAccount(notification.account));
-
- if (notification.status) {
- dispatch(importFetchedStatus(notification.status));
- }
-
- dispatch({
- type: NOTIFICATIONS_UPDATE,
- notification,
- });
-
- fetchRelatedRelationships(dispatch, [notification]);
- }
- };
-};
-
-export function updateNotificationsQueue(notification, intlMessages, intlLocale, curPath) {
- return (dispatch, getState) => {
- // : todo :
- // const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
- const filters = getFilters(getState(), { contextType: 'notifications' });
-
- let filtered = false;
-
- const isOnNotificationsPage = curPath === '/notifications';
-
- if (notification.type === 'mention') {
- const regex = regexFromFilters(filters);
- const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content);
- filtered = regex && regex.test(searchIndex);
- }
-
- // Desktop notifications
- // : todo :
- // if (typeof window.Notification !== 'undefined' && showAlert && !filtered) {
- // const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username });
- // const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : '');
-
- // const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id });
-
- // notify.addEventListener('click', () => {
- // window.focus();
- // notify.close();
- // });
- // }
-
- if (isOnNotificationsPage) {
- dispatch({
- type: NOTIFICATIONS_UPDATE_QUEUE,
- notification,
- intlMessages,
- intlLocale,
- });
- } else {
- dispatch(updateNotifications(notification, intlMessages, intlLocale));
- }
- }
-};
-
-export function forceDequeueNotifications() {
- return (dispatch,) => {
- dispatch({
- type: NOTIFICATIONS_DEQUEUE,
- })
- }
-}
-
-export function dequeueNotifications() {
- return (dispatch, getState) => {
- const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableList());
- const totalQueuedNotificationsCount = getState().getIn(['notifications', 'totalQueuedNotificationsCount'], 0);
-
- if (totalQueuedNotificationsCount === 0) {
- return;
- } else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
- queuedNotifications.forEach(block => {
- dispatch(updateNotifications(block.notification, block.intlMessages, block.intlLocale));
- });
- } else {
- dispatch(expandNotifications());
- }
-
- dispatch({
- type: NOTIFICATIONS_DEQUEUE,
- });
- dispatch(markReadNotifications());
- }
-};
-
const excludeTypesFromFilter = filter => {
- const allTypes = ImmutableList(['follow', 'favourite', 'reblog', 'mention', 'poll']);
- return allTypes.filterNot(item => item === filter).toJS();
-};
+ const allTypes = ImmutableList(['follow', 'favourite', 'reblog', 'mention', 'poll'])
+ return allTypes.filterNot(item => item === filter).toJS()
+}
const noOp = () => {}
-export function expandNotifications({ maxId } = {}, done = noOp) {
- return (dispatch, getState) => {
- if (!me) return
+/**
+ *
+ */
+export const initializeNotifications = () => ({
+ type: NOTIFICATIONS_INITIALIZE,
+})
- const onlyVerified = getState().getIn(['notifications', 'filter', 'onlyVerified'])
- const onlyFollowing = getState().getIn(['notifications', 'filter', 'onlyFollowing'])
- const activeFilter = getState().getIn(['notifications', 'filter', 'active'])
- const notifications = getState().get('notifications')
- const isLoadingMore = !!maxId
+/**
+ *
+ */
+export const updateNotifications = (notification, intlMessages, intlLocale) => (dispatch, getState) => {
+ const showInColumn = getState().getIn(['notifications', 'filter', notification.type], true)
- if (notifications.get('isLoading') || activeFilter === 'follow_requests') {
- done();
- return;
+ if (showInColumn) {
+ dispatch(importFetchedAccount(notification.account))
+
+ if (notification.status) {
+ dispatch(importFetchedStatus(notification.status))
}
- const params = {
- max_id: maxId,
- exclude_types: activeFilter === 'all' ? null : excludeTypesFromFilter(activeFilter),
- }
-
- if (!!onlyVerified) params.only_verified = onlyVerified
- if (!!onlyFollowing) params.only_following = onlyFollowing
-
- if (!maxId && notifications.get('items').size > 0) {
- params.since_id = notifications.getIn(['items', 0, 'id']);
- }
-
- dispatch(expandNotificationsRequest(isLoadingMore));
-
- api(getState).get('/api/v1/notifications', { params }).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
-
- dispatch(importFetchedAccounts(response.data.map(item => item.account)));
- dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
-
- dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore));
-
- fetchRelatedRelationships(dispatch, response.data);
-
- done();
- }).catch(error => {
- dispatch(expandNotificationsFail(error, isLoadingMore));
- done();
- });
- };
-};
-
-export function expandNotificationsRequest(isLoadingMore) {
- return {
- type: NOTIFICATIONS_EXPAND_REQUEST,
- skipLoading: !isLoadingMore,
- };
-};
-
-export function expandNotificationsSuccess(notifications, next, isLoadingMore) {
- return {
- type: NOTIFICATIONS_EXPAND_SUCCESS,
- notifications,
- next,
- skipLoading: !isLoadingMore,
- };
-};
-
-export function expandNotificationsFail(error, isLoadingMore) {
- return {
- type: NOTIFICATIONS_EXPAND_FAIL,
- error,
- skipLoading: !isLoadingMore,
- };
-};
-
-export function clearNotifications() {
- return (dispatch, getState) => {
- if (!me) return;
-
dispatch({
- type: NOTIFICATIONS_CLEAR,
- });
-
- api(getState).post('/api/v1/notifications/clear');
- };
-};
-
-export function scrollTopNotifications(top) {
- return (dispatch, getState) => {
- dispatch({
- type: NOTIFICATIONS_SCROLL_TOP,
- top,
- });
- dispatch(markReadNotifications());
- }
-};
-
-export function setFilter(path, value) {
- return (dispatch) => {
- if (path === 'active' && NOTIFICATION_FILTERS.indexOf(value) === -1) return
-
- dispatch({
- type: NOTIFICATIONS_FILTER_SET,
- path: path,
- value: value,
+ type: NOTIFICATIONS_UPDATE,
+ notification,
})
- dispatch(expandNotifications())
+
+ fetchRelatedRelationships(dispatch, [notification])
}
}
-export function markReadNotifications() {
- return (dispatch, getState) => {
- if (!me) return
-
- const topNotification = parseInt(getState().getIn(['notifications', 'items', 0, 'id']))
- const lastReadId = getState().getIn(['notifications', 'lastReadId'])
+/**
+ *
+ */
+export const updateNotificationsQueue = (notification, intlMessages, intlLocale, curPath) => (dispatch, getState) => {
+ // : todo :
+ // const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true)
+ const filters = getFilters(getState(), { contextType: 'notifications' })
- if (topNotification && topNotification > lastReadId && lastReadId !== -1) {
- api(getState).post('/api/v1/notifications/mark_read', {
- id: topNotification
- }).then(() => {
- dispatch({
- type: NOTIFICATIONS_MARK_READ,
- notification: topNotification,
- })
+ let filtered = false
+
+ const isOnNotificationsPage = curPath === '/notifications'
+
+ if (notification.type === 'mention') {
+ const regex = regexFromFilters(filters)
+ const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content)
+ filtered = regex && regex.test(searchIndex)
+ }
+
+ // Desktop notifications
+ // : todo :
+ // if (typeof window.Notification !== 'undefined' && showAlert && !filtered) {
+ // const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username })
+ // const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : '')
+
+ // const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id })
+
+ // notify.addEventListener('click', () => {
+ // window.focus()
+ // notify.close()
+ // })
+ // }
+
+ if (isOnNotificationsPage) {
+ dispatch({
+ type: NOTIFICATIONS_UPDATE_QUEUE,
+ notification,
+ intlMessages,
+ intlLocale,
+ })
+ } else {
+ dispatch(updateNotifications(notification, intlMessages, intlLocale))
+ }
+}
+
+/**
+ *
+ */
+export const forceDequeueNotifications = () => (dispatch) => {
+ dispatch({
+ type: NOTIFICATIONS_DEQUEUE,
+ })
+}
+
+/**
+ *
+ */
+export const dequeueNotifications = () => (dispatch, getState) => {
+ const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableList())
+ const totalQueuedNotificationsCount = getState().getIn(['notifications', 'totalQueuedNotificationsCount'], 0)
+
+ if (totalQueuedNotificationsCount === 0) {
+ return
+ } else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
+ queuedNotifications.forEach((block) => {
+ dispatch(updateNotifications(block.notification, block.intlMessages, block.intlLocale))
+ })
+ } else {
+ dispatch(expandNotifications())
+ }
+
+ dispatch({
+ type: NOTIFICATIONS_DEQUEUE,
+ })
+ dispatch(markReadNotifications())
+}
+
+/**
+ *
+ */
+export const expandNotifications = ({ maxId } = {}, done = noOp) => (dispatch, getState) => {
+ if (!me) return
+
+ const onlyVerified = getState().getIn(['notifications', 'filter', 'onlyVerified'])
+ const onlyFollowing = getState().getIn(['notifications', 'filter', 'onlyFollowing'])
+ const activeFilter = getState().getIn(['notifications', 'filter', 'active'])
+ const notifications = getState().get('notifications')
+ const isLoadingMore = !!maxId
+
+ if (notifications.get('isLoading') || notifications.get('isError')|| activeFilter === 'follow_requests') {
+ done()
+ return
+ }
+
+ const params = {
+ max_id: maxId,
+ exclude_types: activeFilter === 'all' ? null : excludeTypesFromFilter(activeFilter),
+ }
+
+ if (!!onlyVerified) params.only_verified = onlyVerified
+ if (!!onlyFollowing) params.only_following = onlyFollowing
+
+ if (!maxId && notifications.get('items').size > 0) {
+ params.since_id = notifications.getIn(['items', 0, 'id'])
+ }
+
+ dispatch(expandNotificationsRequest(isLoadingMore))
+
+ api(getState).get('/api/v1/notifications', { params }).then((response) => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+
+ dispatch(importFetchedAccounts(response.data.map(item => item.account)))
+ dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)))
+
+ dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore))
+
+ fetchRelatedRelationships(dispatch, response.data)
+
+ done()
+ }).catch((error) => {
+ dispatch(expandNotificationsFail(error, isLoadingMore))
+ done()
+ })
+}
+
+export const expandNotificationsRequest = (isLoadingMore) => ({
+ type: NOTIFICATIONS_EXPAND_REQUEST,
+ skipLoading: !isLoadingMore,
+})
+
+export const expandNotificationsSuccess = (notifications, next, isLoadingMore) => ({
+ type: NOTIFICATIONS_EXPAND_SUCCESS,
+ notifications,
+ next,
+ skipLoading: !isLoadingMore,
+})
+
+export const expandNotificationsFail = (error, isLoadingMore) => ({
+ type: NOTIFICATIONS_EXPAND_FAIL,
+ error,
+ skipLoading: !isLoadingMore,
+})
+
+/**
+ *
+ */
+// : todo : implement with alert/warning
+export const clearNotifications = () => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch({
+ type: NOTIFICATIONS_CLEAR,
+ })
+
+ api(getState).post('/api/v1/notifications/clear')
+}
+
+/**
+ *
+ */
+export const scrollTopNotifications = (top) => (dispatch, getState) => {
+ dispatch({
+ type: NOTIFICATIONS_SCROLL_TOP,
+ top,
+ })
+ dispatch(markReadNotifications())
+}
+
+/**
+ *
+ */
+export const setFilter = (path, value) => (dispatch) => {
+ if (path === 'active' && NOTIFICATION_FILTERS.indexOf(value) === -1) return
+
+ dispatch({
+ type: NOTIFICATIONS_FILTER_SET,
+ path: path,
+ value: value,
+ })
+ dispatch(expandNotifications())
+}
+
+/**
+ *
+ */
+export const markReadNotifications = () => (dispatch, getState) => {
+ if (!me) return
+
+ const topNotification = parseInt(getState().getIn(['notifications', 'items', 0, 'id']))
+ const lastReadId = getState().getIn(['notifications', 'lastReadId'])
+
+ if (topNotification && topNotification > lastReadId && lastReadId !== -1) {
+ api(getState).post('/api/v1/notifications/mark_read', {
+ id: topNotification
+ }).then(() => {
+ dispatch({
+ type: NOTIFICATIONS_MARK_READ,
+ notification: topNotification,
})
- }
+ })
}
}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/onboarding.js b/app/javascript/gabsocial/actions/onboarding.js
deleted file mode 100644
index 52733a44..00000000
--- a/app/javascript/gabsocial/actions/onboarding.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { changeSetting, saveSettings } from './settings'
-
-export const saveShownOnboarding = () => (dispatch) => {
- dispatch(changeSetting(['shownOnboarding'], true))
- dispatch(saveSettings())
-}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/polls.js b/app/javascript/gabsocial/actions/polls.js
index 8e8b82df..29ba4f7d 100644
--- a/app/javascript/gabsocial/actions/polls.js
+++ b/app/javascript/gabsocial/actions/polls.js
@@ -1,60 +1,66 @@
-import api from '../api';
-import { importFetchedPoll } from './importer';
+import api from '../api'
+import { importFetchedPoll } from './importer'
-export const POLL_VOTE_REQUEST = 'POLL_VOTE_REQUEST';
-export const POLL_VOTE_SUCCESS = 'POLL_VOTE_SUCCESS';
-export const POLL_VOTE_FAIL = 'POLL_VOTE_FAIL';
+export const POLL_VOTE_REQUEST = 'POLL_VOTE_REQUEST'
+export const POLL_VOTE_SUCCESS = 'POLL_VOTE_SUCCESS'
+export const POLL_VOTE_FAIL = 'POLL_VOTE_FAIL'
-export const POLL_FETCH_REQUEST = 'POLL_FETCH_REQUEST';
-export const POLL_FETCH_SUCCESS = 'POLL_FETCH_SUCCESS';
-export const POLL_FETCH_FAIL = 'POLL_FETCH_FAIL';
+export const POLL_FETCH_REQUEST = 'POLL_FETCH_REQUEST'
+export const POLL_FETCH_SUCCESS = 'POLL_FETCH_SUCCESS'
+export const POLL_FETCH_FAIL = 'POLL_FETCH_FAIL'
+/**
+ *
+ */
export const vote = (pollId, choices) => (dispatch, getState) => {
- dispatch(voteRequest());
+ dispatch(voteRequest())
api(getState).post(`/api/v1/polls/${pollId}/votes`, { choices })
.then(({ data }) => {
- dispatch(importFetchedPoll(data));
- dispatch(voteSuccess(data));
+ dispatch(importFetchedPoll(data))
+ dispatch(voteSuccess(data))
})
- .catch(err => dispatch(voteFail(err)));
-};
+ .catch(err => dispatch(voteFail(err)))
+}
+const voteRequest = () => ({
+ type: POLL_VOTE_REQUEST,
+})
+
+const voteSuccess = (poll) => ({
+ type: POLL_VOTE_SUCCESS,
+ poll,
+})
+
+const voteFail = (error) => ({
+ type: POLL_VOTE_FAIL,
+ error,
+})
+
+/**
+ *
+ */
export const fetchPoll = pollId => (dispatch, getState) => {
- dispatch(fetchPollRequest());
+ dispatch(fetchPollRequest())
api(getState).get(`/api/v1/polls/${pollId}`)
.then(({ data }) => {
- dispatch(importFetchedPoll(data));
- dispatch(fetchPollSuccess(data));
+ dispatch(importFetchedPoll(data))
+ dispatch(fetchPollSuccess(data))
})
- .catch(err => dispatch(fetchPollFail(err)));
-};
+ .catch(err => dispatch(fetchPollFail(err)))
+}
-export const voteRequest = () => ({
- type: POLL_VOTE_REQUEST,
-});
-
-export const voteSuccess = poll => ({
- type: POLL_VOTE_SUCCESS,
- poll,
-});
-
-export const voteFail = error => ({
- type: POLL_VOTE_FAIL,
- error,
-});
-
-export const fetchPollRequest = () => ({
+const fetchPollRequest = () => ({
type: POLL_FETCH_REQUEST,
-});
+})
-export const fetchPollSuccess = poll => ({
+const fetchPollSuccess = (poll) => ({
type: POLL_FETCH_SUCCESS,
poll,
-});
+})
-export const fetchPollFail = error => ({
+const fetchPollFail = (error) => ({
type: POLL_FETCH_FAIL,
error,
-});
+})
diff --git a/app/javascript/gabsocial/actions/popover.js b/app/javascript/gabsocial/actions/popover.js
index f872fc03..25a4636b 100644
--- a/app/javascript/gabsocial/actions/popover.js
+++ b/app/javascript/gabsocial/actions/popover.js
@@ -1,29 +1,23 @@
export const POPOVER_OPEN = 'POPOVER_OPEN'
export const POPOVER_CLOSE = 'POPOVER_CLOSE'
-export function openPopover(type, props) {
- return function (dispatch, getState) {
- const currentlyOpenPopover = getState().getIn(['popover', 'popoverType'])
+export const openPopover = (type, props) => (dispatch, getState) => {
+ const currentlyOpenPopover = getState().getIn(['popover', 'popoverType'])
- if (currentlyOpenPopover === type) {
- dispatch(closePopover(type))
- } else {
- dispatch(handleOpenPopover(type, props))
- }
+ if (currentlyOpenPopover === type) {
+ dispatch(closePopover(type))
+ } else {
+ dispatch(handleOpenPopover(type, props))
}
}
-export function closePopover(type) {
- return {
- type: POPOVER_CLOSE,
- popoverType: type,
- }
-}
+export const closePopover = (type) => ({
+ type: POPOVER_CLOSE,
+ popoverType: type,
+})
-const handleOpenPopover = (type, props) => {
- return {
- type: POPOVER_OPEN,
- popoverType: type,
- popoverProps: props,
- }
-}
\ No newline at end of file
+const handleOpenPopover = (type, props) => ({
+ type: POPOVER_OPEN,
+ popoverType: type,
+ popoverProps: props,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/promotions.js b/app/javascript/gabsocial/actions/promotions.js
index c4cfeb80..bdca5e80 100644
--- a/app/javascript/gabsocial/actions/promotions.js
+++ b/app/javascript/gabsocial/actions/promotions.js
@@ -5,18 +5,19 @@ export const PROMOTIONS_FETCH_REQUEST = 'PROMOTIONS_FETCH_REQUEST'
export const PROMOTIONS_FETCH_SUCCESS = 'PROMOTIONS_FETCH_SUCCESS'
export const PROMOTIONS_FETCH_FAIL = 'PROMOTIONS_FETCH_FAIL'
-export const fetchPromotions = () => {
- return (dispatch, getState) => {
- if (!me) return
+/**
+ *
+ */
+export const fetchPromotions = () => (dispatch, getState) => {
+ if (!me) return
- dispatch(fetchPromotionsRequest())
+ dispatch(fetchPromotionsRequest())
- api(getState).get('/api/v1/promotions').then((response) => {
- dispatch(fetchPromotionsSuccess(response.data))
- }).catch((error) => {
- dispatch(fetchPromotionsFail(error))
- })
- }
+ api(getState).get('/api/v1/promotions').then((response) => {
+ dispatch(fetchPromotionsSuccess(response.data))
+ }).catch((error) => {
+ dispatch(fetchPromotionsFail(error))
+ })
}
const fetchPromotionsRequest = () => ({
diff --git a/app/javascript/gabsocial/actions/push_notifications/index.js b/app/javascript/gabsocial/actions/push_notifications/index.js
index 2ffec500..d7cc788e 100644
--- a/app/javascript/gabsocial/actions/push_notifications/index.js
+++ b/app/javascript/gabsocial/actions/push_notifications/index.js
@@ -4,8 +4,8 @@ import {
CLEAR_SUBSCRIPTION,
SET_ALERTS,
setAlerts,
-} from './setter';
-import { register, saveSettings } from './registerer';
+} from './setter'
+import { register, saveSettings } from './registerer'
export {
SET_BROWSER_SUPPORT,
@@ -13,11 +13,9 @@ export {
CLEAR_SUBSCRIPTION,
SET_ALERTS,
register,
-};
-
-export function changeAlerts(path, value) {
- return dispatch => {
- dispatch(setAlerts(path, value));
- dispatch(saveSettings());
- };
+}
+
+export const changeAlerts = (path, value) => (dispatch) => {
+ dispatch(setAlerts(path, value))
+ dispatch(saveSettings())
}
diff --git a/app/javascript/gabsocial/actions/push_notifications/setter.js b/app/javascript/gabsocial/actions/push_notifications/setter.js
index 5561766b..bcef5c6e 100644
--- a/app/javascript/gabsocial/actions/push_notifications/setter.js
+++ b/app/javascript/gabsocial/actions/push_notifications/setter.js
@@ -1,34 +1,26 @@
-export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT';
-export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION';
-export const CLEAR_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION';
-export const SET_ALERTS = 'PUSH_NOTIFICATIONS_SET_ALERTS';
+export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT'
+export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION'
+export const CLEAR_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION'
+export const SET_ALERTS = 'PUSH_NOTIFICATIONS_SET_ALERTS'
-export function setBrowserSupport (value) {
- return {
- type: SET_BROWSER_SUPPORT,
+export const setBrowserSupport = (value) => ({
+ type: SET_BROWSER_SUPPORT,
+ value,
+})
+
+export const setSubscription = (subscription) => ({
+ type: SET_SUBSCRIPTION,
+ subscription,
+})
+
+export const clearSubscription = () => ({
+ type: CLEAR_SUBSCRIPTION,
+})
+
+export const setAlerts = (path, value) => (dispatch) => {
+ dispatch({
+ type: SET_ALERTS,
+ path,
value,
- };
-}
-
-export function setSubscription (subscription) {
- return {
- type: SET_SUBSCRIPTION,
- subscription,
- };
-}
-
-export function clearSubscription () {
- return {
- type: CLEAR_SUBSCRIPTION,
- };
-}
-
-export function setAlerts (path, value) {
- return dispatch => {
- dispatch({
- type: SET_ALERTS,
- path,
- value,
- });
- };
+ })
}
diff --git a/app/javascript/gabsocial/actions/reports.js b/app/javascript/gabsocial/actions/reports.js
index afa0c341..094b3cf2 100644
--- a/app/javascript/gabsocial/actions/reports.js
+++ b/app/javascript/gabsocial/actions/reports.js
@@ -1,89 +1,82 @@
-import api from '../api';
-import { openModal, closeModal } from './modal';
+import api from '../api'
+import { openModal, closeModal } from './modal'
+import { MODAL_REPORT } from '../constants'
-export const REPORT_INIT = 'REPORT_INIT';
-export const REPORT_CANCEL = 'REPORT_CANCEL';
+export const REPORT_INIT = 'REPORT_INIT'
+export const REPORT_CANCEL = 'REPORT_CANCEL'
-export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST';
-export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS';
-export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
+export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST'
+export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS'
+export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'
-export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE';
-export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE';
-export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE';
+export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE'
+export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE'
+export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE'
-export function initReport(account, status) {
- return dispatch => {
- dispatch({
- type: REPORT_INIT,
- account,
- status,
- });
+/**
+ *
+ */
+export const initReport = (account, status) => (dispatch) => {
+ dispatch({
+ type: REPORT_INIT,
+ account,
+ status,
+ })
- dispatch(openModal('REPORT'));
- };
-};
+ dispatch(openModal(MODAL_REPORT))
+}
-export function cancelReport() {
- return {
- type: REPORT_CANCEL,
- };
-};
+/**
+ *
+ */
+export const cancelReport = () => ({
+ type: REPORT_CANCEL,
+})
-export function toggleStatusReport(statusId, checked) {
- return {
- type: REPORT_STATUS_TOGGLE,
- statusId,
- checked,
- };
-};
+/**
+ *
+ */
+export const toggleStatusReport = (statusId, checked) => ({
+ type: REPORT_STATUS_TOGGLE,
+ statusId,
+ checked,
+})
-export function submitReport() {
- return (dispatch, getState) => {
- dispatch(submitReportRequest());
+/**
+ *
+ */
+export const submitReport = () => (dispatch, getState) => {
+ dispatch(submitReportRequest())
- api(getState).post('/api/v1/reports', {
- account_id: getState().getIn(['reports', 'new', 'account_id']),
- status_ids: getState().getIn(['reports', 'new', 'status_ids']),
- comment: getState().getIn(['reports', 'new', 'comment']),
- forward: getState().getIn(['reports', 'new', 'forward']),
- }).then(response => {
- dispatch(closeModal());
- dispatch(submitReportSuccess(response.data));
- }).catch(error => dispatch(submitReportFail(error)));
- };
-};
+ api(getState).post('/api/v1/reports', {
+ account_id: getState().getIn(['reports', 'new', 'account_id']),
+ status_ids: getState().getIn(['reports', 'new', 'status_ids']),
+ comment: getState().getIn(['reports', 'new', 'comment']),
+ forward: getState().getIn(['reports', 'new', 'forward']),
+ }).then((response) => {
+ dispatch(closeModal());
+ dispatch(submitReportSuccess(response.data))
+ }).catch((error) => dispatch(submitReportFail(error)))
+}
-export function submitReportRequest() {
- return {
- type: REPORT_SUBMIT_REQUEST,
- };
-};
+const submitReportRequest = () => ({
+ type: REPORT_SUBMIT_REQUEST,
+})
-export function submitReportSuccess(report) {
- return {
- type: REPORT_SUBMIT_SUCCESS,
- report,
- };
-};
+const submitReportSuccess = (report) => ({
+ type: REPORT_SUBMIT_SUCCESS,
+ report,
+})
-export function submitReportFail(error) {
- return {
- type: REPORT_SUBMIT_FAIL,
- error,
- };
-};
+const submitReportFail = (error) => ({
+ type: REPORT_SUBMIT_FAIL,
+ error,
+})
-export function changeReportComment(comment) {
- return {
- type: REPORT_COMMENT_CHANGE,
- comment,
- };
-};
-
-export function changeReportForward(forward) {
- return {
- type: REPORT_FORWARD_CHANGE,
- forward,
- };
-};
+/**
+ *
+ */
+export const changeReportComment = (comment) => ({
+ type: REPORT_COMMENT_CHANGE,
+ comment,
+})
diff --git a/app/javascript/gabsocial/actions/search.js b/app/javascript/gabsocial/actions/search.js
index e98af32a..81d021cc 100644
--- a/app/javascript/gabsocial/actions/search.js
+++ b/app/javascript/gabsocial/actions/search.js
@@ -18,93 +18,92 @@ export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL';
export const SEARCH_FILTER_SET = 'SEARCH_FILTER_SET'
-export function changeSearch(value) {
- return {
- type: SEARCH_CHANGE,
- value,
- };
-};
+/**
+ *
+ */
+export const changeSearch = (value) => ({
+ type: SEARCH_CHANGE,
+ value,
+})
-export function clearSearch() {
- return {
- type: SEARCH_CLEAR,
- };
-};
+/**
+ *
+ */
+export const clearSearch = () => ({
+ type: SEARCH_CLEAR,
+})
-export function submitSearch() {
- return (dispatch, getState) => {
- const value = getState().getIn(['search', 'value']);
- const onlyVerified = getState().getIn(['search', 'filter', 'onlyVerified'])
+/**
+ *
+ */
+export const submitSearch = () => (dispatch, getState) => {
+ const value = getState().getIn(['search', 'value'])
+ const onlyVerified = getState().getIn(['search', 'filter', 'onlyVerified'])
- if (value.length === 0) return
+ if (value.length === 0) return
- dispatch(fetchSearchRequest());
+ dispatch(fetchSearchRequest())
- api(getState).get('/api/v2/search', {
- params: {
- onlyVerified,
- q: value,
- resolve: true,
- },
- }).then(response => {
- if (response.data.accounts) {
- dispatch(importFetchedAccounts(response.data.accounts));
- dispatch(fetchRelationships(response.data.accounts.map(item => item.id)));
- }
+ api(getState).get('/api/v2/search', {
+ params: {
+ onlyVerified,
+ q: value,
+ resolve: true,
+ },
+ }).then((response) => {
+ if (response.data.accounts) {
+ dispatch(importFetchedAccounts(response.data.accounts))
+ dispatch(fetchRelationships(response.data.accounts.map(item => item.id)))
+ }
- if (response.data.statuses) {
- dispatch(importFetchedStatuses(response.data.statuses));
- }
+ if (response.data.statuses) {
+ dispatch(importFetchedStatuses(response.data.statuses))
+ }
- if (response.data.links) {
- dispatch(importLinkCards(response.data.links));
- }
+ if (response.data.links) {
+ dispatch(importLinkCards(response.data.links))
+ }
- if (response.data.groups) {
- dispatch(fetchGroupsSuccess(response.data.groups))
- dispatch(fetchGroupRelationships(response.data.groups.map(item => item.id)))
- }
+ if (response.data.groups) {
+ dispatch(fetchGroupsSuccess(response.data.groups))
+ dispatch(fetchGroupRelationships(response.data.groups.map(item => item.id)))
+ }
- dispatch(fetchSearchSuccess(response.data));
- }).catch(error => {
- dispatch(fetchSearchFail(error));
- });
- };
-};
+ dispatch(fetchSearchSuccess(response.data))
+ }).catch((error) => {
+ dispatch(fetchSearchFail(error))
+ })
+}
-export function fetchSearchRequest() {
- return {
- type: SEARCH_FETCH_REQUEST,
- };
-};
+const fetchSearchRequest = () => ({
+ type: SEARCH_FETCH_REQUEST,
+})
-export function fetchSearchSuccess(results) {
- return {
- type: SEARCH_FETCH_SUCCESS,
- results,
- };
-};
+const fetchSearchSuccess = (results) => ({
+ type: SEARCH_FETCH_SUCCESS,
+ results,
+})
-export function fetchSearchFail(error) {
- return {
- type: SEARCH_FETCH_FAIL,
- error,
- };
-};
+const fetchSearchFail = (error) => ({
+ type: SEARCH_FETCH_FAIL,
+ error,
+})
-export function showSearch() {
- return {
- type: SEARCH_SHOW,
- };
-};
+/**
+ *
+ */
+export const showSearch = () => ({
+ type: SEARCH_SHOW,
+})
-export function setFilter(path, value, shouldSubmit) {
- return (dispatch) => {
- dispatch({
- type: SEARCH_FILTER_SET,
- path: path,
- value: value,
- })
- if (shouldSubmit) dispatch(submitSearch())
- }
+/**
+ *
+ */
+export const setFilter = (path, value, shouldSubmit) => (dispatch) => {
+ dispatch({
+ type: SEARCH_FILTER_SET,
+ path: path,
+ value: value,
+ })
+ if (shouldSubmit) dispatch(submitSearch())
}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/settings.js b/app/javascript/gabsocial/actions/settings.js
index 175c511a..2c18fb85 100644
--- a/app/javascript/gabsocial/actions/settings.js
+++ b/app/javascript/gabsocial/actions/settings.js
@@ -5,16 +5,26 @@ import { me } from '../initial_state'
export const SETTING_CHANGE = 'SETTING_CHANGE'
export const SETTING_SAVE = 'SETTING_SAVE'
-export function changeSetting(path, value) {
- return dispatch => {
- dispatch({
- type: SETTING_CHANGE,
- path,
- value,
- })
+export const saveShownOnboarding = () => (dispatch) => {
+ dispatch(changeSetting(['shownOnboarding'], true))
+ dispatch(saveSettings())
+}
- dispatch(saveSettings())
- }
+export const changeSetting = (path, value) => (dispatch) => {
+ dispatch({
+ type: SETTING_CHANGE,
+ path,
+ value,
+ })
+
+ dispatch(saveSettings())
+}
+
+/**
+ *
+ */
+export const saveSettings = () => (dispatch, getState) => {
+ debouncedSave(dispatch, getState)
}
const debouncedSave = debounce((dispatch, getState) => {
@@ -28,7 +38,3 @@ const debouncedSave = debounce((dispatch, getState) => {
.then(() => dispatch({ type: SETTING_SAVE }))
.catch(() => { /* */ })
}, 350, { trailing: true })
-
-export function saveSettings() {
- return (dispatch, getState) => debouncedSave(dispatch, getState)
-}
diff --git a/app/javascript/gabsocial/actions/shop.js b/app/javascript/gabsocial/actions/shop.js
index a437ec61..3d44c12a 100644
--- a/app/javascript/gabsocial/actions/shop.js
+++ b/app/javascript/gabsocial/actions/shop.js
@@ -1,47 +1,44 @@
+
import axios from 'axios'
+import api from '../api'
import { me } from '../initial_state'
export const SHOP_FEATURED_PRODUCTS_FETCH_REQUEST = 'SHOP_FEATURED_PRODUCTS_FETCH_REQUEST'
export const SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS = 'SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS'
export const SHOP_FEATURED_PRODUCTS_FETCH_FAIL = 'SHOP_FEATURED_PRODUCTS_FETCH_FAIL'
-export const fetchFeaturedProducts = () => {
- return function (dispatch, getState) {
- if (!me) return
+/**
+ *
+ */
+export const fetchFeaturedProducts = () => (dispatch, getState) => {
+ if (!me) return
- dispatch(fetchFeaturedProductsRequest('featured'))
+ dispatch(fetchFeaturedProductsRequest('featured'))
- axios.get('https://dissenter-shop.gab.com/product/group/json').then((response) => {
- try {
- dispatch(fetchFeaturedProductsSuccess(response.data.data, 'featured'))
- } catch (error) {
- //
- }
- }).catch(function (error) {
- dispatch(fetchFeaturedProductsFail(error, 'featured'))
- })
- }
+ axios.get('https://dissenter-shop.gab.com/product/group/json').then((response) => {
+ try {
+ dispatch(fetchFeaturedProductsSuccess(response.data.data, 'featured'))
+ } catch (error) {
+ //
+ }
+ }).catch((error) => {
+ dispatch(fetchFeaturedProductsFail(error, 'featured'))
+ })
}
-function fetchFeaturedProductsRequest(listType) {
- return {
- type: SHOP_FEATURED_PRODUCTS_FETCH_REQUEST,
- listType,
- }
-}
+const fetchFeaturedProductsRequest = (listType) => ({
+ type: SHOP_FEATURED_PRODUCTS_FETCH_REQUEST,
+ listType,
+})
-function fetchFeaturedProductsSuccess(items, listType) {
- return {
- type: SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS,
- items,
- listType,
- }
-}
+const fetchFeaturedProductsSuccess = (items, listType) => ({
+ type: SHOP_FEATURED_PRODUCTS_FETCH_SUCCESS,
+ items,
+ listType,
+})
-function fetchFeaturedProductsFail(error, listType) {
- return {
- type: SHOP_FEATURED_PRODUCTS_FETCH_FAIL,
- error,
- listType,
- }
-}
\ No newline at end of file
+const fetchFeaturedProductsFail = (error, listType) => ({
+ type: SHOP_FEATURED_PRODUCTS_FETCH_FAIL,
+ error,
+ listType,
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/shortcuts.js b/app/javascript/gabsocial/actions/shortcuts.js
index 92d53ad2..6b1169d3 100644
--- a/app/javascript/gabsocial/actions/shortcuts.js
+++ b/app/javascript/gabsocial/actions/shortcuts.js
@@ -13,116 +13,104 @@ export const SHORTCUTS_REMOVE_REQUEST = 'SHORTCUTS_REMOVE_REQUEST'
export const SHORTCUTS_REMOVE_SUCCESS = 'SHORTCUTS_REMOVE_SUCCESS'
export const SHORTCUTS_REMOVE_FAIL = 'SHORTCUTS_REMOVE_FAIL'
-export function fetchShortcuts() {
- return (dispatch, getState) => {
- if (!me) return
+/**
+ *
+ */
+export const fetchShortcuts = () => (dispatch, getState) => {
+ if (!me) return
+
+ const isFetched = getState().getIn(['shortcuts', 'isFetched'], false)
+ if (isFetched) return
- dispatch(fetchShortcutsRequest())
+ dispatch(fetchShortcutsRequest())
- api(getState).get('/api/v1/shortcuts').then(response => {
- dispatch(fetchShortcutsSuccess(response.data))
- }).catch(error => dispatch(fetchShortcutsFail(error)))
- }
+ api(getState).get('/api/v1/shortcuts').then(response => {
+ dispatch(fetchShortcutsSuccess(response.data))
+ }).catch(error => dispatch(fetchShortcutsFail(error)))
}
-export function fetchShortcutsRequest() {
- return {
- type: SHORTCUTS_FETCH_REQUEST,
- }
+const fetchShortcutsRequest = () => ({
+ type: SHORTCUTS_FETCH_REQUEST,
+})
+
+const fetchShortcutsSuccess = (shortcuts) => ({
+ type: SHORTCUTS_FETCH_SUCCESS,
+ shortcuts,
+})
+
+const fetchShortcutsFail = (error) => ({
+ type: SHORTCUTS_FETCH_FAIL,
+ error,
+})
+
+/**
+ *
+ */
+export const addShortcut = (shortcutType, shortcutId) => (dispatch, getState) => {
+ if (!me) return
+
+ dispatch(addShortcutsRequest())
+
+ api(getState).post('/api/v1/shortcuts', {
+ shortcut_type: shortcutType,
+ shortcut_id: shortcutId,
+ }).then(response => {
+ dispatch(addShortcutsSuccess(response.data))
+ }).catch(error => dispatch(addShortcutsFail(error)))
}
-export function fetchShortcutsSuccess(shortcuts) {
- return {
- shortcuts,
- type: SHORTCUTS_FETCH_SUCCESS,
- }
-}
+const addShortcutsRequest = () => ({
+ type: SHORTCUTS_ADD_REQUEST,
+})
-export function fetchShortcutsFail(error) {
- return {
- error,
- type: SHORTCUTS_FETCH_FAIL,
- }
-}
+const addShortcutsSuccess = (shortcut) => ({
+ type: SHORTCUTS_ADD_SUCCESS,
+ shortcut,
+})
-export function addShortcut(shortcutType, shortcutId) {
- return (dispatch, getState) => {
- if (!me) return
+const addShortcutsFail = (error) => ({
+ type: SHORTCUTS_ADD_FAIL,
+ error,
+})
- dispatch(addShortcutsRequest())
-
- api(getState).post('/api/v1/shortcuts', {
- shortcut_type: shortcutType,
- shortcut_id: shortcutId,
- }).then(response => {
- dispatch(addShortcutsSuccess(response.data))
- }).catch(error => dispatch(addShortcutsFail(error)))
- }
-}
-
-export function addShortcutsRequest() {
- return {
- type: SHORTCUTS_ADD_REQUEST,
- }
-}
-
-export function addShortcutsSuccess(shortcut) {
- return {
- shortcut,
- type: SHORTCUTS_ADD_SUCCESS,
- }
-}
-
-export function addShortcutsFail(error) {
- return {
- error,
- type: SHORTCUTS_ADD_FAIL,
- }
-}
-
-export function removeShortcut(shortcutObjectId, shortcutType, shortcutId) {
- return (dispatch, getState) => {
- if (!me) return
-
- let id
- if (shortcutObjectId) {
- id = shortcutObjectId
- } else if (shortcutType && shortcutId) {
- const shortcuts = getState().getIn(['shortcuts', 'items'])
- const shortcut = shortcuts.find((s) => {
- return s.get('shortcut_id') == shortcutId && s.get('shortcut_type') === shortcutType
- })
- if (!!shortcut) {
- id = shortcut.get('id')
- }
+/**
+ *
+ */
+export const removeShortcut = (shortcutObjectId, shortcutType, shortcutId) => (dispatch, getState) => {
+ if (!me) return
+
+ let id
+ if (shortcutObjectId) {
+ id = shortcutObjectId
+ } else if (shortcutType && shortcutId) {
+ const shortcuts = getState().getIn(['shortcuts', 'items'])
+ const shortcut = shortcuts.find((s) => {
+ return s.get('shortcut_id') == shortcutId && s.get('shortcut_type') === shortcutType
+ })
+ if (!!shortcut) {
+ id = shortcut.get('id')
}
-
- if (!id) return
-
- dispatch(removeShortcutsRequest())
-
- api(getState).delete(`/api/v1/shortcuts/${id}`).then(response => {
- dispatch(removeShortcutsSuccess(response.data.id))
- }).catch(error => dispatch(removeShortcutsFail(error)))
}
+
+ if (!id) return
+
+ dispatch(removeShortcutsRequest())
+
+ api(getState).delete(`/api/v1/shortcuts/${id}`).then(response => {
+ dispatch(removeShortcutsSuccess(response.data.id))
+ }).catch(error => dispatch(removeShortcutsFail(error)))
}
-export function removeShortcutsRequest() {
- return {
- type: SHORTCUTS_REMOVE_REQUEST,
- }
-}
+const removeShortcutsRequest = () => ({
+ type: SHORTCUTS_REMOVE_REQUEST,
+})
-export function removeShortcutsSuccess(shortcutId) {
- return {
- shortcutId,
- type: SHORTCUTS_REMOVE_SUCCESS,
- }
-}
+const removeShortcutsSuccess = (shortcutId) => ({
+ type: SHORTCUTS_REMOVE_SUCCESS,
+ shortcutId,
+})
-export function removeShortcutsFail(error) {
- return {
- error,
- type: SHORTCUTS_REMOVE_FAIL,
- }
-}
+const removeShortcutsFail = (error) => ({
+ type: SHORTCUTS_REMOVE_FAIL,
+ error,
+})
diff --git a/app/javascript/gabsocial/actions/sidebar.js b/app/javascript/gabsocial/actions/sidebar.js
index 07c62911..d9268422 100644
--- a/app/javascript/gabsocial/actions/sidebar.js
+++ b/app/javascript/gabsocial/actions/sidebar.js
@@ -1,14 +1,10 @@
export const SIDEBAR_OPEN = 'SIDEBAR_OPEN'
export const SIDEBAR_CLOSE = 'SIDEBAR_CLOSE'
-export function openSidebar() {
- return {
- type: SIDEBAR_OPEN,
- }
-}
+export const openSidebar = () => ({
+ type: SIDEBAR_OPEN,
+})
-export function closeSidebar() {
- return {
- type: SIDEBAR_CLOSE,
- }
-}
+export const closeSidebar = () => ({
+ type: SIDEBAR_CLOSE,
+})
diff --git a/app/javascript/gabsocial/actions/status_revisions.js b/app/javascript/gabsocial/actions/status_revisions.js
index ae879788..6425a381 100644
--- a/app/javascript/gabsocial/actions/status_revisions.js
+++ b/app/javascript/gabsocial/actions/status_revisions.js
@@ -4,6 +4,12 @@ export const STATUS_REVISIONS_LOAD = 'STATUS_REVISIONS_LOAD'
export const STATUS_REVISIONS_LOAD_SUCCESS = 'STATUS_REVISIONS_SUCCESS'
export const STATUS_REVISIONS_LOAD_FAIL = 'STATUS_REVISIONS_FAIL'
+export const loadStatusRevisions = (statusId) => (dispatch, getState) => {
+ api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
+ .then(res => dispatch(loadStatusRevisionsSuccess(res.data)))
+ .catch(() => dispatch(loadStatusRevisionsFail()))
+}
+
const loadStatusRevisionsSuccess = (data) => ({
type: STATUS_REVISIONS_LOAD_SUCCESS,
revisions: data,
@@ -12,12 +18,4 @@ const loadStatusRevisionsSuccess = (data) => ({
const loadStatusRevisionsFail = () => ({
type: STATUS_REVISIONS_LOAD_FAIL,
error: true,
-})
-
-export function loadStatusRevisions(statusId) {
- return (dispatch, getState) => {
- api(getState).get(`/api/v1/statuses/${statusId}/revisions`)
- .then(res => dispatch(loadStatusRevisionsSuccess(res.data)))
- .catch(() => dispatch(loadStatusRevisionsFail()))
- }
-}
\ No newline at end of file
+})
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/statuses.js b/app/javascript/gabsocial/actions/statuses.js
index d22b6df1..3c9074ae 100644
--- a/app/javascript/gabsocial/actions/statuses.js
+++ b/app/javascript/gabsocial/actions/statuses.js
@@ -22,19 +22,13 @@ export const COMMENTS_FETCH_REQUEST = 'COMMENTS_FETCH_REQUEST';
export const COMMENTS_FETCH_SUCCESS = 'COMMENTS_FETCH_SUCCESS';
export const COMMENTS_FETCH_FAIL = 'COMMENTS_FETCH_FAIL';
-export const STATUS_MUTE_REQUEST = 'STATUS_MUTE_REQUEST';
-export const STATUS_MUTE_SUCCESS = 'STATUS_MUTE_SUCCESS';
-export const STATUS_MUTE_FAIL = 'STATUS_MUTE_FAIL';
-
-export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST';
-export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
-export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
-
export const STATUS_REVEAL = 'STATUS_REVEAL';
export const STATUS_HIDE = 'STATUS_HIDE';
export const STATUS_EDIT = 'STATUS_EDIT';
+export const UPDATE_STATUS_STATS = 'UPDATE_STATUS_STATS'
+
export function fetchStatusRequest(id, skipLoading) {
return {
type: STATUS_FETCH_REQUEST,
@@ -280,78 +274,6 @@ export function fetchCommentsFail(id, error) {
};
};
-export function muteStatus(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(muteStatusRequest(id));
-
- api(getState).post(`/api/v1/statuses/${id}/mute`).then(() => {
- dispatch(muteStatusSuccess(id));
- }).catch(error => {
- dispatch(muteStatusFail(id, error));
- });
- };
-};
-
-export function muteStatusRequest(id) {
- return {
- type: STATUS_MUTE_REQUEST,
- id,
- };
-};
-
-export function muteStatusSuccess(id) {
- return {
- type: STATUS_MUTE_SUCCESS,
- id,
- };
-};
-
-export function muteStatusFail(id, error) {
- return {
- type: STATUS_MUTE_FAIL,
- id,
- error,
- };
-};
-
-export function unmuteStatus(id) {
- return (dispatch, getState) => {
- if (!me) return;
-
- dispatch(unmuteStatusRequest(id));
-
- api(getState).post(`/api/v1/statuses/${id}/unmute`).then(() => {
- dispatch(unmuteStatusSuccess(id));
- }).catch(error => {
- dispatch(unmuteStatusFail(id, error));
- });
- };
-};
-
-export function unmuteStatusRequest(id) {
- return {
- type: STATUS_UNMUTE_REQUEST,
- id,
- };
-};
-
-export function unmuteStatusSuccess(id) {
- return {
- type: STATUS_UNMUTE_SUCCESS,
- id,
- };
-};
-
-export function unmuteStatusFail(id, error) {
- return {
- type: STATUS_UNMUTE_FAIL,
- id,
- error,
- };
-};
-
export function hideStatus(ids) {
if (!Array.isArray(ids)) {
ids = [ids];
@@ -373,3 +295,10 @@ export function revealStatus(ids) {
ids,
};
};
+
+export function updateStatusStats(data) {
+ return {
+ type: UPDATE_STATUS_STATS,
+ data,
+ };
+};
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/store.js b/app/javascript/gabsocial/actions/store.js
index 0e60259f..9df1cdf7 100644
--- a/app/javascript/gabsocial/actions/store.js
+++ b/app/javascript/gabsocial/actions/store.js
@@ -1,24 +1,22 @@
-import { Iterable, fromJS } from 'immutable';
-import { hydrateCompose } from './compose';
-import { importFetchedAccounts } from './importer';
+import { Iterable, fromJS } from 'immutable'
+import { hydrateCompose } from './compose'
+import { importFetchedAccounts } from './importer'
-export const STORE_HYDRATE = 'STORE_HYDRATE';
-export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
+export const STORE_HYDRATE = 'STORE_HYDRATE'
+export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY'
-const convertState = rawState =>
- fromJS(rawState, (k, v) =>
- Iterable.isIndexed(v) ? v.toList() : v.toMap());
+const convertState = (rawState) => {
+ return fromJS(rawState, (k, v) => Iterable.isIndexed(v) ? v.toList() : v.toMap())
+}
-export function hydrateStore(rawState) {
- return (dispatch) => {
- const state = convertState(rawState);
+export const hydrateStore = (rawState) => (dispatch) => {
+ const state = convertState(rawState)
- dispatch({
- type: STORE_HYDRATE,
- state,
- });
+ dispatch({
+ type: STORE_HYDRATE,
+ state,
+ })
- dispatch(hydrateCompose());
- if (rawState.accounts) dispatch(importFetchedAccounts(Object.values(rawState.accounts)));
- };
-};
+ dispatch(hydrateCompose())
+ if (rawState.accounts) dispatch(importFetchedAccounts(Object.values(rawState.accounts)))
+}
\ No newline at end of file
diff --git a/app/javascript/gabsocial/actions/streaming.js b/app/javascript/gabsocial/actions/streaming.js
index 8b6d247d..60c6ae42 100644
--- a/app/javascript/gabsocial/actions/streaming.js
+++ b/app/javascript/gabsocial/actions/streaming.js
@@ -1,70 +1,73 @@
-import { connectStream } from '../stream';
+import { connectStream } from '../stream'
import {
deleteFromTimelines,
connectTimeline,
disconnectTimeline,
updateTimelineQueue,
-} from './timelines';
-import { updateNotificationsQueue } from './notifications';
-import { updateConversations } from './conversations';
-import { fetchFilters } from './filters';
-import { getLocale } from '../locales';
-import { handleComposeSubmit } from './compose';
+} from './timelines'
+import { updateNotificationsQueue } from './notifications'
+import { fetchFilters } from './filters'
+import { getLocale } from '../locales'
+import { handleComposeSubmit } from './compose'
-const { messages } = getLocale();
+const { messages } = getLocale()
-export function connectTimelineStream (timelineId, path, pollingRefresh = null, accept = null) {
+/**
+ *
+ */
+export const connectTimelineStream = (timelineId, path, pollingRefresh = null, accept = null) => {
return connectStream (path, pollingRefresh, (dispatch, getState) => {
- const locale = getState().getIn(['meta', 'locale']);
+ const locale = getState().getIn(['meta', 'locale'])
return {
onConnect() {
- dispatch(connectTimeline(timelineId));
+ dispatch(connectTimeline(timelineId))
},
-
onDisconnect() {
- dispatch(disconnectTimeline(timelineId));
+ dispatch(disconnectTimeline(timelineId))
},
-
onReceive (data) {
switch(data.event) {
case 'update':
- dispatch(updateTimelineQueue(timelineId, JSON.parse(data.payload), accept));
- break;
+ dispatch(updateTimelineQueue(timelineId, JSON.parse(data.payload), accept))
+ break
case 'delete':
- dispatch(deleteFromTimelines(data.payload));
- break;
+ dispatch(deleteFromTimelines(data.payload))
+ break
case 'notification':
- dispatch(updateNotificationsQueue(JSON.parse(data.payload), messages, locale, window.location.pathname));
- break;
- case 'conversation':
- dispatch(updateConversations(JSON.parse(data.payload)));
- break;
+ dispatch(updateNotificationsQueue(JSON.parse(data.payload), messages, locale, window.location.pathname))
+ break
case 'filters_changed':
- dispatch(fetchFilters());
- break;
+ dispatch(fetchFilters())
+ break
}
},
- };
- });
+ }
+ })
}
-export const connectUserStream = () => connectTimelineStream('home', 'user');
-export const connectProStream = () => connectTimelineStream('pro', 'pro');
-export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`);
-
+/**
+ *
+ */
export const connectStatusUpdateStream = () => {
+
return connectStream('statuscard', null, (dispatch, getState) => {
+
return {
onConnect() {},
onDisconnect() {},
onReceive (data) {
- if (!data['event'] || !data['payload']) return;
+ if (!data['event'] || !data['payload']) return
if (data.event === 'update') {
handleComposeSubmit(dispatch, getState, {data: JSON.parse(data.payload)}, null)
}
},
- };
- });
-}
\ No newline at end of file
+ }
+ })
+}
+
+/**
+ *
+ */
+export const connectUserStream = () => connectTimelineStream('home', 'user')
diff --git a/app/javascript/gabsocial/actions/suggestions.js b/app/javascript/gabsocial/actions/suggestions.js
index 77799ee5..efc6a21b 100644
--- a/app/javascript/gabsocial/actions/suggestions.js
+++ b/app/javascript/gabsocial/actions/suggestions.js
@@ -13,61 +13,59 @@ export const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL'
export const SUGGESTIONS_DISMISS = 'SUGGESTIONS_DISMISS'
-export function fetchPopularSuggestions() {
- return (dispatch, getState) => {
- if (!me) return false
-
- dispatch(fetchSuggestionsRequest(SUGGESTION_TYPE_VERIFIED))
-
- api(getState).get(`/api/v1/suggestions?type=${SUGGESTION_TYPE_VERIFIED}`).then(response => {
- dispatch(importFetchedAccounts(response.data))
- dispatch(fetchSuggestionsSuccess(response.data, SUGGESTION_TYPE_VERIFIED))
- dispatch(fetchRelationships(response.data.map(item => item.id)))
- }).catch(error => dispatch(fetchSuggestionsFail(error, SUGGESTION_TYPE_VERIFIED)))
- }
+/**
+ *
+ */
+export const fetchPopularSuggestions = () => (dispatch, getState) => {
+ if (!me) return false
+ fetchSuggestions(SUGGESTION_TYPE_VERIFIED, dispatch, getState)
}
-export function fetchRelatedSuggestions(unlimited = false) {
- return (dispatch, getState) => {
- if (!me) return false
-
- dispatch(fetchSuggestionsRequest(SUGGESTION_TYPE_RELATED))
-
- api(getState).get(`/api/v1/suggestions?type=${SUGGESTION_TYPE_RELATED}&unlimited=${!!unlimited}`).then(response => {
- dispatch(importFetchedAccounts(response.data))
- dispatch(fetchSuggestionsSuccess(response.data, SUGGESTION_TYPE_RELATED))
- dispatch(fetchRelationships(response.data.map(item => item.id)))
- }).catch(error => dispatch(fetchSuggestionsFail(error, SUGGESTION_TYPE_RELATED)))
- }
+/**
+ *
+ */
+export const fetchRelatedSuggestions = (unlimited = false) => (dispatch, getState) => {
+ if (!me) return false
+ fetchSuggestions(SUGGESTION_TYPE_RELATED, dispatch, getState, unlimited)
}
-export function fetchSuggestionsRequest(suggestionType) {
- return {
- type: SUGGESTIONS_FETCH_REQUEST,
- skipLoading: true,
- suggestionType,
- }
+/**
+ *
+ */
+const fetchSuggestions = (suggestionType, dispatch, getState, unlimited = false) => {
+ dispatch(fetchSuggestionsRequest(suggestionType))
+
+ api(getState).get(`/api/v1/suggestions?type=${suggestionType}&unlimited=${!!unlimited}`).then((response) => {
+ dispatch(importFetchedAccounts(response.data))
+ dispatch(fetchSuggestionsSuccess(response.data, suggestionType))
+ dispatch(fetchRelationships(response.data.map(item => item.id)))
+ }).catch(error => dispatch(fetchSuggestionsFail(error, suggestionType)))
}
-export function fetchSuggestionsSuccess(accounts, suggestionType) {
- return {
- type: SUGGESTIONS_FETCH_SUCCESS,
- skipLoading: true,
- accounts,
- suggestionType
- }
-}
+const fetchSuggestionsRequest = (suggestionType) => ({
+ type: SUGGESTIONS_FETCH_REQUEST,
+ skipLoading: true,
+ suggestionType,
+})
-export function fetchSuggestionsFail(error, suggestionType) {
- return {
- type: SUGGESTIONS_FETCH_FAIL,
- skipLoading: true,
- skipAlert: true,
- error,
- suggestionType,
- }
-}
+const fetchSuggestionsSuccess = (accounts, suggestionType) => ({
+ type: SUGGESTIONS_FETCH_SUCCESS,
+ skipLoading: true,
+ accounts,
+ suggestionType
+})
+const fetchSuggestionsFail = (error, suggestionType) => ({
+ type: SUGGESTIONS_FETCH_FAIL,
+ skipLoading: true,
+ skipAlert: true,
+ error,
+ suggestionType,
+})
+
+/**
+ *
+ */
export const dismissRelatedSuggestion = (accountId) => (dispatch, getState) => {
if (!me) return
diff --git a/app/javascript/gabsocial/actions/timeline_injections.js b/app/javascript/gabsocial/actions/timeline_injections.js
index 7d3ec55f..511f8cec 100644
--- a/app/javascript/gabsocial/actions/timeline_injections.js
+++ b/app/javascript/gabsocial/actions/timeline_injections.js
@@ -19,7 +19,7 @@ export const showTimelineInjection = (injectionId) => (dispatch) => {
export const hideTimelineInjection = (injectionId) => (dispatch, getState) => {
const existingInjectionWeight = getState().getIn(['settings', 'injections', injectionId], null)
- if (!existingInjectionWeight) return false
+ if (!existingInjectionWeight) return
const newInjectionWeight = Math.max(existingInjectionWeight - 0.005, 0.01)
diff --git a/app/javascript/gabsocial/actions/timelines.js b/app/javascript/gabsocial/actions/timelines.js
index 300bb1bf..560d4b92 100644
--- a/app/javascript/gabsocial/actions/timelines.js
+++ b/app/javascript/gabsocial/actions/timelines.js
@@ -19,13 +19,6 @@ export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
export const MAX_QUEUED_ITEMS = 40;
-const fetchStatusesAccountsRelationships = (dispatch, statuses) => {
- const accountIds = statuses.map(item => item.account.id)
- if (accountIds.length > 0) {
- dispatch(fetchRelationships(accountIds));
- }
-}
-
export function updateTimeline(timeline, status, accept) {
return dispatch => {
if (typeof accept === 'function' && !accept(status)) {
@@ -134,36 +127,34 @@ const parseTags = (tags = {}, mode) => {
});
};
-export function expandTimeline(timelineId, path, params = {}, done = noOp) {
- return (dispatch, getState) => {
- const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
- const isLoadingMore = !!params.max_id;
+export const expandTimeline = (timelineId, path, params = {}, done = noOp) => (dispatch, getState) => {
+ const timeline = getState().getIn(['timelines', timelineId], ImmutableMap())
+ const isLoadingMore = !!params.max_id
- if (timeline.get('isLoading')) {
- done();
- return;
- }
+ if (!!timeline && (timeline.get('isLoading') || timeline.get('isError'))) {
+ done()
+ return
+ }
- if (!params.max_id && !params.pinned && timeline.get('items', ImmutableList()).size > 0) {
- params.since_id = timeline.getIn(['items', 0]);
- }
+ if (!params.max_id && !params.pinned && timeline.get('items', ImmutableList()).size > 0) {
+ params.since_id = timeline.getIn(['items', 0])
+ }
- const isLoadingRecent = !!params.since_id;
+ const isLoadingRecent = !!params.since_id
- dispatch(expandTimelineRequest(timelineId, isLoadingMore));
+ dispatch(expandTimelineRequest(timelineId, isLoadingMore))
- api(getState).get(path, { params }).then(response => {
- const next = getLinks(response).refs.find(link => link.rel === 'next');
- dispatch(importFetchedStatuses(response.data));
- dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206, isLoadingRecent, isLoadingMore));
- fetchStatusesAccountsRelationships(dispatch, response.data)
- done();
- }).catch(error => {
- dispatch(expandTimelineFail(timelineId, error, isLoadingMore));
- done();
- });
- };
-};
+ api(getState).get(path, { params }).then((response) => {
+ console.log("response:", response)
+ const next = getLinks(response).refs.find(link => link.rel === 'next')
+ dispatch(importFetchedStatuses(response.data))
+ dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.code === 206, isLoadingRecent, isLoadingMore))
+ done()
+ }).catch((error) => {
+ dispatch(expandTimelineFail(timelineId, error, isLoadingMore))
+ done()
+ })
+}
export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
export const expandExploreTimeline = ({ maxId, sortBy } = {}, done = noOp) => expandTimeline('explore', '/api/v1/timelines/explore', { max_id: maxId, sort_by: sortBy }, done);
diff --git a/app/javascript/gabsocial/actions/toasts.js b/app/javascript/gabsocial/actions/toasts.js
index 4616c610..3910f75d 100644
--- a/app/javascript/gabsocial/actions/toasts.js
+++ b/app/javascript/gabsocial/actions/toasts.js
@@ -7,26 +7,29 @@ export const TOAST_SHOW = 'TOAST_SHOW'
export const TOAST_DISMISS = 'TOAST_DISMISS'
export const TOAST_CLEAR = 'TOAST_CLEAR'
-export function dismissToast(alert) {
- return {
- type: TOAST_DISMISS,
- alert,
- }
-}
+/**
+ *
+ */
+export const dismissToast = (alert) => ({
+ type: TOAST_DISMISS,
+ alert,
+})
-export function clearToast() {
- return {
- type: TOAST_CLEAR,
- }
-}
+/**
+ *
+ */
+export const clearToast = () => ({
+ type: TOAST_CLEAR,
+})
-function showToast(type, message) {
- return {
- type: TOAST_SHOW,
- toastType: type,
- message,
- }
-}
+/**
+ *
+ */
+export const showToast = (type, message) => ({
+ type: TOAST_SHOW,
+ toastType: type,
+ message,
+})
export const showToastError = (message) => {
return showToast(TOAST_TYPE_ERROR, message)
diff --git a/app/javascript/gabsocial/actions/user.js b/app/javascript/gabsocial/actions/user.js
index 4e9f93a0..67c858b9 100644
--- a/app/javascript/gabsocial/actions/user.js
+++ b/app/javascript/gabsocial/actions/user.js
@@ -11,52 +11,50 @@ export const SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS = 'SAVE_USER_PROFILE_IN
export const SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL = 'SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL'
export const RESEND_USER_CONFIRMATION_EMAIL_SUCCESS = 'RESEND_USER_CONFIRMATION_EMAIL_SUCCESS'
-export const saveUserProfileInformation = (data) => {
- return function (dispatch, getState) {
- if (!isObject(data) || !me) return
+/**
+ *
+ */
+export const saveUserProfileInformation = (data) => (dispatch, getState) => {
+ if (!isObject(data) || !me) return
- dispatch(saveUserProfileInformationRequest())
+ dispatch(saveUserProfileInformationRequest())
- const formData = new FormData()
- if (!!data.displayName) formData.append('display_name', data.displayName)
- if (data.note !== undefined) formData.append('note', data.note)
- if (data.avatar !== undefined) formData.append('avatar', data.avatar)
- if (data.header !== undefined) formData.append('header', data.header)
- if (data.locked !== undefined) formData.append('locked', data.locked)
+ const formData = new FormData()
+ if (!!data.displayName) formData.append('display_name', data.displayName)
+ if (data.note !== undefined) formData.append('note', data.note)
+ if (data.avatar !== undefined) formData.append('avatar', data.avatar)
+ if (data.header !== undefined) formData.append('header', data.header)
+ if (data.locked !== undefined) formData.append('locked', data.locked)
- api(getState).patch('/api/v1/accounts/update_credentials', formData, {
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
- }).then((response) => {
- dispatch(importFetchedAccount(response.data))
- dispatch(saveUserProfileInformationSuccess(response.data))
- }).catch(error => {
- dispatch(saveUserProfileInformationFail(error))
- })
- }
+ api(getState).patch('/api/v1/accounts/update_credentials', formData, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ }).then((response) => {
+ dispatch(importFetchedAccount(response.data))
+ dispatch(saveUserProfileInformationSuccess(response.data))
+ }).catch((error) => {
+ dispatch(saveUserProfileInformationFail(error))
+ })
}
-function saveUserProfileInformationRequest() {
- return {
- type: SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST,
- }
-}
+const saveUserProfileInformationRequest = () => ({
+ type: SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST,
+})
-function saveUserProfileInformationSuccess(userProfileData) {
- return {
- type: SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS,
- userProfileData,
- }
-}
+const saveUserProfileInformationSuccess = (userProfileData) => ({
+ type: SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS,
+ userProfileData,
+})
-function saveUserProfileInformationFail(error) {
- return {
- type: SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL,
- error,
- }
-}
+const saveUserProfileInformationFail = (error) => ({
+ type: SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL,
+ error,
+})
+/**
+ *
+ */
export const resendUserConfirmationEmail = () => (dispatch, getState) => {
if (!me || emailConfirmed) return
diff --git a/app/javascript/gabsocial/components/emoji/__tests__/emoji-test.js b/app/javascript/gabsocial/components/emoji/__tests__/emoji-test.js
deleted file mode 100644
index c8425c4c..00000000
--- a/app/javascript/gabsocial/components/emoji/__tests__/emoji-test.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import emojify from '../emoji';
-
-describe('emoji', () => {
- describe('.emojify', () => {
- it('ignores unknown shortcodes', () => {
- expect(emojify(':foobarbazfake:')).toEqual(':foobarbazfake:');
- });
-
- it('ignores shortcodes inside of tags', () => {
- expect(emojify('
')).toEqual('
');
- });
-
- it('works with unclosed tags', () => {
- expect(emojify('hello>')).toEqual('hello>');
- expect(emojify(' {
- expect(emojify('smile:')).toEqual('smile:');
- expect(emojify(':smile')).toEqual(':smile');
- });
-
- it('does unicode', () => {
- expect(emojify('\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66')).toEqual(
- ' ');
- expect(emojify('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§')).toEqual(
- ' ');
- expect(emojify('👩â€ðŸ‘©â€ðŸ‘¦')).toEqual(' ');
- expect(emojify('\u2757')).toEqual(
- ' ');
- });
-
- it('does multiple unicode', () => {
- expect(emojify('\u2757 #\uFE0F\u20E3')).toEqual(
- ' ');
- expect(emojify('\u2757#\uFE0F\u20E3')).toEqual(
- ' ');
- expect(emojify('\u2757 #\uFE0F\u20E3 \u2757')).toEqual(
- ' ');
- expect(emojify('foo \u2757 #\uFE0F\u20E3 bar')).toEqual(
- 'foo bar');
- });
-
- it('ignores unicode inside of tags', () => {
- expect(emojify('
')).toEqual('
');
- });
-
- it('does multiple emoji properly (issue 5188)', () => {
- expect(emojify('👌🌈💕')).toEqual(' ');
- expect(emojify('👌 🌈 💕')).toEqual(' ');
- });
-
- it('does an emoji that has no shortcode', () => {
- expect(emojify('ðŸ‘â€ðŸ—¨')).toEqual(' ');
- });
-
- it('does an emoji whose filename is irregular', () => {
- expect(emojify('↙ï¸')).toEqual(' ');
- });
-
- it('avoid emojifying on invisible text', () => {
- expect(emojify('http:// example.com/te st😄 '))
- .toEqual('http:// example.com/te st😄 ');
- expect(emojify(':luigi: ', { ':luigi:': { static_url: 'luigi.exe' } }))
- .toEqual(':luigi: ');
- });
-
- it('avoid emojifying on invisible text with nested tags', () => {
- expect(emojify('😄bar 😴 😇'))
- .toEqual('😄bar 😴 ');
- expect(emojify('😄😕 😴 😇'))
- .toEqual('😄😕 😴 ');
- expect(emojify('😄 😴 😇'))
- .toEqual('😄 😴 ');
- });
-
- it('skips the textual presentation VS15 character', () => {
- expect(emojify('✴︎')) // This is U+2734 EIGHT POINTED BLACK STAR then U+FE0E VARIATION SELECTOR-15
- .toEqual(' ');
- });
- });
-});
diff --git a/app/javascript/gabsocial/components/emoji/__tests__/emoji_index-test.js b/app/javascript/gabsocial/components/emoji/__tests__/emoji_index-test.js
deleted file mode 100644
index 849502d7..00000000
--- a/app/javascript/gabsocial/components/emoji/__tests__/emoji_index-test.js
+++ /dev/null
@@ -1,176 +0,0 @@
-import pick from 'lodash.pick'
-import { emojiIndex } from 'emoji-mart';
-import { search } from '../emoji_mart_search_light';
-
-const trimEmojis = emoji => pick(emoji, ['id', 'unified', 'native', 'custom']);
-
-describe('emoji_index', () => {
- it('should give same result for emoji_index_light and emoji-mart', () => {
- const expected = [
- {
- id: 'pineapple',
- unified: '1f34d',
- native: 'ðŸ',
- },
- ];
- expect(search('pineapple').map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('pineapple').map(trimEmojis)).toEqual(expected);
- });
-
- it('orders search results correctly', () => {
- const expected = [
- {
- id: 'apple',
- unified: '1f34e',
- native: 'ðŸŽ',
- },
- {
- id: 'pineapple',
- unified: '1f34d',
- native: 'ðŸ',
- },
- {
- id: 'green_apple',
- unified: '1f34f',
- native: 'ðŸ',
- },
- {
- id: 'iphone',
- unified: '1f4f1',
- native: '📱',
- },
- ];
- expect(search('apple').map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('apple').map(trimEmojis)).toEqual(expected);
- });
-
- it('can include/exclude categories', () => {
- expect(search('flag', { include: ['people'] })).toEqual([]);
- expect(emojiIndex.search('flag', { include: ['people'] })).toEqual([]);
- });
-
- it('(different behavior from emoji-mart) do not erases custom emoji if not passed again', () => {
- const custom = [
- {
- id: 'gabsocial',
- name: 'gabsocial',
- short_names: ['gabsocial'],
- text: '',
- emoticons: [],
- keywords: ['gabsocial'],
- imageUrl: 'http://example.com',
- custom: true,
- },
- ];
- search('', { custom });
- emojiIndex.search('', { custom });
- const expected = [];
- const lightExpected = [
- {
- id: 'gabsocial',
- custom: true,
- },
- ];
- expect(search('masto').map(trimEmojis)).toEqual(lightExpected);
- expect(emojiIndex.search('masto').map(trimEmojis)).toEqual(expected);
- });
-
- it('(different behavior from emoji-mart) erases custom emoji if another is passed', () => {
- const custom = [
- {
- id: 'gabsocial',
- name: 'gabsocial',
- short_names: ['gabsocial'],
- text: '',
- emoticons: [],
- keywords: ['gabsocial'],
- imageUrl: 'http://example.com',
- custom: true,
- },
- ];
- search('', { custom });
- emojiIndex.search('', { custom });
- const expected = [];
- expect(search('masto', { custom: [] }).map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('masto').map(trimEmojis)).toEqual(expected);
- });
-
- it('handles custom emoji', () => {
- const custom = [
- {
- id: 'gabsocial',
- name: 'gabsocial',
- short_names: ['gabsocial'],
- text: '',
- emoticons: [],
- keywords: ['gabsocial'],
- imageUrl: 'http://example.com',
- custom: true,
- },
- ];
- search('', { custom });
- emojiIndex.search('', { custom });
- const expected = [
- {
- id: 'gabsocial',
- custom: true,
- },
- ];
- expect(search('masto', { custom }).map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('masto', { custom }).map(trimEmojis)).toEqual(expected);
- });
-
- it('should filter only emojis we care about, exclude pineapple', () => {
- const emojisToShowFilter = emoji => emoji.unified !== '1F34D';
- expect(search('apple', { emojisToShowFilter }).map((obj) => obj.id))
- .not.toContain('pineapple');
- expect(emojiIndex.search('apple', { emojisToShowFilter }).map((obj) => obj.id))
- .not.toContain('pineapple');
- });
-
- it('does an emoji whose unified name is irregular', () => {
- const expected = [
- {
- 'id': 'water_polo',
- 'unified': '1f93d',
- 'native': '🤽',
- },
- {
- 'id': 'man-playing-water-polo',
- 'unified': '1f93d-200d-2642-fe0f',
- 'native': '🤽â€â™‚ï¸',
- },
- {
- 'id': 'woman-playing-water-polo',
- 'unified': '1f93d-200d-2640-fe0f',
- 'native': '🤽â€â™€ï¸',
- },
- ];
- expect(search('polo').map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('polo').map(trimEmojis)).toEqual(expected);
- });
-
- it('can search for thinking_face', () => {
- const expected = [
- {
- id: 'thinking_face',
- unified: '1f914',
- native: '🤔',
- },
- ];
- expect(search('thinking_fac').map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('thinking_fac').map(trimEmojis)).toEqual(expected);
- });
-
- it('can search for woman-facepalming', () => {
- const expected = [
- {
- id: 'woman-facepalming',
- unified: '1f926-200d-2640-fe0f',
- native: '🤦â€â™€ï¸',
- },
- ];
- expect(search('woman-facep').map(trimEmojis)).toEqual(expected);
- expect(emojiIndex.search('woman-facep').map(trimEmojis)).toEqual(expected);
- });
-});
diff --git a/app/javascript/gabsocial/components/image.js b/app/javascript/gabsocial/components/image.js
index 9d29e758..0906d15a 100644
--- a/app/javascript/gabsocial/components/image.js
+++ b/app/javascript/gabsocial/components/image.js
@@ -54,7 +54,7 @@ class Image extends React.PureComponent {
{
- this.setState({ loading: false, oembed: res.data })
-
- const iframeDocument = this.iframe.contentWindow.document
-
- iframeDocument.open()
- iframeDocument.write(res.data.html)
- iframeDocument.close()
-
- iframeDocument.body.style.margin = 0
- this.iframe.width = iframeDocument.body.scrollWidth
- this.iframe.height = iframeDocument.body.scrollHeight
- }).catch(error => {
- this.props.onError(error)
- })
- }
-
- setIframeRef = c => {
- this.iframe = c
- }
-
- handleTextareaClick = (e) => {
- e.target.select()
- }
-
- render() {
- const { intl, onClose } = this.props
- const { oembed } = this.state
-
- return (
-
-
-
- {intl.formatMessage(messages.instructions)}
-
-
-
-
-
-
-
-
-
- {intl.formatMessage(messages.preview)}
-
-
-
-
- {
- !oembed &&
-
- }
-
-
-
-
- )
- }
-
-}
-
-const messages = defineMessages({
- embed: { id: 'status.embed', defaultMessage: 'Embed' },
- instructions: { id: 'embed.instructions', defaultMessage: 'Embed this status on your website by copying the code below.' },
- preview: { id: 'embed.preview', defaultMessage: 'Here is what it will look like:' },
-})
-
-EmbedModal.propTypes = {
- url: PropTypes.string.isRequired,
- onClose: PropTypes.func.isRequired,
- onError: PropTypes.func.isRequired,
- intl: PropTypes.object.isRequired,
-}
-
-export default injectIntl(EmbedModal)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/components/modal/modal_root.js b/app/javascript/gabsocial/components/modal/modal_root.js
index 3a017122..58bbe5c9 100644
--- a/app/javascript/gabsocial/components/modal/modal_root.js
+++ b/app/javascript/gabsocial/components/modal/modal_root.js
@@ -17,7 +17,6 @@ import {
MODAL_EDIT_PROFILE,
MODAL_EDIT_SHORTCUTS,
MODAL_EMAIL_CONFIRMATION_REMINDER,
- MODAL_EMBED,
MODAL_GROUP_CREATE,
MODAL_GROUP_DELETE,
MODAL_GROUP_PASSWORD,
@@ -50,7 +49,6 @@ import {
EditProfileModal,
EditShortcutsModal,
EmailConfirmationReminderModal,
- EmbedModal,
GroupCreateModal,
GroupDeleteModal,
GroupMembersModal,
@@ -86,7 +84,6 @@ MODAL_COMPONENTS[MODAL_DISPLAY_OPTIONS] = DisplayOptionsModal
MODAL_COMPONENTS[MODAL_EDIT_SHORTCUTS] = EditShortcutsModal
MODAL_COMPONENTS[MODAL_EDIT_PROFILE] = EditProfileModal
MODAL_COMPONENTS[MODAL_EMAIL_CONFIRMATION_REMINDER] = EmailConfirmationReminderModal
-MODAL_COMPONENTS[MODAL_EMBED] = EmbedModal
MODAL_COMPONENTS[MODAL_GROUP_CREATE] = GroupCreateModal
MODAL_COMPONENTS[MODAL_GROUP_DELETE] = GroupDeleteModal
MODAL_COMPONENTS[MODAL_GROUP_PASSWORD] = GroupPasswordModal
diff --git a/app/javascript/gabsocial/components/panel/media_gallery_panel.js b/app/javascript/gabsocial/components/panel/media_gallery_panel.js
index f74be368..f5835fcd 100644
--- a/app/javascript/gabsocial/components/panel/media_gallery_panel.js
+++ b/app/javascript/gabsocial/components/panel/media_gallery_panel.js
@@ -12,19 +12,38 @@ import MediaGalleryPanelPlaceholder from '../placeholder/media_gallery_panel_pla
class MediaGalleryPanel extends ImmutablePureComponent {
+ state = {
+ fetched: false,
+ }
+
+ static getDerivedStateFromProps(nextProps, prevState) {
+ if (nextProps.shouldLoad && !prevState.fetched) {
+ return { fetched: true }
+ }
+
+ return null
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if (!prevState.fetched && this.state.fetched && this.props.isLazy) {
+ this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { limit: 8 }))
+ }
+ }
+
componentDidMount() {
- const { accountId } = this.props
+ const { accountId, isLazy } = this.props
- if (accountId && accountId !== -1) {
+ if (!isLazy && !!accountId && accountId !== -1) {
this.props.dispatch(expandAccountMediaTimeline(accountId, { limit: 8 }))
+ this.setState({ fetched: true })
}
}
- componentWillReceiveProps(nextProps) {
- if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
- this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, { limit: 8 }))
- }
- }
+ // componentWillReceiveProps(nextProps) {
+ // if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
+ // this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, { limit: 8 }))
+ // }
+ // }
render() {
const {
@@ -33,8 +52,9 @@ class MediaGalleryPanel extends ImmutablePureComponent {
intl,
isLoading,
} = this.props
+ const { fetched } = this.state
- if (!attachments) return null
+ if (!attachments && fetched) return null
return (
diff --git a/app/javascript/gabsocial/components/popover/status_options_popover.js b/app/javascript/gabsocial/components/popover/status_options_popover.js
index 702b0677..f11b468d 100644
--- a/app/javascript/gabsocial/components/popover/status_options_popover.js
+++ b/app/javascript/gabsocial/components/popover/status_options_popover.js
@@ -14,8 +14,6 @@ import {
unbookmark,
} from '../../actions/interactions';
import {
- muteStatus,
- unmuteStatus,
deleteStatus,
editStatus,
} from '../../actions/statuses';
@@ -27,7 +25,6 @@ import {
pinGroupStatus,
unpinGroupStatus,
} from '../../actions/groups'
-import { initMuteModal } from '../../actions/mutes'
import { initReport } from '../../actions/reports'
import { openModal } from '../../actions/modal'
import {
@@ -35,7 +32,6 @@ import {
openPopover,
} from '../../actions/popover'
import {
- MODAL_EMBED,
MODAL_PRO_UPGRADE,
POPOVER_STATUS_SHARE,
} from '../../constants'
@@ -57,13 +53,12 @@ class StatusOptionsPopover extends ImmutablePureComponent {
componentDidMount() {
if (!this.props.groupRelationships && this.props.groupId) {
this.props.onFetchGroupRelationships(this.props.groupId)
+ // : todo :
+ // check if pin
+ // check if bookmark
}
}
- handleConversationMuteClick = () => {
- this.props.onMuteConversation(this.props.status)
- }
-
handleGroupRemoveAccount = () => {
const { status } = this.props
@@ -144,15 +139,6 @@ class StatusOptionsPopover extends ImmutablePureComponent {
let menu = []
if (me) {
- if (status.getIn(['account', 'id']) === me) {
- menu.push({
- icon: 'audio-mute',
- hideArrow: true,
- title: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation),
- onClick: this.handleConversationMuteClick,
- })
- }
-
if (isReply) {
menu.push({
icon: 'repost',
@@ -296,8 +282,6 @@ const messages = defineMessages({
cannot_quote: { id: 'status.cannot_quote', defaultMessage: 'This post cannot be quoted' },
like: { id: 'status.like', defaultMessage: 'Like' },
report: { id: 'status.report', defaultMessage: 'Report @{name}' },
- muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' },
- unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
pin: { id: 'status.pin', defaultMessage: 'Pin on profile' },
unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' },
groupPin: { id: 'status.group_pin', defaultMessage: 'Pin in group' },
@@ -327,16 +311,6 @@ const mapStateToProps = (state, { status }) => {
const mapDispatchToProps = (dispatch) => ({
- onMuteConversation(status) {
- dispatch(closePopover())
-
- if (status.get('muted')) {
- dispatch(unmuteStatus(status.get('id')))
- } else {
- dispatch(muteStatus(status.get('id')))
- }
- },
-
onPin(status) {
dispatch(closePopover())
@@ -411,11 +385,6 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(editStatus(status))
},
- onMute(account) {
- dispatch(closePopover())
- dispatch(initMuteModal(account))
- },
-
onBlock(status) {
dispatch(closePopover())
const account = status.get('account')
@@ -480,11 +449,9 @@ StatusOptionsPopover.propTypes = {
onMute: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired,
onReport: PropTypes.func.isRequired,
- onMuteConversation: PropTypes.func.isRequired,
onPin: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
onFetchGroupRelationships: PropTypes.func.isRequired,
- onOpenEmbedModal: PropTypes.func.isRequired,
onOpenProUpgradeModal: PropTypes.func.isRequired,
onClosePopover: PropTypes.func.isRequired,
isXS: PropTypes.bool,
diff --git a/app/javascript/gabsocial/components/sidebar/default_sidebar.js b/app/javascript/gabsocial/components/sidebar/default_sidebar.js
index ea9c0b51..1098893e 100644
--- a/app/javascript/gabsocial/components/sidebar/default_sidebar.js
+++ b/app/javascript/gabsocial/components/sidebar/default_sidebar.js
@@ -82,6 +82,7 @@ class DefaultSidebar extends ImmutablePureComponent {
+
diff --git a/app/javascript/gabsocial/components/tab_bar_item.js b/app/javascript/gabsocial/components/tab_bar_item.js
index b5694d53..2bee0758 100644
--- a/app/javascript/gabsocial/components/tab_bar_item.js
+++ b/app/javascript/gabsocial/components/tab_bar_item.js
@@ -52,7 +52,7 @@ class TabBarItem extends React.PureComponent {
// Combine state, props, location to make absolutely
// sure of active status.
- const active = isActive || (to === location.pathname && !location.search) || isCurrent
+ const active = (isActive === true || isCurrent || (to === location.pathname && !location.search))
const containerClasses = CX({
d: 1,
diff --git a/app/javascript/gabsocial/components/toast.js b/app/javascript/gabsocial/components/toast.js
new file mode 100644
index 00000000..4d75fe02
--- /dev/null
+++ b/app/javascript/gabsocial/components/toast.js
@@ -0,0 +1,125 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import {
+ CX,
+ TOAST_TYPE_ERROR,
+ TOAST_TYPE_SUCCESS,
+ // TOAST_TYPE_NOTIFICATION,
+} from '../constants'
+import Button from './button'
+import Image from './image'
+import RelativeTimestamp from './relative_timestamp'
+import Text from './text'
+
+class Toast extends React.PureComponent {
+
+ componentDidMount() {
+ this._timer = setTimeout(() => {
+ this.handleOnDismiss()
+ }, 5000)
+ }
+
+ componentWillUnmount() {
+ clearTimeout(this._timer)
+ }
+
+ handleOnDismiss = () => {
+ this.props.onDismiss(this.props.id)
+ }
+
+ render() {
+ const {
+ image,
+ isImageAccount,
+ title,
+ message,
+ date,
+ to,
+ type,
+ } = this.props
+
+ const contentClasses = CX({
+ default: 1,
+ mt5: 1,
+ pt2: 1,
+ maxWidth240PX: 1,
+ flexRow: !!image,
+ })
+
+ const innerContentClasses = CX({
+ default: 1,
+ flexNormal: 1,
+ pl10: !!image,
+ pt2: !!image,
+ displayInline: !!date && !image,
+ })
+
+ const imageClasses = CX({
+ radiusSmall: !isImageAccount,
+ circle: isImageAccount,
+ })
+
+ const dateClasses = CX({
+ mr5: 1,
+ mt2: !!image,
+ })
+
+ return (
+
+
+
+ {title}
+
+
+
+
+ {
+ !!image &&
+
+ }
+
+
+ {message}
+
+ {
+ date &&
+
+
+
+ }
+
+
+
+ )
+ }
+
+}
+
+Toast.propTypes = {
+ date: PropTypes.string.isRequired,
+ image: PropTypes.string,
+ isImageAccount: PropTypes.bool,
+ id: PropTypes.string.isRequired,
+ message: PropTypes.string.isRequired,
+ onDismiss: PropTypes.func.isRequired,
+ title: PropTypes.string.isRequired,
+ to: PropTypes.string,
+ type: PropTypes.oneOf([
+ TOAST_TYPE_ERROR,
+ TOAST_TYPE_SUCCESS,
+ ]).isRequired,
+}
+
+export default Toast
\ No newline at end of file
diff --git a/app/javascript/gabsocial/constants.js b/app/javascript/gabsocial/constants.js
index 678272f3..42c517f8 100644
--- a/app/javascript/gabsocial/constants.js
+++ b/app/javascript/gabsocial/constants.js
@@ -11,6 +11,8 @@ export const BREAKPOINT_MEDIUM = 1160
export const BREAKPOINT_SMALL = 1080
export const BREAKPOINT_EXTRA_SMALL = 992
+export const LAZY_LOAD_SCROLL_OFFSET = 50
+
export const ALLOWED_AROUND_SHORT_CODE = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'
export const MAX_POST_CHARACTER_COUNT = 3000
@@ -48,7 +50,6 @@ export const MODAL_DISPLAY_OPTIONS = 'DISPLAY_OPTIONS'
export const MODAL_EDIT_PROFILE = 'EDIT_PROFILE'
export const MODAL_EDIT_SHORTCUTS = 'EDIT_SHORTCUTS'
export const MODAL_EMAIL_CONFIRMATION_REMINDER = 'EMAIL_CONFIRMATION_REMINDER'
-export const MODAL_EMBED = 'EMBED'
export const MODAL_GROUP_CREATE = 'GROUP_CREATE'
export const MODAL_GROUP_DELETE = 'GROUP_DELETE'
export const MODAL_GROUP_PASSWORD = 'GROUP_PASSWORD'
diff --git a/app/javascript/gabsocial/containers/toasts_container.js b/app/javascript/gabsocial/containers/toasts_container.js
new file mode 100644
index 00000000..c497c828
--- /dev/null
+++ b/app/javascript/gabsocial/containers/toasts_container.js
@@ -0,0 +1,67 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { getToasts } from '../selectors'
+import { dismissToast } from '../actions/toasts'
+import { CX } from '../constants'
+import Toast from '../components/toast'
+
+class ToastsContainer extends React.PureComponent {
+
+ handleOnDismiss = (key) => {
+ this.props.dispatch(dismissToast(key))
+ }
+
+ render() {
+ const { notifications } = this.props
+ const hasNotifications = Array.isArray(notifications) && notifications.length > 0
+
+ const containerClasses = CX({
+ default: 1,
+ z5: 1,
+ posFixed: 1,
+ bottom0: 1,
+ left0: 1,
+ pl15: 1,
+ pt15: 1,
+ heightMax100VH: 1,
+ pb10: 1,
+ displayNone: !hasNotifications
+ })
+
+ return (
+
+ {
+ hasNotifications && notifications.map((notification) => (
+
+ ))
+ }
+
+ )
+
+ }
+
+}
+
+const mapStateToProps = (state) => {
+ const notifications = getToasts(state)
+ if (!notifications) return {}
+ return { notifications }
+}
+
+ToastsContainer.propTypes = {
+ notifications: PropTypes.array,
+}
+
+export default connect(mapStateToProps)(ToastsContainer)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/introduction.js b/app/javascript/gabsocial/features/introduction.js
index e3b608f3..dfff01e2 100644
--- a/app/javascript/gabsocial/features/introduction.js
+++ b/app/javascript/gabsocial/features/introduction.js
@@ -10,7 +10,7 @@ import {
GAB_COM_INTRODUCE_YOURSELF_GROUP_ID,
} from '../constants'
import { me } from '../initial_state'
-import { saveShownOnboarding } from '../actions/onboarding'
+import { saveShownOnboarding } from '../actions/settings'
import { fetchGroups } from '../actions/groups'
import { saveUserProfileInformation } from '../actions/user'
import { makeGetAccount } from '../selectors'
diff --git a/app/javascript/gabsocial/features/list_timeline.js b/app/javascript/gabsocial/features/list_timeline.js
index 3dc52f54..a3bfca76 100644
--- a/app/javascript/gabsocial/features/list_timeline.js
+++ b/app/javascript/gabsocial/features/list_timeline.js
@@ -4,7 +4,6 @@ import { connect } from 'react-redux'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { FormattedMessage } from 'react-intl'
-import { connectListStream } from '../actions/streaming'
import { expandListTimeline } from '../actions/timelines'
import { fetchList, deleteList } from '../actions/lists'
import { openModal } from '../actions/modal'
@@ -29,7 +28,6 @@ class ListTimeline extends ImmutablePureComponent {
componentWillReceiveProps(nextProps) {
if (nextProps.params.id !== this.props.params.id) {
- this.handleDisconnect()
this.handleConnect(nextProps.params.id)
}
}
@@ -39,15 +37,6 @@ class ListTimeline extends ImmutablePureComponent {
dispatch(fetchList(id))
dispatch(expandListTimeline(id))
-
- this.disconnect = dispatch(connectListStream(id))
- }
-
- handleDisconnect() {
- if (this.disconnect) {
- this.disconnect()
- this.disconnect = null
- }
}
handleLoadMore = (maxId) => {
diff --git a/app/javascript/gabsocial/features/messages/components/message_item.js b/app/javascript/gabsocial/features/messages/components/message_item.js
new file mode 100644
index 00000000..85a739f1
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/components/message_item.js
@@ -0,0 +1,116 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import ImmutablePureComponent from 'react-immutable-pure-component'
+import ImmutablePropTypes from 'react-immutable-proptypes'
+import { NavLink } from 'react-router-dom'
+import { CX } from '../../../constants'
+import Input from '../../../components/input'
+import Avatar from '../../../components/avatar'
+import Button from '../../../components/button'
+import Text from '../../../components/text'
+import RelativeTimestamp from '../../../components/relative_timestamp'
+import { makeGetAccount } from '../../../selectors'
+
+class MessagesItem extends ImmutablePureComponent {
+
+ static contextTypes = {
+ router: PropTypes.object,
+ }
+
+ state = {
+ hovering: false,
+ }
+
+ handleOnMouseEnter = () => {
+ this.setState({ isHovering: true })
+ }
+
+ handleOnMouseLeave = () => {
+ this.setState({ isHovering: false })
+ }
+
+ render() {
+ const {
+ account,
+ intl,
+ alt,
+ } = this.props
+ const { isHovering } = this.state
+
+ const content = { __html: 'REEEE i heard you have the sauce2?' }
+ const messageContainerClasses = CX({
+ d: 1,
+ flexRow: !alt,
+ flexRowReverse: alt,
+ })
+ const messageInnerContainerClasses = CX({
+ d: 1,
+ px15: 1,
+ py5: 1,
+ bgSecondary: !alt,
+ bgBrandLight: alt,
+ circle: 1,
+ ml10: 1,
+ mr10: 1,
+ })
+
+ const lowerContainerClasses = CX({
+ d: 1,
+ pt10: 1,
+ pl50: !alt,
+ pr50: alt,
+ })
+
+ const buttonContainerClasses = CX({
+ d: 1,
+ flexRow: 1,
+ displayNone: !isHovering,
+ })
+
+ return (
+
+
+
+
+
+
+ Apr 16, 2020, 8:20 AM
+ { /* */ }
+
+
+
+
+ )
+ }
+
+}
+
+const mapStateToProps = (state, props) => ({
+ account: makeGetAccount()(state, '1'),
+})
+
+MessagesItem.propTypes = {
+ intl: PropTypes.object.isRequired,
+ alt: PropTypes.bool,
+}
+
+export default connect(mapStateToProps)(MessagesItem)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/messages/components/messages_header.js b/app/javascript/gabsocial/features/messages/components/messages_header.js
new file mode 100644
index 00000000..1d51fcf4
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/components/messages_header.js
@@ -0,0 +1,47 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import ImmutablePureComponent from 'react-immutable-pure-component'
+import ImmutablePropTypes from 'react-immutable-proptypes'
+import Heading from '../../../components/heading'
+import Button from '../../../components/button'
+
+class MessagesHeader extends ImmutablePureComponent {
+
+ render() {
+ const {
+ account,
+ } = this.props
+
+ return (
+
+
+
+ Messages
+
+
+
+ New
+
+
+
+
+
+ )
+ }
+
+}
+
+export default MessagesHeader
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/messages/components/messages_list.js b/app/javascript/gabsocial/features/messages/components/messages_list.js
new file mode 100644
index 00000000..4fea864d
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/components/messages_list.js
@@ -0,0 +1,36 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import ImmutablePureComponent from 'react-immutable-pure-component'
+import ImmutablePropTypes from 'react-immutable-proptypes'
+import MessagesListItem from './messages_list_item'
+import { makeGetAccount } from '../../../selectors'
+
+class MessagesList extends ImmutablePureComponent {
+
+ render() {
+ const {
+ account,
+ } = this.props
+
+ return (
+
+
+
+
+
+
+ )
+ }
+
+}
+
+const mapStateToProps = (state, props) => ({
+ account: makeGetAccount()(state, '1'),
+})
+
+MessagesList.propTypes = {
+ intl: PropTypes.object.isRequired,
+}
+
+export default connect(mapStateToProps)(MessagesList)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/messages/components/messages_list_item.js b/app/javascript/gabsocial/features/messages/components/messages_list_item.js
new file mode 100644
index 00000000..36cf40b2
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/components/messages_list_item.js
@@ -0,0 +1,107 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import ImmutablePureComponent from 'react-immutable-pure-component'
+import ImmutablePropTypes from 'react-immutable-proptypes'
+import { NavLink } from 'react-router-dom'
+import { CX } from '../../../constants'
+import Input from '../../../components/input'
+import DisplayName from '../../../components/display_name'
+import Avatar from '../../../components/avatar'
+import Text from '../../../components/text'
+import RelativeTimestamp from '../../../components/relative_timestamp'
+import { makeGetAccount } from '../../../selectors'
+
+class MessagesListItem extends ImmutablePureComponent {
+
+ static contextTypes = {
+ router: PropTypes.object,
+ }
+
+ state = {
+ composeFocused: false,
+ }
+
+ render() {
+ const {
+ account,
+ intl,
+ selected,
+ } = this.props
+
+ const buttonClasses = CX({
+ d: 1,
+ pt2: 1,
+ pr5: 1,
+ noUnderline: 1,
+ overflowHidden: 1,
+ flexNormal: 1,
+ flexRow: 1,
+ aiStart: 1,
+ aiCenter: 1,
+ })
+
+ const containerClasses = CX({
+ d: 1,
+ bgSubtle_onHover: 1,
+ borderBottom1PX: 1,
+ borderColorSecondary: 1,
+ noUnderline: 1,
+ })
+
+ const innerContainerClasses = CX({
+ d: 1,
+ flexRow: 1,
+ aiStart: 1,
+ aiCenter: 0,
+ px15: 1,
+ py15: 1,
+ borderRight4PX: selected,
+ borderColorBrand: selected,
+ })
+
+ const avatarSize = 49
+ const content = { __html: 'REEEE i heard you have the sauce?' }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ May 1
+ { /* */ }
+
+
+
+
+
+
+
+
+ )
+ }
+
+}
+
+const mapStateToProps = (state, props) => ({
+ account: makeGetAccount()(state, '1'),
+})
+
+MessagesListItem.propTypes = {
+ intl: PropTypes.object.isRequired,
+ selected: PropTypes.bool,
+}
+
+export default connect(mapStateToProps)(MessagesListItem)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/messages/components/messages_search.js b/app/javascript/gabsocial/features/messages/components/messages_search.js
new file mode 100644
index 00000000..91345a95
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/components/messages_search.js
@@ -0,0 +1,45 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { defineMessages, injectIntl } from 'react-intl'
+import ImmutablePureComponent from 'react-immutable-pure-component'
+import ImmutablePropTypes from 'react-immutable-proptypes'
+import Input from '../../../components/input'
+
+class MessagesSearch extends ImmutablePureComponent {
+
+ static contextTypes = {
+ router: PropTypes.object,
+ }
+
+ state = {
+ composeFocused: false,
+ }
+
+ render() {
+ const {
+ intl,
+ } = this.props
+
+ return (
+
+
+
+ )
+ }
+
+}
+
+const messages = defineMessages({
+ placeholder: { id: 'compose_form.placeholder', defaultMessage: "What's on your mind?" },
+})
+
+MessagesSearch.propTypes = {
+ intl: PropTypes.object.isRequired,
+}
+
+export default injectIntl(MessagesSearch)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/messages/index.js b/app/javascript/gabsocial/features/messages/index.js
new file mode 100644
index 00000000..508230fe
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/index.js
@@ -0,0 +1 @@
+export { default } from './messages'
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/messages/messages.js b/app/javascript/gabsocial/features/messages/messages.js
new file mode 100644
index 00000000..434e1607
--- /dev/null
+++ b/app/javascript/gabsocial/features/messages/messages.js
@@ -0,0 +1,103 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { makeGetAccount } from '../../selectors'
+import Text from '../../components/text'
+import Button from '../../components/button'
+import Avatar from '../../components/avatar'
+import DisplayName from '../../components/display_name'
+import Input from '../../components/input'
+import EmojiPickerButton from '../compose/components/emoji_picker_button'
+import UploadButton from '../compose/components/media_upload_button'
+import MessageItem from './components/message_item'
+
+// import MessagesContainer from './containers/messages_container'
+
+class Messages extends React.PureComponent {
+
+ render () {
+ const { account } = this.props
+
+ const selectedMessage = true
+
+ return (
+
+ {
+ !selectedMessage &&
+
+
+ You don’t have a message selected
+
+
+ Choose one from your existing messages, or start a new one.
+
+
+
+ New Message
+
+
+
+ }
+ {
+ selectedMessage &&
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+ )
+ }
+
+}
+
+const mapStateToProps = (state, props) => ({
+ account: makeGetAccount()(state, '1'),
+})
+
+Messages.propTypes = {
+ intl: PropTypes.object.isRequired,
+ selected: PropTypes.bool,
+}
+
+export default connect(mapStateToProps)(Messages)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/news.js b/app/javascript/gabsocial/features/news.js
index f2934fc2..067627cc 100644
--- a/app/javascript/gabsocial/features/news.js
+++ b/app/javascript/gabsocial/features/news.js
@@ -3,7 +3,10 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import throttle from 'lodash.throttle'
import { fetchPopularLinks } from '../actions/links'
-import { BREAKPOINT_EXTRA_SMALL } from '../constants'
+import {
+ BREAKPOINT_EXTRA_SMALL,
+ LAZY_LOAD_SCROLL_OFFSET,
+} from '../constants'
import Button from '../components/button'
import Text from '../components/text'
import TrendsItem from '../components/trends_item'
@@ -46,14 +49,12 @@ class News extends React.PureComponent {
if (this.window) {
const { scrollTop } = this.documentElement
- if (scrollTop > 25 && !this.state.lazyLoaded) {
+ if (scrollTop > LAZY_LOAD_SCROLL_OFFSET && !this.state.lazyLoaded) {
this.setState({ lazyLoaded: true })
this.detachScrollListener()
}
}
- }, 150, {
- trailing: true,
- })
+ }, 150, { trailing: true })
render() {
const { children } = this.props
diff --git a/app/javascript/gabsocial/features/pro_timeline.js b/app/javascript/gabsocial/features/pro_timeline.js
index e1f3706f..39e0c4c0 100644
--- a/app/javascript/gabsocial/features/pro_timeline.js
+++ b/app/javascript/gabsocial/features/pro_timeline.js
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { defineMessages, injectIntl } from 'react-intl'
import { expandProTimeline } from '../actions/timelines'
-import { connectProStream } from '../actions/streaming'
import StatusList from '../components/status_list'
class ProTimeline extends React.PureComponent {
@@ -16,15 +15,6 @@ class ProTimeline extends React.PureComponent {
const { dispatch } = this.props
dispatch(expandProTimeline())
-
- this.disconnect = dispatch(connectProStream())
- }
-
- componentWillUnmount() {
- if (this.disconnect) {
- this.disconnect()
- this.disconnect = null
- }
}
handleLoadMore = (maxId) => {
diff --git a/app/javascript/gabsocial/features/search.js b/app/javascript/gabsocial/features/search.js
index bc0207fd..26f7d617 100644
--- a/app/javascript/gabsocial/features/search.js
+++ b/app/javascript/gabsocial/features/search.js
@@ -6,7 +6,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import { withRouter } from 'react-router-dom'
import { me } from '../initial_state'
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
-import HashtagItem from '../components/hashtag_item'
import GroupListItem from '../components/group_list_item'
import Text from '../components/text'
import Account from '../components/account'
@@ -60,14 +59,13 @@ class Search extends ImmutablePureComponent {
const pathname = location.pathname || ''
const showPeople = pathname === '/search/people'
- const showHashtags = pathname === '/search/hashtags'
const showGroups = pathname === '/search/groups'
const showStatuses = pathname === '/search/statuses'
const showLinks = pathname === '/search/links'
- const isTop = !showPeople && !showHashtags && !showGroups && !showStatuses && !showLinks
+ const isTop = !showPeople && !showGroups && !showStatuses && !showLinks
const theLimit = 4
- let accounts, statuses, hashtags, groups, links
+ let accounts, statuses, groups, links
if (results.get('accounts') && results.get('accounts').size > 0 && (isTop || showPeople)) {
const size = isTop ? Math.min(results.get('accounts').size, theLimit) : results.get('accounts').size;
@@ -192,30 +190,7 @@ class Search extends ImmutablePureComponent {
)
}
- if (results.get('hashtags') && results.get('hashtags').size > 0 && me && (isTop || showHashtags)) {
- const size = isTop ? Math.min(results.get('hashtags').size, theLimit) : results.get('hashtags').size;
- const isMax = size === results.get('hashtags').size
-
- hashtags = (
-
-
-
- Showing {size} of {results.get('hashtags').size} results
-
-
- {results.get('hashtags').slice(0, size).map(hashtag => )}
-
- )
- }
-
- if (!accounts && !statuses && !hashtags && !groups && !links) {
+ if (!accounts && !statuses && !groups && !links) {
return (
@@ -231,7 +206,6 @@ class Search extends ImmutablePureComponent {
{groups}
{statuses}
{links}
- {hashtags}
)
}
diff --git a/app/javascript/gabsocial/features/ui/ui.js b/app/javascript/gabsocial/features/ui/ui.js
index 0f7fc7f2..0000ffbc 100644
--- a/app/javascript/gabsocial/features/ui/ui.js
+++ b/app/javascript/gabsocial/features/ui/ui.js
@@ -23,6 +23,7 @@ import { clearHeight } from '../../actions/height_cache'
import { openModal } from '../../actions/modal'
import WrappedRoute from './util/wrapped_route'
import ModalRoot from '../../components/modal/modal_root'
+import ToastsContainer from '../../containers/toasts_container'
import PopoverRoot from '../../components/popover/popover_root'
import UploadArea from '../../components/upload_area'
import ProfilePage from '../../pages/profile_page'
@@ -45,6 +46,8 @@ import ExplorePage from '../../pages/explore_page'
import NewsPage from '../../pages/news_page'
import AboutPage from '../../pages/about_page'
import LinkPage from '../../pages/link_page'
+import MessagesPage from '../../pages/messages_page'
+import ComposePage from '../../pages/compose_page'
import {
About,
@@ -83,6 +86,7 @@ import {
ListsDirectory,
ListEdit,
ListTimeline,
+ Messages,
Mutes,
News,
NewsView,
@@ -190,12 +194,14 @@ class SwitchingArea extends React.PureComponent {
-
-
+
+
+
+
@@ -234,7 +240,6 @@ class SwitchingArea extends React.PureComponent {
-
@@ -593,6 +598,8 @@ class UI extends React.PureComponent {
+
+
)
}
diff --git a/app/javascript/gabsocial/features/ui/util/async_components.js b/app/javascript/gabsocial/features/ui/util/async_components.js
index 5986548e..34c37689 100644
--- a/app/javascript/gabsocial/features/ui/util/async_components.js
+++ b/app/javascript/gabsocial/features/ui/util/async_components.js
@@ -20,7 +20,6 @@ export function DMCA() { return import(/* webpackChunkName: "features/about/dmca
export function EditProfileModal() { return import(/* webpackChunkName: "components/edit_profile_modal" */'../../../components/modal/edit_profile_modal') }
export function EditShortcutsModal() { return import(/* webpackChunkName: "components/edit_shortcuts_modal" */'../../../components/modal/edit_shortcuts_modal') }
export function EmailConfirmationReminderModal() { return import(/* webpackChunkName: "components/email_confirmation_reminder_modal" */'../../../components/modal/email_confirmation_reminder_modal') }
-export function EmbedModal() { return import(/* webpackChunkName: "modals/embed_modal" */'../../../components/modal/embed_modal') }
export function EmojiPicker() { return import(/* webpackChunkName: "emoji_picker" */'../../../components/emoji/emoji_picker') }
export function EmojiPickerPopover() { return import(/* webpackChunkName: "components/emoji_picker_popover" */'../../../components/popover/emoji_picker_popover') }
export function ExploreTimeline() { return import(/* webpackChunkName: "features/explore_timeline" */'../../explore_timeline') }
diff --git a/app/javascript/gabsocial/initial_state.js b/app/javascript/gabsocial/initial_state.js
index 66d84a9e..9b6faa1b 100644
--- a/app/javascript/gabsocial/initial_state.js
+++ b/app/javascript/gabsocial/initial_state.js
@@ -20,7 +20,6 @@ export const isStaff = getMeta('is_staff');
export const unreadCount = getMeta('unread_count');
export const lastReadNotificationId = getMeta('last_read_notification_id');
export const monthlyExpensesComplete = getMeta('monthly_expenses_complete');
-export const favouritesCount = getMeta('favourites_count');
export const isFirstSession = getMeta('is_first_session');
export const emailConfirmed = getMeta('email_confirmed');
export const meEmail = getMeta('email');
diff --git a/app/javascript/gabsocial/layouts/explore_layout.js b/app/javascript/gabsocial/layouts/explore_layout.js
index be3313ae..63240f42 100644
--- a/app/javascript/gabsocial/layouts/explore_layout.js
+++ b/app/javascript/gabsocial/layouts/explore_layout.js
@@ -5,7 +5,10 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
import throttle from 'lodash.throttle'
import Sticky from 'react-stickynode'
import { me } from '../initial_state'
-import { BREAKPOINT_EXTRA_SMALL } from '../constants'
+import {
+ BREAKPOINT_EXTRA_SMALL,
+ LAZY_LOAD_SCROLL_OFFSET,
+} from '../constants'
import Layout from './layout'
import SidebarPanelGroup from '../components/sidebar_panel_group'
import Responsive from '../features/ui/util/responsive_component'
@@ -43,14 +46,12 @@ class ExploreLayout extends ImmutablePureComponent {
if (this.window) {
const { scrollTop } = this.documentElement
- if (scrollTop > 25 && !this.state.lazyLoaded) {
+ if (scrollTop > LAZY_LOAD_SCROLL_OFFSET && !this.state.lazyLoaded) {
this.setState({ lazyLoaded: true })
this.detachScrollListener()
}
}
- }, 150, {
- trailing: true,
- })
+ }, 150, { trailing: true })
render() {
const { children, title } = this.props
@@ -67,7 +68,7 @@ class ExploreLayout extends ImmutablePureComponent {
,
]
if (!!me) {
- layout.push( )
+ layout.push( )
}
layout.push( )
diff --git a/app/javascript/gabsocial/layouts/layout.js b/app/javascript/gabsocial/layouts/layout.js
index 4fa39c63..455dc0ad 100644
--- a/app/javascript/gabsocial/layouts/layout.js
+++ b/app/javascript/gabsocial/layouts/layout.js
@@ -40,13 +40,15 @@ class Layout extends React.PureComponent {
title,
} = this.props
+ const noPaddingPages = ['group', 'messages']
+ const hasPadding = noPaddingPages.indexOf(page) === -1
const mainBlockClasses = CX({
d: 1,
w1015PX: 1,
flexRow: 1,
jcEnd: 1,
- py15: page !== 'group',
- pb15: page === 'group',
+ py15: hasPadding,
+ pb15: hasPadding,
})
return (
diff --git a/app/javascript/gabsocial/layouts/messages_layout.js b/app/javascript/gabsocial/layouts/messages_layout.js
new file mode 100644
index 00000000..aa010769
--- /dev/null
+++ b/app/javascript/gabsocial/layouts/messages_layout.js
@@ -0,0 +1,96 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import ImmutablePropTypes from 'react-immutable-proptypes'
+import ImmutablePureComponent from 'react-immutable-pure-component'
+import { me } from '../initial_state'
+import {
+ CX,
+ BREAKPOINT_EXTRA_SMALL,
+} from '../constants'
+import Layout from './layout'
+import Responsive from '../features/ui/util/responsive_component'
+import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
+import MessagesSearch from '../features/messages/components/messages_search'
+import MessagesList from '../features/messages/components/messages_list'
+import MessagesHeader from '../features/messages/components/messages_header'
+
+class MessagesLayout extends ImmutablePureComponent {
+
+ render() {
+ const {
+ children,
+ showBackBtn,
+ title,
+ } = this.props
+
+ const mainBlockClasses = CX({
+ d: 1,
+ w1015PX: 1,
+ h100PC: 1,
+ flexRow: 1,
+ jcEnd: 1,
+ })
+
+ return (
+
+
+
+
+
+
+
+
+
+ { /* */ }
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+
+}
+
+MessagesLayout.propTypes = {
+ children: PropTypes.node,
+ showBackBtn: PropTypes.bool,
+ title: PropTypes.string,
+}
+
+export default MessagesLayout
\ No newline at end of file
diff --git a/app/javascript/gabsocial/layouts/profile_layout.js b/app/javascript/gabsocial/layouts/profile_layout.js
index 769bfc6f..c34c99f7 100644
--- a/app/javascript/gabsocial/layouts/profile_layout.js
+++ b/app/javascript/gabsocial/layouts/profile_layout.js
@@ -4,8 +4,12 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import Sticky from 'react-stickynode'
+import throttle from 'lodash.throttle'
import { me } from '../initial_state'
-import { CX } from '../constants'
+import {
+ CX,
+ LAZY_LOAD_SCROLL_OFFSET,
+} from '../constants'
import DefaultNavigationBar from '../components/navigation_bar/default_navigation_bar'
import FooterBar from '../components/footer_bar'
import ProfileHeader from '../components/profile_header'
@@ -26,6 +30,37 @@ import {
class ProfileLayout extends ImmutablePureComponent {
+ state = {
+ lazyLoaded: false,
+ }
+
+ componentDidMount() {
+ this.window = window
+ this.documentElement = document.scrollingElement || document.documentElement
+
+ this.window.addEventListener('scroll', this.handleScroll)
+ }
+
+ componentWillUnmount() {
+ this.detachScrollListener()
+ }
+
+ detachScrollListener = () => {
+ this.window.removeEventListener('scroll', this.handleScroll)
+ }
+
+ handleScroll = throttle(() => {
+ if (this.window) {
+ const { scrollTop } = this.documentElement
+
+ if (scrollTop > LAZY_LOAD_SCROLL_OFFSET && !this.state.lazyLoaded) {
+ this.setState({ lazyLoaded: true })
+ this.detachScrollListener()
+ }
+ }
+ }, 150, { trailing: true })
+
+
render() {
const {
account,
@@ -34,6 +69,7 @@ class ProfileLayout extends ImmutablePureComponent {
unavailable,
noSidebar,
} = this.props
+ const { lazyLoaded } = this.state
const mainContentClasses = CX({
d: 1,
@@ -121,7 +157,7 @@ class ProfileLayout extends ImmutablePureComponent {
- { !unavailable && }
+ { !unavailable && }
{ !me && }
diff --git a/app/javascript/gabsocial/pages/compose_page.js b/app/javascript/gabsocial/pages/compose_page.js
new file mode 100644
index 00000000..d4714ffa
--- /dev/null
+++ b/app/javascript/gabsocial/pages/compose_page.js
@@ -0,0 +1,40 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import PageTitle from '../features/ui/util/page_title'
+import DefaultLayout from '../layouts/default_layout'
+
+class ComposePage extends React.PureComponent {
+
+ render() {
+ const {
+ children,
+ page,
+ title,
+ } = this.props
+
+ return (
+
+
+ {children}
+
+ )
+ }
+
+}
+
+ComposePage.propTypes = {
+ children: PropTypes.node.isRequired,
+}
+
+export default ComposePage
\ No newline at end of file
diff --git a/app/javascript/gabsocial/pages/home_page.js b/app/javascript/gabsocial/pages/home_page.js
index 2a054972..4e72f345 100644
--- a/app/javascript/gabsocial/pages/home_page.js
+++ b/app/javascript/gabsocial/pages/home_page.js
@@ -2,13 +2,17 @@ import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import throttle from 'lodash.throttle'
-import { openModal } from '../actions/modal'
import { defineMessages, injectIntl } from 'react-intl'
-import { MODAL_HOME_TIMELINE_SETTINGS } from '../constants'
+import { openModal } from '../actions/modal'
+import {
+ MODAL_HOME_TIMELINE_SETTINGS,
+ LAZY_LOAD_SCROLL_OFFSET,
+} from '../constants'
import { me } from '../initial_state'
import PageTitle from '../features/ui/util/page_title'
import DefaultLayout from '../layouts/default_layout'
import TimelineComposeBlock from '../components/timeline_compose_block'
+import TabBar from '../components/tab_bar'
import WrappedBundle from '../features/ui/util/wrapped_bundle'
import {
UserPanel,
@@ -47,7 +51,7 @@ class HomePage extends React.PureComponent {
if (this.window) {
const { scrollTop } = this.documentElement
- if (scrollTop > 25 && !this.state.lazyLoaded) {
+ if (scrollTop > LAZY_LOAD_SCROLL_OFFSET && !this.state.lazyLoaded) {
this.setState({ lazyLoaded: true })
this.detachScrollListener()
}
@@ -98,11 +102,10 @@ class HomePage extends React.PureComponent {
path={title}
badge={totalQueuedItemsCount}
/>
-
+
-
{children}
-
+
)
}
diff --git a/app/javascript/gabsocial/pages/messages_page.js b/app/javascript/gabsocial/pages/messages_page.js
new file mode 100644
index 00000000..1e74721e
--- /dev/null
+++ b/app/javascript/gabsocial/pages/messages_page.js
@@ -0,0 +1,38 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { defineMessages, injectIntl } from 'react-intl'
+import PageTitle from '../features/ui/util/page_title'
+import MessagesLayout from '../layouts/messages_layout'
+
+class MessagesPage extends React.PureComponent {
+
+ render() {
+ const { children, intl } = this.props
+
+ const title = intl.formatMessage(messages.chats)
+
+ return (
+
+
+ {children}
+
+ )
+ }
+
+}
+
+const messages = defineMessages({
+ chats: { id: 'chats', defaultMessage: 'Chats' },
+})
+
+MessagesPage.propTypes = {
+ intl: PropTypes.object.isRequired,
+ children: PropTypes.node.isRequired,
+ dispatch: PropTypes.func.isRequired,
+}
+
+export default injectIntl(connect()(MessagesPage))
\ No newline at end of file
diff --git a/app/javascript/gabsocial/pages/profile_page.js b/app/javascript/gabsocial/pages/profile_page.js
index 73749efd..61dd6a79 100644
--- a/app/javascript/gabsocial/pages/profile_page.js
+++ b/app/javascript/gabsocial/pages/profile_page.js
@@ -15,7 +15,9 @@ import ProfileLayout from '../layouts/profile_layout'
class ProfilePage extends ImmutablePureComponent {
componentDidMount() {
- this.props.dispatch(fetchAccountByUsername(this.props.params.username))
+ if (!this.props.account) {
+ this.props.dispatch(fetchAccountByUsername(this.props.params.username))
+ }
}
render() {
diff --git a/app/javascript/gabsocial/reducers/conversations.js b/app/javascript/gabsocial/reducers/conversations.js
deleted file mode 100644
index e45a56da..00000000
--- a/app/javascript/gabsocial/reducers/conversations.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import {
- CONVERSATIONS_MOUNT,
- CONVERSATIONS_UNMOUNT,
- CONVERSATIONS_FETCH_REQUEST,
- CONVERSATIONS_FETCH_SUCCESS,
- CONVERSATIONS_FETCH_FAIL,
- CONVERSATIONS_UPDATE,
- CONVERSATIONS_READ,
-} from '../actions/conversations';
-import compareId from '../utils/compare_id';
-
-const initialState = ImmutableMap({
- items: ImmutableList(),
- isLoading: false,
- hasMore: true,
- mounted: false,
-});
-
-const conversationToMap = item => ImmutableMap({
- id: item.id,
- unread: item.unread,
- accounts: ImmutableList(item.accounts.map(a => a.id)),
- last_status: item.last_status ? item.last_status.id : null,
-});
-
-const updateConversation = (state, item) => state.update('items', list => {
- const index = list.findIndex(x => x.get('id') === item.id);
- const newItem = conversationToMap(item);
-
- if (index === -1) {
- return list.unshift(newItem);
- } else {
- return list.set(index, newItem);
- }
-});
-
-const expandNormalizedConversations = (state, conversations, next, isLoadingRecent) => {
- let items = ImmutableList(conversations.map(conversationToMap));
-
- return state.withMutations(mutable => {
- if (!items.isEmpty()) {
- mutable.update('items', list => {
- list = list.map(oldItem => {
- const newItemIndex = items.findIndex(x => x.get('id') === oldItem.get('id'));
-
- if (newItemIndex === -1) {
- return oldItem;
- }
-
- const newItem = items.get(newItemIndex);
- items = items.delete(newItemIndex);
-
- return newItem;
- });
-
- list = list.concat(items);
-
- return list.sortBy(x => x.get('last_status'), (a, b) => {
- if(a === null || b === null) {
- return -1;
- }
-
- return compareId(a, b) * -1;
- });
- });
- }
-
- if (!next && !isLoadingRecent) {
- mutable.set('hasMore', false);
- }
-
- mutable.set('isLoading', false);
- });
-};
-
-export default function conversations(state = initialState, action) {
- switch (action.type) {
- case CONVERSATIONS_FETCH_REQUEST:
- return state.set('isLoading', true);
- case CONVERSATIONS_FETCH_FAIL:
- return state.set('isLoading', false);
- case CONVERSATIONS_FETCH_SUCCESS:
- return expandNormalizedConversations(state, action.conversations, action.next, action.isLoadingRecent);
- case CONVERSATIONS_UPDATE:
- return updateConversation(state, action.conversation);
- case CONVERSATIONS_MOUNT:
- return state.update('mounted', count => count + 1);
- case CONVERSATIONS_UNMOUNT:
- return state.update('mounted', count => count - 1);
- case CONVERSATIONS_READ:
- return state.update('items', list => list.map(item => {
- if (item.get('id') === action.id) {
- return item.set('unread', false);
- }
-
- return item;
- }));
- default:
- return state;
- }
-};
diff --git a/app/javascript/gabsocial/reducers/index.js b/app/javascript/gabsocial/reducers/index.js
index adbc8574..be38575d 100644
--- a/app/javascript/gabsocial/reducers/index.js
+++ b/app/javascript/gabsocial/reducers/index.js
@@ -4,7 +4,6 @@ import accounts from './accounts'
import accounts_counters from './accounts_counters'
import compose from './compose'
import contexts from './contexts'
-import conversations from './conversations'
import custom_emojis from './custom_emojis'
import filters from './filters'
import groups from './groups'
@@ -49,7 +48,6 @@ const reducers = {
accounts_counters,
compose,
contexts,
- conversations,
custom_emojis,
filters,
groups,
diff --git a/app/javascript/gabsocial/reducers/notifications.js b/app/javascript/gabsocial/reducers/notifications.js
index 2a92088b..ad8591dc 100644
--- a/app/javascript/gabsocial/reducers/notifications.js
+++ b/app/javascript/gabsocial/reducers/notifications.js
@@ -31,6 +31,7 @@ const initialState = ImmutableMap({
top: false,
unread: 0,
isLoading: false,
+ isError: false,
queuedNotifications: ImmutableList(), //max = MAX_QUEUED_NOTIFICATIONS
totalQueuedNotificationsCount: 0, //used for queuedItems overflow for MAX_QUEUED_NOTIFICATIONS+
lastReadId: -1,
@@ -271,7 +272,10 @@ export default function notifications(state = initialState, action) {
case NOTIFICATIONS_EXPAND_REQUEST:
return state.set('isLoading', true);
case NOTIFICATIONS_EXPAND_FAIL:
- return state.set('isLoading', false);
+ return state.withMutations(mutable => {
+ mutable.set('isLoading', false)
+ mutable.set('isError', true)
+ })
case NOTIFICATIONS_FILTER_SET:
return state.withMutations(mutable => {
mutable.set('items', ImmutableList()).set('hasMore', true)
diff --git a/app/javascript/gabsocial/reducers/relationships.js b/app/javascript/gabsocial/reducers/relationships.js
index 1777d3f8..e2a08d17 100644
--- a/app/javascript/gabsocial/reducers/relationships.js
+++ b/app/javascript/gabsocial/reducers/relationships.js
@@ -9,8 +9,6 @@ import {
ACCOUNT_UNBLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNMUTE_SUCCESS,
- ACCOUNT_PIN_SUCCESS,
- ACCOUNT_UNPIN_SUCCESS,
RELATIONSHIPS_FETCH_SUCCESS,
} from '../actions/accounts';
import { Map as ImmutableMap, fromJS } from 'immutable';
@@ -43,8 +41,6 @@ export default function relationships(state = initialState, action) {
case ACCOUNT_UNBLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
case ACCOUNT_UNMUTE_SUCCESS:
- case ACCOUNT_PIN_SUCCESS:
- case ACCOUNT_UNPIN_SUCCESS:
return normalizeRelationship(state, action.relationship);
case RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);
diff --git a/app/javascript/gabsocial/reducers/shortcuts.js b/app/javascript/gabsocial/reducers/shortcuts.js
index 9da61e86..ceccee2e 100644
--- a/app/javascript/gabsocial/reducers/shortcuts.js
+++ b/app/javascript/gabsocial/reducers/shortcuts.js
@@ -12,6 +12,7 @@ import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'
const initialState = ImmutableMap({
items: ImmutableList(),
isLoading: false,
+ isFetched: false,
isError: false,
})
@@ -50,17 +51,20 @@ export default function shortcutsReducer(state = initialState, action) {
case SHORTCUTS_FETCH_REQUEST:
return state.withMutations((map) => {
map.set('isLoading', true)
+ map.set('isFetched', false)
map.set('isError', false)
})
case SHORTCUTS_FETCH_SUCCESS:
return state.withMutations((map) => {
map.set('items', normalizeShortcuts(action.shortcuts))
map.set('isLoading', false)
+ map.set('isFetched', true)
map.set('isError', false)
})
case SHORTCUTS_FETCH_FAIL:
return state.withMutations((map) => {
map.set('isLoading', false)
+ map.set('isFetched', true)
map.set('isError', true)
})
case SHORTCUTS_ADD_SUCCESS:
diff --git a/app/javascript/gabsocial/reducers/status_lists.js b/app/javascript/gabsocial/reducers/status_lists.js
index c0b9c9ff..d108a06b 100644
--- a/app/javascript/gabsocial/reducers/status_lists.js
+++ b/app/javascript/gabsocial/reducers/status_lists.js
@@ -15,14 +15,6 @@ import {
BOOKMARKED_STATUSES_EXPAND_FAIL,
} from '../actions/bookmarks'
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import {
- FAVORITE_SUCCESS,
- UNFAVORITE_SUCCESS,
- PIN_SUCCESS,
- UNPIN_SUCCESS,
- BOOKMARK_SUCCESS,
- UNBOOKMARK_SUCCESS,
-} from '../actions/interactions';
const initialState = ImmutableMap({
bookmarks: ImmutableMap({
@@ -35,11 +27,6 @@ const initialState = ImmutableMap({
loaded: false,
items: ImmutableList(),
}),
- pins: ImmutableMap({
- next: null,
- loaded: false,
- items: ImmutableList(),
- }),
});
const normalizeList = (state, listType, statuses, next) => {
@@ -93,18 +80,6 @@ export default function statusLists(state = initialState, action) {
return normalizeList(state, 'favorites', action.statuses, action.next);
case FAVORITED_STATUSES_EXPAND_SUCCESS:
return appendToList(state, 'favorites', action.statuses, action.next);
- case FAVORITE_SUCCESS:
- return prependOneToList(state, 'favorites', action.status);
- case UNFAVORITE_SUCCESS:
- return removeOneFromList(state, 'favorites', action.status);
- case PIN_SUCCESS:
- return prependOneToList(state, 'pins', action.status);
- case UNPIN_SUCCESS:
- return removeOneFromList(state, 'pins', action.status);
- case BOOKMARK_SUCCESS:
- return prependOneToList(state, 'bookmarks', action.status);
- case UNBOOKMARK_SUCCESS:
- return removeOneFromList(state, 'bookmarks', action.status);
default:
return state;
}
diff --git a/app/javascript/gabsocial/reducers/statuses.js b/app/javascript/gabsocial/reducers/statuses.js
index 8c450b7e..2baf8c8b 100644
--- a/app/javascript/gabsocial/reducers/statuses.js
+++ b/app/javascript/gabsocial/reducers/statuses.js
@@ -6,10 +6,9 @@ import {
UNFAVORITE_REQUEST,
} from '../actions/interactions';
import {
- STATUS_MUTE_SUCCESS,
- STATUS_UNMUTE_SUCCESS,
STATUS_REVEAL,
STATUS_HIDE,
+ UPDATE_STATUS_STATS,
} from '../actions/statuses';
import { TIMELINE_DELETE } from '../actions/timelines';
import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer';
@@ -46,10 +45,6 @@ export default function statuses(state = initialState, action) {
return state.setIn([action.status.get('id'), 'reblogged'], true);
case REPOST_FAIL:
return state.get(action.status.get('id')) === undefined ? state : state.setIn([action.status.get('id'), 'reblogged'], false);
- case STATUS_MUTE_SUCCESS:
- return state.setIn([action.id, 'muted'], true);
- case STATUS_UNMUTE_SUCCESS:
- return state.setIn([action.id, 'muted'], false);
case STATUS_REVEAL:
return state.withMutations(map => {
action.ids.forEach(id => {
@@ -68,6 +63,9 @@ export default function statuses(state = initialState, action) {
});
case TIMELINE_DELETE:
return deleteStatus(state, action.id, action.references);
+ case UPDATE_STATUS_STATS:
+ // : todo :
+ return state;
default:
return state;
}
diff --git a/app/javascript/gabsocial/reducers/timelines.js b/app/javascript/gabsocial/reducers/timelines.js
index 8d843f33..7baac6b5 100644
--- a/app/javascript/gabsocial/reducers/timelines.js
+++ b/app/javascript/gabsocial/reducers/timelines.js
@@ -28,6 +28,7 @@ const initialTimeline = ImmutableMap({
online: false,
top: true,
isLoading: false,
+ isError: false,
hasMore: true,
items: ImmutableList(),
queuedItems: ImmutableList(), //max= MAX_QUEUED_ITEMS
@@ -49,10 +50,15 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
return newIds;
}
+ // const realtime = ['home']
+ // if no realtime, do all that, otherwise just concat
+ // return oldIds.concat(newIds);
+
const lastIndex = oldIds.findLastIndex(id => id !== null && compareId(id, newIds.last()) >= 0) + 1;
const firstIndex = oldIds.take(lastIndex).findLastIndex(id => id !== null && compareId(id, newIds.first()) > 0);
if (firstIndex < 0) {
+ console.log("----2")
return (isPartial ? newIds.unshift(null) : newIds).concat(oldIds.skip(lastIndex));
}
@@ -162,7 +168,10 @@ export default function timelines(state = initialState, action) {
case TIMELINE_EXPAND_REQUEST:
return state.update(action.timeline, initialTimeline, map => map.set('isLoading', true));
case TIMELINE_EXPAND_FAIL:
- return state.update(action.timeline, initialTimeline, map => map.set('isLoading', false));
+ return state.update(action.timeline, initialTimeline, map => map.withMutations(mMap => {
+ map.set('isLoading', false)
+ map.set('isError', true)
+ }));
case TIMELINE_EXPAND_SUCCESS:
return expandNormalizedTimeline(state, action.timeline, fromJS(action.statuses), action.next, action.partial, action.isLoadingRecent);
case TIMELINE_UPDATE:
diff --git a/app/javascript/gabsocial/selectors/index.js b/app/javascript/gabsocial/selectors/index.js
index f33e21d4..4d9fe666 100644
--- a/app/javascript/gabsocial/selectors/index.js
+++ b/app/javascript/gabsocial/selectors/index.js
@@ -78,6 +78,7 @@ export const makeGetStatus = () => {
[
(state) => state,
(state, { id }) => state.getIn(['statuses', id]),
+ (state, { id }) => state.getIn(['groups', state.getIn(['statuses', id, 'group'])]),
(state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'quote_of_id'])]),
(state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]),
(state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
@@ -87,7 +88,7 @@ export const makeGetStatus = () => {
getFilters,
],
- (state, statusBase, quotedStatus, statusRepost, accountBase, accountQuoted, accountRepost, username, filters) => {
+ (state, statusBase, group, quotedStatus, statusRepost, accountBase, accountQuoted, accountRepost, username, filters) => {
if (!statusBase) {
return null
}
@@ -122,16 +123,20 @@ export const makeGetStatus = () => {
quotedStatus = quotedStatus.set('account', accountQuoted);
}
+
+ console.log("group:", group)
+
//Find ancestor status
const regex = (accountRepost || accountBase).get('id') !== me && regexFromFilters(filters);
const filtered = regex && regex.test(statusBase.get('reblog') ? statusRepost.get('search_index') : statusBase.get('search_index'));
- return statusBase.withMutations(map => {
+ return statusBase.withMutations((map) => {
map.set('quoted_status', quotedStatus);
map.set('reblog', statusRepost);
map.set('account', accountBase);
map.set('filtered', filtered);
+ map.set('group', group);
});
}
);
diff --git a/app/javascript/gabsocial/service_worker/entry.js b/app/javascript/gabsocial/service_worker/entry.js
index 64ea5a43..72743186 100644
--- a/app/javascript/gabsocial/service_worker/entry.js
+++ b/app/javascript/gabsocial/service_worker/entry.js
@@ -50,13 +50,11 @@ self.addEventListener('fetch', function(event) {
url.pathname.startsWith('/about') ||
url.pathname.startsWith('/auth') ||
url.pathname.startsWith('/oauth') ||
- url.pathname.startsWith('/invites') ||
url.pathname.startsWith('/pghero') ||
url.pathname.startsWith('/sidekiq') ||
url.pathname.startsWith('/filters') ||
url.pathname.startsWith('/tags') ||
url.pathname.startsWith('/emojis') ||
- url.pathname.startsWith('/inbox') ||
url.pathname.startsWith('/accounts') ||
url.pathname.startsWith('/user') ||
url.pathname.startsWith('/users') ||
@@ -64,8 +62,7 @@ self.addEventListener('fetch', function(event) {
url.pathname.startsWith('/public') ||
url.pathname.startsWith('/avatars') ||
url.pathname.startsWith('/authorize_follow') ||
- url.pathname.startsWith('/media_proxy') ||
- url.pathname.startsWith('/relationships')) {
+ url.pathname.startsWith('/media_proxy')) {
//non-webapp routes
} else if (url.pathname.startsWith('/')) {
// : TODO : if is /web
diff --git a/app/javascript/gabsocial/test_setup.js b/app/javascript/gabsocial/test_setup.js
deleted file mode 100644
index 655ce97e..00000000
--- a/app/javascript/gabsocial/test_setup.js
+++ /dev/null
@@ -1,7 +0,0 @@
-'use strict';
-
-import { configure } from 'enzyme';
-import Adapter from 'enzyme-adapter-react-16';
-
-const adapter = new Adapter();
-configure({ adapter });
diff --git a/app/javascript/gabsocial/utils/__tests__/base64-test.js b/app/javascript/gabsocial/utils/__tests__/base64-test.js
deleted file mode 100644
index 1b3260fa..00000000
--- a/app/javascript/gabsocial/utils/__tests__/base64-test.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import * as base64 from '../base64';
-
-describe('base64', () => {
- describe('decode', () => {
- it('returns a uint8 array', () => {
- const arr = base64.decode('dGVzdA==');
- expect(arr).toEqual(new Uint8Array([116, 101, 115, 116]));
- });
- });
-});
diff --git a/app/javascript/gabsocial/utils/__tests__/html-test.js b/app/javascript/gabsocial/utils/__tests__/html-test.js
deleted file mode 100644
index ef9296e6..00000000
--- a/app/javascript/gabsocial/utils/__tests__/html-test.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import * as html from '../html';
-
-describe('html', () => {
- describe('unsecapeHTML', () => {
- it('returns unescaped HTML', () => {
- const output = html.unescapeHTML('lorem
ipsum
<br>');
- expect(output).toEqual('lorem\n\nipsum\n ');
- });
- });
-});
diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb
deleted file mode 100644
index f049fd63..00000000
--- a/app/lib/activitypub/activity.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity
- include JsonLdHelper
- include Redisable
-
- SUPPORTED_TYPES = %w(Note Question).freeze
- CONVERTED_TYPES = %w(Image Video Article Page).freeze
-
- def initialize(json, account, **options)
- @json = json
- @account = account
- @object = @json['object']
- @options = options
- end
-
- def perform
- raise NotImplementedError
- end
-
- class << self
- def factory(json, account, **options)
- @json = json
- klass&.new(json, account, options)
- end
-
- private
-
- def klass
- case @json['type']
- when 'Create'
- ActivityPub::Activity::Create
- when 'Announce'
- ActivityPub::Activity::Announce
- when 'Delete'
- ActivityPub::Activity::Delete
- when 'Follow'
- ActivityPub::Activity::Follow
- when 'Like'
- ActivityPub::Activity::Like
- when 'Block'
- ActivityPub::Activity::Block
- when 'Update'
- ActivityPub::Activity::Update
- when 'Undo'
- ActivityPub::Activity::Undo
- when 'Accept'
- ActivityPub::Activity::Accept
- when 'Reject'
- ActivityPub::Activity::Reject
- when 'Flag'
- ActivityPub::Activity::Flag
- when 'Add'
- ActivityPub::Activity::Add
- when 'Remove'
- ActivityPub::Activity::Remove
- when 'Move'
- ActivityPub::Activity::Move
- end
- end
- end
-
- protected
-
- def status_from_uri(uri)
- ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
- end
-
- def account_from_uri(uri)
- ActivityPub::TagManager.instance.uri_to_resource(uri, Account)
- end
-
- def object_uri
- @object_uri ||= value_or_id(@object)
- end
-
- def unsupported_object_type?
- @object.is_a?(String) || !(supported_object_type? || converted_object_type?)
- end
-
- def supported_object_type?
- equals_or_includes_any?(@object['type'], SUPPORTED_TYPES)
- end
-
- def converted_object_type?
- equals_or_includes_any?(@object['type'], CONVERTED_TYPES)
- end
-
- def distribute(status)
- crawl_links(status)
-
- notify_about_reblog(status) if reblog_of_local_account?(status)
- notify_about_mentions(status)
-
- # Only continue if the status is supposed to have arrived in real-time.
- # Note that if @options[:override_timestamps] isn't set, the status
- # may have a lower snowflake id than other existing statuses, potentially
- # "hiding" it from paginated API calls
- return unless @options[:override_timestamps] || status.within_realtime_window?
-
- distribute_to_followers(status)
- end
-
- def reblog_of_local_account?(status)
- status.reblog? && status.reblog.account.local?
- end
-
- def notify_about_reblog(status)
- NotifyService.new.call(status.reblog.account, status)
- end
-
- def notify_about_mentions(status)
- status.active_mentions.includes(:account).each do |mention|
- next unless mention.account.local? && audience_includes?(mention.account)
- NotifyService.new.call(mention.account, mention)
- end
- end
-
- def crawl_links(status)
- return if status.spoiler_text?
-
- # Spread out crawling randomly to avoid DDoSing the link
- LinkCrawlWorker.perform_in(rand(1..59).seconds, status.id)
- end
-
- def distribute_to_followers(status)
- ::DistributionWorker.perform_async(status.id)
- end
-
- def delete_arrived_first?(uri)
- redis.exists("delete_upon_arrival:#{@account.id}:#{uri}")
- end
-
- def delete_later!(uri)
- redis.setex("delete_upon_arrival:#{@account.id}:#{uri}", 6.hours.seconds, uri)
- end
-
- def status_from_object
- # If the status is already known, return it
- status = status_from_uri(object_uri)
-
- return status unless status.nil?
-
- # If the reposted gab is embedded and it is a self-repost, handle it like a Create
- unless unsupported_object_type?
- actor_id = value_or_id(first_of_value(@object['attributedTo'])) || @account.uri
-
- if actor_id == @account.uri
- return ActivityPub::Activity.factory({ 'type' => 'Create', 'actor' => actor_id, 'object' => @object }, @account).perform
- end
- end
-
- fetch_remote_original_status
- end
-
- def fetch_remote_original_status
- if object_uri.start_with?('http')
- return if ActivityPub::TagManager.instance.local_uri?(object_uri)
- ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first)
- elsif @object['url'].present?
- ::FetchRemoteStatusService.new.call(@object['url'])
- end
- end
-
- def lock_or_return(key, expire_after = 7.days.seconds)
- yield if redis.set(key, true, nx: true, ex: expire_after)
- ensure
- redis.del(key)
- end
-
- def fetch?
- !@options[:delivery]
- end
-
- def followed_by_local_accounts?
- @account.passive_relationships.exists?
- end
-
- def requested_through_relay?
- @options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled?
- end
-
- def reject_payload!
- Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}")
- nil
- end
-end
diff --git a/app/lib/activitypub/activity/accept.rb b/app/lib/activitypub/activity/accept.rb
deleted file mode 100644
index 348ee0d1..00000000
--- a/app/lib/activitypub/activity/accept.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Accept < ActivityPub::Activity
- def perform
- case @object['type']
- when 'Follow'
- accept_follow
- end
- end
-
- private
-
- def accept_follow
- return accept_follow_for_relay if relay_follow?
-
- target_account = account_from_uri(target_uri)
-
- return if target_account.nil? || !target_account.local?
-
- follow_request = FollowRequest.find_by(account: target_account, target_account: @account)
- follow_request&.authorize!
- end
-
- def accept_follow_for_relay
- relay.update!(state: :accepted)
- end
-
- def relay
- @relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
- end
-
- def relay_follow?
- relay.present?
- end
-
- def target_uri
- @target_uri ||= value_or_id(@object['actor'])
- end
-end
diff --git a/app/lib/activitypub/activity/add.rb b/app/lib/activitypub/activity/add.rb
deleted file mode 100644
index 688ab00b..00000000
--- a/app/lib/activitypub/activity/add.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Add < ActivityPub::Activity
- def perform
- return unless @json['target'].present? && value_or_id(@json['target']) == @account.featured_collection_url
-
- status = status_from_uri(object_uri)
- status ||= fetch_remote_original_status
-
- return unless !status.nil? && status.account_id == @account.id && !@account.pinned?(status)
-
- StatusPin.create!(account: @account, status: status)
- end
-end
diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb
deleted file mode 100644
index 1aa6ee9e..00000000
--- a/app/lib/activitypub/activity/announce.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Announce < ActivityPub::Activity
- def perform
- return reject_payload! if delete_arrived_first?(@json['id']) || !related_to_local_activity?
-
- original_status = status_from_object
-
- return reject_payload! if original_status.nil? || !announceable?(original_status)
-
- status = Status.find_by(account: @account, reblog: original_status)
-
- return status unless status.nil?
-
- status = Status.create!(
- account: @account,
- reblog: original_status,
- uri: @json['id'],
- created_at: @json['published'],
- override_timestamps: @options[:override_timestamps],
- visibility: visibility_from_audience
- )
-
- distribute(status)
- status
- end
-
- private
-
- def visibility_from_audience
- if equals_or_includes?(@json['to'], ActivityPub::TagManager::COLLECTIONS[:public])
- :public
- elsif equals_or_includes?(@json['cc'], ActivityPub::TagManager::COLLECTIONS[:public])
- :unlisted
- elsif equals_or_includes?(@json['to'], @account.followers_url)
- :private
- else
- :direct
- end
- end
-
- def announceable?(status)
- status.account_id == @account.id || status.public_visibility? || status.unlisted_visibility?
- end
-
- def related_to_local_activity?
- followed_by_local_accounts? || requested_through_relay? || reblog_of_local_status?
- end
-
- def requested_through_relay?
- super || Relay.find_by(inbox_url: @account.inbox_url)&.enabled?
- end
-
- def reblog_of_local_status?
- status_from_uri(object_uri)&.account&.local?
- end
-end
diff --git a/app/lib/activitypub/activity/block.rb b/app/lib/activitypub/activity/block.rb
deleted file mode 100644
index a17a2d50..00000000
--- a/app/lib/activitypub/activity/block.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Block < ActivityPub::Activity
- def perform
- target_account = account_from_uri(object_uri)
-
- return if target_account.nil? || !target_account.local? || @account.blocking?(target_account)
-
- UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
-
- @account.block!(target_account, uri: @json['id']) unless delete_arrived_first?(@json['id'])
- end
-end
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
deleted file mode 100644
index eee57769..00000000
--- a/app/lib/activitypub/activity/create.rb
+++ /dev/null
@@ -1,417 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Create < ActivityPub::Activity
- def perform
- return reject_payload! if unsupported_object_type? || invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity?
-
- RedisLock.acquire(lock_options) do |lock|
- if lock.acquired?
- return if delete_arrived_first?(object_uri) || poll_vote?
-
- @status = find_existing_status
-
- if @status.nil?
- process_status
- elsif @options[:delivered_to_account_id].present?
- postprocess_audience_and_deliver
- end
- else
- raise GabSocial::RaceConditionError
- end
- end
-
- @status
- end
-
- private
-
- def process_status
- @tags = []
- @mentions = []
- @params = {}
-
- process_status_params
- process_tags
- process_audience
-
- ApplicationRecord.transaction do
- @status = Status.create!(@params)
- attach_tags(@status)
- end
-
- resolve_thread(@status)
- fetch_replies(@status)
- distribute(@status)
- forward_for_reply if @status.public_visibility? || @status.unlisted_visibility?
- end
-
- def find_existing_status
- status = status_from_uri(object_uri)
- status ||= Status.find_by(uri: @object['atomUri']) if @object['atomUri'].present?
- status
- end
-
- def process_status_params
- @params = begin
- {
- uri: @object['id'],
- url: object_url || @object['id'],
- account: @account,
- text: text_from_content || '',
- language: detected_language,
- spoiler_text: converted_object_type? ? '' : (text_from_summary || ''),
- created_at: @object['published'],
- override_timestamps: @options[:override_timestamps],
- reply: @object['inReplyTo'].present?,
- sensitive: @object['sensitive'] || false,
- visibility: visibility_from_audience,
- thread: replied_to_status,
- conversation: conversation_from_uri(@object['conversation']),
- media_attachment_ids: process_attachments.take(4).map(&:id),
- poll: process_poll,
- }
- end
- end
-
- def process_audience
- (as_array(@object['to']) + as_array(@object['cc'])).uniq.each do |audience|
- next if audience == ActivityPub::TagManager::COLLECTIONS[:public]
-
- # Unlike with tags, there is no point in resolving accounts we don't already
- # know here, because silent mentions would only be used for local access
- # control anyway
- account = account_from_uri(audience)
-
- next if account.nil? || @mentions.any? { |mention| mention.account_id == account.id }
-
- @mentions << Mention.new(account: account, silent: true)
-
- # If there is at least one silent mention, then the status can be considered
- # as a limited-audience status, and not strictly a direct message, but only
- # if we considered a direct message in the first place
- next unless @params[:visibility] == :direct
-
- @params[:visibility] = :limited
- end
-
- # If the payload was delivered to a specific inbox, the inbox owner must have
- # access to it, unless they already have access to it anyway
- return if @options[:delivered_to_account_id].nil? || @mentions.any? { |mention| mention.account_id == @options[:delivered_to_account_id] }
-
- @mentions << Mention.new(account_id: @options[:delivered_to_account_id], silent: true)
-
- return unless @params[:visibility] == :direct
-
- @params[:visibility] = :limited
- end
-
- def postprocess_audience_and_deliver
- return if @status.mentions.find_by(account_id: @options[:delivered_to_account_id])
-
- delivered_to_account = Account.find(@options[:delivered_to_account_id])
-
- @status.mentions.create(account: delivered_to_account, silent: true)
- @status.update(visibility: :limited) if @status.direct_visibility?
-
- return unless delivered_to_account.following?(@account)
-
- FeedInsertWorker.perform_async(@status.id, delivered_to_account.id, :home)
- end
-
- def attach_tags(status)
- @tags.each do |tag|
- status.tags << tag
- TrendingTags.record_use!(tag, status.account, status.created_at) if status.public_visibility?
- end
-
- @mentions.each do |mention|
- mention.status = status
- mention.save
- end
- end
-
- def process_tags
- return if @object['tag'].nil?
-
- as_array(@object['tag']).each do |tag|
- if equals_or_includes?(tag['type'], 'Hashtag')
- process_hashtag tag
- elsif equals_or_includes?(tag['type'], 'Mention')
- process_mention tag
- elsif equals_or_includes?(tag['type'], 'Emoji')
- process_emoji tag
- end
- end
- end
-
- def process_hashtag(tag)
- return if tag['name'].blank?
-
- hashtag = tag['name'].gsub(/\A#/, '').mb_chars.downcase
- hashtag = Tag.where(name: hashtag).first_or_create!(name: hashtag)
-
- return if @tags.include?(hashtag)
-
- @tags << hashtag
- rescue ActiveRecord::RecordInvalid
- nil
- end
-
- def process_mention(tag)
- return if tag['href'].blank?
-
- account = account_from_uri(tag['href'])
- account = ::FetchRemoteAccountService.new.call(tag['href']) if account.nil?
-
- return if account.nil?
-
- @mentions << Mention.new(account: account, silent: false)
- end
-
- def process_emoji(tag)
- return if skip_download?
- return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?
-
- shortcode = tag['name'].delete(':')
- image_url = tag['icon']['url']
- uri = tag['id']
- updated = tag['updated']
- emoji = CustomEmoji.find_by(shortcode: shortcode, domain: @account.domain)
-
- return unless emoji.nil? || image_url != emoji.image_remote_url || (updated && updated >= emoji.updated_at)
-
- emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: shortcode, uri: uri)
- emoji.image_remote_url = image_url
- emoji.save
- end
-
- def process_attachments
- return [] if @object['attachment'].nil?
-
- media_attachments = []
-
- as_array(@object['attachment']).each do |attachment|
- next if attachment['url'].blank?
-
- href = Addressable::URI.parse(attachment['url']).normalize.to_s
- media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['name'].presence, focus: attachment['focalPoint'], blurhash: supported_blurhash?(attachment['blurhash']) ? attachment['blurhash'] : nil)
- media_attachments << media_attachment
-
- next if unsupported_media_type?(attachment['mediaType']) || skip_download?
-
- media_attachment.file_remote_url = href
- media_attachment.save
- end
-
- media_attachments
- rescue Addressable::URI::InvalidURIError => e
- Rails.logger.debug e
-
- media_attachments
- end
-
- def process_poll
- return unless @object['type'] == 'Question' && (@object['anyOf'].is_a?(Array) || @object['oneOf'].is_a?(Array))
-
- expires_at = begin
- if @object['closed'].is_a?(String)
- @object['closed']
- elsif !@object['closed'].nil? && !@object['closed'].is_a?(FalseClass)
- Time.now.utc
- else
- @object['endTime']
- end
- end
-
- if @object['anyOf'].is_a?(Array)
- multiple = true
- items = @object['anyOf']
- else
- multiple = false
- items = @object['oneOf']
- end
-
- @account.polls.new(
- multiple: multiple,
- expires_at: expires_at,
- options: items.map { |item| item['name'].presence || item['content'] }.compact,
- cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 }
- )
- end
-
- def poll_vote?
- return false if replied_to_status.nil? || replied_to_status.preloadable_poll.nil? || !replied_to_status.local? || !replied_to_status.preloadable_poll.options.include?(@object['name'])
-
- unless replied_to_status.preloadable_poll.expired?
- replied_to_status.preloadable_poll.votes.create!(account: @account, choice: replied_to_status.preloadable_poll.options.index(@object['name']), uri: @object['id'])
- ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, replied_to_status.id) unless replied_to_status.preloadable_poll.hide_totals?
- end
-
- true
- end
-
- def resolve_thread(status)
- return unless status.reply? && status.thread.nil? && Request.valid_url?(in_reply_to_uri)
- ThreadResolveWorker.perform_async(status.id, in_reply_to_uri)
- end
-
- def fetch_replies(status)
- collection = @object['replies']
- return if collection.nil?
- replies = ActivityPub::FetchRepliesService.new.call(status, collection, false)
- return unless replies.nil?
- uri = value_or_id(collection)
- ActivityPub::FetchRepliesWorker.perform_async(status.id, uri) unless uri.nil?
- end
-
- def conversation_from_uri(uri)
- return nil if uri.nil?
- return Conversation.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')) if OStatus::TagManager.instance.local_id?(uri)
- begin
- Conversation.find_or_create_by!(uri: uri)
- rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
- retry
- end
- end
-
- def visibility_from_audience
- if equals_or_includes?(@object['to'], ActivityPub::TagManager::COLLECTIONS[:public])
- :public
- elsif equals_or_includes?(@object['cc'], ActivityPub::TagManager::COLLECTIONS[:public])
- :unlisted
- elsif equals_or_includes?(@object['to'], @account.followers_url)
- :private
- else
- :direct
- end
- end
-
- def audience_includes?(account)
- uri = ActivityPub::TagManager.instance.uri_for(account)
- equals_or_includes?(@object['to'], uri) || equals_or_includes?(@object['cc'], uri)
- end
-
- def replied_to_status
- return @replied_to_status if defined?(@replied_to_status)
-
- if in_reply_to_uri.blank?
- @replied_to_status = nil
- else
- @replied_to_status = status_from_uri(in_reply_to_uri)
- @replied_to_status ||= status_from_uri(@object['inReplyToAtomUri']) if @object['inReplyToAtomUri'].present?
- @replied_to_status
- end
- end
-
- def in_reply_to_uri
- value_or_id(@object['inReplyTo'])
- end
-
- def text_from_content
- return Formatter.instance.linkify([[text_from_name, text_from_summary.presence].compact.join("\n\n"), object_url || @object['id']].join(' ')) if converted_object_type?
-
- if @object['content'].present?
- @object['content']
- elsif content_language_map?
- @object['contentMap'].values.first
- end
- end
-
- def text_from_summary
- if @object['summary'].present?
- @object['summary']
- elsif summary_language_map?
- @object['summaryMap'].values.first
- end
- end
-
- def text_from_name
- if @object['name'].present?
- @object['name']
- elsif name_language_map?
- @object['nameMap'].values.first
- end
- end
-
- def detected_language
- if content_language_map?
- @object['contentMap'].keys.first
- elsif name_language_map?
- @object['nameMap'].keys.first
- elsif summary_language_map?
- @object['summaryMap'].keys.first
- elsif supported_object_type?
- LanguageDetector.instance.detect(text_from_content, @account)
- end
- end
-
- def object_url
- return if @object['url'].blank?
-
- url_candidate = url_to_href(@object['url'], 'text/html')
-
- if invalid_origin?(url_candidate)
- nil
- else
- url_candidate
- end
- end
-
- def summary_language_map?
- @object['summaryMap'].is_a?(Hash) && !@object['summaryMap'].empty?
- end
-
- def content_language_map?
- @object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty?
- end
-
- def name_language_map?
- @object['nameMap'].is_a?(Hash) && !@object['nameMap'].empty?
- end
-
- def unsupported_media_type?(mime_type)
- mime_type.present? && !(MediaAttachment::IMAGE_MIME_TYPES + MediaAttachment::VIDEO_MIME_TYPES).include?(mime_type)
- end
-
- def supported_blurhash?(blurhash)
- components = blurhash.blank? ? nil : Blurhash.components(blurhash)
- components.present? && components.none? { |comp| comp > 5 }
- end
-
- def skip_download?
- return @skip_download if defined?(@skip_download)
- @skip_download ||= DomainBlock.find_by(domain: @account.domain)&.reject_media?
- end
-
- def reply_to_local?
- !replied_to_status.nil? && replied_to_status.account.local?
- end
-
- def related_to_local_activity?
- fetch? || followed_by_local_accounts? || requested_through_relay? ||
- responds_to_followed_account? || addresses_local_accounts?
- end
-
- def responds_to_followed_account?
- !replied_to_status.nil? && (replied_to_status.account.local? || replied_to_status.account.passive_relationships.exists?)
- end
-
- def addresses_local_accounts?
- return true if @options[:delivered_to_account_id]
-
- local_usernames = (as_array(@object['to']) + as_array(@object['cc'])).uniq.select { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }.map { |uri| ActivityPub::TagManager.instance.uri_to_local_id(uri, :username) }
-
- return false if local_usernames.empty?
-
- Account.local.where(username: local_usernames).exists?
- end
-
- def forward_for_reply
- return unless @json['signature'].present? && reply_to_local?
- ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
- end
-
- def lock_options
- { redis: Redis.current, key: "create:#{@object['id']}" }
- end
-end
diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb
deleted file mode 100644
index 4236af07..00000000
--- a/app/lib/activitypub/activity/delete.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Delete < ActivityPub::Activity
- def perform
- if @account.uri == object_uri
- delete_person
- else
- delete_note
- end
- end
-
- private
-
- def delete_person
- lock_or_return("delete_in_progress:#{@account.id}") do
- SuspendAccountService.new.call(@account)
- @account.destroy!
- end
- end
-
- def delete_note
- return if object_uri.nil?
-
- unless invalid_origin?(object_uri)
- RedisLock.acquire(lock_options) { |_lock| delete_later!(object_uri) }
- Tombstone.find_or_create_by(uri: object_uri, account: @account)
- end
-
- @status = Status.find_by(uri: object_uri, account: @account)
- @status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?
-
- return if @status.nil?
-
- if @status.public_visibility? || @status.unlisted_visibility?
- forward_for_reply
- forward_for_reblogs
- end
-
- delete_now!
- end
-
- def forward_for_reblogs
- return if @json['signature'].blank?
-
- rebloggers_ids = @status.reblogs.includes(:account).references(:account).merge(Account.local).pluck(:account_id)
- inboxes = Account.where(id: ::Follow.where(target_account_id: rebloggers_ids).select(:account_id)).inboxes - [@account.preferred_inbox_url]
-
- ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
- [payload, rebloggers_ids.first, inbox_url]
- end
- end
-
- def replied_to_status
- return @replied_to_status if defined?(@replied_to_status)
- @replied_to_status = @status.thread
- end
-
- def reply_to_local?
- !replied_to_status.nil? && replied_to_status.account.local?
- end
-
- def forward_for_reply
- return unless @json['signature'].present? && reply_to_local?
- ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
- end
-
- def delete_now!
- RemoveStatusService.new.call(@status)
- end
-
- def payload
- @payload ||= Oj.dump(@json)
- end
-
- def lock_options
- { redis: Redis.current, key: "create:#{object_uri}" }
- end
-end
diff --git a/app/lib/activitypub/activity/flag.rb b/app/lib/activitypub/activity/flag.rb
deleted file mode 100644
index f73b9305..00000000
--- a/app/lib/activitypub/activity/flag.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Flag < ActivityPub::Activity
- def perform
- return if skip_reports?
-
- target_accounts = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?)
- target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id)
-
- target_accounts.each do |target_account|
- target_statuses = target_statuses_by_account[target_account.id]
-
- ReportService.new.call(
- @account,
- target_account,
- status_ids: target_statuses.nil? ? [] : target_statuses.map(&:id),
- comment: @json['content'] || '',
- uri: report_uri
- )
- end
- end
-
- private
-
- def skip_reports?
- DomainBlock.find_by(domain: @account.domain)&.reject_reports?
- end
-
- def object_uris
- @object_uris ||= Array(@object.is_a?(Array) ? @object.map { |item| value_or_id(item) } : value_or_id(@object))
- end
-
- def report_uri
- @json['id'] unless @json['id'].nil? || invalid_origin?(@json['id'])
- end
-end
diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb
deleted file mode 100644
index 1e805c0d..00000000
--- a/app/lib/activitypub/activity/follow.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Follow < ActivityPub::Activity
- def perform
- target_account = account_from_uri(object_uri)
-
- return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id']) || @account.requested?(target_account)
-
- if target_account.blocking?(@account) || target_account.domain_blocking?(@account.domain) || target_account.moved?
- reject_follow_request!(target_account)
- return
- end
-
- # Fast-forward repeat follow requests
- if @account.following?(target_account)
- AuthorizeFollowService.new.call(@account, target_account, skip_follow_request: true, follow_request_uri: @json['id'])
- return
- end
-
- follow_request = FollowRequest.create!(account: @account, target_account: target_account, uri: @json['id'])
-
- if target_account.locked?
- NotifyService.new.call(target_account, follow_request)
- else
- AuthorizeFollowService.new.call(@account, target_account)
- NotifyService.new.call(target_account, ::Follow.find_by(account: @account, target_account: target_account))
- end
- end
-
- def reject_follow_request!(target_account)
- json = ActiveModelSerializers::SerializableResource.new(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), serializer: ActivityPub::RejectFollowSerializer, adapter: ActivityPub::Adapter).to_json
- ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url)
- end
-end
diff --git a/app/lib/activitypub/activity/like.rb b/app/lib/activitypub/activity/like.rb
deleted file mode 100644
index 674d5fe4..00000000
--- a/app/lib/activitypub/activity/like.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Like < ActivityPub::Activity
- def perform
- original_status = status_from_uri(object_uri)
-
- return if original_status.nil? || !original_status.account.local? || delete_arrived_first?(@json['id']) || @account.favourited?(original_status)
-
- favourite = original_status.favourites.create!(account: @account)
- NotifyService.new.call(original_status.account, favourite)
- end
-end
diff --git a/app/lib/activitypub/activity/move.rb b/app/lib/activitypub/activity/move.rb
deleted file mode 100644
index d7a5f595..00000000
--- a/app/lib/activitypub/activity/move.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Move < ActivityPub::Activity
- PROCESSING_COOLDOWN = 7.days.seconds
-
- def perform
- return if origin_account.uri != object_uri || processed?
-
- mark_as_processing!
-
- target_account = ActivityPub::FetchRemoteAccountService.new.call(target_uri)
-
- return if target_account.nil? || !target_account.also_known_as.include?(origin_account.uri)
-
- # In case for some reason we didn't have a redirect for the profile already, set it
- origin_account.update(moved_to_account: target_account) if origin_account.moved_to_account_id.nil?
-
- # Initiate a re-follow for each follower
- origin_account.followers.local.select(:id).find_in_batches do |follower_accounts|
- UnfollowFollowWorker.push_bulk(follower_accounts.map(&:id)) do |follower_account_id|
- [follower_account_id, origin_account.id, target_account.id]
- end
- end
- end
-
- private
-
- def origin_account
- @account
- end
-
- def target_uri
- value_or_id(@json['target'])
- end
-
- def processed?
- redis.exists("move_in_progress:#{@account.id}")
- end
-
- def mark_as_processing!
- redis.setex("move_in_progress:#{@account.id}", PROCESSING_COOLDOWN, true)
- end
-end
diff --git a/app/lib/activitypub/activity/reject.rb b/app/lib/activitypub/activity/reject.rb
deleted file mode 100644
index dba21fb9..00000000
--- a/app/lib/activitypub/activity/reject.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Reject < ActivityPub::Activity
- def perform
- case @object['type']
- when 'Follow'
- reject_follow
- end
- end
-
- private
-
- def reject_follow
- return reject_follow_for_relay if relay_follow?
-
- target_account = account_from_uri(target_uri)
-
- return if target_account.nil? || !target_account.local?
-
- follow_request = FollowRequest.find_by(account: target_account, target_account: @account)
- follow_request&.reject!
-
- UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
- end
-
- def reject_follow_for_relay
- relay.update!(state: :rejected)
- end
-
- def relay
- @relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
- end
-
- def relay_follow?
- relay.present?
- end
-
- def target_uri
- @target_uri ||= value_or_id(@object['actor'])
- end
-end
diff --git a/app/lib/activitypub/activity/remove.rb b/app/lib/activitypub/activity/remove.rb
deleted file mode 100644
index f523ead9..00000000
--- a/app/lib/activitypub/activity/remove.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Remove < ActivityPub::Activity
- def perform
- return unless @json['target'].present? && value_or_id(@json['target']) == @account.featured_collection_url
-
- status = status_from_uri(object_uri)
-
- return unless !status.nil? && status.account_id == @account.id
-
- pin = StatusPin.find_by(account: @account, status: status)
- pin&.destroy!
- end
-end
diff --git a/app/lib/activitypub/activity/undo.rb b/app/lib/activitypub/activity/undo.rb
deleted file mode 100644
index 599823c6..00000000
--- a/app/lib/activitypub/activity/undo.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Undo < ActivityPub::Activity
- def perform
- case @object['type']
- when 'Announce'
- undo_announce
- when 'Accept'
- undo_accept
- when 'Follow'
- undo_follow
- when 'Like'
- undo_like
- when 'Block'
- undo_block
- end
- end
-
- private
-
- def undo_announce
- return if object_uri.nil?
-
- status = Status.find_by(uri: object_uri, account: @account)
- status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?
-
- if status.nil?
- delete_later!(object_uri)
- else
- RemoveStatusService.new.call(status)
- end
- end
-
- def undo_accept
- ::Follow.find_by(target_account: @account, uri: target_uri)&.revoke_request!
- end
-
- def undo_follow
- target_account = account_from_uri(target_uri)
-
- return if target_account.nil? || !target_account.local?
-
- if @account.following?(target_account)
- @account.unfollow!(target_account)
- elsif @account.requested?(target_account)
- FollowRequest.find_by(account: @account, target_account: target_account)&.destroy
- else
- delete_later!(object_uri)
- end
- end
-
- def undo_like
- status = status_from_uri(target_uri)
-
- return if status.nil? || !status.account.local?
-
- if @account.favourited?(status)
- favourite = status.favourites.where(account: @account).first
- favourite&.destroy
- else
- delete_later!(object_uri)
- end
- end
-
- def undo_block
- target_account = account_from_uri(target_uri)
-
- return if target_account.nil? || !target_account.local?
-
- if @account.blocking?(target_account)
- UnblockService.new.call(@account, target_account)
- else
- delete_later!(object_uri)
- end
- end
-
- def target_uri
- @target_uri ||= value_or_id(@object['object'])
- end
-end
diff --git a/app/lib/activitypub/activity/update.rb b/app/lib/activitypub/activity/update.rb
deleted file mode 100644
index 70035325..00000000
--- a/app/lib/activitypub/activity/update.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Activity::Update < ActivityPub::Activity
- SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
-
- def perform
- if equals_or_includes_any?(@object['type'], SUPPORTED_TYPES)
- update_account
- elsif equals_or_includes_any?(@object['type'], %w(Question))
- update_poll
- end
- end
-
- private
-
- def update_account
- return if @account.uri != object_uri
-
- ActivityPub::ProcessAccountService.new.call(@account.username, @account.domain, @object, signed_with_known_key: true)
- end
-
- def update_poll
- return reject_payload! if invalid_origin?(@object['id'])
-
- status = Status.find_by(uri: object_uri, account_id: @account.id)
- return if status.nil? || status.preloadable_poll.nil?
-
- ActivityPub::ProcessPollService.new.call(status.preloadable_poll, @object)
- end
-end
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
deleted file mode 100644
index c259c96f..00000000
--- a/app/lib/activitypub/adapter.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
- NAMED_CONTEXT_MAP = {
- activitystreams: 'https://www.w3.org/ns/activitystreams',
- security: 'https://w3id.org/security/v1',
- }.freeze
-
- CONTEXT_EXTENSION_MAP = {
- manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' },
- sensitive: { 'sensitive' => 'as:sensitive' },
- hashtag: { 'Hashtag' => 'as:Hashtag' },
- moved_to: { 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' } },
- also_known_as: { 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' } },
- emoji: { 'toot' => 'http://joinmastodon.org/ns#', 'Emoji' => 'toot:Emoji' },
- featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' } },
- property_value: { 'schema' => 'http://schema.org#', 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value' },
- atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' },
- conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' },
- focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } },
- identity_proof: { 'toot' => 'http://joinmastodon.org/ns#', 'IdentityProof' => 'toot:IdentityProof' },
- blurhash: { 'toot' => 'http://joinmastodon.org/ns#', 'blurhash' => 'toot:blurhash' },
- }.freeze
-
- def self.default_key_transform
- :camel_lower
- end
-
- def self.transform_key_casing!(value, _options)
- ActivityPub::CaseTransform.camel_lower(value)
- end
-
- def serializable_hash(options = nil)
- options = serialization_options(options)
- serialized_hash = serializer.serializable_hash(options)
- serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options)
-
- { '@context' => serialized_context }.merge(serialized_hash)
- end
-
- private
-
- def serialized_context
- context_array = []
-
- serializer_options = serializer.send(:instance_options) || {}
- named_contexts = [:activitystreams] + serializer._named_contexts.keys + serializer_options.fetch(:named_contexts, {}).keys
- context_extensions = serializer._context_extensions.keys + serializer_options.fetch(:context_extensions, {}).keys
-
- named_contexts.each do |key|
- context_array << NAMED_CONTEXT_MAP[key]
- end
-
- extensions = context_extensions.each_with_object({}) do |key, h|
- h.merge!(CONTEXT_EXTENSION_MAP[key])
- end
-
- context_array << extensions unless extensions.empty?
-
- if context_array.size == 1
- context_array.first
- else
- context_array
- end
- end
-end
diff --git a/app/lib/activitypub/case_transform.rb b/app/lib/activitypub/case_transform.rb
deleted file mode 100644
index 7f716f86..00000000
--- a/app/lib/activitypub/case_transform.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-module ActivityPub::CaseTransform
- class << self
- def camel_lower_cache
- @camel_lower_cache ||= {}
- end
-
- def camel_lower(value)
- case value
- when Array then value.map { |item| camel_lower(item) }
- when Hash then value.deep_transform_keys! { |key| camel_lower(key) }
- when Symbol then camel_lower(value.to_s).to_sym
- when String
- camel_lower_cache[value] ||= if value.start_with?('_:')
- '_:' + value.gsub(/\A_:/, '').underscore.camelize(:lower)
- else
- value.underscore.camelize(:lower)
- end
- else value
- end
- end
- end
-end
diff --git a/app/lib/activitypub/linked_data_signature.rb b/app/lib/activitypub/linked_data_signature.rb
deleted file mode 100644
index f52a8f40..00000000
--- a/app/lib/activitypub/linked_data_signature.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::LinkedDataSignature
- include JsonLdHelper
-
- CONTEXT = 'https://w3id.org/identity/v1'
-
- def initialize(json)
- @json = json.with_indifferent_access
- end
-
- def verify_account!
- return unless @json['signature'].is_a?(Hash)
-
- type = @json['signature']['type']
- creator_uri = @json['signature']['creator']
- signature = @json['signature']['signatureValue']
-
- return unless type == 'RsaSignature2017'
-
- creator = ActivityPub::TagManager.instance.uri_to_resource(creator_uri, Account)
- creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
-
- return if creator.nil?
-
- options_hash = hash(@json['signature'].without('type', 'id', 'signatureValue').merge('@context' => CONTEXT))
- document_hash = hash(@json.without('signature'))
- to_be_verified = options_hash + document_hash
-
- if creator.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), to_be_verified)
- creator
- end
- end
-
- def sign!(creator, sign_with: nil)
- options = {
- 'type' => 'RsaSignature2017',
- 'creator' => [ActivityPub::TagManager.instance.uri_for(creator), '#main-key'].join,
- 'created' => Time.now.utc.iso8601,
- }
-
- options_hash = hash(options.without('type', 'id', 'signatureValue').merge('@context' => CONTEXT))
- document_hash = hash(@json.without('signature'))
- to_be_signed = options_hash + document_hash
- keypair = sign_with.present? ? OpenSSL::PKey::RSA.new(sign_with) : creator.keypair
-
- signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest::SHA256.new, to_be_signed))
-
- @json.merge('signature' => options.merge('signatureValue' => signature))
- end
-
- private
-
- def hash(obj)
- Digest::SHA256.hexdigest(canonicalize(obj))
- end
-end
diff --git a/app/lib/activitypub/serializer.rb b/app/lib/activitypub/serializer.rb
deleted file mode 100644
index 07bd8c49..00000000
--- a/app/lib/activitypub/serializer.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::Serializer < ActiveModel::Serializer
- with_options instance_writer: false, instance_reader: true do |serializer|
- serializer.class_attribute :_named_contexts
- serializer.class_attribute :_context_extensions
-
- self._named_contexts ||= {}
- self._context_extensions ||= {}
- end
-
- def self.inherited(base)
- super
-
- base._named_contexts = _named_contexts.dup
- base._context_extensions = _context_extensions.dup
- end
-
- def self.context(*named_contexts)
- named_contexts.each do |context|
- _named_contexts[context] = true
- end
- end
-
- def self.context_extensions(*extension_names)
- extension_names.each do |extension_name|
- _context_extensions[extension_name] = true
- end
- end
-end
diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb
deleted file mode 100644
index 59529134..00000000
--- a/app/lib/activitypub/tag_manager.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-require 'singleton'
-
-class ActivityPub::TagManager
- include Singleton
- include RoutingHelper
-
- CONTEXT = 'https://www.w3.org/ns/activitystreams'
-
- COLLECTIONS = {
- public: 'https://www.w3.org/ns/activitystreams#Public',
- }.freeze
-
- def url_for(target)
- return target.url if target.respond_to?(:local?) && !target.local?
-
- case target.object_type
- when :person
- short_account_url(target)
- when :note, :comment, :activity
- return activity_account_status_url(target.account, target) if target.reblog?
- short_account_status_url(target.account, target)
- end
- end
-
- def uri_for(target)
- return target.uri if target.respond_to?(:local?) && !target.local?
-
- case target.object_type
- when :person
- account_url(target)
- when :note, :comment, :activity
- return activity_account_status_url(target.account, target) if target.reblog?
- account_status_url(target.account, target)
- when :emoji
- emoji_url(target)
- end
- end
-
- def generate_uri_for(_target)
- URI.join(root_url, 'payloads', SecureRandom.uuid)
- end
-
- def activity_uri_for(target)
- raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?
-
- activity_account_status_url(target.account, target)
- end
-
- def replies_uri_for(target, page_params = nil)
- raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?
-
- replies_account_status_url(target.account, target, page_params)
- end
-
- # Primary audience of a status
- # Public statuses go out to primarily the public collection
- # Unlisted and private statuses go out primarily to the followers collection
- # Others go out only to the people they mention
- def to(status)
- case status.visibility
- when 'public'
- [COLLECTIONS[:public]]
- when 'unlisted', 'private'
- [account_followers_url(status.account)]
- when 'direct', 'limited'
- if status.account.silenced?
- # Only notify followers if the account is locally silenced
- account_ids = status.active_mentions.pluck(:account_id)
- to = status.account.followers.where(id: account_ids).map { |account| uri_for(account) }
- to.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).map { |request| uri_for(request.account) })
- else
- status.active_mentions.map { |mention| uri_for(mention.account) }
- end
- end
- end
-
- # Secondary audience of a status
- # Public statuses go out to followers as well
- # Unlisted statuses go to the public as well
- # Both of those and private statuses also go to the people mentioned in them
- # Direct ones don't have a secondary audience
- def cc(status)
- cc = []
-
- cc << uri_for(status.reblog.account) if status.reblog?
-
- case status.visibility
- when 'public'
- cc << account_followers_url(status.account)
- when 'unlisted'
- cc << COLLECTIONS[:public]
- end
-
- unless status.direct_visibility? || status.limited_visibility?
- if status.account.silenced?
- # Only notify followers if the account is locally silenced
- account_ids = status.active_mentions.pluck(:account_id)
- cc.concat(status.account.followers.where(id: account_ids).map { |account| uri_for(account) })
- cc.concat(FollowRequest.where(target_account_id: status.account_id, account_id: account_ids).map { |request| uri_for(request.account) })
- else
- cc.concat(status.active_mentions.map { |mention| uri_for(mention.account) })
- end
- end
-
- cc
- end
-
- def local_uri?(uri)
- return false if uri.nil?
-
- uri = Addressable::URI.parse(uri)
- host = uri.normalized_host
- host = "#{host}:#{uri.port}" if uri.port
-
- !host.nil? && (::TagManager.instance.local_domain?(host) || ::TagManager.instance.web_domain?(host))
- end
-
- def uri_to_local_id(uri, param = :id)
- path_params = Rails.application.routes.recognize_path(uri)
- path_params[param]
- end
-
- def uri_to_resource(uri, klass)
- return if uri.nil?
-
- if local_uri?(uri)
- case klass.name
- when 'Account'
- klass.find_local(uri_to_local_id(uri, :username))
- else
- StatusFinder.new(uri).status
- end
- elsif OStatus::TagManager.instance.local_id?(uri)
- klass.find_by(id: OStatus::TagManager.instance.unique_tag_to_local_id(uri, klass.to_s))
- else
- klass.find_by(uri: uri.split('#').first)
- end
- rescue ActiveRecord::RecordNotFound
- nil
- end
-end
diff --git a/app/lib/delivery_failure_tracker.rb b/app/lib/delivery_failure_tracker.rb
deleted file mode 100644
index 8d3be35d..00000000
--- a/app/lib/delivery_failure_tracker.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-class DeliveryFailureTracker
- FAILURE_DAYS_THRESHOLD = 7
-
- def initialize(inbox_url)
- @inbox_url = inbox_url
- end
-
- def track_failure!
- Redis.current.sadd(exhausted_deliveries_key, today)
- Redis.current.sadd('unavailable_inboxes', @inbox_url) if reached_failure_threshold?
- end
-
- def track_success!
- Redis.current.del(exhausted_deliveries_key)
- Redis.current.srem('unavailable_inboxes', @inbox_url)
- end
-
- def days
- Redis.current.scard(exhausted_deliveries_key) || 0
- end
-
- class << self
- def filter(arr)
- arr.reject(&method(:unavailable?))
- end
-
- def unavailable?(url)
- Redis.current.sismember('unavailable_inboxes', url)
- end
-
- def available?(url)
- !unavailable?(url)
- end
-
- def track_inverse_success!(from_account)
- new(from_account.inbox_url).track_success! if from_account.inbox_url.present?
- new(from_account.shared_inbox_url).track_success! if from_account.shared_inbox_url.present?
- end
- end
-
- private
-
- def exhausted_deliveries_key
- "exhausted_deliveries:#{@inbox_url}"
- end
-
- def today
- Time.now.utc.strftime('%Y%m%d')
- end
-
- def reached_failure_threshold?
- days >= FAILURE_DAYS_THRESHOLD
- end
-end
diff --git a/app/lib/entity_cache.rb b/app/lib/entity_cache.rb
index 8fff544a..d2a21630 100644
--- a/app/lib/entity_cache.rb
+++ b/app/lib/entity_cache.rb
@@ -8,7 +8,7 @@ class EntityCache
MAX_EXPIRATION = 7.days.freeze
def mention(username, domain)
- Rails.cache.fetch(to_key(:mention, username, domain), expires_in: MAX_EXPIRATION) { Account.select(:username, :domain, :url).find_remote(username, domain) }
+ Rails.cache.fetch(to_key(:mention, username, domain), expires_in: MAX_EXPIRATION) { Account.select(:username, :domain, :url).find_local(username) }
end
def emoji(shortcodes, domain)
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 0791251a..43348c91 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -6,7 +6,7 @@ class FeedManager
include Singleton
include Redisable
- MAX_ITEMS = 400
+ MAX_ITEMS = 150
# Must be <= MAX_ITEMS or the tracking sets will grow forever
REBLOG_FALLOFF = 40
@@ -40,18 +40,6 @@ class FeedManager
true
end
- def push_to_list(list, status)
- if status.reply? && status.in_reply_to_account_id != status.account_id
- should_filter = status.in_reply_to_account_id != list.account_id
- should_filter &&= !ListAccount.where(list_id: list.id, account_id: status.in_reply_to_account_id).exists?
- return false if should_filter
- end
- return false unless add_to_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?)
- trim(:list, list.id)
- PushUpdateWorker.perform_async(list.account_id, status.id, "timeline:list:#{list.id}") if push_update_required?("timeline:list:#{list.id}")
- true
- end
-
def unpush_from_list(list, status)
return false unless remove_from_feed(:list, list.id, status)
redis.publish("timeline:list:#{list.id}", Oj.dump(event: :delete, payload: status.id.to_s))
@@ -93,7 +81,7 @@ class FeedManager
end
query.each do |status|
- next if status.direct_visibility? || status.limited_visibility? || filter?(:home, status, into_account)
+ next if status.limited_visibility? || filter?(:home, status, into_account)
add_to_feed(:home, into_account.id, status, into_account.user&.aggregates_reblogs?)
end
@@ -173,9 +161,7 @@ class FeedManager
should_filter &&= status.account_id != status.in_reply_to_account_id # and it's not a self-reply
return should_filter
elsif status.reblog? # Filter out a reblog
- should_filter = Follow.where(account_id: receiver_id, target_account_id: status.account_id, show_reblogs: false).exists? # if the reblogger's reblogs are suppressed
should_filter ||= Block.where(account_id: status.reblog.account_id, target_account_id: receiver_id).exists? # or if the author of the reblogged status is blocking me
- should_filter ||= AccountDomainBlock.where(account_id: receiver_id, domain: status.reblog.account.domain).exists? # or the author's domain is blocked
return should_filter
end
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 8dcd82d0..cc178f88 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -457,12 +457,12 @@ class Formatter
"#{encode(prefix)} #{encode(text)}#{encode(suffix)} " + (cutoff ? " " : "")
end
- def hashtag_html(tag)
- "##{encode(tag)} "
+ def hashtag_html(tagName)
+ "##{encode(tagName)} "
end
- def cashtag_html(tag)
- "$#{encode(tag)} "
+ def cashtag_html(tagName)
+ "$#{encode(tagName)} "
end
def mention_html(account)
diff --git a/app/lib/ostatus/activity/base.rb b/app/lib/ostatus/activity/base.rb
deleted file mode 100644
index db70f199..00000000
--- a/app/lib/ostatus/activity/base.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::Base
- include Redisable
-
- def initialize(xml, account = nil, **options)
- @xml = xml
- @account = account
- @options = options
- end
-
- def status?
- [:activity, :note, :comment].include?(type)
- end
-
- def verb
- raw = @xml.at_xpath('./activity:verb', activity: OStatus::TagManager::AS_XMLNS).content
- OStatus::TagManager::VERBS.key(raw)
- rescue
- :post
- end
-
- def type
- raw = @xml.at_xpath('./activity:object-type', activity: OStatus::TagManager::AS_XMLNS).content
- OStatus::TagManager::TYPES.key(raw)
- rescue
- :activity
- end
-
- def id
- @xml.at_xpath('./xmlns:id', xmlns: OStatus::TagManager::XMLNS).content
- end
-
- def url
- link = @xml.xpath('./xmlns:link[@rel="alternate"]', xmlns: OStatus::TagManager::XMLNS).find { |link_candidate| link_candidate['type'] == 'text/html' }
- link.nil? ? nil : link['href']
- end
-
- def activitypub_uri
- link = @xml.xpath('./xmlns:link[@rel="alternate"]', xmlns: OStatus::TagManager::XMLNS).find { |link_candidate| ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(link_candidate['type']) }
- link.nil? ? nil : link['href']
- end
-
- def activitypub_uri?
- activitypub_uri.present?
- end
-
- private
-
- def find_status(uri)
- if OStatus::TagManager.instance.local_id?(uri)
- local_id = OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Status')
- return Status.find_by(id: local_id)
- elsif ActivityPub::TagManager.instance.local_uri?(uri)
- local_id = ActivityPub::TagManager.instance.uri_to_local_id(uri)
- return Status.find_by(id: local_id)
- end
-
- Status.find_by(uri: uri)
- end
-
- def find_activitypub_status(uri, href)
- tag_matches = /tag:([^,:]+)[^:]*:objectId=([\d]+)/.match(uri)
- href_matches = %r{/users/([^/]+)}.match(href)
-
- unless tag_matches.nil? || href_matches.nil?
- uri = "https://#{tag_matches[1]}/users/#{href_matches[1]}/statuses/#{tag_matches[2]}"
- Status.find_by(uri: uri)
- end
- end
-end
diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb
deleted file mode 100644
index 2b258afe..00000000
--- a/app/lib/ostatus/activity/creation.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::Creation < OStatus::Activity::Base
- def perform
- if redis.exists("delete_upon_arrival:#{@account.id}:#{id}")
- Rails.logger.debug "Delete for status #{id} was queued, ignoring"
- return [nil, false]
- end
-
- return [nil, false] if @account.suspended? || invalid_origin?
-
- RedisLock.acquire(lock_options) do |lock|
- if lock.acquired?
- # Return early if status already exists in db
- @status = find_status(id)
- return [@status, false] unless @status.nil?
- @status = process_status
- else
- raise GabSocial::RaceConditionError
- end
- end
-
- [@status, true]
- end
-
- def process_status
- Rails.logger.debug "Creating remote status #{id}"
- cached_reblog = reblog
- status = nil
-
- # Skip if the reblogged status is not public
- return if cached_reblog && !(cached_reblog.public_visibility? || cached_reblog.unlisted_visibility?)
-
- media_attachments = save_media.take(4)
-
- ApplicationRecord.transaction do
- status = Status.create!(
- uri: id,
- url: url,
- account: @account,
- reblog: cached_reblog,
- text: content,
- spoiler_text: content_warning,
- created_at: published,
- override_timestamps: @options[:override_timestamps],
- reply: thread?,
- language: content_language,
- visibility: visibility_scope,
- conversation: find_or_create_conversation,
- thread: thread? ? find_status(thread.first) || find_activitypub_status(thread.first, thread.second) : nil,
- media_attachment_ids: media_attachments.map(&:id),
- sensitive: sensitive?
- )
-
- save_mentions(status)
- save_hashtags(status)
- save_emojis(status)
- end
-
- if thread? && status.thread.nil? && Request.valid_url?(thread.second)
- Rails.logger.debug "Trying to attach #{status.id} (#{id}) to #{thread.first}"
- ThreadResolveWorker.perform_async(status.id, thread.second)
- end
-
- Rails.logger.debug "Queuing remote status #{status.id} (#{id}) for distribution"
-
- LinkCrawlWorker.perform_async(status.id) unless status.spoiler_text?
-
- # Only continue if the status is supposed to have arrived in real-time.
- # Note that if @options[:override_timestamps] isn't set, the status
- # may have a lower snowflake id than other existing statuses, potentially
- # "hiding" it from paginated API calls
- return status unless @options[:override_timestamps] || status.within_realtime_window?
-
- DistributionWorker.perform_async(status.id)
-
- status
- end
-
- def content
- @xml.at_xpath('./xmlns:content', xmlns: OStatus::TagManager::XMLNS).content
- end
-
- def content_language
- @xml.at_xpath('./xmlns:content', xmlns: OStatus::TagManager::XMLNS)['xml:lang']&.presence || 'en'
- end
-
- def content_warning
- @xml.at_xpath('./xmlns:summary', xmlns: OStatus::TagManager::XMLNS)&.content || ''
- end
-
- def visibility_scope
- @xml.at_xpath('./mastodon:scope', mastodon: OStatus::TagManager::MTDN_XMLNS)&.content&.to_sym || :public
- end
-
- def published
- @xml.at_xpath('./xmlns:published', xmlns: OStatus::TagManager::XMLNS).content
- end
-
- def thread?
- !@xml.at_xpath('./thr:in-reply-to', thr: OStatus::TagManager::THR_XMLNS).nil?
- end
-
- def thread
- thr = @xml.at_xpath('./thr:in-reply-to', thr: OStatus::TagManager::THR_XMLNS)
- [thr['ref'], thr['href']]
- end
-
- private
-
- def sensitive?
- # OStatus-specific convention (not standard)
- @xml.xpath('./xmlns:category', xmlns: OStatus::TagManager::XMLNS).any? { |category| category['term'] == 'nsfw' }
- end
-
- def find_or_create_conversation
- uri = @xml.at_xpath('./ostatus:conversation', ostatus: OStatus::TagManager::OS_XMLNS)&.attribute('ref')&.content
- return if uri.nil?
-
- if OStatus::TagManager.instance.local_id?(uri)
- local_id = OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Conversation')
- return Conversation.find_by(id: local_id)
- end
-
- Conversation.find_by(uri: uri) || Conversation.create!(uri: uri)
- end
-
- def save_mentions(parent)
- processed_account_ids = []
-
- @xml.xpath('./xmlns:link[@rel="mentioned"]', xmlns: OStatus::TagManager::XMLNS).each do |link|
- next if [OStatus::TagManager::TYPES[:group], OStatus::TagManager::TYPES[:collection]].include? link['ostatus:object-type']
-
- mentioned_account = account_from_href(link['href'])
-
- next if mentioned_account.nil? || processed_account_ids.include?(mentioned_account.id)
-
- mentioned_account.mentions.where(status: parent).first_or_create(status: parent)
-
- # So we can skip duplicate mentions
- processed_account_ids << mentioned_account.id
- end
- end
-
- def save_hashtags(parent)
- tags = @xml.xpath('./xmlns:category', xmlns: OStatus::TagManager::XMLNS).map { |category| category['term'] }.select(&:present?)
- ProcessHashtagsService.new.call(parent, tags)
- end
-
- def save_media
- do_not_download = DomainBlock.find_by(domain: @account.domain)&.reject_media?
- media_attachments = []
-
- @xml.xpath('./xmlns:link[@rel="enclosure"]', xmlns: OStatus::TagManager::XMLNS).each do |link|
- next unless link['href']
-
- media = MediaAttachment.where(status: nil, remote_url: link['href']).first_or_initialize(account: @account, status: nil, remote_url: link['href'])
- parsed_url = Addressable::URI.parse(link['href']).normalize
-
- next if !%w(http https).include?(parsed_url.scheme) || parsed_url.host.empty?
-
- media.save
- media_attachments << media
-
- next if do_not_download
-
- begin
- media.file_remote_url = link['href']
- media.save!
- rescue ActiveRecord::RecordInvalid
- next
- end
- end
-
- media_attachments
- end
-
- def save_emojis(parent)
- do_not_download = DomainBlock.find_by(domain: parent.account.domain)&.reject_media?
-
- return if do_not_download
-
- @xml.xpath('./xmlns:link[@rel="emoji"]', xmlns: OStatus::TagManager::XMLNS).each do |link|
- next unless link['href'] && link['name']
-
- shortcode = link['name'].delete(':')
- emoji = CustomEmoji.find_by(shortcode: shortcode, domain: parent.account.domain)
-
- next unless emoji.nil?
-
- emoji = CustomEmoji.new(shortcode: shortcode, domain: parent.account.domain)
- emoji.image_remote_url = link['href']
- emoji.save
- end
- end
-
- def account_from_href(href)
- url = Addressable::URI.parse(href).normalize
-
- if TagManager.instance.web_domain?(url.host)
- Account.find_local(url.path.gsub('/users/', ''))
- else
- Account.where(uri: href).or(Account.where(url: href)).first || FetchRemoteAccountService.new.call(href)
- end
- end
-
- def invalid_origin?
- return false unless id.start_with?('http') # Legacy IDs cannot be checked
-
- needle = Addressable::URI.parse(id).normalized_host
-
- !(needle.casecmp(@account.domain).zero? ||
- needle.casecmp(Addressable::URI.parse(@account.remote_url.presence || @account.uri).normalized_host).zero?)
- end
-
- def lock_options
- { redis: Redis.current, key: "create:#{id}" }
- end
-end
diff --git a/app/lib/ostatus/activity/deletion.rb b/app/lib/ostatus/activity/deletion.rb
deleted file mode 100644
index c98f5ee0..00000000
--- a/app/lib/ostatus/activity/deletion.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::Deletion < OStatus::Activity::Base
- def perform
- Rails.logger.debug "Deleting remote status #{id}"
-
- status = Status.find_by(uri: id, account: @account)
- status ||= Status.find_by(uri: activitypub_uri, account: @account) if activitypub_uri?
-
- if status.nil?
- redis.setex("delete_upon_arrival:#{@account.id}:#{id}", 6 * 3_600, id)
- else
- RemoveStatusService.new.call(status)
- end
- end
-end
diff --git a/app/lib/ostatus/activity/general.rb b/app/lib/ostatus/activity/general.rb
deleted file mode 100644
index 8a6aabc3..00000000
--- a/app/lib/ostatus/activity/general.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::General < OStatus::Activity::Base
- def specialize
- special_class&.new(@xml, @account, @options)
- end
-
- private
-
- def special_class
- case verb
- when :post
- OStatus::Activity::Post
- when :share
- OStatus::Activity::Share
- when :delete
- OStatus::Activity::Deletion
- end
- end
-end
diff --git a/app/lib/ostatus/activity/post.rb b/app/lib/ostatus/activity/post.rb
deleted file mode 100644
index 755ed865..00000000
--- a/app/lib/ostatus/activity/post.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::Post < OStatus::Activity::Creation
- def perform
- status, just_created = super
-
- if just_created
- status.mentions.includes(:account).each do |mention|
- mentioned_account = mention.account
- next unless mentioned_account.local?
- NotifyService.new.call(mentioned_account, mention)
- end
- end
-
- status
- end
-
- private
-
- def reblog
- nil
- end
-end
diff --git a/app/lib/ostatus/activity/remote.rb b/app/lib/ostatus/activity/remote.rb
deleted file mode 100644
index 5b204b6d..00000000
--- a/app/lib/ostatus/activity/remote.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::Remote < OStatus::Activity::Base
- def perform
- if activitypub_uri?
- find_status(activitypub_uri) || FetchRemoteStatusService.new.call(url)
- else
- find_status(id) || FetchRemoteStatusService.new.call(url)
- end
- end
-end
diff --git a/app/lib/ostatus/activity/share.rb b/app/lib/ostatus/activity/share.rb
deleted file mode 100644
index 5ca60141..00000000
--- a/app/lib/ostatus/activity/share.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::Activity::Share < OStatus::Activity::Creation
- def perform
- return if reblog.nil?
-
- status, just_created = super
- NotifyService.new.call(reblog.account, status) if reblog.account.local? && just_created
- status
- end
-
- def object
- @xml.at_xpath('.//activity:object', activity: OStatus::TagManager::AS_XMLNS)
- end
-
- private
-
- def reblog
- return @reblog if defined? @reblog
-
- original_status = OStatus::Activity::Remote.new(object).perform
- return if original_status.nil?
-
- @reblog = original_status.reblog? ? original_status.reblog : original_status
- end
-end
diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb
deleted file mode 100644
index 962a6151..00000000
--- a/app/lib/ostatus/atom_serializer.rb
+++ /dev/null
@@ -1,377 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::AtomSerializer
- include RoutingHelper
- include ActionView::Helpers::SanitizeHelper
-
- class << self
- def render(element)
- document = Ox::Document.new(version: '1.0')
- document << element
- ('' + Ox.dump(element, effort: :tolerant)).force_encoding('UTF-8')
- end
- end
-
- def author(account)
- author = Ox::Element.new('author')
-
- uri = OStatus::TagManager.instance.uri_for(account)
-
- append_element(author, 'id', uri)
- append_element(author, 'activity:object-type', OStatus::TagManager::TYPES[:person])
- append_element(author, 'uri', uri)
- append_element(author, 'name', account.username)
- append_element(author, 'email', account.local? ? account.local_username_and_domain : account.acct)
- append_element(author, 'summary', Formatter.instance.simplified_format(account).to_str, type: :html) if account.note?
- append_element(author, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(account))
- append_element(author, 'link', nil, rel: :avatar, type: account.avatar_content_type, 'media:width': 120, 'media:height': 120, href: full_asset_url(account.avatar.url(:original))) if account.avatar?
- append_element(author, 'link', nil, rel: :header, type: account.header_content_type, 'media:width': 700, 'media:height': 335, href: full_asset_url(account.header.url(:original))) if account.header?
- account.emojis.each do |emoji|
- append_element(author, 'link', nil, rel: :emoji, href: full_asset_url(emoji.image.url), name: emoji.shortcode)
- end
- append_element(author, 'poco:preferredUsername', account.username)
- append_element(author, 'poco:displayName', account.display_name) if account.display_name?
- append_element(author, 'poco:note', account.local? ? account.note : strip_tags(account.note)) if account.note?
- append_element(author, 'mastodon:scope', account.locked? ? :private : :public)
-
- author
- end
-
- def feed(account, stream_entries)
- feed = Ox::Element.new('feed')
-
- add_namespaces(feed)
-
- append_element(feed, 'id', account_url(account, format: 'atom'))
- append_element(feed, 'title', account.display_name.presence || account.username)
- append_element(feed, 'subtitle', account.note)
- append_element(feed, 'updated', account.updated_at.iso8601)
- append_element(feed, 'logo', full_asset_url(account.avatar.url(:original)))
-
- feed << author(account)
-
- append_element(feed, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(account))
- append_element(feed, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_url(account, format: 'atom'))
- append_element(feed, 'link', nil, rel: :next, type: 'application/atom+xml', href: account_url(account, format: 'atom', max_id: stream_entries.last.id)) if stream_entries.size == 20
- append_element(feed, 'link', nil, rel: :hub, href: api_push_url)
-
- stream_entries.each do |stream_entry|
- feed << entry(stream_entry)
- end
-
- feed
- end
-
- def entry(stream_entry, root = false)
- entry = Ox::Element.new('entry')
-
- add_namespaces(entry) if root
-
- append_element(entry, 'id', OStatus::TagManager.instance.uri_for(stream_entry.status))
- append_element(entry, 'published', stream_entry.created_at.iso8601)
- append_element(entry, 'updated', stream_entry.updated_at.iso8601)
- append_element(entry, 'title', stream_entry&.status&.title || "#{stream_entry.account.acct} deleted status")
-
- entry << author(stream_entry.account) if root
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[stream_entry.object_type])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[stream_entry.verb])
-
- entry << object(stream_entry.target) if stream_entry.targeted?
-
- if stream_entry.status.nil?
- append_element(entry, 'content', 'Deleted status')
- elsif stream_entry.status.destroyed?
- append_element(entry, 'content', 'Deleted status')
- append_element(entry, 'link', nil, rel: :alternate, type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(stream_entry.status)) if stream_entry.account.local?
- else
- serialize_status_attributes(entry, stream_entry.status)
- end
-
- append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(stream_entry.status))
- append_element(entry, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom'))
- append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(stream_entry.thread), href: ::TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded?
- append_element(entry, 'ostatus:conversation', nil, ref: conversation_uri(stream_entry.status.conversation)) unless stream_entry&.status&.conversation_id.nil?
-
- entry
- end
-
- def object(status)
- object = Ox::Element.new('activity:object')
-
- append_element(object, 'id', OStatus::TagManager.instance.uri_for(status))
- append_element(object, 'published', status.created_at.iso8601)
- append_element(object, 'updated', status.updated_at.iso8601)
- append_element(object, 'title', status.title)
-
- object << author(status.account)
-
- append_element(object, 'activity:object-type', OStatus::TagManager::TYPES[status.object_type])
- append_element(object, 'activity:verb', OStatus::TagManager::VERBS[status.verb])
-
- serialize_status_attributes(object, status)
-
- append_element(object, 'link', nil, rel: :alternate, type: 'text/html', href: ::TagManager.instance.url_for(status))
- append_element(object, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(status.thread), href: ::TagManager.instance.url_for(status.thread)) unless status.thread.nil?
- append_element(object, 'ostatus:conversation', nil, ref: conversation_uri(status.conversation)) unless status.conversation_id.nil?
-
- object
- end
-
- def follow_salmon(follow)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- description = "#{follow.account.acct} started following #{follow.target_account.acct}"
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(follow.created_at, follow.id, 'Follow'))
- append_element(entry, 'title', description)
- append_element(entry, 'content', description, type: :html)
-
- entry << author(follow.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:follow])
-
- object = author(follow.target_account)
- object.value = 'activity:object'
-
- entry << object
- entry
- end
-
- def follow_request_salmon(follow_request)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(follow_request.created_at, follow_request.id, 'FollowRequest'))
- append_element(entry, 'title', "#{follow_request.account.acct} requested to follow #{follow_request.target_account.acct}")
-
- entry << author(follow_request.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:request_friend])
-
- object = author(follow_request.target_account)
- object.value = 'activity:object'
-
- entry << object
- entry
- end
-
- def authorize_follow_request_salmon(follow_request)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(Time.now.utc, follow_request.id, 'FollowRequest'))
- append_element(entry, 'title', "#{follow_request.target_account.acct} authorizes follow request by #{follow_request.account.acct}")
-
- entry << author(follow_request.target_account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:authorize])
-
- object = Ox::Element.new('activity:object')
- object << author(follow_request.account)
-
- append_element(object, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(object, 'activity:verb', OStatus::TagManager::VERBS[:request_friend])
-
- inner_object = author(follow_request.target_account)
- inner_object.value = 'activity:object'
-
- object << inner_object
- entry << object
- entry
- end
-
- def reject_follow_request_salmon(follow_request)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(Time.now.utc, follow_request.id, 'FollowRequest'))
- append_element(entry, 'title', "#{follow_request.target_account.acct} rejects follow request by #{follow_request.account.acct}")
-
- entry << author(follow_request.target_account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:reject])
-
- object = Ox::Element.new('activity:object')
- object << author(follow_request.account)
-
- append_element(object, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(object, 'activity:verb', OStatus::TagManager::VERBS[:request_friend])
-
- inner_object = author(follow_request.target_account)
- inner_object.value = 'activity:object'
-
- object << inner_object
- entry << object
- entry
- end
-
- def unfollow_salmon(follow)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- description = "#{follow.account.acct} is no longer following #{follow.target_account.acct}"
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(Time.now.utc, follow.id, 'Follow'))
- append_element(entry, 'title', description)
- append_element(entry, 'content', description, type: :html)
-
- entry << author(follow.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:unfollow])
-
- object = author(follow.target_account)
- object.value = 'activity:object'
-
- entry << object
- entry
- end
-
- def block_salmon(block)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- description = "#{block.account.acct} no longer wishes to interact with #{block.target_account.acct}"
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(Time.now.utc, block.id, 'Block'))
- append_element(entry, 'title', description)
-
- entry << author(block.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:block])
-
- object = author(block.target_account)
- object.value = 'activity:object'
-
- entry << object
- entry
- end
-
- def unblock_salmon(block)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- description = "#{block.account.acct} no longer blocks #{block.target_account.acct}"
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(Time.now.utc, block.id, 'Block'))
- append_element(entry, 'title', description)
-
- entry << author(block.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:unblock])
-
- object = author(block.target_account)
- object.value = 'activity:object'
-
- entry << object
- entry
- end
-
- def favourite_salmon(favourite)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- description = "#{favourite.account.acct} favorited a status by #{favourite.status.account.acct}"
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(favourite.created_at, favourite.id, 'Favourite'))
- append_element(entry, 'title', description)
- append_element(entry, 'content', description, type: :html)
-
- entry << author(favourite.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:favorite])
-
- entry << object(favourite.status)
-
- append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(favourite.status), href: ::TagManager.instance.url_for(favourite.status))
-
- entry
- end
-
- def unfavourite_salmon(favourite)
- entry = Ox::Element.new('entry')
- add_namespaces(entry)
-
- description = "#{favourite.account.acct} no longer favorites a status by #{favourite.status.account.acct}"
-
- append_element(entry, 'id', OStatus::TagManager.instance.unique_tag(Time.now.utc, favourite.id, 'Favourite'))
- append_element(entry, 'title', description)
- append_element(entry, 'content', description, type: :html)
-
- entry << author(favourite.account)
-
- append_element(entry, 'activity:object-type', OStatus::TagManager::TYPES[:activity])
- append_element(entry, 'activity:verb', OStatus::TagManager::VERBS[:unfavorite])
-
- entry << object(favourite.status)
-
- append_element(entry, 'thr:in-reply-to', nil, ref: OStatus::TagManager.instance.uri_for(favourite.status), href: ::TagManager.instance.url_for(favourite.status))
-
- entry
- end
-
- private
-
- def append_element(parent, name, content = nil, **attributes)
- element = Ox::Element.new(name)
- attributes.each { |k, v| element[k] = sanitize_str(v) }
- element << sanitize_str(content) unless content.nil?
- parent << element
- end
-
- def sanitize_str(raw_str)
- raw_str.to_s
- end
-
- def conversation_uri(conversation)
- return conversation.uri if conversation.uri?
- OStatus::TagManager.instance.unique_tag(conversation.created_at, conversation.id, 'Conversation')
- end
-
- def add_namespaces(parent)
- parent['xmlns'] = OStatus::TagManager::XMLNS
- parent['xmlns:thr'] = OStatus::TagManager::THR_XMLNS
- parent['xmlns:activity'] = OStatus::TagManager::AS_XMLNS
- parent['xmlns:poco'] = OStatus::TagManager::POCO_XMLNS
- parent['xmlns:media'] = OStatus::TagManager::MEDIA_XMLNS
- parent['xmlns:ostatus'] = OStatus::TagManager::OS_XMLNS
- parent['xmlns:mastodon'] = OStatus::TagManager::MTDN_XMLNS
- end
-
- def serialize_status_attributes(entry, status)
- append_element(entry, 'link', nil, rel: :alternate, type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(status)) if status.account.local?
-
- append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text?
- append_element(entry, 'content', Formatter.instance.format(status, inline_poll_options: true).to_str || '.', type: 'html', 'xml:lang': status.language)
-
- status.active_mentions.sort_by(&:id).each do |mentioned|
- append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account))
- end
-
- append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:collection], href: OStatus::TagManager::COLLECTIONS[:public]) if status.public_visibility?
-
- status.tags.each do |tag|
- append_element(entry, 'category', nil, term: tag.name)
- end
-
- status.media_attachments.each do |media|
- append_element(entry, 'link', nil, rel: :enclosure, type: media.file_content_type, length: media.file_file_size, href: full_asset_url(media.file.url(:original, false)))
- end
-
- append_element(entry, 'category', nil, term: 'nsfw') if status.sensitive? && status.media_attachments.any?
- append_element(entry, 'mastodon:scope', status.visibility)
-
- status.emojis.each do |emoji|
- append_element(entry, 'link', nil, rel: :emoji, href: full_asset_url(emoji.image.url), name: emoji.shortcode)
- end
- end
-end
diff --git a/app/lib/ostatus/tag_manager.rb b/app/lib/ostatus/tag_manager.rb
deleted file mode 100644
index e04b4144..00000000
--- a/app/lib/ostatus/tag_manager.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-class OStatus::TagManager
- include Singleton
- include RoutingHelper
-
- VERBS = {
- post: 'http://activitystrea.ms/schema/1.0/post',
- share: 'http://activitystrea.ms/schema/1.0/share',
- favorite: 'http://activitystrea.ms/schema/1.0/favorite',
- unfavorite: 'http://activitystrea.ms/schema/1.0/unfavorite',
- delete: 'http://activitystrea.ms/schema/1.0/delete',
- follow: 'http://activitystrea.ms/schema/1.0/follow',
- request_friend: 'http://activitystrea.ms/schema/1.0/request-friend',
- authorize: 'http://activitystrea.ms/schema/1.0/authorize',
- reject: 'http://activitystrea.ms/schema/1.0/reject',
- unfollow: 'http://ostatus.org/schema/1.0/unfollow',
- block: 'http://mastodon.social/schema/1.0/block',
- unblock: 'http://mastodon.social/schema/1.0/unblock',
- }.freeze
-
- TYPES = {
- activity: 'http://activitystrea.ms/schema/1.0/activity',
- note: 'http://activitystrea.ms/schema/1.0/note',
- comment: 'http://activitystrea.ms/schema/1.0/comment',
- person: 'http://activitystrea.ms/schema/1.0/person',
- collection: 'http://activitystrea.ms/schema/1.0/collection',
- group: 'http://activitystrea.ms/schema/1.0/group',
- }.freeze
-
- COLLECTIONS = {
- public: 'http://activityschema.org/collection/public',
- }.freeze
-
- XMLNS = 'http://www.w3.org/2005/Atom'
- MEDIA_XMLNS = 'http://purl.org/syndication/atommedia'
- AS_XMLNS = 'http://activitystrea.ms/spec/1.0/'
- THR_XMLNS = 'http://purl.org/syndication/thread/1.0'
- POCO_XMLNS = 'http://portablecontacts.net/spec/1.0'
- DFRN_XMLNS = 'http://purl.org/macgirvin/dfrn/1.0'
- OS_XMLNS = 'http://ostatus.org/schema/1.0'
- MTDN_XMLNS = 'http://mastodon.social/schema/1.0'
-
- def unique_tag(date, id, type)
- "tag:#{Rails.configuration.x.local_domain},#{date.strftime('%Y-%m-%d')}:objectId=#{id}:objectType=#{type}"
- end
-
- def unique_tag_to_local_id(tag, expected_type)
- return nil unless local_id?(tag)
-
- if ActivityPub::TagManager.instance.local_uri?(tag)
- ActivityPub::TagManager.instance.uri_to_local_id(tag)
- else
- matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag)
- return matches[1] unless matches.nil?
- end
- end
-
- def local_id?(id)
- id.start_with?("tag:#{Rails.configuration.x.local_domain}") || ActivityPub::TagManager.instance.local_uri?(id)
- end
-
- def uri_for(target)
- return target.uri if target.respond_to?(:local?) && !target.local?
-
- case target.object_type
- when :person
- account_url(target)
- when :note, :comment, :activity
- target.uri || unique_tag(target.created_at, target.id, 'Status')
- end
- end
-end
diff --git a/app/lib/proof_provider.rb b/app/lib/proof_provider.rb
deleted file mode 100644
index 102c50f4..00000000
--- a/app/lib/proof_provider.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module ProofProvider
- SUPPORTED_PROVIDERS = %w(keybase).freeze
-
- def self.find(identifier, proof = nil)
- case identifier
- when 'keybase'
- ProofProvider::Keybase.new(proof)
- end
- end
-end
diff --git a/app/lib/proof_provider/keybase.rb b/app/lib/proof_provider/keybase.rb
deleted file mode 100644
index 8e51d714..00000000
--- a/app/lib/proof_provider/keybase.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-
-class ProofProvider::Keybase
- BASE_URL = ENV.fetch('KEYBASE_BASE_URL', 'https://keybase.io')
- DOMAIN = ENV.fetch('KEYBASE_DOMAIN', Rails.configuration.x.web_domain)
-
- class Error < StandardError; end
-
- class ExpectedProofLiveError < Error; end
-
- class UnexpectedResponseError < Error; end
-
- def initialize(proof = nil)
- @proof = proof
- end
-
- def serializer_class
- ProofProvider::Keybase::Serializer
- end
-
- def worker_class
- ProofProvider::Keybase::Worker
- end
-
- def validate!
- unless @proof.token&.size == 66
- @proof.errors.add(:base, I18n.t('identity_proofs.errors.keybase.invalid_token'))
- return
- end
-
- # Do not perform synchronous validation for remote accounts
- return if @proof.provider_username.blank? || !@proof.account.local?
-
- if verifier.valid?
- @proof.verified = true
- @proof.live = false
- else
- @proof.errors.add(:base, I18n.t('identity_proofs.errors.keybase.verification_failed', kb_username: @proof.provider_username))
- end
- end
-
- def refresh!
- worker_class.new.perform(@proof)
- rescue ProofProvider::Keybase::Error
- nil
- end
-
- def on_success_path(user_agent = nil)
- verifier.on_success_path(user_agent)
- end
-
- def badge
- @badge ||= ProofProvider::Keybase::Badge.new(@proof.account.username, @proof.provider_username, @proof.token, domain)
- end
-
- def verifier
- @verifier ||= ProofProvider::Keybase::Verifier.new(@proof.account.username, @proof.provider_username, @proof.token, domain)
- end
-
- private
-
- def domain
- if @proof.account.local?
- DOMAIN
- else
- @proof.account.domain
- end
- end
-end
diff --git a/app/lib/proof_provider/keybase/badge.rb b/app/lib/proof_provider/keybase/badge.rb
deleted file mode 100644
index f587b1cc..00000000
--- a/app/lib/proof_provider/keybase/badge.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-class ProofProvider::Keybase::Badge
- include RoutingHelper
-
- def initialize(local_username, provider_username, token, domain)
- @local_username = local_username
- @provider_username = provider_username
- @token = token
- @domain = domain
- end
-
- def proof_url
- "#{ProofProvider::Keybase::BASE_URL}/#{@provider_username}/sigchain\##{@token}"
- end
-
- def profile_url
- "#{ProofProvider::Keybase::BASE_URL}/#{@provider_username}"
- end
-
- def icon_url
- "#{ProofProvider::Keybase::BASE_URL}/#{@provider_username}/proof_badge/#{@token}?username=#{@local_username}&domain=#{@domain}"
- end
-
- def avatar_url
- Rails.cache.fetch("proof_providers/keybase/#{@provider_username}/avatar_url", expires_in: 5.minutes) { remote_avatar_url } || default_avatar_url
- end
-
- private
-
- def remote_avatar_url
- request = Request.new(:get, "#{ProofProvider::Keybase::BASE_URL}/_/api/1.0/user/pic_url.json", params: { username: @provider_username })
-
- request.perform do |res|
- json = Oj.load(res.body_with_limit, mode: :strict)
- json['pic_url'] if json.is_a?(Hash)
- end
- rescue Oj::ParseError, HTTP::Error, OpenSSL::SSL::SSLError
- nil
- end
-
- def default_avatar_url
- asset_pack_path('media/images/proof_providers/keybase.png')
- end
-end
diff --git a/app/lib/proof_provider/keybase/config_serializer.rb b/app/lib/proof_provider/keybase/config_serializer.rb
deleted file mode 100644
index 7e90120f..00000000
--- a/app/lib/proof_provider/keybase/config_serializer.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer
- include RoutingHelper
- include ActionView::Helpers::TextHelper
-
- attributes :version, :domain, :display_name, :username,
- :brand_color, :logo, :description, :prefill_url,
- :profile_url, :check_url, :check_path, :avatar_path,
- :contact
-
- def version
- 1
- end
-
- def domain
- ProofProvider::Keybase::DOMAIN
- end
-
- def display_name
- Setting::SITE_TITLE
- end
-
- def logo
- { svg_black: full_asset_url(asset_pack_path('media/images/logo_transparent_black.svg')), svg_full: full_asset_url(asset_pack_path('media/images/logo.png')) }
- end
-
- def brand_color
- '#21D07B'
- end
-
- def description
- strip_tags(Setting.site_short_description.presence || I18n.t('about.about_gabsocial_html'))
- end
-
- def username
- { min: 1, max: 30, re: '[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?' }
- end
-
- def prefill_url
- params = {
- provider: 'keybase',
- token: '%{sig_hash}',
- provider_username: '%{kb_username}',
- username: '%{username}',
- user_agent: '%{kb_ua}',
- }
-
- CGI.unescape(new_settings_identity_proof_url(params))
- end
-
- def profile_url
- CGI.unescape(short_account_url('%{username}')) # rubocop:disable Style/FormatStringToken
- end
-
- def check_url
- CGI.unescape(api_proofs_url(username: '%{username}', provider: 'keybase'))
- end
-
- def check_path
- ['signatures']
- end
-
- def avatar_path
- ['avatar']
- end
-
- def contact
- [Setting.site_contact_email.presence || 'unknown'].compact
- end
-end
diff --git a/app/lib/proof_provider/keybase/serializer.rb b/app/lib/proof_provider/keybase/serializer.rb
deleted file mode 100644
index d2928360..00000000
--- a/app/lib/proof_provider/keybase/serializer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class ProofProvider::Keybase::Serializer < ActiveModel::Serializer
- include RoutingHelper
-
- attribute :avatar
-
- has_many :identity_proofs, key: :signatures
-
- def avatar
- full_asset_url(object.avatar_original_url)
- end
-
- class AccountIdentityProofSerializer < ActiveModel::Serializer
- attributes :sig_hash, :kb_username
-
- def sig_hash
- object.token
- end
-
- def kb_username
- object.provider_username
- end
- end
-end
diff --git a/app/lib/proof_provider/keybase/verifier.rb b/app/lib/proof_provider/keybase/verifier.rb
deleted file mode 100644
index af69b1bf..00000000
--- a/app/lib/proof_provider/keybase/verifier.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-class ProofProvider::Keybase::Verifier
- def initialize(local_username, provider_username, token, domain)
- @local_username = local_username
- @provider_username = provider_username
- @token = token
- @domain = domain
- end
-
- def valid?
- request = Request.new(:get, "#{ProofProvider::Keybase::BASE_URL}/_/api/1.0/sig/proof_valid.json", params: query_params)
-
- request.perform do |res|
- json = Oj.load(res.body_with_limit, mode: :strict)
-
- if json.is_a?(Hash)
- json.fetch('proof_valid', false)
- else
- false
- end
- end
- rescue Oj::ParseError, HTTP::Error, OpenSSL::SSL::SSLError
- false
- end
-
- def on_success_path(user_agent = nil)
- url = Addressable::URI.parse("#{ProofProvider::Keybase::BASE_URL}/_/proof_creation_success")
- url.query_values = query_params.merge(kb_ua: user_agent || 'unknown')
- url.to_s
- end
-
- def status
- request = Request.new(:get, "#{ProofProvider::Keybase::BASE_URL}/_/api/1.0/sig/proof_live.json", params: query_params)
-
- request.perform do |res|
- raise ProofProvider::Keybase::UnexpectedResponseError unless res.code == 200
-
- json = Oj.load(res.body_with_limit, mode: :strict)
-
- raise ProofProvider::Keybase::UnexpectedResponseError unless json.is_a?(Hash) && json.key?('proof_valid') && json.key?('proof_live')
-
- json
- end
- rescue Oj::ParseError, HTTP::Error, OpenSSL::SSL::SSLError
- raise ProofProvider::Keybase::UnexpectedResponseError
- end
-
- private
-
- def query_params
- {
- domain: @domain,
- kb_username: @provider_username,
- username: @local_username,
- sig_hash: @token,
- }
- end
-end
diff --git a/app/lib/proof_provider/keybase/worker.rb b/app/lib/proof_provider/keybase/worker.rb
deleted file mode 100644
index df6f5876..00000000
--- a/app/lib/proof_provider/keybase/worker.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class ProofProvider::Keybase::Worker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: 20, unique: :until_executed
-
- sidekiq_retry_in do |count, exception|
- # Retry aggressively when the proof is valid but not live in Keybase.
- # This is likely because Keybase just hasn't noticed the proof being
- # served from here yet.
-
- if exception.class == ProofProvider::Keybase::ExpectedProofLiveError
- case count
- when 0..2 then 0.seconds
- when 2..6 then 1.second
- end
- end
- end
-
- def perform(proof_id)
- proof = proof_id.is_a?(AccountIdentityProof) ? proof_id : AccountIdentityProof.find(proof_id)
- status = proof.provider_instance.verifier.status
-
- # If Keybase thinks the proof is valid, and it exists here in Gab Social,
- # then it should be live. Keybase just has to notice that it's here
- # and then update its state. That might take a couple seconds.
- raise ProofProvider::Keybase::ExpectedProofLiveError if status['proof_valid'] && !status['proof_live']
-
- proof.update!(verified: status['proof_valid'], live: status['proof_live'])
- end
-end
diff --git a/app/lib/request.rb b/app/lib/request.rb
index bbae44ea..cd3f1420 100644
--- a/app/lib/request.rb
+++ b/app/lib/request.rb
@@ -108,12 +108,8 @@ class Request
end
def key_id
- case @key_id_format
- when :acct
- @account.to_webfinger_s
- when :uri
- [ActivityPub::TagManager.instance.uri_for(@account), '#main-key'].join
- end
+ # : todo : remove
+ nil
end
def timeout
diff --git a/app/lib/rss_builder.rb b/app/lib/rss_builder.rb
deleted file mode 100644
index 63ddba2e..00000000
--- a/app/lib/rss_builder.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-
-class RSSBuilder
- class ItemBuilder
- def initialize
- @item = Ox::Element.new('item')
- end
-
- def title(str)
- @item << (Ox::Element.new('title') << str)
-
- self
- end
-
- def link(str)
- @item << Ox::Element.new('guid').tap do |guid|
- guid['isPermalink'] = 'true'
- guid << str
- end
-
- @item << (Ox::Element.new('link') << str)
-
- self
- end
-
- def pub_date(date)
- @item << (Ox::Element.new('pubDate') << date.to_formatted_s(:rfc822))
-
- self
- end
-
- def description(str)
- @item << (Ox::Element.new('description') << str)
-
- self
- end
-
- def enclosure(url, type, size)
- @item << Ox::Element.new('enclosure').tap do |enclosure|
- enclosure['url'] = url
- enclosure['length'] = size
- enclosure['type'] = type
- end
-
- self
- end
-
- def to_element
- @item
- end
- end
-
- def initialize
- @document = Ox::Document.new(version: '1.0')
- @channel = Ox::Element.new('channel')
-
- @document << (rss << @channel)
- end
-
- def title(str)
- @channel << (Ox::Element.new('title') << str)
-
- self
- end
-
- def link(str)
- @channel << (Ox::Element.new('link') << str)
-
- self
- end
-
- def image(str)
- @channel << Ox::Element.new('image').tap do |image|
- image << (Ox::Element.new('url') << str)
- image << (Ox::Element.new('title') << '')
- image << (Ox::Element.new('link') << '')
- end
-
- @channel << (Ox::Element.new('webfeeds:icon') << str)
-
- self
- end
-
- def cover(str)
- @channel << Ox::Element.new('webfeeds:cover').tap do |cover|
- cover['image'] = str
- end
-
- self
- end
-
- def logo(str)
- @channel << (Ox::Element.new('webfeeds:logo') << str)
-
- self
- end
-
- def accent_color(str)
- @channel << (Ox::Element.new('webfeeds:accentColor') << str)
-
- self
- end
-
- def description(str)
- @channel << (Ox::Element.new('description') << str)
-
- self
- end
-
- def item
- @channel << ItemBuilder.new.tap do |item|
- yield item
- end.to_element
-
- self
- end
-
- def to_xml
- ('' + Ox.dump(@document, effort: :tolerant)).force_encoding('UTF-8')
- end
-
- private
-
- def rss
- Ox::Element.new('rss').tap do |rss|
- rss['version'] = '2.0'
- rss['xmlns:webfeeds'] = 'http://webfeeds.org/rss/1.0'
- end
- end
-end
diff --git a/app/lib/sorting_query_builder.rb b/app/lib/sorting_query_builder.rb
new file mode 100644
index 00000000..b9be19d1
--- /dev/null
+++ b/app/lib/sorting_query_builder.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+class SortingQueryBuilder < BaseService
+ def call(sort_type, max_id = nil, group = nil)
+ min_likes = 20
+ min_reblogs = 10
+ min_replies = 2
+ date_limit = 30.days.ago
+
+ case sort_type
+ when 'hot'
+ date_limit = 8.hours.ago
+ when 'top_today'
+ date_limit = 24.hours.ago
+ when 'top_weekly'
+ date_limit = 7.days.ago
+ when 'top_monthly'
+ date_limit = 30.days.ago
+ when 'top_yearly'
+ date_limit = 1.year.ago
+ end
+
+ top_order = 'status_stats.favourites_count DESC, status_stats.reblogs_count DESC, status_stats.replies_count DESC'
+ valid_sort_types = [
+ 'hot',
+ 'newest',
+ 'recent',
+ 'top_today',
+ 'top_weekly',
+ 'top_monthly',
+ 'top_yearly',
+ 'top_all_time',
+ ]
+
+ query = Status.unscoped.without_replies
+ query = query.joins(:status_stat).order(top_order) unless ['newest'].include? sort_type
+ query = query.where('statuses.created_at > ?', date_limit)
+ query = query.where(group: @group) unless group.nil?
+ query = query.where('statuses.id > ? AND statuses.id <> ?', max_id, max_id) unless max_id.nil? || max_id.empty?
+ query = query.limit(20)
+
+ # SELECT "statuses".*
+ # FROM "statuses"
+ # INNER JOIN "status_stats" ON "status_stats"."status_id" = "statuses"."id"
+ # WHERE (statuses.reply IS FALSE) AND (statuses.created_at > '2020-11-02 22:01:36.197805')
+ # ORDER BY "statuses"."created_at" DESC, status_stats.favourites_count DESC, status_stats.reblogs_count DESC, status_stats.replies_count DESC LIMIT $1
+
+ query
+ end
+
+end
diff --git a/app/lib/status_filter.rb b/app/lib/status_filter.rb
index b6c80b80..a0f30b64 100644
--- a/app/lib/status_filter.rb
+++ b/app/lib/status_filter.rb
@@ -28,10 +28,6 @@ class StatusFilter
@preloaded_relations[:blocking] ? @preloaded_relations[:blocking][status.account_id] : account.blocking?(status.account_id)
end
- def blocking_domain?
- @preloaded_relations[:domain_blocking_by_domain] ? @preloaded_relations[:domain_blocking_by_domain][status.account_domain] : account.domain_blocking?(status.account_domain)
- end
-
def muting_account?
@preloaded_relations[:muting] ? @preloaded_relations[:muting][status.account_id] : account.muting?(status.account_id)
end
diff --git a/app/lib/status_finder.rb b/app/lib/status_finder.rb
index 4d1aed29..22ced8bf 100644
--- a/app/lib/status_finder.rb
+++ b/app/lib/status_finder.rb
@@ -13,8 +13,6 @@ class StatusFinder
raise ActiveRecord::RecordNotFound unless TagManager.instance.local_url?(url)
case recognized_params[:controller]
- when 'stream_entries'
- StreamEntry.find(recognized_params[:id]).status
when 'statuses'
Status.find(recognized_params[:id])
else
diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb
index fb364cb9..f9a3ac41 100644
--- a/app/lib/tag_manager.rb
+++ b/app/lib/tag_manager.rb
@@ -39,9 +39,9 @@ class TagManager
case target.object_type
when :person
- short_account_url(target)
+ "/#{target.username}"
when :note, :comment, :activity
- short_account_status_url(target.account, target)
+ "/#{target.account.username}/posts/#{target.id}"
end
end
end
diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb
index 401e87cf..bcbf3081 100644
--- a/app/lib/user_settings_decorator.rb
+++ b/app/lib/user_settings_decorator.rb
@@ -30,7 +30,6 @@ class UserSettingsDecorator
user.settings['theme'] = theme_preference if change?('setting_theme')
user.settings['hide_network'] = hide_network_preference if change?('setting_hide_network')
user.settings['aggregate_reblogs'] = aggregate_reblogs_preference if change?('setting_aggregate_reblogs')
- user.settings['show_application'] = show_application_preference if change?('setting_show_application')
user.settings['group_in_home_feed'] = group_in_home_feed_preference if change?('setting_group_in_home_feed')
end
@@ -82,10 +81,6 @@ class UserSettingsDecorator
boolean_cast_setting 'setting_hide_network'
end
- def show_application_preference
- boolean_cast_setting 'setting_show_application'
- end
-
def theme_preference
settings['setting_theme']
end
diff --git a/app/lib/webfinger_resource.rb b/app/lib/webfinger_resource.rb
deleted file mode 100644
index a54a702a..00000000
--- a/app/lib/webfinger_resource.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-class WebfingerResource
- attr_reader :resource
-
- def initialize(resource)
- @resource = resource
- end
-
- def username
- case resource
- when /\Ahttps?/i
- username_from_url
- when /\@/
- username_from_acct
- else
- raise(ActiveRecord::RecordNotFound)
- end
- end
-
- private
-
- def username_from_url
- if account_show_page?
- path_params[:username]
- else
- raise ActiveRecord::RecordNotFound
- end
- end
-
- def account_show_page?
- path_params[:controller] == 'accounts' && path_params[:action] == 'show'
- end
-
- def path_params
- Rails.application.routes.recognize_path(resource)
- end
-
- def username_from_acct
- if domain_matches_local?
- local_username
- else
- raise ActiveRecord::RecordNotFound
- end
- end
-
- def split_acct
- resource_without_acct_string.split('@')
- end
-
- def resource_without_acct_string
- resource.gsub(/\Aacct:/, '')
- end
-
- def local_username
- split_acct.first
- end
-
- def local_domain
- split_acct.last
- end
-
- def domain_matches_local?
- TagManager.instance.local_domain?(local_domain) || TagManager.instance.web_domain?(local_domain)
- end
-end
diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb
index db154cad..3b116555 100644
--- a/app/mailers/admin_mailer.rb
+++ b/app/mailers/admin_mailer.rb
@@ -3,7 +3,7 @@
class AdminMailer < ApplicationMailer
layout 'plain_mailer'
- helper :stream_entries
+ helper :statuses
def new_report(recipient, report)
@report = report
@@ -15,13 +15,4 @@ class AdminMailer < ApplicationMailer
end
end
- def new_pending_account(recipient, user)
- @account = user.account
- @me = recipient
- @instance = Rails.configuration.x.local_domain
-
- locale_for_account(@me) do
- mail to: @me.user_email, subject: I18n.t('admin_mailer.new_pending_account.subject', instance: @instance, username: @account.username)
- end
- end
end
diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb
index 66fa337c..723d901f 100644
--- a/app/mailers/notification_mailer.rb
+++ b/app/mailers/notification_mailer.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class NotificationMailer < ApplicationMailer
- helper :stream_entries
+ helper :statuses
add_template_helper RoutingHelper
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index cbe5e323..94c007b5 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -148,7 +148,7 @@ class UserMailer < Devise::Mailer
I18n.with_locale(@resource.locale || I18n.default_locale) do
mail to: @resource.email,
subject: I18n.t("user_mailer.warning.subject.#{@warning.action}", acct: "@#{user.account.local_username_and_domain}"),
- reply_to: Setting.site_contact_email
+ reply_to: 'support@gab.com'
end
end
diff --git a/app/models/account.rb b/app/models/account.rb
index 6f31615c..41840714 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -35,7 +35,7 @@
# outbox_url :string default(""), not null
# shared_inbox_url :string default(""), not null
# followers_url :string default(""), not null
-# protocol :integer default("ostatus"), not null
+# protocol :integer default(0), not null
# memorial :boolean default(FALSE), not null
# moved_to_account_id :bigint(8)
# featured_collection_url :string
@@ -67,8 +67,6 @@ class Account < ApplicationRecord
include AccountCounters
include DomainNormalizable
- enum protocol: [:ostatus, :activitypub]
-
validates :username, presence: true
# Remote user validations
@@ -85,7 +83,6 @@ class Account < ApplicationRecord
scope :remote, -> { where.not(domain: nil) }
scope :local, -> { where(domain: nil) }
- scope :expiring, ->(time) { remote.where.not(subscription_expires_at: nil).where('subscription_expires_at < ?', time) }
scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
scope :silenced, -> { where.not(silenced_at: nil) }
scope :suspended, -> { where.not(suspended_at: nil) }
@@ -110,13 +107,11 @@ class Account < ApplicationRecord
:current_sign_in_at,
:confirmed?,
:approved?,
- :pending?,
:admin?,
:moderator?,
:staff?,
:locale,
:hides_network?,
- :shows_application?,
to: :user,
prefix: true,
allow_nil: true
@@ -153,23 +148,6 @@ class Account < ApplicationRecord
Follow.where(target_account_id: id).count
end
- def to_webfinger_s
- "acct:#{local_username_and_domain}"
- end
-
- def subscribed?
- subscription_expires_at.present?
- end
-
- def possibly_stale?
- last_webfingered_at.nil? || last_webfingered_at <= 1.day.ago
- end
-
- def refresh!
- return if local?
- ResolveAccountService.new.call(acct)
- end
-
def silenced?
silenced_at.present?
end
@@ -247,10 +225,6 @@ class Account < ApplicationRecord
end
end
- def also_known_as
- self[:also_known_as] || []
- end
-
def fields
(self[:fields] || []).map { |f| Field.new(self, f) }
end
@@ -307,17 +281,11 @@ class Account < ApplicationRecord
(['RSA'] + [modulus, exponent].map { |n| Base64.urlsafe_encode64(n) }).join('.')
end
- def subscription(webhook_url)
- @subscription ||= OStatus2::Subscription.new(remote_url, secret: secret, webhook: webhook_url, hub: hub_url)
- end
-
def save_with_optional_media!
save!
rescue ActiveRecord::RecordInvalid
self.avatar = nil
self.header = nil
- self[:avatar_remote_url] = ''
- self[:header_remote_url] = ''
save!
end
@@ -400,11 +368,6 @@ class Account < ApplicationRecord
reorder(nil).pluck(Arel.sql('distinct accounts.domain'))
end
- def inboxes
- urls = reorder(nil).where(protocol: :activitypub).pluck(Arel.sql("distinct coalesce(nullif(accounts.shared_inbox_url, ''), accounts.inbox_url)"))
- DeliveryFailureTracker.filter(urls)
- end
-
def search_for(terms, limit = 10, offset = 0, options = {})
textsearch, query = generate_query_for_search(terms)
@onlyVerified = options[:onlyVerified] || false
diff --git a/app/models/account_domain_block.rb b/app/models/account_domain_block.rb
deleted file mode 100644
index 7c0d6037..00000000
--- a/app/models/account_domain_block.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: account_domain_blocks
-#
-# id :bigint(8) not null, primary key
-# domain :string
-# created_at :datetime not null
-# updated_at :datetime not null
-# account_id :bigint(8)
-#
-
-class AccountDomainBlock < ApplicationRecord
- include Paginable
- include DomainNormalizable
-
- belongs_to :account
- validates :domain, presence: true, uniqueness: { scope: :account_id }
-
- after_commit :remove_blocking_cache
- after_commit :remove_relationship_cache
-
- private
-
- def remove_blocking_cache
- Rails.cache.delete("exclude_domains_for:#{account_id}")
- end
-
- def remove_relationship_cache
- Rails.cache.delete_matched("relationship:#{account_id}:*")
- end
-end
diff --git a/app/models/account_identity_proof.rb b/app/models/account_identity_proof.rb
deleted file mode 100644
index 10b66ccc..00000000
--- a/app/models/account_identity_proof.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: account_identity_proofs
-#
-# id :bigint(8) not null, primary key
-# account_id :bigint(8)
-# provider :string default(""), not null
-# provider_username :string default(""), not null
-# token :text default(""), not null
-# verified :boolean default(FALSE), not null
-# live :boolean default(FALSE), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class AccountIdentityProof < ApplicationRecord
- belongs_to :account
-
- validates :provider, inclusion: { in: ProofProvider::SUPPORTED_PROVIDERS }
- validates :provider_username, format: { with: /\A[a-z0-9_]+\z/i }, length: { minimum: 2, maximum: 30 }
- validates :provider_username, uniqueness: { scope: [:account_id, :provider] }
- validates :token, format: { with: /\A[a-f0-9]+\z/ }, length: { maximum: 66 }
-
- validate :validate_with_provider, if: :token_changed?
-
- scope :active, -> { where(verified: true, live: true) }
-
- after_commit :queue_worker, if: :saved_change_to_token?
-
- delegate :refresh!, :on_success_path, :badge, to: :provider_instance
-
- def provider_instance
- @provider_instance ||= ProofProvider.find(provider, self)
- end
-
- private
-
- def queue_worker
- provider_instance.worker_class.perform_async(id)
- end
-
- def validate_with_provider
- provider_instance.validate!
- end
-end
diff --git a/app/models/account_pin.rb b/app/models/account_pin.rb
deleted file mode 100644
index b51d3d4c..00000000
--- a/app/models/account_pin.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: account_pins
-#
-# id :bigint(8) not null, primary key
-# account_id :bigint(8)
-# target_account_id :bigint(8)
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class AccountPin < ApplicationRecord
- include Paginable
- include RelationshipCacheable
-
- belongs_to :account
- belongs_to :target_account, class_name: 'Account'
-
- validate :validate_follow_relationship
-
- private
-
- def validate_follow_relationship
- errors.add(:base, I18n.t('accounts.pin_errors.following')) unless account.following?(target_account)
- end
-end
diff --git a/app/models/block.rb b/app/models/block.rb
index bf3e0760..cc670f28 100644
--- a/app/models/block.rb
+++ b/app/models/block.rb
@@ -25,7 +25,6 @@ class Block < ApplicationRecord
end
after_commit :remove_blocking_cache
- before_validation :set_uri, only: :create
private
@@ -33,8 +32,4 @@ class Block < ApplicationRecord
Rails.cache.delete("exclude_account_ids_for:#{account_id}")
Rails.cache.delete("exclude_account_ids_for:#{target_account_id}")
end
-
- def set_uri
- self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
- end
end
diff --git a/app/models/concerns/account_associations.rb b/app/models/concerns/account_associations.rb
index c6bcc5a3..217b8d78 100644
--- a/app/models/concerns/account_associations.rb
+++ b/app/models/concerns/account_associations.rb
@@ -7,16 +7,11 @@ module AccountAssociations
# Local users
has_one :user, inverse_of: :account, dependent: :destroy
- # Identity proofs
- has_many :identity_proofs, class_name: 'AccountIdentityProof', dependent: :destroy, inverse_of: :account
-
# Timelines
- has_many :stream_entries, inverse_of: :account, dependent: :destroy
has_many :statuses, inverse_of: :account, dependent: :destroy
has_many :favourites, inverse_of: :account, dependent: :destroy
has_many :mentions, inverse_of: :account, dependent: :destroy
has_many :notifications, inverse_of: :account, dependent: :destroy
- has_many :conversations, class_name: 'AccountConversation', dependent: :destroy, inverse_of: :account
has_many :scheduled_statuses, inverse_of: :account, dependent: :destroy
# Pinned statuses
@@ -27,10 +22,6 @@ module AccountAssociations
has_many :status_pins, inverse_of: :account, dependent: :destroy
has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status
- # Endorsements
- has_many :account_pins, inverse_of: :account, dependent: :destroy
- has_many :endorsed_accounts, through: :account_pins, class_name: 'Account', source: :target_account
-
# Media
has_many :media_attachments, dependent: :destroy
has_many :polls, dependent: :destroy
@@ -63,7 +54,6 @@ module AccountAssociations
# Hashtags
has_and_belongs_to_many :tags
- has_many :featured_tags, -> { includes(:tag) }, dependent: :destroy, inverse_of: :account
# Billing
has_many :transactions, class_name: 'Transaction', dependent: :destroy, inverse_of: :account
diff --git a/app/models/concerns/account_finder_concern.rb b/app/models/concerns/account_finder_concern.rb
index f0b93df6..e7c19503 100644
--- a/app/models/concerns/account_finder_concern.rb
+++ b/app/models/concerns/account_finder_concern.rb
@@ -8,10 +8,6 @@ module AccountFinderConcern
find_local(username) || raise(ActiveRecord::RecordNotFound)
end
- def find_remote!(username, domain)
- find_remote(username, domain) || raise(ActiveRecord::RecordNotFound)
- end
-
def find_acct!(acct)
find_acct(acct) || raise(ActiveRecord::RecordNotFound)
end
@@ -21,25 +17,24 @@ module AccountFinderConcern
end
def find_local(username)
- find_remote(username, nil)
- end
-
- def find_remote(username, domain)
- AccountFinder.new(username, domain).account
+ find_now(username)
end
def find_acct(acct)
username, domain = acct.split("@")
- find_remote(username, domain)
+ find_now(username)
+ end
+
+ def find_now(username)
+ AccountFinder.new(username).account
end
end
class AccountFinder
- attr_reader :username, :domain
+ attr_reader :username
- def initialize(username, domain)
+ def initialize(username)
@username = username
- @domain = domain
end
def account
@@ -65,11 +60,7 @@ module AccountFinderConcern
end
def matching_domain
- if domain.nil?
- Account.where(domain: nil)
- else
- Account.where(Account.arel_table[:domain].lower.eq domain.to_s.downcase)
- end
+ Account.where(domain: nil)
end
end
end
diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb
index 053960b6..88032004 100644
--- a/app/models/concerns/account_interactions.rb
+++ b/app/models/concerns/account_interactions.rb
@@ -40,20 +40,6 @@ module AccountInteractions
end
end
- def endorsed_map(target_account_ids, account_id)
- follow_mapping(AccountPin.where(account_id: account_id, target_account_id: target_account_ids), :target_account_id)
- end
-
- def domain_blocking_map(target_account_ids, account_id)
- accounts_map = Account.where(id: target_account_ids).select('id, domain').each_with_object({}) { |a, h| h[a.id] = a.domain }
- blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id)
- accounts_map.reduce({}) { |h, (id, domain)| h.merge(id => blocked_domains[domain]) }
- end
-
- def domain_blocking_map_by_domain(target_domains, account_id)
- follow_mapping(AccountDomainBlock.where(account_id: account_id, domain: target_domains), :domain)
- end
-
private
def follow_mapping(query, field)
@@ -85,8 +71,6 @@ module AccountInteractions
has_many :muting, -> { order('mutes.id desc') }, through: :mute_relationships, source: :target_account
has_many :muted_by_relationships, class_name: 'Mute', foreign_key: :target_account_id, dependent: :destroy
has_many :muted_by, -> { order('mutes.id desc') }, through: :muted_by_relationships, source: :account
- has_many :conversation_mutes, dependent: :destroy
- has_many :domain_blocks, class_name: 'AccountDomainBlock', dependent: :destroy
end
def follow!(other_account, reblogs: nil, uri: nil)
@@ -120,14 +104,6 @@ module AccountInteractions
mute
end
- def mute_conversation!(conversation)
- conversation_mutes.find_or_create_by!(conversation: conversation)
- end
-
- def block_domain!(other_domain)
- domain_blocks.find_or_create_by!(domain: other_domain)
- end
-
def unfollow!(other_account)
follow = active_relationships.find_by(target_account: other_account)
follow&.destroy
@@ -143,16 +119,6 @@ module AccountInteractions
mute&.destroy
end
- def unmute_conversation!(conversation)
- mute = conversation_mutes.find_by(conversation: conversation)
- mute&.destroy!
- end
-
- def unblock_domain!(other_domain)
- block = domain_blocks.find_by(domain: other_domain)
- block&.destroy
- end
-
def following?(other_account)
active_relationships.where(target_account: other_account).exists?
end
@@ -161,18 +127,10 @@ module AccountInteractions
block_relationships.where(target_account: other_account).exists?
end
- def domain_blocking?(other_domain)
- domain_blocks.where(domain: other_domain).exists?
- end
-
def muting?(other_account)
mute_relationships.where(target_account: other_account).exists?
end
- def muting_conversation?(conversation)
- conversation_mutes.where(conversation: conversation).exists?
- end
-
def muting_notifications?(other_account)
mute_relationships.where(target_account: other_account, hide_notifications: true).exists?
end
@@ -201,10 +159,6 @@ module AccountInteractions
status_pins.where(status: status).exists?
end
- def endorsed?(account)
- account_pins.where(target_account: account).exists?
- end
-
def followers_for_local_distribution
followers.local
.joins(:user)
diff --git a/app/models/concerns/omniauthable.rb b/app/models/concerns/omniauthable.rb
index 28303308..c940ac1b 100644
--- a/app/models/concerns/omniauthable.rb
+++ b/app/models/concerns/omniauthable.rb
@@ -44,9 +44,9 @@ module Omniauthable
# verified email. If no verified email was provided or the user already
# exists, we assign a temporary email and ask the user to verify it on
# the next step via Auth::ConfirmationsController.finish_signup
-
+
+ # : TODO : remove, no sign up from app. only website
user = User.new(user_params_from_auth(auth))
- user.account.avatar_remote_url = auth.info.image if auth.info.image =~ /\A#{URI.regexp(%w(http https))}\z/
user.skip_confirmation!
user.save!
user
diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb
index 15eb695c..af4fa45a 100644
--- a/app/models/concerns/status_threading_concern.rb
+++ b/app/models/concerns/status_threading_concern.rb
@@ -122,7 +122,6 @@ module StatusThreadingConcern
blocked_by: Account.blocked_by_map(account_ids, account.id),
muting: Account.muting_map(account_ids, account.id),
following: Account.following_map(account_ids, account.id),
- domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id),
}
end
diff --git a/app/models/concerns/streamable.rb b/app/models/concerns/streamable.rb
deleted file mode 100644
index 7c9edb8e..00000000
--- a/app/models/concerns/streamable.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module Streamable
- extend ActiveSupport::Concern
-
- included do
- has_one :stream_entry, as: :activity
-
- after_create do
- account.stream_entries.create!(activity: self, hidden: hidden?) if needs_stream_entry?
- end
- end
-
- def title
- super
- end
-
- def content
- title
- end
-
- def target
- super
- end
-
- def object_type
- :activity
- end
-
- def thread
- super
- end
-
- def hidden?
- false
- end
-
- private
-
- def needs_stream_entry?
- account.local?
- end
-end
diff --git a/app/models/conversation_mute.rb b/app/models/conversation_mute.rb
deleted file mode 100644
index 52c1a33e..00000000
--- a/app/models/conversation_mute.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: conversation_mutes
-#
-# id :bigint(8) not null, primary key
-# conversation_id :bigint(8) not null
-# account_id :bigint(8) not null
-#
-
-class ConversationMute < ApplicationRecord
- belongs_to :account
- belongs_to :conversation
-end
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index d3cc7050..7db7fdd3 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -12,7 +12,6 @@
# image_updated_at :datetime
# created_at :datetime not null
# updated_at :datetime not null
-# disabled :boolean default(FALSE), not null
# uri :string
# image_remote_url :string
# visible_in_picker :boolean default(TRUE), not null
diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb
deleted file mode 100644
index 84c08c15..00000000
--- a/app/models/domain_block.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: domain_blocks
-#
-# id :bigint(8) not null, primary key
-# domain :string default(""), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# severity :integer default("silence")
-# reject_media :boolean default(FALSE), not null
-# reject_reports :boolean default(FALSE), not null
-#
-
-class DomainBlock < ApplicationRecord
- include DomainNormalizable
-
- enum severity: [:silence, :suspend, :noop]
-
- validates :domain, presence: true, uniqueness: true
-
- has_many :accounts, foreign_key: :domain, primary_key: :domain
- delegate :count, to: :accounts, prefix: true
-
- scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
-
- def self.blocked?(domain)
- where(domain: domain, severity: :suspend).exists?
- end
-
- def stricter_than?(other_block)
- return true if suspend?
- return false if other_block.suspend? && (silence? || noop?)
- return false if other_block.silence? && noop?
- (reject_media || !other_block.reject_media) && (reject_reports || !other_block.reject_reports)
- end
-
- def affected_accounts_count
- scope = suspend? ? accounts.where(suspended_at: created_at) : accounts.where(silenced_at: created_at)
- scope.count
- end
-end
diff --git a/app/models/export.rb b/app/models/export.rb
index 3b76699c..73144c73 100644
--- a/app/models/export.rb
+++ b/app/models/export.rb
@@ -39,14 +39,6 @@ class Export
end
end
- def to_blocked_domains_csv
- CSV.generate do |csv|
- account.domain_blocks.pluck(:domain).each do |domain|
- csv << [domain]
- end
- end
- end
-
def total_storage
account.media_attachments.sum(:file_file_size)
end
@@ -75,10 +67,6 @@ class Export
account.muting.count
end
- def total_domain_blocks
- account.domain_blocks.count
- end
-
private
def to_csv(accounts)
diff --git a/app/models/featured_tag.rb b/app/models/featured_tag.rb
deleted file mode 100644
index d06ae26a..00000000
--- a/app/models/featured_tag.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: featured_tags
-#
-# id :bigint(8) not null, primary key
-# account_id :bigint(8)
-# tag_id :bigint(8)
-# statuses_count :bigint(8) default(0), not null
-# last_status_at :datetime
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class FeaturedTag < ApplicationRecord
- belongs_to :account, inverse_of: :featured_tags, required: true
- belongs_to :tag, inverse_of: :featured_tags, required: true
-
- delegate :name, to: :tag, allow_nil: true
-
- validates_associated :tag, on: :create
- validates :name, presence: true, on: :create
- validate :validate_featured_tags_limit, on: :create
-
- def name=(str)
- self.tag = Tag.find_or_initialize_by(name: str.strip.delete('#').mb_chars.downcase.to_s)
- end
-
- def increment(timestamp)
- update(statuses_count: statuses_count + 1, last_status_at: timestamp)
- end
-
- def decrement(deleted_status_id)
- update(statuses_count: [0, statuses_count - 1].max, last_status_at: account.statuses.where(visibility: %i(public unlisted)).tagged_with(tag).where.not(id: deleted_status_id).select(:created_at).first&.created_at)
- end
-
- def reset_data
- self.statuses_count = account.statuses.where(visibility: %i(public unlisted)).tagged_with(tag).count
- self.last_status_at = account.statuses.where(visibility: %i(public unlisted)).tagged_with(tag).select(:created_at).first&.created_at
- end
-
- private
-
- def validate_featured_tags_limit
- errors.add(:base, I18n.t('featured_tags.errors.limit')) if account.featured_tags.count >= 10
- end
-end
diff --git a/app/models/follow.rb b/app/models/follow.rb
index 87fa1142..3e1268e8 100644
--- a/app/models/follow.rb
+++ b/app/models/follow.rb
@@ -31,25 +31,15 @@ class Follow < ApplicationRecord
end
def revoke_request!
- FollowRequest.create!(account: account, target_account: target_account, show_reblogs: show_reblogs, uri: uri)
+ FollowRequest.create!(account: account, target_account: target_account)
destroy!
end
- before_validation :set_uri, only: :create
after_create :increment_cache_counters
- after_destroy :remove_endorsements
after_destroy :decrement_cache_counters
private
- def set_uri
- self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
- end
-
- def remove_endorsements
- AccountPin.where(target_account_id: target_account_id, account_id: account_id).delete_all
- end
-
def increment_cache_counters
account&.increment_count!(:following_count)
target_account&.increment_count!(:followers_count)
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
index 96ac7eaa..baea0536 100644
--- a/app/models/follow_request.rb
+++ b/app/models/follow_request.rb
@@ -25,7 +25,7 @@ class FollowRequest < ApplicationRecord
validates_with FollowLimitValidator, on: :create
def authorize!
- account.follow!(target_account, reblogs: show_reblogs, uri: uri)
+ account.follow!(target_account)
MergeWorker.perform_async(target_account.id, account.id) if account.local?
destroy!
end
@@ -33,14 +33,6 @@ class FollowRequest < ApplicationRecord
alias reject! destroy!
def local?
- false # Force uri_for to use uri attribute
- end
-
- before_validation :set_uri, only: :create
-
- private
-
- def set_uri
- self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
+ false
end
end
diff --git a/app/models/form/account_batch.rb b/app/models/form/account_batch.rb
index 1b48a763..df9af02f 100644
--- a/app/models/form/account_batch.rb
+++ b/app/models/form/account_batch.rb
@@ -12,8 +12,6 @@ class Form::AccountBatch
unfollow!
when 'remove_from_followers'
remove_from_followers!
- when 'block_domains'
- block_domains!
when 'approve'
approve!
when 'reject'
@@ -35,12 +33,6 @@ class Form::AccountBatch
end
end
- def block_domains!
- AfterAccountDomainBlockWorker.push_bulk(account_domains) do |domain|
- [current_account.id, domain]
- end
- end
-
def account_domains
accounts.pluck(Arel.sql('distinct domain')).compact
end
diff --git a/app/models/form/admin_settings.rb b/app/models/form/admin_settings.rb
index e044c562..a6785bb6 100644
--- a/app/models/form/admin_settings.rb
+++ b/app/models/form/admin_settings.rb
@@ -9,47 +9,25 @@ class Form::AdminSettings
site_title
site_short_description
site_description
- site_extended_description
- site_terms
registrations_mode
- closed_registrations_message
- open_deletion
- timeline_preview
- show_staff_badge
bootstrap_timeline_accounts
theme
min_invite_role
- activity_api_enabled
- peers_api_enabled
- show_known_fediverse_at_about_page
preview_sensitive_media
- profile_directory
thumbnail
- hero
- mascot
).freeze
BOOLEAN_KEYS = %i(
- open_deletion
- timeline_preview
- show_staff_badge
- activity_api_enabled
- peers_api_enabled
- show_known_fediverse_at_about_page
preview_sensitive_media
- profile_directory
).freeze
UPLOAD_KEYS = %i(
thumbnail
- hero
- mascot
).freeze
attr_accessor(*KEYS)
validates :site_short_description, :site_description, html: { wrap_with: :p }
- validates :site_extended_description, :site_terms, :closed_registrations_message, html: true
validates :registrations_mode, inclusion: { in: %w(open approved none) }
validates :min_invite_role, inclusion: { in: %w(disabled user moderator admin) }
validates :site_contact_email, :site_contact_username, presence: true
diff --git a/app/models/form/migration.rb b/app/models/form/migration.rb
index c2a8655e..fedd8cdb 100644
--- a/app/models/form/migration.rb
+++ b/app/models/form/migration.rb
@@ -20,6 +20,6 @@ class Form::Migration
private
def set_account
- self.account = (ResolveAccountService.new.call(acct) if account.nil? && acct.present?)
+ self.account = nil
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 70def81e..4e847d65 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -56,6 +56,7 @@ class Group < ApplicationRecord
record.errors.add(:base, I18n.t('groups.errors.limit')) if Group.where(account_id: value).count >= PER_ACCOUNT_LIMIT
end
+ before_save :set_slug
before_save :set_password
before_destroy :clean_feed_manager
after_create :add_owner_to_accounts
@@ -80,6 +81,20 @@ class Group < ApplicationRecord
password
end
end
+
+ def set_slug
+ puts "tilly-5: " + slug.to_s
+ puts "tilly-6: " + self.member_count.to_s
+
+ if !slug.nil? && self.member_count > 50 && self.slug.nil?
+ self.slug = slug.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
+ elsif !slug.nil? && self.member_count < 50 && self.slug.nil?
+ self.slug = nil
+ else
+ self.slug = self.slug
+ end
+ end
+
def add_owner_to_accounts
group_accounts << GroupAccount.new(account: account, role: :admin, write_permissions: true)
end
diff --git a/app/models/group_account.rb b/app/models/group_account.rb
index 901f5810..44d1a423 100644
--- a/app/models/group_account.rb
+++ b/app/models/group_account.rb
@@ -13,6 +13,7 @@
class GroupAccount < ApplicationRecord
self.ignored_columns = ["unread_count"]
+ # : todo : enum: 1,2,3,4,5...
enum role: {
admin: "admin",
moderator: "moderator"
diff --git a/app/models/import.rb b/app/models/import.rb
deleted file mode 100644
index a7a0d806..00000000
--- a/app/models/import.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: imports
-#
-# id :bigint(8) not null, primary key
-# type :integer not null
-# approved :boolean default(FALSE), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# data_file_name :string
-# data_content_type :string
-# data_file_size :integer
-# data_updated_at :datetime
-# account_id :bigint(8) not null
-# overwrite :boolean default(FALSE), not null
-#
-
-class Import < ApplicationRecord
- FILE_TYPES = %w(text/plain text/csv).freeze
- MODES = %i(merge overwrite).freeze
-
- self.inheritance_column = false
-
- belongs_to :account
-
- enum type: [:following, :blocking, :muting, :domain_blocking]
-
- validates :type, presence: true
-
- has_attached_file :data
- validates_attachment_content_type :data, content_type: FILE_TYPES
- validates_attachment_presence :data
-
- def mode
- overwrite? ? :overwrite : :merge
- end
-
- def mode=(str)
- self.overwrite = str.to_sym == :overwrite
- end
-end
diff --git a/app/models/invite.rb b/app/models/invite.rb
deleted file mode 100644
index fe232246..00000000
--- a/app/models/invite.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: invites
-#
-# id :bigint(8) not null, primary key
-# user_id :bigint(8) not null
-# code :string default(""), not null
-# expires_at :datetime
-# max_uses :integer
-# uses :integer default(0), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# autofollow :boolean default(FALSE), not null
-#
-
-class Invite < ApplicationRecord
- include Expireable
-
- belongs_to :user
- has_many :users, inverse_of: :invite
-
- scope :available, -> { where(expires_at: nil).or(where('expires_at >= ?', Time.now.utc)) }
-
- before_validation :set_code
-
- def valid_for_use?
- (max_uses.nil? || uses < max_uses) && !expired?
- end
-
- private
-
- def set_code
- loop do
- self.code = ([*('a'..'z'), *('A'..'Z'), *('0'..'9')] - %w(0 1 I l O)).sample(8).join
- break if Invite.find_by(code: code).nil?
- end
- end
-end
diff --git a/app/models/invite_filter.rb b/app/models/invite_filter.rb
deleted file mode 100644
index 7d89bad4..00000000
--- a/app/models/invite_filter.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class InviteFilter
- attr_reader :params
-
- def initialize(params)
- @params = params
- end
-
- def results
- scope = Invite.order(created_at: :desc)
-
- params.each do |key, value|
- scope.merge!(scope_for(key, value)) if value.present?
- end
-
- scope
- end
-
- private
-
- def scope_for(key, _value)
- case key.to_s
- when 'available'
- Invite.available
- when 'expired'
- Invite.expired
- else
- raise "Unknown filter: #{key}"
- end
- end
-end
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 333134f6..e22d0a7b 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -16,6 +16,7 @@ class Notification < ApplicationRecord
include Paginable
include Cacheable
+ # : todo : enums, 1,2,3,4,5,...
TYPE_CLASS_MAP = {
mention: 'Mention',
reblog: 'Status',
diff --git a/app/models/poll.rb b/app/models/poll.rb
index 8f72c7b1..e27b71da 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -46,10 +46,6 @@ class Poll < ApplicationRecord
options.map.with_index { |title, key| Option.new(self, key.to_s, title, show_totals_now? ? cached_tallies[key] : nil) }
end
- def possibly_stale?
- remote? && last_fetched_before_expiration? && time_passed_since_last_fetch?
- end
-
def voted?(account)
account.id == account_id || votes.where(account: account).exists?
end
@@ -94,15 +90,7 @@ class Poll < ApplicationRecord
Rails.cache.delete("statuses/#{status_id}")
end
- def last_fetched_before_expiration?
- last_fetched_at.nil? || expires_at.nil? || last_fetched_at < expires_at
- end
-
- def time_passed_since_last_fetch?
- last_fetched_at.nil? || last_fetched_at < 1.minute.ago
- end
-
def show_totals_now?
- expired? || !hide_totals?
+ expired?
end
end
diff --git a/app/models/relay.rb b/app/models/relay.rb
deleted file mode 100644
index 888e0d8e..00000000
--- a/app/models/relay.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: relays
-#
-# id :bigint(8) not null, primary key
-# inbox_url :string default(""), not null
-# follow_activity_id :string
-# created_at :datetime not null
-# updated_at :datetime not null
-# state :integer default("idle"), not null
-#
-
-class Relay < ApplicationRecord
- PRESET_RELAY = 'https://relay.gab.com/inbox'
-
- validates :inbox_url, presence: true, uniqueness: true, url: true, if: :will_save_change_to_inbox_url?
-
- enum state: [:idle, :pending, :accepted, :rejected]
-
- scope :enabled, -> { accepted }
-
- before_destroy :ensure_disabled
-
- alias enabled? accepted?
-
- def enable!
- activity_id = ActivityPub::TagManager.instance.generate_uri_for(nil)
- payload = Oj.dump(follow_activity(activity_id))
-
- update!(state: :pending, follow_activity_id: activity_id)
- DeliveryFailureTracker.new(inbox_url).track_success!
- ActivityPub::DeliveryWorker.perform_async(payload, some_local_account.id, inbox_url)
- end
-
- def disable!
- activity_id = ActivityPub::TagManager.instance.generate_uri_for(nil)
- payload = Oj.dump(unfollow_activity(activity_id))
-
- update!(state: :idle, follow_activity_id: nil)
- DeliveryFailureTracker.new(inbox_url).track_success!
- ActivityPub::DeliveryWorker.perform_async(payload, some_local_account.id, inbox_url)
- end
-
- private
-
- def follow_activity(activity_id)
- {
- '@context': ActivityPub::TagManager::CONTEXT,
- id: activity_id,
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(some_local_account),
- object: ActivityPub::TagManager::COLLECTIONS[:public],
- }
- end
-
- def unfollow_activity(activity_id)
- {
- '@context': ActivityPub::TagManager::CONTEXT,
- id: activity_id,
- type: 'Undo',
- actor: ActivityPub::TagManager.instance.uri_for(some_local_account),
- object: {
- id: follow_activity_id,
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(some_local_account),
- object: ActivityPub::TagManager::COLLECTIONS[:public],
- },
- }
- end
-
- def some_local_account
- @some_local_account ||= Account.representative
- end
-
- def ensure_disabled
- return unless enabled?
- disable!
- end
-end
diff --git a/app/models/remote_follow.rb b/app/models/remote_follow.rb
deleted file mode 100644
index 2537de36..00000000
--- a/app/models/remote_follow.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteFollow
- include ActiveModel::Validations
-
- attr_accessor :acct, :addressable_template
-
- validates :acct, presence: true
-
- def initialize(attrs = nil)
- @acct = attrs[:acct].gsub(/\A@/, '').strip if !attrs.nil? && !attrs[:acct].nil?
- end
-
- def valid?
- return false unless super
-
- populate_template
- errors.empty?
- end
-
- def subscribe_address_for(account)
- addressable_template.expand(uri: account.local_username_and_domain).to_s
- end
-
- def interact_address_for(status)
- addressable_template.expand(uri: ActivityPub::TagManager.instance.uri_for(status)).to_s
- end
-
- private
-
- def populate_template
- if acct.blank? || redirect_url_link.nil? || redirect_url_link.template.nil?
- missing_resource_error
- else
- @addressable_template = Addressable::Template.new(redirect_uri_template)
- end
- end
-
- def redirect_uri_template
- redirect_url_link.template
- end
-
- def redirect_url_link
- acct_resource&.link('http://ostatus.org/schema/1.0/subscribe')
- end
-
- def acct_resource
- @_acct_resource ||= Goldfinger.finger("acct:#{acct}")
- rescue Goldfinger::Error, HTTP::ConnectionError
- nil
- end
-
- def missing_resource_error
- errors.add(:acct, I18n.t('remote_follow.missing_resource'))
- end
-end
diff --git a/app/models/remote_profile.rb b/app/models/remote_profile.rb
deleted file mode 100644
index 742d2b56..00000000
--- a/app/models/remote_profile.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteProfile
- include ActiveModel::Model
-
- attr_reader :document
-
- def initialize(body)
- @document = Nokogiri::XML.parse(body, nil, 'utf-8')
- end
-
- def root
- @root ||= document.at_xpath('/atom:feed|/atom:entry', atom: OStatus::TagManager::XMLNS)
- end
-
- def author
- @author ||= root.at_xpath('./atom:author|./dfrn:owner', atom: OStatus::TagManager::XMLNS, dfrn: OStatus::TagManager::DFRN_XMLNS)
- end
-
- def hub_link
- @hub_link ||= link_href_from_xml(root, 'hub')
- end
-
- def display_name
- @display_name ||= author.at_xpath('./poco:displayName', poco: OStatus::TagManager::POCO_XMLNS)&.content
- end
-
- def note
- @note ||= author.at_xpath('./atom:summary|./poco:note', atom: OStatus::TagManager::XMLNS, poco: OStatus::TagManager::POCO_XMLNS)&.content
- end
-
- def scope
- @scope ||= author.at_xpath('./mastodon:scope', mastodon: OStatus::TagManager::MTDN_XMLNS)&.content
- end
-
- def avatar
- @avatar ||= link_href_from_xml(author, 'avatar')
- end
-
- def header
- @header ||= link_href_from_xml(author, 'header')
- end
-
- def emojis
- @emojis ||= author.xpath('./xmlns:link[@rel="emoji"]', xmlns: OStatus::TagManager::XMLNS)
- end
-
- def locked?
- scope == 'private'
- end
-
- private
-
- def link_href_from_xml(xml, type)
- xml.at_xpath(%(./atom:link[@rel="#{type}"]/@href), atom: OStatus::TagManager::XMLNS)&.content
- end
-end
diff --git a/app/models/report.rb b/app/models/report.rb
index 86c30379..5d43d9b1 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -33,8 +33,6 @@ class Report < ApplicationRecord
false # Force uri_for to use uri attribute
end
- before_validation :set_uri, only: :create
-
def object_type
:flag
end
@@ -97,7 +95,4 @@ class Report < ApplicationRecord
Admin::ActionLog.from("(#{sql}) AS admin_action_logs")
end
- def set_uri
- self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil? && account.local?
- end
end
diff --git a/app/models/shortcut.rb b/app/models/shortcut.rb
index 49869268..04bdab65 100644
--- a/app/models/shortcut.rb
+++ b/app/models/shortcut.rb
@@ -12,6 +12,7 @@
#
class Shortcut < ApplicationRecord
+ # : todo : enum 1,2, etc.
# enum shortcut_type: {
# account: 'account',
# group: 'group'
diff --git a/app/models/status.rb b/app/models/status.rb
index 0e3d355f..c6d907ee 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -34,7 +34,6 @@ class Status < ApplicationRecord
before_destroy :unlink_from_conversations
include Paginable
- include Streamable
include Cacheable
include StatusThreadingConcern
@@ -48,7 +47,6 @@ class Status < ApplicationRecord
:public,
:unlisted,
:private,
- :direct,
:limited,
:private_group,
], _suffix: :visibility
@@ -79,16 +77,14 @@ class Status < ApplicationRecord
has_and_belongs_to_many :preview_cards
has_one :notification, as: :activity, dependent: :destroy
- has_one :stream_entry, as: :activity, inverse_of: :status
has_one :status_stat, inverse_of: :status
has_one :poll, inverse_of: :status, dependent: :destroy
validates :uri, uniqueness: true, presence: true, unless: :local?
validates :text, presence: true, unless: -> { with_media? || reblog? }
validates_with StatusLengthValidator
- validates_with DisallowedHashtagsValidator
validates :reblog, uniqueness: { scope: :account }, if: :reblog?
- validates :visibility, exclusion: { in: %w(direct limited) }, if: :reblog?
+ validates :visibility, exclusion: { in: %w(limited) }, if: :reblog?
accepts_nested_attributes_for :poll
@@ -127,13 +123,11 @@ class Status < ApplicationRecord
:status_stat,
:tags,
:preview_cards,
- :stream_entry,
:preloadable_poll,
account: :account_stat,
active_mentions: { account: :account_stat },
reblog: [
:application,
- :stream_entry,
:tags,
:preview_cards,
:media_attachments,
@@ -147,8 +141,6 @@ class Status < ApplicationRecord
delegate :domain, to: :account, prefix: true
- REAL_TIME_WINDOW = 6.hours
-
def searchable_by(preloaded = nil)
ids = [account_id]
@@ -181,10 +173,6 @@ class Status < ApplicationRecord
!quote_of_id.nil?
end
- def within_realtime_window?
- created_at >= REAL_TIME_WINDOW.ago
- end
-
def verb
if destroyed?
:delete
@@ -222,7 +210,7 @@ class Status < ApplicationRecord
end
def hidden?
- private_visibility? || private_group_visibility? || direct_visibility? || limited_visibility?
+ private_visibility? || private_group_visibility? || limited_visibility?
end
def distributable?
@@ -294,7 +282,7 @@ class Status < ApplicationRecord
class << self
def selectable_visibilities
- visibilities.keys - %w(direct limited private_group)
+ visibilities.keys - %w(limited private_group)
end
def in_chosen_languages(account)
@@ -315,57 +303,11 @@ class Status < ApplicationRecord
where(group: groupIds, reply: false)
end
- def as_direct_timeline(account, limit = 20, max_id = nil, since_id = nil, cache_ids = false)
- # direct timeline is mix of direct message from_me and to_me.
- # 2 queries are executed with pagination.
- # constant expression using arel_table is required for partial index
-
- # _from_me part does not require any timeline filters
- query_from_me = where(account_id: account.id)
- .where(Status.arel_table[:visibility].eq(3))
- .limit(limit)
- .order('statuses.id DESC')
-
- # _to_me part requires mute and block filter.
- # FIXME: may we check mutes.hide_notifications?
- query_to_me = Status
- .joins(:mentions)
- .merge(Mention.where(account_id: account.id))
- .where(Status.arel_table[:visibility].eq(3))
- .limit(limit)
- .order('mentions.status_id DESC')
- .not_excluded_by_account(account)
-
- if max_id.present?
- query_from_me = query_from_me.where('statuses.id < ?', max_id)
- query_to_me = query_to_me.where('mentions.status_id < ?', max_id)
- end
-
- if since_id.present?
- query_from_me = query_from_me.where('statuses.id > ?', since_id)
- query_to_me = query_to_me.where('mentions.status_id > ?', since_id)
- end
-
- if cache_ids
- # returns array of cache_ids object that have id and updated_at
- (query_from_me.cache_ids.to_a + query_to_me.cache_ids.to_a).uniq(&:id).sort_by(&:id).reverse.take(limit)
- else
- # returns ActiveRecord.Relation
- items = (query_from_me.select(:id).to_a + query_to_me.select(:id).to_a).uniq(&:id).sort_by(&:id).reverse.take(limit)
- Status.where(id: items.map(&:id))
- end
- end
-
def as_pro_timeline(account = nil)
query = timeline_scope.without_replies.popular_accounts.where('statuses.updated_at > ?', 2.hours.ago)
apply_timeline_filters(query, account)
end
- def as_public_timeline(account = nil)
- query = timeline_scope.without_replies.where('statuses.updated_at > ?', 15.minutes.ago)
- apply_timeline_filters(query, account)
- end
-
def as_tag_timeline(tag, account = nil)
query = timeline_scope.tagged_with(tag).without_replies
@@ -388,10 +330,6 @@ class Status < ApplicationRecord
select('reblog_of_id').where(reblog_of_id: status_ids).where(account_id: account_id).reorder(nil).each_with_object({}) { |s, h| h[s.reblog_of_id] = true }
end
- def mutes_map(conversation_ids, account_id)
- ConversationMute.select('conversation_id').where(conversation_id: conversation_ids).where(account_id: account_id).each_with_object({}) { |m, h| h[m.conversation_id] = true }
- end
-
def pins_map(status_ids, account_id)
StatusPin.select('status_id').where(status_id: status_ids).where(account_id: account_id).each_with_object({}) { |p, h| h[p.status_id] = true }
end
@@ -490,7 +428,7 @@ class Status < ApplicationRecord
end
def store_uri
- update_column(:uri, ActivityPub::TagManager.instance.uri_for(self)) if uri.nil?
+ update_column(:uri, "/#{self.account.username}/posts/#{self.id}") if uri.nil?
end
def prepare_contents
@@ -556,15 +494,13 @@ class Status < ApplicationRecord
end
def increment_counter_caches
- return if direct_visibility?
-
account&.increment_count!(:statuses_count)
reblog&.increment_count!(:reblogs_count) if reblog? && (public_visibility? || unlisted_visibility?)
thread&.increment_count!(:replies_count) if in_reply_to_id.present? && (public_visibility? || unlisted_visibility?)
end
def decrement_counter_caches
- return if direct_visibility? || marked_for_mass_destruction?
+ return if marked_for_mass_destruction?
account&.decrement_count!(:statuses_count)
reblog&.decrement_count!(:reblogs_count) if reblog? && (public_visibility? || unlisted_visibility?)
@@ -572,14 +508,14 @@ class Status < ApplicationRecord
end
def unlink_from_conversations
- return unless direct_visibility?
+ # return unless direct_visibility?
- mentioned_accounts = mentions.includes(:account).map(&:account)
- inbox_owners = mentioned_accounts.select(&:local?) + (account.local? ? [account] : [])
+ # mentioned_accounts = mentions.includes(:account).map(&:account)
+ # inbox_owners = mentioned_accounts.select(&:local?) + (account.local? ? [account] : [])
- inbox_owners.each do |inbox_owner|
- AccountConversation.remove_status(inbox_owner, self)
- end
+ # inbox_owners.each do |inbox_owner|
+ # AccountConversation.remove_status(inbox_owner, self)
+ # end
end
end
diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb
deleted file mode 100644
index 1a9afc5c..00000000
--- a/app/models/stream_entry.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: stream_entries
-#
-# id :bigint(8) not null, primary key
-# activity_id :bigint(8)
-# activity_type :string
-# created_at :datetime not null
-# updated_at :datetime not null
-# hidden :boolean default(FALSE), not null
-# account_id :bigint(8)
-#
-
-class StreamEntry < ApplicationRecord
- include Paginable
-
- belongs_to :account, inverse_of: :stream_entries
- belongs_to :activity, polymorphic: true
- belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', inverse_of: :stream_entry
-
- validates :account, :activity, presence: true
-
- STATUS_INCLUDES = [:account, :stream_entry, :conversation, :media_attachments, :tags, mentions: :account, reblog: [:stream_entry, :account, :conversation, :media_attachments, :tags, mentions: :account], thread: [:stream_entry, :account]].freeze
-
- default_scope { where(activity_type: 'Status') }
- scope :recent, -> { reorder(id: :desc) }
- scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) }
-
- delegate :target, :title, :content, :thread,
- to: :status,
- allow_nil: true
-
- def object_type
- orphaned? || targeted? ? :activity : status.object_type
- end
-
- def verb
- orphaned? ? :delete : status.verb
- end
-
- def targeted?
- [:follow, :request_friend, :authorize, :reject, :unfollow, :block, :unblock, :share, :favorite].include? verb
- end
-
- def threaded?
- (verb == :favorite || object_type == :comment) && !thread.nil?
- end
-
- def mentions
- orphaned? ? [] : status.active_mentions.map(&:account)
- end
-
- private
-
- def orphaned?
- status.nil?
- end
-end
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
deleted file mode 100644
index 79b81828..00000000
--- a/app/models/subscription.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-# == Schema Information
-#
-# Table name: subscriptions
-#
-# id :bigint(8) not null, primary key
-# callback_url :string default(""), not null
-# secret :string
-# expires_at :datetime
-# confirmed :boolean default(FALSE), not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# last_successful_delivery_at :datetime
-# domain :string
-# account_id :bigint(8) not null
-#
-
-class Subscription < ApplicationRecord
- MIN_EXPIRATION = 1.day.to_i
- MAX_EXPIRATION = 30.days.to_i
-
- belongs_to :account
-
- validates :callback_url, presence: true
- validates :callback_url, uniqueness: { scope: :account_id }
-
- scope :confirmed, -> { where(confirmed: true) }
- scope :future_expiration, -> { where(arel_table[:expires_at].gt(Time.now.utc)) }
- scope :expired, -> { where(arel_table[:expires_at].lt(Time.now.utc)) }
- scope :active, -> { confirmed.future_expiration }
-
- def lease_seconds=(value)
- self.expires_at = future_expiration(value)
- end
-
- def lease_seconds
- (expires_at - Time.now.utc).to_i
- end
-
- def expired?
- Time.now.utc > expires_at
- end
-
- before_validation :set_min_expiration
-
- private
-
- def future_expiration(value)
- Time.now.utc + future_offset(value).seconds
- end
-
- def future_offset(seconds)
- [
- [MIN_EXPIRATION, seconds.to_i].max,
- MAX_EXPIRATION,
- ].min
- end
-
- def set_min_expiration
- self.lease_seconds = 0 unless expires_at
- end
-end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 88d65426..f34f8424 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -14,7 +14,6 @@ class Tag < ApplicationRecord
has_and_belongs_to_many :accounts
has_and_belongs_to_many :sample_accounts, -> { searchable.discoverable.popular.limit(3) }, class_name: 'Account'
- has_many :featured_tags, dependent: :destroy, inverse_of: :tag
has_one :account_tag_stat, dependent: :destroy
HASHTAG_NAME_RE = '[[:word:]_]*[[:alpha:]_·][[:word:]_]*'
diff --git a/app/models/trending_tags.rb b/app/models/trending_tags.rb
deleted file mode 100644
index 148535c2..00000000
--- a/app/models/trending_tags.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class TrendingTags
- KEY = 'trending_tags'
- EXPIRE_HISTORY_AFTER = 7.days.seconds
- EXPIRE_TRENDS_AFTER = 1.day.seconds
- THRESHOLD = 5
-
- class << self
- include Redisable
-
- def record_use!(tag, account, at_time = Time.now.utc)
- return if disallowed_hashtags.include?(tag.name) || account.silenced? || account.bot?
-
- increment_historical_use!(tag.id, at_time)
- increment_unique_use!(tag.id, account.id, at_time)
- increment_vote!(tag.id, at_time)
- end
-
- def get(limit)
- key = "#{KEY}:#{Time.now.utc.beginning_of_day.to_i}"
- tag_ids = redis.zrevrange(key, 0, limit - 1).map(&:to_i)
- tags = Tag.where(id: tag_ids).to_a.each_with_object({}) { |tag, h| h[tag.id] = tag }
- tag_ids.map { |tag_id| tags[tag_id] }.compact
- end
-
- private
-
- def increment_historical_use!(tag_id, at_time)
- key = "activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}"
- redis.incrby(key, 1)
- redis.expire(key, EXPIRE_HISTORY_AFTER)
- end
-
- def increment_unique_use!(tag_id, account_id, at_time)
- key = "activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}:accounts"
- redis.pfadd(key, account_id)
- redis.expire(key, EXPIRE_HISTORY_AFTER)
- end
-
- def increment_vote!(tag_id, at_time)
- key = "#{KEY}:#{at_time.beginning_of_day.to_i}"
- expected = redis.pfcount("activity:tags:#{tag_id}:#{(at_time - 1.day).beginning_of_day.to_i}:accounts").to_f
- expected = 1.0 if expected.zero?
- observed = redis.pfcount("activity:tags:#{tag_id}:#{at_time.beginning_of_day.to_i}:accounts").to_f
-
- if expected > observed || observed < THRESHOLD
- redis.zrem(key, tag_id.to_s)
- else
- score = ((observed - expected)**2) / expected
- redis.zadd(key, score, tag_id.to_s)
- end
-
- redis.expire(key, EXPIRE_TRENDS_AFTER)
- end
-
- def disallowed_hashtags
- return @disallowed_hashtags if defined?(@disallowed_hashtags)
-
- @disallowed_hashtags = Setting.disallowed_hashtags.nil? ? [] : Setting.disallowed_hashtags
- @disallowed_hashtags = @disallowed_hashtags.split(' ') if @disallowed_hashtags.is_a? String
- @disallowed_hashtags = @disallowed_hashtags.map(&:downcase)
- end
- end
-end
diff --git a/app/models/user.rb b/app/models/user.rb
index ba9a33b6..a714f660 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -33,7 +33,6 @@
# account_id :bigint(8) not null
# disabled :boolean default(FALSE), not null
# moderator :boolean default(FALSE), not null
-# invite_id :bigint(8)
# remember_token :string
# chosen_languages :string is an Array
# created_by_application_id :bigint(8)
@@ -43,6 +42,8 @@
#
class User < ApplicationRecord
+ self.ignored_columns = ["{:column=>:invite}_id"]
+
include Settings::Extend
include UserRoles
@@ -69,24 +70,18 @@ class User < ApplicationRecord
include LdapAuthenticable
belongs_to :account, inverse_of: :user
- belongs_to :invite, counter_cache: :uses, optional: true
belongs_to :created_by_application, class_name: 'Doorkeeper::Application', optional: true
accepts_nested_attributes_for :account
has_many :applications, class_name: 'Doorkeeper::Application', as: :owner
has_many :backups, inverse_of: :user
- has_one :invite_request, class_name: 'UserInviteRequest', inverse_of: :user, dependent: :destroy
- accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? }
-
validates :locale, inclusion: I18n.available_locales.map(&:to_s), if: :locale?
- validates :unique_email, uniqueness: true, on: :create
validates_with BlacklistedEmailValidator, on: :create
validates_with EmailMxValidator, if: :validate_email_dns?
validates :agreement, acceptance: { allow_nil: false, accept: [true, 'true', '1'] }, on: :create
scope :recent, -> { order(id: :desc) }
- scope :pending, -> { where(approved: false) }
scope :approved, -> { where(approved: true) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :enabled, -> { where(disabled: false) }
@@ -96,7 +91,6 @@ class User < ApplicationRecord
scope :emailable, -> { confirmed.enabled.joins(:account).merge(Account.searchable) }
before_validation :sanitize_languages
- before_validation :set_unique_email
before_create :set_approved
after_create :prepare_new_user!
@@ -109,24 +103,15 @@ class User < ApplicationRecord
delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal,
:noindex, :theme, :display_media, :hide_network,
- :expand_spoilers, :default_language, :aggregate_reblogs, :show_application,
+ :expand_spoilers, :default_language, :aggregate_reblogs,
:group_in_home_feed, to: :settings, prefix: :setting, allow_nil: false
- attr_reader :invite_code
attr_writer :external
def confirmed?
confirmed_at.present?
end
- def invited?
- invite_id.present?
- end
-
- def valid_invitation?
- invite_id.present? && invite.valid_for_use?
- end
-
def disable!
update!(disabled: true,
last_sign_in_at: current_sign_in_at,
@@ -138,8 +123,8 @@ class User < ApplicationRecord
end
def confirm
- new_user = !confirmed?
- self.approved = true if open_registrations?
+ new_user = !confirmed?
+ self.approved = true
super
@@ -149,8 +134,8 @@ class User < ApplicationRecord
end
def confirm!
- new_user = !confirmed?
- self.approved = true if open_registrations?
+ new_user = !confirmed?
+ self.approved = true
skip_confirmation!
save!
@@ -158,18 +143,10 @@ class User < ApplicationRecord
# prepare_new_user! if new_user && approved?
end
- def pending?
- !approved?
- end
-
def active_for_authentication?
super && approved?
end
- def inactive_message
- !approved? ? :pending : super
- end
-
def approve!
return if approved?
@@ -200,10 +177,6 @@ class User < ApplicationRecord
settings.notification_emails['report']
end
- def allows_pending_account_emails?
- settings.notification_emails['pending_account']
- end
-
def hides_network?
@hides_network ||= settings.hide_network
end
@@ -212,10 +185,6 @@ class User < ApplicationRecord
@aggregates_reblogs ||= settings.aggregate_reblogs
end
- def shows_application?
- @shows_application ||= settings.show_application
- end
-
def allows_group_in_home_feed?
settings.group_in_home_feed
end
@@ -249,11 +218,6 @@ class User < ApplicationRecord
session.web_push_subscription.nil? ? nil : session.web_push_subscription
end
- def invite_code=(code)
- self.invite = Invite.find_by(code: code) if code.present?
- @invite_code = code
- end
-
def challenge
#
end
@@ -294,11 +258,7 @@ class User < ApplicationRecord
private
def set_approved
- self.approved = open_registrations? || valid_invitation? || external?
- end
-
- def open_registrations?
- Setting.registrations_mode == 'open'
+ self.approved = true
end
def external?
@@ -345,12 +305,4 @@ class User < ApplicationRecord
end
end
- def set_unique_email
- user, domain = self.email.split('@')
- user = user.split('+').first
- if ((domain == 'gmail.com') || (domain == 'hotmail.com'))
- user = user.gsub('.', '')
- end
- self.unique_email = "#{user}@#{domain}"
- end
end
diff --git a/app/models/user_invite_request.rb b/app/models/user_invite_request.rb
deleted file mode 100644
index 2b76c88b..00000000
--- a/app/models/user_invite_request.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-# == Schema Information
-#
-# Table name: user_invite_requests
-#
-# id :bigint(8) not null, primary key
-# user_id :bigint(8)
-# text :text
-# created_at :datetime not null
-# updated_at :datetime not null
-#
-
-class UserInviteRequest < ApplicationRecord
- belongs_to :user, inverse_of: :invite_request
- validates :text, presence: true, length: { maximum: 420 }
-end
diff --git a/app/policies/domain_block_policy.rb b/app/policies/domain_block_policy.rb
deleted file mode 100644
index 47c0a81a..00000000
--- a/app/policies/domain_block_policy.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class DomainBlockPolicy < ApplicationPolicy
- def index?
- admin?
- end
-
- def show?
- admin?
- end
-
- def create?
- admin?
- end
-
- def destroy?
- admin?
- end
-end
diff --git a/app/policies/instance_policy.rb b/app/policies/instance_policy.rb
deleted file mode 100644
index a7382355..00000000
--- a/app/policies/instance_policy.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class InstancePolicy < ApplicationPolicy
- def index?
- admin?
- end
-
- def show?
- admin?
- end
-end
diff --git a/app/policies/invite_policy.rb b/app/policies/invite_policy.rb
deleted file mode 100644
index 14236f78..00000000
--- a/app/policies/invite_policy.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class InvitePolicy < ApplicationPolicy
- def index?
- staff?
- end
-
- def create?
- min_required_role?
- end
-
- def deactivate_all?
- admin?
- end
-
- def destroy?
- owner? || (Setting.min_invite_role == 'admin' ? admin? : staff?)
- end
-
- private
-
- def owner?
- record.user_id == current_user&.id
- end
-
- def min_required_role?
- current_user&.role?(Setting.min_invite_role)
- end
-end
diff --git a/app/policies/relay_policy.rb b/app/policies/relay_policy.rb
deleted file mode 100644
index bd75e219..00000000
--- a/app/policies/relay_policy.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-class RelayPolicy < ApplicationPolicy
- def update?
- admin?
- end
-end
diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb
index dfe983cf..a8b05f18 100644
--- a/app/policies/status_policy.rb
+++ b/app/policies/status_policy.rb
@@ -42,7 +42,7 @@ class StatusPolicy < ApplicationPolicy
private
def requires_mention?
- record.direct_visibility? || record.limited_visibility?
+ record.limited_visibility?
end
def owned?
diff --git a/app/policies/subscription_policy.rb b/app/policies/subscription_policy.rb
deleted file mode 100644
index ac9a8a6c..00000000
--- a/app/policies/subscription_policy.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-class SubscriptionPolicy < ApplicationPolicy
- def index?
- admin?
- end
-end
diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb
index b05673a3..02929e45 100644
--- a/app/presenters/account_relationships_presenter.rb
+++ b/app/presenters/account_relationships_presenter.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
class AccountRelationshipsPresenter
- attr_reader :following, :followed_by, :blocking, :blocked_by,
- :muting, :requested, :domain_blocking,
- :endorsed
+ attr_reader :following, :followed_by, :blocking,
+ :blocked_by, :muting, :requested
def initialize(account_ids, current_account_id, **options)
@account_ids = account_ids.map { |a| a.is_a?(Account) ? a.id : a }
@@ -15,8 +14,6 @@ class AccountRelationshipsPresenter
@blocked_by = cached[:blocked_by].merge(Account.blocked_by_map(@uncached_account_ids, @current_account_id))
@muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id))
@requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id))
- @domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id))
- @endorsed = cached[:endorsed].merge(Account.endorsed_map(@uncached_account_ids, @current_account_id))
cache_uncached!
@@ -26,8 +23,6 @@ class AccountRelationshipsPresenter
@blocked_by.merge!(options[:blocked_by_map] || {})
@muting.merge!(options[:muting_map] || {})
@requested.merge!(options[:requested_map] || {})
- @domain_blocking.merge!(options[:domain_blocking_map] || {})
- @endorsed.merge!(options[:endorsed_map] || {})
end
private
@@ -42,8 +37,6 @@ class AccountRelationshipsPresenter
blocked_by: {},
muting: {},
requested: {},
- domain_blocking: {},
- endorsed: {},
}
@uncached_account_ids = []
@@ -70,8 +63,6 @@ class AccountRelationshipsPresenter
blocked_by: { account_id => blocked_by[account_id] },
muting: { account_id => muting[account_id] },
requested: { account_id => requested[account_id] },
- domain_blocking: { account_id => domain_blocking[account_id] },
- endorsed: { account_id => endorsed[account_id] },
}
Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day)
diff --git a/app/presenters/instance_presenter.rb b/app/presenters/instance_presenter.rb
index b43024b1..100bb9ba 100644
--- a/app/presenters/instance_presenter.rb
+++ b/app/presenters/instance_presenter.rb
@@ -6,9 +6,6 @@ class InstancePresenter
:site_title,
:site_short_description,
:site_description,
- :site_extended_description,
- :site_terms,
- :closed_registrations_message,
to: Setting
)
@@ -25,6 +22,7 @@ class InstancePresenter
end
def status_count
+ puts "tilly-hello-1"
Rails.cache.fetch('local_status_count') { Account.local.joins(:account_stat).sum('account_stats.statuses_count') }.to_i
end
@@ -47,9 +45,5 @@ class InstancePresenter
def thumbnail
@thumbnail ||= Rails.cache.fetch('site_uploads/thumbnail') { SiteUpload.find_by(var: 'thumbnail') }
end
-
- def hero
- @hero ||= Rails.cache.fetch('site_uploads/hero') { SiteUpload.find_by(var: 'hero') }
- end
end
diff --git a/app/presenters/status_relationships_presenter.rb b/app/presenters/status_relationships_presenter.rb
index 6847e2b5..6ad4be2b 100644
--- a/app/presenters/status_relationships_presenter.rb
+++ b/app/presenters/status_relationships_presenter.rb
@@ -1,32 +1,18 @@
# frozen_string_literal: true
class StatusRelationshipsPresenter
- attr_reader :reblogs_map, :favourites_map, :mutes_map, :pins_map, :group_pins_map, :bookmarks_map
+ attr_reader :reblogs_map, :favourites_map, :group_pins_map
def initialize(statuses, current_account_id = nil, **options)
if current_account_id.nil?
- @reblogs_map = {}
+ @reblogs_map = {}
@favourites_map = {}
- @mutes_map = {}
- @bookmarks_map = {}
- @pins_map = {}
- @group_pins_map = {}
else
- statuses = statuses.compact
- status_ids = statuses.flat_map { |s| [s.id, s.reblog_of_id, s.quote_of_id] }.uniq.compact
- conversation_ids = statuses.map(&:conversation_id).compact.uniq
- pinnable_status_ids = statuses.map(&:proper).select { |s| s.account_id == current_account_id && %w(public unlisted).include?(s.visibility) }.map(&:id)
+ statuses = statuses.compact
+ status_ids = statuses.flat_map { |s| [s.id, s.reblog_of_id, s.quote_of_id] }.uniq.compact
- @reblogs_map = Status.reblogs_map(status_ids, current_account_id).merge(options[:reblogs_map] || {})
+ @reblogs_map = Status.reblogs_map(status_ids, current_account_id).merge(options[:reblogs_map] || {})
@favourites_map = Status.favourites_map(status_ids, current_account_id).merge(options[:favourites_map] || {})
- @mutes_map = Status.mutes_map(conversation_ids, current_account_id).merge(options[:mutes_map] || {})
- @bookmarks_map = Status.bookmarks_map(status_ids, current_account_id).merge(options[:bookmarks_map] || {})
- @pins_map = Status.pins_map(pinnable_status_ids, current_account_id).merge(options[:pins_map] || {})
- if options[:group_id]
- @group_pins_map = Status.group_pins_map(status_ids, options[:group_id]).merge(options[:group_pins_map] || {})
- else
- @group_pins_map = {}
- end
end
end
end
diff --git a/app/serializers/activitypub/accept_follow_serializer.rb b/app/serializers/activitypub/accept_follow_serializer.rb
deleted file mode 100644
index 1c1c6ab7..00000000
--- a/app/serializers/activitypub/accept_follow_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::AcceptFollowSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
-
- has_one :object, serializer: ActivityPub::FollowSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.target_account), '#accepts/follows/', object.id].join
- end
-
- def type
- 'Accept'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.target_account)
- end
-end
diff --git a/app/serializers/activitypub/activity_serializer.rb b/app/serializers/activitypub/activity_serializer.rb
deleted file mode 100644
index 451c5bfe..00000000
--- a/app/serializers/activitypub/activity_serializer.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ActivitySerializer < ActivityPub::Serializer
- attributes :id, :type, :actor, :published, :to, :cc
-
- has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer, if: :serialize_object?
- attribute :proper_uri, key: :object, unless: :serialize_object?
- attribute :atom_uri, if: :announce?
-
- def id
- ActivityPub::TagManager.instance.activity_uri_for(object)
- end
-
- def type
- announce? ? 'Announce' : 'Create'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def published
- object.created_at.iso8601
- end
-
- def to
- ActivityPub::TagManager.instance.to(object)
- end
-
- def cc
- ActivityPub::TagManager.instance.cc(object)
- end
-
- def proper_uri
- ActivityPub::TagManager.instance.uri_for(object.proper)
- end
-
- def atom_uri
- OStatus::TagManager.instance.uri_for(object)
- end
-
- def announce?
- object.reblog?
- end
-
- def serialize_object?
- return true unless announce?
- # Serialize private self-reposts of local gabs
- object.account == object.proper.account && object.proper.private_visibility? && object.local?
- end
-end
diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb
deleted file mode 100644
index 1b00cd73..00000000
--- a/app/serializers/activitypub/actor_serializer.rb
+++ /dev/null
@@ -1,200 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ActorSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- # Conditionally serialize Gab image for gab:// URLs
- def self.serializer_for(object, options)
- gab_image = object.is_a?(String) and object.start_with?('gab://')
- if gab_image and options[:serializer] == ActivityPub::ImageSerializer
- return ActivityPub::GabImageSerializer
- end
- super
- end
-
- context :security
-
- context_extensions :manually_approves_followers, :featured, :also_known_as,
- :moved_to, :property_value, :hashtag, :emoji, :identity_proof
-
- attributes :id, :type, :following, :followers,
- :inbox, :outbox, :featured,
- :preferred_username, :name, :summary,
- :url, :manually_approves_followers
-
- has_one :public_key, serializer: ActivityPub::PublicKeySerializer
-
- has_many :virtual_tags, key: :tag
- has_many :virtual_attachments, key: :attachment
-
- attribute :moved_to, if: :moved?
- attribute :also_known_as, if: :also_known_as?
-
- class EndpointsSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- attributes :shared_inbox
-
- def shared_inbox
- inbox_url
- end
- end
-
- has_one :endpoints, serializer: EndpointsSerializer
-
- has_one :icon, serializer: ActivityPub::ImageSerializer, if: :avatar_exists?
- has_one :image, serializer: ActivityPub::ImageSerializer, if: :header_exists?
-
- delegate :moved?, to: :object
-
- def id
- account_url(object)
- end
-
- def type
- object.bot? ? 'Service' : 'Person'
- end
-
- def following
- account_following_index_url(object)
- end
-
- def followers
- account_followers_url(object)
- end
-
- def inbox
- account_inbox_url(object)
- end
-
- def outbox
- account_outbox_url(object)
- end
-
- def featured
- account_collection_url(object, :featured)
- end
-
- def endpoints
- object
- end
-
- def preferred_username
- object.username
- end
-
- def name
- object.display_name
- end
-
- def summary
- Formatter.instance.simplified_format(object)
- end
-
- def icon
- return object.avatar if object.avatar?
- return object.avatar_remote_url if is_gab_avatar?
- end
-
- def image
- return object.header if object.header?
- return object.header_remote_url if is_gab_header?
- end
-
- def public_key
- object
- end
-
- def url
- short_account_url(object)
- end
-
- def avatar_exists?
- object.avatar? or is_gab_avatar?
- end
-
- def header_exists?
- object.header? or is_gab_header?
- end
-
- def is_gab_avatar?
- object.avatar_remote_url&.start_with?('gab://') or false
- end
-
- def is_gab_header?
- object.header_remote_url&.start_with?('gab://') or false
- end
-
- def manually_approves_followers
- object.locked
- end
-
- def virtual_tags
- object.emojis + object.tags
- end
-
- def virtual_attachments
- object.fields + object.identity_proofs.active
- end
-
- def moved_to
- ActivityPub::TagManager.instance.uri_for(object.moved_to_account)
- end
-
- def also_known_as?
- !object.also_known_as.empty?
- end
-
- class CustomEmojiSerializer < ActivityPub::EmojiSerializer
- end
-
- class TagSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- attributes :type, :href, :name
-
- def type
- 'Hashtag'
- end
-
- def href
- explore_hashtag_url(object)
- end
-
- def name
- "##{object.name}"
- end
- end
-
- class Account::FieldSerializer < ActivityPub::Serializer
- attributes :type, :name, :value
-
- def type
- 'PropertyValue'
- end
-
- def value
- Formatter.instance.format_field(object.account, object.value)
- end
- end
-
- class AccountIdentityProofSerializer < ActivityPub::Serializer
- attributes :type, :name, :signature_algorithm, :signature_value
-
- def type
- 'IdentityProof'
- end
-
- def name
- object.provider_username
- end
-
- def signature_algorithm
- object.provider
- end
-
- def signature_value
- object.token
- end
- end
-end
diff --git a/app/serializers/activitypub/add_serializer.rb b/app/serializers/activitypub/add_serializer.rb
deleted file mode 100644
index 6f5aab17..00000000
--- a/app/serializers/activitypub/add_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::AddSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- attributes :type, :actor, :target
- attribute :proper_object, key: :object
-
- def type
- 'Add'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def proper_object
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def target
- account_collection_url(object.account, :featured)
- end
-end
diff --git a/app/serializers/activitypub/block_serializer.rb b/app/serializers/activitypub/block_serializer.rb
deleted file mode 100644
index e6c69329..00000000
--- a/app/serializers/activitypub/block_serializer.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::BlockSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
- attribute :virtual_object, key: :object
-
- def id
- ActivityPub::TagManager.instance.uri_for(object) || [ActivityPub::TagManager.instance.uri_for(object.account), '#blocks/', object.id].join
- end
-
- def type
- 'Block'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def virtual_object
- ActivityPub::TagManager.instance.uri_for(object.target_account)
- end
-end
diff --git a/app/serializers/activitypub/collection_serializer.rb b/app/serializers/activitypub/collection_serializer.rb
deleted file mode 100644
index da1ba735..00000000
--- a/app/serializers/activitypub/collection_serializer.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::CollectionSerializer < ActivityPub::Serializer
- def self.serializer_for(model, options)
- return ActivityPub::NoteSerializer if model.class.name == 'Status'
- return ActivityPub::CollectionSerializer if model.class.name == 'ActivityPub::CollectionPresenter'
- super
- end
-
- attribute :id, if: -> { object.id.present? }
- attribute :type
- attribute :total_items, if: -> { object.size.present? }
- attribute :next, if: -> { object.next.present? }
- attribute :prev, if: -> { object.prev.present? }
- attribute :part_of, if: -> { object.part_of.present? }
-
- has_one :first, if: -> { object.first.present? }
- has_one :last, if: -> { object.last.present? }
- has_many :items, key: :items, if: -> { (!object.items.nil? || page?) && !ordered? }
- has_many :items, key: :ordered_items, if: -> { (!object.items.nil? || page?) && ordered? }
-
- def type
- if page?
- ordered? ? 'OrderedCollectionPage' : 'CollectionPage'
- else
- ordered? ? 'OrderedCollection' : 'Collection'
- end
- end
-
- def total_items
- object.size
- end
-
- private
-
- def ordered?
- object.type == :ordered
- end
-
- def page?
- object.part_of.present? || object.page.present?
- end
-end
diff --git a/app/serializers/activitypub/delete_actor_serializer.rb b/app/serializers/activitypub/delete_actor_serializer.rb
deleted file mode 100644
index a6c5e238..00000000
--- a/app/serializers/activitypub/delete_actor_serializer.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::DeleteActorSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor, :to
- attribute :virtual_object, key: :object
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object), '#delete'].join
- end
-
- def type
- 'Delete'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def virtual_object
- actor
- end
-
- def to
- [ActivityPub::TagManager::COLLECTIONS[:public]]
- end
-end
diff --git a/app/serializers/activitypub/delete_serializer.rb b/app/serializers/activitypub/delete_serializer.rb
deleted file mode 100644
index a7d5bd46..00000000
--- a/app/serializers/activitypub/delete_serializer.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::DeleteSerializer < ActivityPub::Serializer
- class TombstoneSerializer < ActivityPub::Serializer
- context_extensions :atom_uri
-
- attributes :id, :type, :atom_uri
-
- def id
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def type
- 'Tombstone'
- end
-
- def atom_uri
- OStatus::TagManager.instance.uri_for(object)
- end
- end
-
- attributes :id, :type, :actor, :to
-
- has_one :object, serializer: TombstoneSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object), '#delete'].join
- end
-
- def type
- 'Delete'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def to
- [ActivityPub::TagManager::COLLECTIONS[:public]]
- end
-end
diff --git a/app/serializers/activitypub/emoji_serializer.rb b/app/serializers/activitypub/emoji_serializer.rb
deleted file mode 100644
index 4dc38f3e..00000000
--- a/app/serializers/activitypub/emoji_serializer.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::EmojiSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- context_extensions :emoji
-
- attributes :id, :type, :name, :updated
-
- has_one :icon, serializer: ActivityPub::ImageSerializer
-
- def id
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def type
- 'Emoji'
- end
-
- def icon
- object.image
- end
-
- def updated
- object.updated_at.iso8601
- end
-
- def name
- ":#{object.shortcode}:"
- end
-end
diff --git a/app/serializers/activitypub/flag_serializer.rb b/app/serializers/activitypub/flag_serializer.rb
deleted file mode 100644
index 2f2a707d..00000000
--- a/app/serializers/activitypub/flag_serializer.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FlagSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor, :content
- attribute :virtual_object, key: :object
-
- def id
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def type
- 'Flag'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(instance_options[:account] || object.account)
- end
-
- def virtual_object
- [ActivityPub::TagManager.instance.uri_for(object.target_account)] + object.statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
- end
-
- def content
- object.comment
- end
-end
diff --git a/app/serializers/activitypub/follow_serializer.rb b/app/serializers/activitypub/follow_serializer.rb
deleted file mode 100644
index 9228d771..00000000
--- a/app/serializers/activitypub/follow_serializer.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FollowSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
- attribute :virtual_object, key: :object
-
- def id
- ActivityPub::TagManager.instance.uri_for(object) || [ActivityPub::TagManager.instance.uri_for(object.account), '#follows/', object.id].join
- end
-
- def type
- 'Follow'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def virtual_object
- ActivityPub::TagManager.instance.uri_for(object.target_account)
- end
-end
diff --git a/app/serializers/activitypub/gab_image_serializer.rb b/app/serializers/activitypub/gab_image_serializer.rb
deleted file mode 100644
index ae2f6f64..00000000
--- a/app/serializers/activitypub/gab_image_serializer.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::GabImageSerializer < ActivityPub::ImageSerializer
- def url
- object
- .sub('gab://avatar/', 'https://gab.com/media/user/')
- .sub('gab://header/', 'https://gab.com/media/user/')
- end
-
- def media_type; end
-end
diff --git a/app/serializers/activitypub/image_serializer.rb b/app/serializers/activitypub/image_serializer.rb
deleted file mode 100644
index 1060f969..00000000
--- a/app/serializers/activitypub/image_serializer.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ImageSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- context_extensions :focal_point
-
- attributes :type, :media_type, :url
- attribute :focal_point, if: :focal_point?
-
- def type
- 'Image'
- end
-
- def url
- full_asset_url(object.url(:original))
- end
-
- def media_type
- object.content_type
- end
-
- def focal_point?
- object.respond_to?(:meta) && object.meta.is_a?(Hash) && object.meta['focus'].is_a?(Hash)
- end
-
- def focal_point
- [object.meta['focus']['x'], object.meta['focus']['y']]
- end
-end
diff --git a/app/serializers/activitypub/like_serializer.rb b/app/serializers/activitypub/like_serializer.rb
deleted file mode 100644
index 0f170ddb..00000000
--- a/app/serializers/activitypub/like_serializer.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::LikeSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
- attribute :virtual_object, key: :object
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.account), '#likes/', object.id].join
- end
-
- def type
- 'Like'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def virtual_object
- ActivityPub::TagManager.instance.uri_for(object.status)
- end
-end
diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb
deleted file mode 100644
index 67f596e7..00000000
--- a/app/serializers/activitypub/note_serializer.rb
+++ /dev/null
@@ -1,250 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::NoteSerializer < ActivityPub::Serializer
- context_extensions :atom_uri, :conversation, :sensitive,
- :hashtag, :emoji, :focal_point, :blurhash
-
- attributes :id, :type, :summary,
- :in_reply_to, :published, :url,
- :attributed_to, :to, :cc, :sensitive,
- :atom_uri, :in_reply_to_atom_uri,
- :conversation
-
- attribute :content
- attribute :content_map, if: :language?
-
- has_many :media_attachments, key: :attachment
- has_many :virtual_tags, key: :tag
-
- has_one :replies, serializer: ActivityPub::CollectionSerializer, if: :local?
-
- has_many :poll_options, key: :one_of, if: :poll_and_not_multiple?
- has_many :poll_options, key: :any_of, if: :poll_and_multiple?
-
- attribute :end_time, if: :poll_and_expires?
- attribute :closed, if: :poll_and_expired?
-
- def id
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def type
- object.preloadable_poll ? 'Question' : 'Note'
- end
-
- def summary
- object.spoiler_text.presence
- end
-
- def content
- Formatter.instance.format(object)
- end
-
- def content_map
- { object.language => Formatter.instance.format(object) }
- end
-
- def replies
- replies = object.self_replies(5).pluck(:id, :uri)
- last_id = replies.last&.first
-
- ActivityPub::CollectionPresenter.new(
- type: :unordered,
- id: ActivityPub::TagManager.instance.replies_uri_for(object),
- first: ActivityPub::CollectionPresenter.new(
- type: :unordered,
- part_of: ActivityPub::TagManager.instance.replies_uri_for(object),
- items: replies.map(&:second),
- next: last_id ? ActivityPub::TagManager.instance.replies_uri_for(object, page: true, min_id: last_id) : nil
- )
- )
- end
-
- def language?
- object.language.present?
- end
-
- def in_reply_to
- return unless object.reply? && !object.thread.nil?
-
- if object.thread.uri.nil? || object.thread.uri.start_with?('http')
- ActivityPub::TagManager.instance.uri_for(object.thread)
- else
- object.thread.url
- end
- end
-
- def published
- object.created_at.iso8601
- end
-
- def url
- ActivityPub::TagManager.instance.url_for(object)
- end
-
- def attributed_to
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def to
- ActivityPub::TagManager.instance.to(object)
- end
-
- def cc
- ActivityPub::TagManager.instance.cc(object)
- end
-
- def virtual_tags
- object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis
- end
-
- def atom_uri
- return unless object.local?
-
- OStatus::TagManager.instance.uri_for(object)
- end
-
- def in_reply_to_atom_uri
- return unless object.reply? && !object.thread.nil?
-
- OStatus::TagManager.instance.uri_for(object.thread)
- end
-
- def conversation
- return if object.conversation.nil?
-
- if object.conversation.uri?
- object.conversation.uri
- else
- OStatus::TagManager.instance.unique_tag(object.conversation.created_at, object.conversation.id, 'Conversation')
- end
- end
-
- def local?
- object.account.local?
- end
-
- def poll_options
- object.preloadable_poll.loaded_options
- end
-
- def poll_and_multiple?
- object.preloadable_poll&.multiple?
- end
-
- def poll_and_not_multiple?
- object.preloadable_poll && !object.preloadable_poll.multiple?
- end
-
- def closed
- object.preloadable_poll.expires_at.iso8601
- end
-
- alias end_time closed
-
- def poll_and_expires?
- object.preloadable_poll&.expires_at&.present?
- end
-
- def poll_and_expired?
- object.preloadable_poll&.expired?
- end
-
- class MediaAttachmentSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- attributes :type, :media_type, :url, :name, :blurhash
- attribute :focal_point, if: :focal_point?
-
- def type
- 'Document'
- end
-
- def name
- object.description
- end
-
- def media_type
- object.file_content_type
- end
-
- def url
- object.local? ? full_asset_url(object.file.url(:original, false)) : object.remote_url
- end
-
- def focal_point?
- object.file.meta.is_a?(Hash) && object.file.meta['focus'].is_a?(Hash)
- end
-
- def focal_point
- [object.file.meta['focus']['x'], object.file.meta['focus']['y']]
- end
- end
-
- class MentionSerializer < ActivityPub::Serializer
- attributes :type, :href, :name
-
- def type
- 'Mention'
- end
-
- def href
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def name
- "@#{object.account.acct}"
- end
- end
-
- class TagSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- attributes :type, :href, :name
-
- def type
- 'Hashtag'
- end
-
- def href
- tag_url(object)
- end
-
- def name
- "##{object.name}"
- end
- end
-
- class CustomEmojiSerializer < ActivityPub::EmojiSerializer
- end
-
- class OptionSerializer < ActivityPub::Serializer
- class RepliesSerializer < ActivityPub::Serializer
- attributes :type, :total_items
-
- def type
- 'Collection'
- end
-
- def total_items
- object.votes_count
- end
- end
-
- attributes :type, :name
-
- has_one :replies, serializer: ActivityPub::NoteSerializer::OptionSerializer::RepliesSerializer
-
- def type
- 'Note'
- end
-
- def name
- object.title
- end
-
- def replies
- object
- end
- end
-end
diff --git a/app/serializers/activitypub/outbox_serializer.rb b/app/serializers/activitypub/outbox_serializer.rb
deleted file mode 100644
index 48fbad0f..00000000
--- a/app/serializers/activitypub/outbox_serializer.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::OutboxSerializer < ActivityPub::CollectionSerializer
- def self.serializer_for(model, options)
- return ActivityPub::ActivitySerializer if model.is_a?(Status)
- super
- end
-end
diff --git a/app/serializers/activitypub/public_key_serializer.rb b/app/serializers/activitypub/public_key_serializer.rb
deleted file mode 100644
index 62ed49e8..00000000
--- a/app/serializers/activitypub/public_key_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::PublicKeySerializer < ActivityPub::Serializer
- context :security
-
- attributes :id, :owner, :public_key_pem
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object), '#main-key'].join
- end
-
- def owner
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def public_key_pem
- object.public_key
- end
-end
diff --git a/app/serializers/activitypub/reject_follow_serializer.rb b/app/serializers/activitypub/reject_follow_serializer.rb
deleted file mode 100644
index 4996c9a3..00000000
--- a/app/serializers/activitypub/reject_follow_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::RejectFollowSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
-
- has_one :object, serializer: ActivityPub::FollowSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.target_account), '#rejects/follows/', object.id].join
- end
-
- def type
- 'Reject'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.target_account)
- end
-end
diff --git a/app/serializers/activitypub/remove_serializer.rb b/app/serializers/activitypub/remove_serializer.rb
deleted file mode 100644
index 7fefda59..00000000
--- a/app/serializers/activitypub/remove_serializer.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::RemoveSerializer < ActivityPub::Serializer
- include RoutingHelper
-
- attributes :type, :actor, :target
- attribute :proper_object, key: :object
-
- def type
- 'Remove'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def proper_object
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def target
- account_collection_url(object.account, :featured)
- end
-end
diff --git a/app/serializers/activitypub/undo_announce_serializer.rb b/app/serializers/activitypub/undo_announce_serializer.rb
deleted file mode 100644
index 6758af67..00000000
--- a/app/serializers/activitypub/undo_announce_serializer.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UndoAnnounceSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor, :to
-
- has_one :object, serializer: ActivityPub::ActivitySerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.account), '#announces/', object.id, '/undo'].join
- end
-
- def type
- 'Undo'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def to
- [ActivityPub::TagManager::COLLECTIONS[:public]]
- end
-end
diff --git a/app/serializers/activitypub/undo_block_serializer.rb b/app/serializers/activitypub/undo_block_serializer.rb
deleted file mode 100644
index b4f04937..00000000
--- a/app/serializers/activitypub/undo_block_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UndoBlockSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
-
- has_one :object, serializer: ActivityPub::BlockSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.account), '#blocks/', object.id, '/undo'].join
- end
-
- def type
- 'Undo'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-end
diff --git a/app/serializers/activitypub/undo_follow_serializer.rb b/app/serializers/activitypub/undo_follow_serializer.rb
deleted file mode 100644
index 9b3e0ca3..00000000
--- a/app/serializers/activitypub/undo_follow_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UndoFollowSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
-
- has_one :object, serializer: ActivityPub::FollowSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.account), '#follows/', object.id, '/undo'].join
- end
-
- def type
- 'Undo'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-end
diff --git a/app/serializers/activitypub/undo_like_serializer.rb b/app/serializers/activitypub/undo_like_serializer.rb
deleted file mode 100644
index 20c786cb..00000000
--- a/app/serializers/activitypub/undo_like_serializer.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UndoLikeSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor
-
- has_one :object, serializer: ActivityPub::LikeSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.account), '#likes/', object.id, '/undo'].join
- end
-
- def type
- 'Undo'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-end
diff --git a/app/serializers/activitypub/update_poll_serializer.rb b/app/serializers/activitypub/update_poll_serializer.rb
deleted file mode 100644
index b894f309..00000000
--- a/app/serializers/activitypub/update_poll_serializer.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UpdatePollSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor, :to
-
- has_one :object, serializer: ActivityPub::NoteSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.preloadable_poll.updated_at.to_i].join
- end
-
- def type
- 'Update'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def to
- ActivityPub::TagManager.instance.to(object)
- end
-
- def cc
- ActivityPub::TagManager.instance.cc(object)
- end
-end
diff --git a/app/serializers/activitypub/update_serializer.rb b/app/serializers/activitypub/update_serializer.rb
deleted file mode 100644
index a5eb857d..00000000
--- a/app/serializers/activitypub/update_serializer.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UpdateSerializer < ActivityPub::Serializer
- attributes :id, :type, :actor, :to
-
- has_one :object, serializer: ActivityPub::ActorSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object), '#updates/', object.updated_at.to_i].join
- end
-
- def type
- 'Update'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object)
- end
-
- def to
- [ActivityPub::TagManager::COLLECTIONS[:public]]
- end
-end
diff --git a/app/serializers/activitypub/vote_serializer.rb b/app/serializers/activitypub/vote_serializer.rb
deleted file mode 100644
index 71ef5c77..00000000
--- a/app/serializers/activitypub/vote_serializer.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::VoteSerializer < ActivityPub::Serializer
- class NoteSerializer < ActivityPub::Serializer
- attributes :id, :type, :name, :attributed_to,
- :in_reply_to, :to
-
- def id
- ActivityPub::TagManager.instance.uri_for(object) || [ActivityPub::TagManager.instance.uri_for(object.account), '#votes/', object.id].join
- end
-
- def type
- 'Note'
- end
-
- def name
- object.poll.options[object.choice.to_i]
- end
-
- def attributed_to
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def in_reply_to
- ActivityPub::TagManager.instance.uri_for(object.poll.status)
- end
-
- def to
- ActivityPub::TagManager.instance.uri_for(object.poll.account)
- end
- end
-
- attributes :id, :type, :actor, :to
-
- has_one :object, serializer: ActivityPub::VoteSerializer::NoteSerializer
-
- def id
- [ActivityPub::TagManager.instance.uri_for(object.account), '#votes/', object.id, '/activity'].join
- end
-
- def type
- 'Create'
- end
-
- def actor
- ActivityPub::TagManager.instance.uri_for(object.account)
- end
-
- def to
- ActivityPub::TagManager.instance.uri_for(object.poll.account)
- end
-end
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index 3e828bca..4afb8d77 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -31,7 +31,6 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:unread_count] = unread_count object.current_account
store[:last_read_notification_id] = object.current_account.user.last_read_notification
store[:monthly_expenses_complete] = Redis.current.get("monthly_funding_amount") || 0
- store[:favourites_count] = object.current_account.favourites.count.to_s
store[:is_first_session] = is_first_session object.current_account
store[:email_confirmed] = object.current_account.user.confirmed?
store[:email] = object.current_account.user.confirmed? ? '[hidden]' : object.current_account.user.email
@@ -65,7 +64,7 @@ class InitialStateSerializer < ActiveModel::Serializer
end
private
-
+
def unread_count(account)
last_read = account.user.last_read_notification || 0
account.notifications.where("id > #{last_read}").count
diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb
index 4019076e..00ee0ef9 100644
--- a/app/serializers/oembed_serializer.rb
+++ b/app/serializers/oembed_serializer.rb
@@ -4,8 +4,8 @@ class OEmbedSerializer < ActiveModel::Serializer
include RoutingHelper
include ActionView::Helpers::TagHelper
- attributes :type, :version, :title, :author_name,
- :author_url, :provider_name, :provider_url,
+ attributes :type, :version, :title
+ :provider_name, :provider_url,
:cache_age, :html, :width, :height
def type
@@ -16,14 +16,6 @@ class OEmbedSerializer < ActiveModel::Serializer
'1.0'
end
- def author_name
- object.account.display_name.presence || object.account.username
- end
-
- def author_url
- short_account_url(object.account)
- end
-
def provider_name
Rails.configuration.x.local_domain
end
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
index 2b23e33c..640538d3 100644
--- a/app/serializers/rest/account_serializer.rb
+++ b/app/serializers/rest/account_serializer.rb
@@ -33,34 +33,18 @@ class REST::AccountSerializer < ActiveModel::Serializer
end
def avatar
- if object.avatar_file_name.nil? and object.avatar_remote_url and object.avatar_remote_url.start_with? "gab://avatar/"
- return object.avatar_remote_url.sub("gab://avatar/", "https://gab.com/media/user/")
- end
-
full_asset_url(object.avatar_original_url)
end
def avatar_static
- if object.avatar_file_name.nil? and object.avatar_remote_url and object.avatar_remote_url.start_with? "gab://avatar/"
- return object.avatar_remote_url.sub("gab://avatar/", "https://gab.com/media/user/")
- end
-
full_asset_url(object.avatar_static_url)
end
def header
- if object.header_file_name.nil? and object.header_remote_url and object.header_remote_url.start_with? "gab://header/"
- return object.header_remote_url.sub("gab://header/", "https://gab.com/media/user/")
- end
-
full_asset_url(object.header_original_url)
end
def header_static
- if object.header_file_name.nil? and object.header_remote_url and object.header_remote_url.start_with? "gab://header/"
- return object.header_remote_url.sub("gab://header/", "https://gab.com/media/user/")
- end
-
full_asset_url(object.header_static_url)
end
diff --git a/app/serializers/rest/group_serializer.rb b/app/serializers/rest/group_serializer.rb
index 4f078cfd..f443ff32 100644
--- a/app/serializers/rest/group_serializer.rb
+++ b/app/serializers/rest/group_serializer.rb
@@ -3,9 +3,10 @@
class REST::GroupSerializer < ActiveModel::Serializer
include RoutingHelper
- attributes :id, :title, :description, :description_html, :cover_image_url, :is_archived,
- :member_count, :created_at, :is_private, :is_visible, :slug, :tags, :group_category, :password,
- :has_password
+ attributes :id, :title, :description, :description_html,
+ :cover_image_url, :is_archived, :member_count,
+ :created_at, :is_private, :is_visible, :slug,
+ :tags, :group_category, :password, :has_password
def id
object.id.to_s
diff --git a/app/serializers/rest/identity_proof_serializer.rb b/app/serializers/rest/identity_proof_serializer.rb
deleted file mode 100644
index 0e741593..00000000
--- a/app/serializers/rest/identity_proof_serializer.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class REST::IdentityProofSerializer < ActiveModel::Serializer
- attributes :provider, :provider_username, :updated_at, :proof_url, :profile_url
-
- def proof_url
- object.badge.proof_url
- end
-
- def profile_url
- object.badge.profile_url
- end
-
- def provider
- object.provider.capitalize
- end
-end
diff --git a/app/serializers/rest/instance_serializer.rb b/app/serializers/rest/instance_serializer.rb
deleted file mode 100644
index bd56c904..00000000
--- a/app/serializers/rest/instance_serializer.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-class REST::InstanceSerializer < ActiveModel::Serializer
- include RoutingHelper
-
- attributes :uri, :title, :description, :email,
- :version, :urls, :stats, :thumbnail,
- :languages, :registrations
-
- has_one :contact_account, serializer: REST::AccountSerializer
-
- delegate :contact_account, to: :instance_presenter
-
- def uri
- Rails.configuration.x.local_domain
- end
-
- def title
- Setting::SITE_TITLE
- end
-
- def description
- Setting.site_description
- end
-
- def email
- Setting.site_contact_email
- end
-
- def version
- GabSocial::Version.to_s
- end
-
- def thumbnail
- instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('media/images/preview.png')
- end
-
- def stats
- {
- user_count: instance_presenter.user_count,
- status_count: instance_presenter.status_count,
- domain_count: instance_presenter.domain_count,
- }
- end
-
- def urls
- { streaming_api: Rails.configuration.x.streaming_api_base_url }
- end
-
- def languages
- [I18n.default_locale]
- end
-
- def registrations
- Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode
- end
-
- private
-
- def instance_presenter
- @instance_presenter ||= InstancePresenter.new
- end
-end
diff --git a/app/serializers/rest/preview_card_serializer.rb b/app/serializers/rest/preview_card_serializer.rb
index 9d0d0db2..102778e4 100644
--- a/app/serializers/rest/preview_card_serializer.rb
+++ b/app/serializers/rest/preview_card_serializer.rb
@@ -4,9 +4,8 @@ class REST::PreviewCardSerializer < ActiveModel::Serializer
include RoutingHelper
attributes :id, :url, :title, :description, :type,
- :author_name, :author_url, :provider_name,
- :provider_url, :html, :width, :height,
- :image, :embed_url, :updated_at
+ :provider_name, :provider_url, :html,
+ :width, :height, :image, :embed_url, :updated_at
def image
object.image? ? full_asset_url(object.image.url(:original)) : nil
diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb
index 1a3fd915..38dad53d 100644
--- a/app/serializers/rest/relationship_serializer.rb
+++ b/app/serializers/rest/relationship_serializer.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
class REST::RelationshipSerializer < ActiveModel::Serializer
- attributes :id, :following, :showing_reblogs, :followed_by, :blocking, :blocked_by,
- :muting, :muting_notifications, :requested, :domain_blocking,
- :endorsed
+ attributes :id, :following, :showing_reblogs, :followed_by, :blocking,
+ :blocked_by, :muting, :muting_notifications, :requested
def id
object.id.to_s
@@ -42,12 +41,4 @@ class REST::RelationshipSerializer < ActiveModel::Serializer
def requested
instance_options[:relationships].requested[object.id] ? true : false
end
-
- def domain_blocking
- instance_options[:relationships].domain_blocking[object.id] || false
- end
-
- def endorsed
- instance_options[:relationships].endorsed[object.id] || false
- end
end
diff --git a/app/serializers/rest/search_serializer.rb b/app/serializers/rest/search_serializer.rb
index f82cbd89..a8897f1b 100644
--- a/app/serializers/rest/search_serializer.rb
+++ b/app/serializers/rest/search_serializer.rb
@@ -1,14 +1,10 @@
# frozen_string_literal: true
class REST::SearchSerializer < ActiveModel::Serializer
- attributes :hashtags
has_many :accounts, serializer: REST::AccountSerializer
has_many :statuses, serializer: REST::StatusSerializer
has_many :groups, serializer: REST::GroupSerializer
has_many :links, serializer: REST::PreviewCardSerializer
- def hashtags
- object.hashtags.map(&:name)
- end
end
diff --git a/app/serializers/rest/status_bookmarked_serializer.rb b/app/serializers/rest/status_bookmarked_serializer.rb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/serializers/rest/status_group_pinned_serializer.rb b/app/serializers/rest/status_group_pinned_serializer.rb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/serializers/rest/status_pinned_serializer.rb b/app/serializers/rest/status_pinned_serializer.rb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb
index b8aed7e4..c99a91ec 100644
--- a/app/serializers/rest/status_serializer.rb
+++ b/app/serializers/rest/status_serializer.rb
@@ -3,15 +3,15 @@
class REST::StatusSerializer < ActiveModel::Serializer
attributes :id, :created_at, :revised_at, :in_reply_to_id, :in_reply_to_account_id,
:sensitive, :spoiler_text, :visibility, :language,
- :uri, :url, :replies_count, :reblogs_count,
+ :url, :replies_count, :reblogs_count,
:favourites_count, :quote_of_id, :expires_at, :has_quote
attribute :favourited, if: :current_user?
attribute :reblogged, if: :current_user?
- attribute :muted, if: :current_user?
- attribute :bookmarked, if: :current_user?
- attribute :pinned, if: :pinnable?
- attribute :pinned_by_group, if: :pinnable_by_group?
+
+ attribute :account_id, if: :account_id?
+ attribute :group_id, if: :group_id?
+ attribute :preview_card_id, if: :preview_card_id?
attribute :content, unless: :source_requested?
attribute :rich_content, unless: :source_requested?
@@ -20,16 +20,15 @@ class REST::StatusSerializer < ActiveModel::Serializer
belongs_to :reblog, serializer: REST::StatusSerializer
belongs_to :quote, serializer: REST::StatusSerializer
- belongs_to :application, if: :show_application?
- belongs_to :account, serializer: REST::AccountSerializer
- belongs_to :group, serializer: REST::GroupSerializer
+ belongs_to :account, serializer: REST::AccountSerializer, unless: :account_id?
+ belongs_to :group, serializer: REST::GroupSerializer, unless: :group_id?
has_many :media_attachments, serializer: REST::MediaAttachmentSerializer
has_many :ordered_mentions, key: :mentions
has_many :tags
has_many :emojis, serializer: REST::CustomEmojiSerializer
- has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer
+ has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer, unless: :preview_card_id?
has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
def id
@@ -52,8 +51,28 @@ class REST::StatusSerializer < ActiveModel::Serializer
!current_user.nil?
end
- def show_application?
- object.account.user_shows_application? || (current_user? && current_user.account_id == object.account_id)
+ def account_id
+ instance_options[:account_id]
+ end
+
+ def account_id?
+ !instance_options[:account_id].nil?
+ end
+
+ def group_id
+ instance_options[:group_id]
+ end
+
+ def group_id?
+ !instance_options[:group_id].nil?
+ end
+
+ def preview_card_id
+ instance_options[:preview_card_id]
+ end
+
+ def preview_card_id?
+ !instance_options[:preview_card_id].nil?
end
def visibility
@@ -68,7 +87,10 @@ class REST::StatusSerializer < ActiveModel::Serializer
end
def uri
- OStatus::TagManager.instance.uri_for(object)
+ "/#{object.account.username}/posts/#{object.id}"
+ # uri: "https://gab.com/users/a/statuses/105075286733432550"
+ # url: "https://gab.com/a/posts/105075286733432550"
+ # TagManager.instance.uri_for(object)
end
def content
@@ -111,14 +133,6 @@ class REST::StatusSerializer < ActiveModel::Serializer
end
end
- def muted
- if instance_options && instance_options[:relationships]
- instance_options[:relationships].mutes_map[object.conversation_id] || false
- else
- current_user.account.muting_conversation?(object.conversation)
- end
- end
-
def bookmarked
if instance_options && instance_options[:relationships]
instance_options[:relationships].bookmarks_map[object.id] || false
@@ -196,7 +210,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
attributes :name, :url
def url
- tag_url(object)
+ "/tags/#{object.name}"
end
end
end
diff --git a/app/serializers/rest/status_stat_serializer.rb b/app/serializers/rest/status_stat_serializer.rb
new file mode 100644
index 00000000..0cef5699
--- /dev/null
+++ b/app/serializers/rest/status_stat_serializer.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+class REST::StatusStatSerializer < ActiveModel::Serializer
+ attributes :status_id, :replies_count, :reblogs_count, :favourites_count
+
+ attribute :favourited, if: :current_user?
+ attribute :reblogged, if: :current_user?
+
+ def status_id
+ object.id.to_s
+ end
+
+ def favourited
+ if instance_options && instance_options[:relationships]
+ instance_options[:relationships].favourites_map[object.id] || false
+ else
+ current_user.account.favourited?(object)
+ end
+ end
+
+ def favourites_count
+ if instance_options && instance_options[:unfavourite]
+ object.favourites_count - 1
+ else
+ object.favourites_count
+ end
+ end
+
+ def reblogged
+ if instance_options && instance_options[:relationships]
+ instance_options[:relationships].reblogs_map[object.id] || false
+ else
+ current_user.account.reblogged?(object)
+ end
+ end
+
+ def current_user?
+ !current_user.nil?
+ end
+
+end
diff --git a/app/serializers/rest/tag_serializer.rb b/app/serializers/rest/tag_serializer.rb
index 74aa571a..6b919673 100644
--- a/app/serializers/rest/tag_serializer.rb
+++ b/app/serializers/rest/tag_serializer.rb
@@ -6,6 +6,6 @@ class REST::TagSerializer < ActiveModel::Serializer
attributes :name, :url, :history
def url
- tag_url(object)
+ "/tags/#{object.name}"
end
end
diff --git a/app/serializers/rest/v2/search_serializer.rb b/app/serializers/rest/v2/search_serializer.rb
index 14fa6be0..1299de7b 100644
--- a/app/serializers/rest/v2/search_serializer.rb
+++ b/app/serializers/rest/v2/search_serializer.rb
@@ -3,7 +3,6 @@
class REST::V2::SearchSerializer < ActiveModel::Serializer
has_many :accounts, serializer: REST::AccountSerializer
has_many :statuses, serializer: REST::StatusSerializer
- has_many :hashtags, serializer: REST::TagSerializer
has_many :groups, serializer: REST::GroupSerializer
has_many :links, serializer: REST::PreviewCardSerializer
end
diff --git a/app/serializers/rss/account_serializer.rb b/app/serializers/rss/account_serializer.rb
deleted file mode 100644
index 361b288c..00000000
--- a/app/serializers/rss/account_serializer.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class RSS::AccountSerializer
- include ActionView::Helpers::NumberHelper
- include StreamEntriesHelper
- include RoutingHelper
-
- def render(account, statuses)
- builder = RSSBuilder.new
-
- builder.title("#{display_name(account)} (@#{account.local_username_and_domain})")
- .description(account_description(account))
- .link(TagManager.instance.url_for(account))
- .logo(full_pack_url('media/images/logo.png'))
- .accent_color('2b90d9')
-
- builder.image(full_asset_url(account.avatar.url(:original))) if account.avatar?
- builder.cover(full_asset_url(account.header.url(:original))) if account.header?
-
- statuses.each do |status|
- builder.item do |item|
- item.title(status.title)
- .link(TagManager.instance.url_for(status))
- .pub_date(status.created_at)
- .description(status.spoiler_text.presence || Formatter.instance.plaintext(status).to_str)
-
- status.media_attachments.each do |media|
- item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, length: media.file.size)
- end
- end
- end
-
- builder.to_xml
- end
-
- def self.render(account, statuses)
- new.render(account, statuses)
- end
-end
diff --git a/app/serializers/rss/tag_serializer.rb b/app/serializers/rss/tag_serializer.rb
deleted file mode 100644
index dc07a837..00000000
--- a/app/serializers/rss/tag_serializer.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-class RSS::TagSerializer
- include ActionView::Helpers::NumberHelper
- include ActionView::Helpers::SanitizeHelper
- include StreamEntriesHelper
- include RoutingHelper
-
- def render(tag, statuses)
- builder = RSSBuilder.new
-
- builder.title("##{tag.name}")
- .description(strip_tags(I18n.t('about.about_hashtag_html', hashtag: tag.name)))
- .link(tag_url(tag))
- .logo(full_pack_url('media/images/logo.png'))
- .accent_color('2b90d9')
-
- statuses.each do |status|
- builder.item do |item|
- item.title(status.title)
- .link(TagManager.instance.url_for(status))
- .pub_date(status.created_at)
- .description(status.spoiler_text.presence || Formatter.instance.plaintext(status).to_str)
-
- status.media_attachments.each do |media|
- item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, length: media.file.size)
- end
- end
- end
-
- builder.to_xml
- end
-
- def self.render(tag, statuses)
- new.render(tag, statuses)
- end
-end
diff --git a/app/serializers/webfinger_serializer.rb b/app/serializers/webfinger_serializer.rb
deleted file mode 100644
index 4220f697..00000000
--- a/app/serializers/webfinger_serializer.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-class WebfingerSerializer < ActiveModel::Serializer
- include RoutingHelper
-
- attributes :subject, :aliases, :links
-
- def subject
- object.to_webfinger_s
- end
-
- def aliases
- [short_account_url(object), account_url(object)]
- end
-
- def links
- [
- { rel: 'http://webfinger.net/rel/profile-page', type: 'text/html', href: short_account_url(object) },
- { rel: 'http://schemas.google.com/g/2010#updates-from', type: 'application/atom+xml', href: account_url(object, format: 'atom') },
- { rel: 'self', type: 'application/activity+json', href: account_url(object) },
- { rel: 'magic-public-key', href: "data:application/magic-public-key,#{object.magic_key}" },
- { rel: 'http://ostatus.org/schema/1.0/subscribe', template: "#{authorize_interaction_url}?uri={uri}" },
- ]
- end
-end
diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb
index b1d77357..9c6b63c9 100644
--- a/app/services/account_search_service.rb
+++ b/app/services/account_search_service.rb
@@ -68,8 +68,6 @@ class AccountSearchService < BaseService
@_exact_match ||= begin
if domain_is_local?
search_from.without_suspended.find_local(query_username)
- else
- search_from.without_suspended.find_remote(query_username, query_domain)
end
end
end
diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb
deleted file mode 100644
index 6a137b52..00000000
--- a/app/services/activitypub/fetch_featured_collection_service.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchFeaturedCollectionService < BaseService
- include JsonLdHelper
-
- def call(account)
- return if account.featured_collection_url.blank?
-
- @account = account
- @json = fetch_resource(@account.featured_collection_url, true)
-
- return unless supported_context?
- return if @account.suspended? || @account.local?
-
- case @json['type']
- when 'Collection', 'CollectionPage'
- process_items @json['items']
- when 'OrderedCollection', 'OrderedCollectionPage'
- process_items @json['orderedItems']
- end
- end
-
- private
-
- def process_items(items)
- status_ids = items.map { |item| value_or_id(item) }
- .reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
- .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) }
- .compact
- .select { |status| status.account_id == @account.id }
- .map(&:id)
-
- to_remove = []
- to_add = status_ids
-
- StatusPin.where(account: @account).pluck(:status_id).each do |status_id|
- if status_ids.include?(status_id)
- to_add.delete(status_id)
- else
- to_remove << status_id
- end
- end
-
- StatusPin.where(account: @account, status_id: to_remove).delete_all unless to_remove.empty?
-
- to_add.each do |status_id|
- StatusPin.create!(account: @account, status_id: status_id)
- end
- end
-
- def supported_context?
- super(@json)
- end
-end
diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb
deleted file mode 100644
index 3c204494..00000000
--- a/app/services/activitypub/fetch_remote_account_service.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchRemoteAccountService < BaseService
- include JsonLdHelper
-
- SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
-
- # Does a WebFinger roundtrip on each call, unless `only_key` is true
- def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false)
- return ActivityPub::TagManager.instance.uri_to_resource(uri, Account) if ActivityPub::TagManager.instance.local_uri?(uri)
-
- @json = if prefetched_body.nil?
- fetch_resource(uri, id)
- else
- body_to_json(prefetched_body, compare_id: id ? uri : nil)
- end
-
- return if !supported_context? || !expected_type? || (break_on_redirect && @json['movedTo'].present?)
-
- @uri = @json['id']
- @username = @json['preferredUsername']
- @domain = Addressable::URI.parse(@uri).normalized_host
-
- return unless only_key || verified_webfinger?
-
- ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key)
- rescue Oj::ParseError
- nil
- end
-
- private
-
- def verified_webfinger?
- webfinger = Goldfinger.finger("acct:#{@username}@#{@domain}")
- confirmed_username, confirmed_domain = split_acct(webfinger.subject)
-
- return webfinger.link('self')&.href == @uri if @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
-
- webfinger = Goldfinger.finger("acct:#{confirmed_username}@#{confirmed_domain}")
- @username, @domain = split_acct(webfinger.subject)
- self_reference = webfinger.link('self')
-
- return false unless @username.casecmp(confirmed_username).zero? && @domain.casecmp(confirmed_domain).zero?
- return false if self_reference&.href != @uri
-
- true
- rescue Goldfinger::Error
- false
- end
-
- def split_acct(acct)
- acct.gsub(/\Aacct:/, '').split('@')
- end
-
- def supported_context?
- super(@json)
- end
-
- def expected_type?
- equals_or_includes_any?(@json['type'], SUPPORTED_TYPES)
- end
-end
diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb
deleted file mode 100644
index df17d907..00000000
--- a/app/services/activitypub/fetch_remote_key_service.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchRemoteKeyService < BaseService
- include JsonLdHelper
-
- # Returns account that owns the key
- def call(uri, id: true, prefetched_body: nil)
- if prefetched_body.nil?
- if id
- @json = fetch_resource_without_id_validation(uri)
- if person?
- @json = fetch_resource(@json['id'], true)
- elsif uri != @json['id']
- return
- end
- else
- @json = fetch_resource(uri, id)
- end
- else
- @json = body_to_json(prefetched_body, compare_id: id ? uri : nil)
- end
-
- return unless supported_context?(@json) && expected_type?
- return find_account(@json['id'], @json) if person?
-
- @owner = fetch_resource(owner_uri, true)
-
- return unless supported_context?(@owner) && confirmed_owner?
-
- find_account(owner_uri, @owner)
- end
-
- private
-
- def find_account(uri, prefetched_body)
- account = ActivityPub::TagManager.instance.uri_to_resource(uri, Account)
- account ||= ActivityPub::FetchRemoteAccountService.new.call(uri, prefetched_body: prefetched_body)
- account
- end
-
- def expected_type?
- person? || public_key?
- end
-
- def person?
- equals_or_includes_any?(@json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES)
- end
-
- def public_key?
- @json['publicKeyPem'].present? && @json['owner'].present?
- end
-
- def owner_uri
- @owner_uri ||= value_or_id(@json['owner'])
- end
-
- def confirmed_owner?
- equals_or_includes_any?(@owner['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) && value_or_id(@owner['publicKey']) == @json['id']
- end
-end
diff --git a/app/services/activitypub/fetch_remote_poll_service.rb b/app/services/activitypub/fetch_remote_poll_service.rb
deleted file mode 100644
index 854a32d0..00000000
--- a/app/services/activitypub/fetch_remote_poll_service.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchRemotePollService < BaseService
- include JsonLdHelper
-
- def call(poll, on_behalf_of = nil)
- json = fetch_resource(poll.status.uri, true, on_behalf_of)
- return unless supported_context?(json)
- ActivityPub::ProcessPollService.new.call(poll, json)
- end
-end
diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb
deleted file mode 100644
index 46982103..00000000
--- a/app/services/activitypub/fetch_remote_status_service.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchRemoteStatusService < BaseService
- include JsonLdHelper
-
- # Should be called when uri has already been checked for locality
- def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil)
- @json = if prefetched_body.nil?
- fetch_resource(uri, id, on_behalf_of)
- else
- body_to_json(prefetched_body, compare_id: id ? uri : nil)
- end
-
- return unless supported_context? && expected_type?
-
- return if actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id)
-
- actor = ActivityPub::TagManager.instance.uri_to_resource(actor_id, Account)
- actor = ActivityPub::FetchRemoteAccountService.new.call(actor_id, id: true) if actor.nil? || needs_update(actor)
-
- return if actor.nil? || actor.suspended?
-
- ActivityPub::Activity.factory(activity_json, actor).perform
- end
-
- private
-
- def activity_json
- { 'type' => 'Create', 'actor' => actor_id, 'object' => @json }
- end
-
- def actor_id
- value_or_id(first_of_value(@json['attributedTo']))
- end
-
- def trustworthy_attribution?(uri, attributed_to)
- return false if uri.nil? || attributed_to.nil?
- Addressable::URI.parse(uri).normalized_host.casecmp(Addressable::URI.parse(attributed_to).normalized_host).zero?
- end
-
- def supported_context?
- super(@json)
- end
-
- def expected_type?
- equals_or_includes_any?(@json['type'], ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
- end
-
- def needs_update(actor)
- actor.possibly_stale?
- end
-end
diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb
deleted file mode 100644
index 8cb309e5..00000000
--- a/app/services/activitypub/fetch_replies_service.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchRepliesService < BaseService
- include JsonLdHelper
-
- def call(parent_status, collection_or_uri, allow_synchronous_requests = true)
- @account = parent_status.account
- @allow_synchronous_requests = allow_synchronous_requests
-
- @items = collection_items(collection_or_uri)
- return if @items.nil?
-
- FetchReplyWorker.push_bulk(filtered_replies)
-
- @items
- end
-
- private
-
- def collection_items(collection_or_uri)
- collection = fetch_collection(collection_or_uri)
- return unless collection.is_a?(Hash)
-
- collection = fetch_collection(collection['first']) if collection['first'].present?
- return unless collection.is_a?(Hash)
-
- case collection['type']
- when 'Collection', 'CollectionPage'
- collection['items']
- when 'OrderedCollection', 'OrderedCollectionPage'
- collection['orderedItems']
- end
- end
-
- def fetch_collection(collection_or_uri)
- return collection_or_uri if collection_or_uri.is_a?(Hash)
- return unless @allow_synchronous_requests
- return if invalid_origin?(collection_or_uri)
- fetch_resource_without_id_validation(collection_or_uri, nil, true)
- end
-
- def filtered_replies
- # Only fetch replies to the same server as the original status to avoid
- # amplification attacks.
-
- # Also limit to 5 fetched replies to limit potential for DoS.
- @items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(5)
- end
-end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
deleted file mode 100644
index f595708a..00000000
--- a/app/services/activitypub/process_account_service.rb
+++ /dev/null
@@ -1,276 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ProcessAccountService < BaseService
- include JsonLdHelper
-
- # Should be called with confirmed valid JSON
- # and WebFinger-resolved username and domain
- def call(username, domain, json, options = {})
- return if json['inbox'].blank? || unsupported_uri_scheme?(json['id'])
-
- @options = options
- @json = json
- @uri = @json['id']
- @username = username
- @domain = domain
- @collections = {}
-
- RedisLock.acquire(lock_options) do |lock|
- if lock.acquired?
- @account = Account.find_remote(@username, @domain)
- @old_public_key = @account&.public_key
- @old_protocol = @account&.protocol
-
- create_account if @account.nil?
- update_account
- process_tags
- process_attachments
- else
- raise GabSocial::RaceConditionError
- end
- end
-
- return if @account.nil?
-
- after_protocol_change! if protocol_changed?
- after_key_change! if key_changed? && !@options[:signed_with_known_key]
- clear_tombstones! if key_changed?
-
- unless @options[:only_key]
- check_featured_collection! if @account.featured_collection_url.present?
- check_links! unless @account.fields.empty?
- end
-
- @account
- rescue Oj::ParseError
- nil
- end
-
- private
-
- def create_account
- @account = Account.new
- @account.protocol = :activitypub
- @account.username = @username
- @account.domain = @domain
- @account.private_key = nil
- @account.suspended_at = domain_block.created_at if auto_suspend?
- @account.silenced_at = domain_block.created_at if auto_silence?
- end
-
- def update_account
- @account.last_webfingered_at = Time.now.utc unless @options[:only_key]
- @account.protocol = :activitypub
-
- set_immediate_attributes!
- set_fetchable_attributes! unless @options[:only_keys]
-
- @account.save_with_optional_media!
- end
-
- def set_immediate_attributes!
- @account.inbox_url = @json['inbox'] || ''
- @account.outbox_url = @json['outbox'] || ''
- @account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || ''
- @account.followers_url = @json['followers'] || ''
- @account.featured_collection_url = @json['featured'] || ''
- @account.url = url || @uri
- @account.uri = @uri
- @account.display_name = @json['name'] || ''
- @account.note = @json['summary'] || ''
- @account.locked = @json['manuallyApprovesFollowers'] || false
- @account.fields = property_values || {}
- @account.also_known_as = as_array(@json['alsoKnownAs'] || []).map { |item| value_or_id(item) }
- @account.actor_type = actor_type
- end
-
- def set_fetchable_attributes!
- @account.avatar_remote_url = image_url('icon') unless skip_download?
- @account.header_remote_url = image_url('image') unless skip_download?
- @account.public_key = public_key || ''
- @account.statuses_count = outbox_total_items if outbox_total_items.present?
- @account.following_count = following_total_items if following_total_items.present?
- @account.followers_count = followers_total_items if followers_total_items.present?
- @account.moved_to_account = @json['movedTo'].present? ? moved_account : nil
- end
-
- def after_protocol_change!
- ActivityPub::PostUpgradeWorker.perform_async(@account.domain)
- end
-
- def after_key_change!
- RefollowWorker.perform_async(@account.id)
- end
-
- def check_featured_collection!
- ActivityPub::SynchronizeFeaturedCollectionWorker.perform_async(@account.id)
- end
-
- def check_links!
- VerifyAccountLinksWorker.perform_async(@account.id)
- end
-
- def actor_type
- if @json['type'].is_a?(Array)
- @json['type'].find { |type| ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(type) }
- else
- @json['type']
- end
- end
-
- def image_url(key)
- value = first_of_value(@json[key])
-
- return if value.nil?
- return value['url'] if value.is_a?(Hash)
-
- image = fetch_resource_without_id_validation(value)
- image['url'] if image
- end
-
- def public_key
- value = first_of_value(@json['publicKey'])
-
- return if value.nil?
- return value['publicKeyPem'] if value.is_a?(Hash)
-
- key = fetch_resource_without_id_validation(value)
- key['publicKeyPem'] if key
- end
-
- def url
- return if @json['url'].blank?
-
- url_candidate = url_to_href(@json['url'], 'text/html')
-
- if unsupported_uri_scheme?(url_candidate) || mismatching_origin?(url_candidate)
- nil
- else
- url_candidate
- end
- end
-
- def property_values
- return unless @json['attachment'].is_a?(Array)
- as_array(@json['attachment']).select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
- end
-
- def mismatching_origin?(url)
- needle = Addressable::URI.parse(url).host
- haystack = Addressable::URI.parse(@uri).host
-
- !haystack.casecmp(needle).zero?
- end
-
- def outbox_total_items
- collection_total_items('outbox')
- end
-
- def following_total_items
- collection_total_items('following')
- end
-
- def followers_total_items
- collection_total_items('followers')
- end
-
- def collection_total_items(type)
- return if @json[type].blank?
- return @collections[type] if @collections.key?(type)
-
- collection = fetch_resource_without_id_validation(@json[type])
-
- @collections[type] = collection.is_a?(Hash) && collection['totalItems'].present? && collection['totalItems'].is_a?(Numeric) ? collection['totalItems'] : nil
- rescue HTTP::Error, OpenSSL::SSL::SSLError
- @collections[type] = nil
- end
-
- def moved_account
- account = ActivityPub::TagManager.instance.uri_to_resource(@json['movedTo'], Account)
- account ||= ActivityPub::FetchRemoteAccountService.new.call(@json['movedTo'], id: true, break_on_redirect: true)
- account
- end
-
- def skip_download?
- @account.suspended? || domain_block&.reject_media?
- end
-
- def auto_suspend?
- domain_block&.suspend?
- end
-
- def auto_silence?
- domain_block&.silence?
- end
-
- def domain_block
- return @domain_block if defined?(@domain_block)
- @domain_block = DomainBlock.find_by(domain: @domain)
- end
-
- def key_changed?
- !@old_public_key.nil? && @old_public_key != @account.public_key
- end
-
- def clear_tombstones!
- Tombstone.where(account_id: @account.id).delete_all
- end
-
- def protocol_changed?
- !@old_protocol.nil? && @old_protocol != @account.protocol
- end
-
- def lock_options
- { redis: Redis.current, key: "process_account:#{@uri}" }
- end
-
- def process_tags
- return if @json['tag'].blank?
-
- as_array(@json['tag']).each do |tag|
- process_emoji tag if equals_or_includes?(tag['type'], 'Emoji')
- end
- end
-
- def process_attachments
- return if @json['attachment'].blank?
-
- previous_proofs = @account.identity_proofs.to_a
- current_proofs = []
-
- as_array(@json['attachment']).each do |attachment|
- next unless equals_or_includes?(attachment['type'], 'IdentityProof')
- current_proofs << process_identity_proof(attachment)
- end
-
- previous_proofs.each do |previous_proof|
- next if current_proofs.any? { |current_proof| current_proof.id == previous_proof.id }
- previous_proof.delete
- end
- end
-
- def process_emoji(tag)
- return if skip_download?
- return if tag['name'].blank? || tag['icon'].blank? || tag['icon']['url'].blank?
-
- shortcode = tag['name'].delete(':')
- image_url = tag['icon']['url']
- uri = tag['id']
- updated = tag['updated']
- emoji = CustomEmoji.find_by(shortcode: shortcode, domain: @account.domain)
-
- return unless emoji.nil? || image_url != emoji.image_remote_url || (updated && updated >= emoji.updated_at)
-
- emoji ||= CustomEmoji.new(domain: @account.domain, shortcode: shortcode, uri: uri)
- emoji.image_remote_url = image_url
- emoji.save
- end
-
- def process_identity_proof(attachment)
- provider = attachment['signatureAlgorithm']
- provider_username = attachment['name']
- token = attachment['signatureValue']
-
- @account.identity_proofs.where(provider: provider, provider_username: provider_username).find_or_create_by(provider: provider, provider_username: provider_username, token: token)
- end
-end
diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb
deleted file mode 100644
index 881df478..00000000
--- a/app/services/activitypub/process_collection_service.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ProcessCollectionService < BaseService
- include JsonLdHelper
-
- def call(body, account, **options)
- @account = account
- @json = Oj.load(body, mode: :strict)
- @options = options
-
- return unless supported_context?
- return if different_actor? && verify_account!.nil?
- return if @account.suspended? || @account.local?
-
- case @json['type']
- when 'Collection', 'CollectionPage'
- process_items @json['items']
- when 'OrderedCollection', 'OrderedCollectionPage'
- process_items @json['orderedItems']
- else
- process_items [@json]
- end
- rescue Oj::ParseError
- nil
- end
-
- private
-
- def different_actor?
- @json['actor'].present? && value_or_id(@json['actor']) != @account.uri
- end
-
- def process_items(items)
- items.reverse_each.map { |item| process_item(item) }.compact
- end
-
- def supported_context?
- super(@json)
- end
-
- def process_item(item)
- activity = ActivityPub::Activity.factory(item, @account, @options)
- activity&.perform
- end
-
- def verify_account!
- @options[:relayed_through_account] = @account
- @account = ActivityPub::LinkedDataSignature.new(@json).verify_account!
- rescue JSON::LD::JsonLdError => e
- Rails.logger.debug "Could not verify LD-Signature for #{value_or_id(@json['actor'])}: #{e.message}"
- nil
- end
-end
diff --git a/app/services/activitypub/process_poll_service.rb b/app/services/activitypub/process_poll_service.rb
deleted file mode 100644
index 61357abd..00000000
--- a/app/services/activitypub/process_poll_service.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ProcessPollService < BaseService
- include JsonLdHelper
-
- def call(poll, json)
- @json = json
- return unless expected_type?
-
- previous_expires_at = poll.expires_at
-
- expires_at = begin
- if @json['closed'].is_a?(String)
- @json['closed']
- elsif !@json['closed'].nil? && !@json['closed'].is_a?(FalseClass)
- Time.now.utc
- else
- @json['endTime']
- end
- end
-
- items = begin
- if @json['anyOf'].is_a?(Array)
- @json['anyOf']
- else
- @json['oneOf']
- end
- end
-
- latest_options = items.map { |item| item['name'].presence || item['content'] }
-
- # If for some reasons the options were changed, it invalidates all previous
- # votes, so we need to remove them
- poll.votes.delete_all if latest_options != poll.options
-
- begin
- poll.update!(
- last_fetched_at: Time.now.utc,
- expires_at: expires_at,
- options: latest_options,
- cached_tallies: items.map { |item| item.dig('replies', 'totalItems') || 0 }
- )
- rescue ActiveRecord::StaleObjectError
- poll.reload
- retry
- end
-
- # If the poll had no expiration date set but now has, and people have voted,
- # schedule a notification.
- if previous_expires_at.nil? && poll.expires_at.present? && poll.votes.exists?
- PollExpirationNotifyWorker.perform_at(poll.expires_at + 5.minutes, poll.id)
- end
- end
-
- private
-
- def expected_type?
- equals_or_includes_any?(@json['type'], %w(Question))
- end
-end
diff --git a/app/services/after_block_domain_from_account_service.rb b/app/services/after_block_domain_from_account_service.rb
deleted file mode 100644
index 3a84bd44..00000000
--- a/app/services/after_block_domain_from_account_service.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class AfterBlockDomainFromAccountService < BaseService
- # This service does not create an AccountDomainBlock record,
- # it's meant to be called after such a record has been created
- # synchronously, to "clean up"
- def call(account, domain)
- @account = account
- @domain = domain
-
- reject_existing_followers!
- reject_pending_follow_requests!
- end
-
- private
-
- def reject_existing_followers!
- @account.passive_relationships.where(account: Account.where(domain: @domain)).includes(:account).reorder(nil).find_each do |follow|
- reject_follow!(follow)
- end
- end
-
- def reject_pending_follow_requests!
- FollowRequest.where(target_account: @account).where(account: Account.where(domain: @domain)).includes(:account).reorder(nil).find_each do |follow_request|
- reject_follow!(follow_request)
- end
- end
-
- def reject_follow!(follow)
- follow.destroy
- end
-end
diff --git a/app/services/after_block_service.rb b/app/services/after_block_service.rb
index 706db0d6..c5bf1615 100644
--- a/app/services/after_block_service.rb
+++ b/app/services/after_block_service.rb
@@ -4,7 +4,6 @@ class AfterBlockService < BaseService
def call(account, target_account)
clear_home_feed(account, target_account)
clear_notifications(account, target_account)
- clear_conversations(account, target_account)
end
private
@@ -13,13 +12,6 @@ class AfterBlockService < BaseService
FeedManager.instance.clear_from_timeline(account, target_account)
end
- def clear_conversations(account, target_account)
- AccountConversation.where(account: account)
- .where('? = ANY(participant_account_ids)', target_account.id)
- .in_batches
- .destroy_all
- end
-
def clear_notifications(account, target_account)
Notification.where(account: account)
.joins(:follow)
diff --git a/app/services/app_sign_up_service.rb b/app/services/app_sign_up_service.rb
index 6dee9cd8..ea02bc51 100644
--- a/app/services/app_sign_up_service.rb
+++ b/app/services/app_sign_up_service.rb
@@ -2,8 +2,6 @@
class AppSignUpService < BaseService
def call(app, params)
- return unless allowed_registrations?
-
user_params = params.slice(:email, :password, :agreement, :locale)
account_params = params.slice(:username)
user = User.create!(user_params.merge(created_by_application: app, password_confirmation: user_params[:password], account_attributes: account_params))
@@ -14,10 +12,4 @@ class AppSignUpService < BaseService
expires_in: Doorkeeper.configuration.access_token_expires_in,
use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?)
end
-
- private
-
- def allowed_registrations?
- Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode
- end
end
diff --git a/app/services/backup_service.rb b/app/services/backup_service.rb
index 4cfa22ab..11a7e6fa 100644
--- a/app/services/backup_service.rb
+++ b/app/services/backup_service.rb
@@ -2,6 +2,7 @@
require 'rubygems/package'
+# : todo :
class BackupService < BaseService
attr_reader :account, :backup, :collection
diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb
index 6bcd3cb8..697608a2 100644
--- a/app/services/batched_remove_status_service.rb
+++ b/app/services/batched_remove_status_service.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class BatchedRemoveStatusService < BaseService
- include StreamEntryRenderer
include Redisable
# Delete given statuses and reblogs of them
@@ -13,15 +12,12 @@ class BatchedRemoveStatusService < BaseService
# @param [Hash] options
# @option [Boolean] :skip_side_effects
def call(statuses, **options)
- statuses = Status.where(id: statuses.map(&:id)).includes(:account, :stream_entry).flat_map { |status| [status] + status.reblogs.includes(:account, :stream_entry).to_a }
+ statuses = Status.where(id: statuses.map(&:id)).includes(:account).flat_map { |status| [status] + status.reblogs.includes(:account).to_a }
@mentions = statuses.each_with_object({}) { |s, h| h[s.id] = s.active_mentions.includes(:account).to_a }
@tags = statuses.each_with_object({}) { |s, h| h[s.id] = s.tags.pluck(:name) }
- @stream_entry_batches = []
- @salmon_batches = []
- @json_payloads = statuses.each_with_object({}) { |s, h| h[s.id] = Oj.dump(event: :delete, payload: s.id.to_s) }
- @activity_xml = {}
+ @json_payloads = statuses.each_with_object({}) { |s, h| h[s.id] = Oj.dump(event: :delete, payload: s.id.to_s) }
# Ensure that rendered XML reflects destroyed state
statuses.each do |status|
@@ -39,28 +35,12 @@ class BatchedRemoveStatusService < BaseService
unpush_from_home_timelines(account, account_statuses)
unpush_from_list_timelines(account, account_statuses)
-
- batch_stream_entries(account, account_statuses) if account.local?
end
- # Cannot be batched
- statuses.each do |status|
- unpush_from_public_timelines(status)
- batch_salmon_slaps(status) if status.local?
- end
-
- Pubsubhubbub::RawDistributionWorker.push_bulk(@stream_entry_batches) { |batch| batch }
- NotificationWorker.push_bulk(@salmon_batches) { |batch| batch }
end
private
- def batch_stream_entries(account, statuses)
- statuses.each do |status|
- @stream_entry_batches << [build_xml(status.stream_entry), account.id]
- end
- end
-
def unpush_from_home_timelines(account, statuses)
recipients = account.followers_for_local_distribution.to_a
@@ -81,36 +61,4 @@ class BatchedRemoveStatusService < BaseService
end
end
- def unpush_from_public_timelines(status)
- return unless status.public_visibility?
-
- payload = @json_payloads[status.id]
-
- redis.pipelined do
- if status.account.is_pro || status.account.is_donor || status.account.is_investor || status.account.is_verified
- redis.publish('timeline:pro', payload)
- end
-
- @tags[status.id].each do |hashtag|
- redis.publish("timeline:hashtag:#{hashtag}", payload)
- redis.publish("timeline:hashtag:#{hashtag}:local", payload) if status.local?
- end
- end
- end
-
- def batch_salmon_slaps(status)
- return if @mentions[status.id].empty?
-
- recipients = @mentions[status.id].map(&:account).reject(&:local?).select(&:ostatus?).uniq(&:domain).map(&:id)
-
- recipients.each do |recipient_id|
- @salmon_batches << [build_xml(status.stream_entry), status.account_id, recipient_id]
- end
- end
-
- def build_xml(stream_entry)
- return @activity_xml[stream_entry.id] if @activity_xml.key?(stream_entry.id)
-
- @activity_xml[stream_entry.id] = stream_entry_to_xml(stream_entry)
- end
end
diff --git a/app/services/block_domain_service.rb b/app/services/block_domain_service.rb
deleted file mode 100644
index 497f0394..00000000
--- a/app/services/block_domain_service.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-class BlockDomainService < BaseService
- attr_reader :domain_block
-
- def call(domain_block)
- @domain_block = domain_block
- process_domain_block!
- end
-
- private
-
- def process_domain_block!
- clear_media! if domain_block.reject_media?
-
- if domain_block.silence?
- silence_accounts!
- elsif domain_block.suspend?
- suspend_accounts!
- end
- end
-
- def invalidate_association_caches!
- # Normally, associated models of a status are immutable (except for accounts)
- # so they are aggressively cached. After updating the media attachments to no
- # longer point to a local file, we need to clear the cache to make those
- # changes appear in the API and UI
- @affected_status_ids.each { |id| Rails.cache.delete_matched("statuses/#{id}-*") }
- end
-
- def silence_accounts!
- blocked_domain_accounts.without_silenced.in_batches.update_all(silenced_at: @domain_block.created_at)
- end
-
- def clear_media!
- @affected_status_ids = []
-
- clear_account_images!
- clear_account_attachments!
- clear_emojos!
-
- invalidate_association_caches!
- end
-
- def suspend_accounts!
- blocked_domain_accounts.without_suspended.reorder(nil).find_each do |account|
- UnsubscribeService.new.call(account) if account.subscribed?
- SuspendAccountService.new.call(account, suspended_at: @domain_block.created_at)
- end
- end
-
- def clear_account_images!
- blocked_domain_accounts.reorder(nil).find_each do |account|
- account.avatar.destroy if account.avatar.exists?
- account.header.destroy if account.header.exists?
- account.save
- end
- end
-
- def clear_account_attachments!
- media_from_blocked_domain.reorder(nil).find_each do |attachment|
- @affected_status_ids << attachment.status_id if attachment.status_id.present?
-
- attachment.file.destroy if attachment.file.exists?
- attachment.type = :unknown
- attachment.save
- end
- end
-
- def clear_emojos!
- emojis_from_blocked_domains.destroy_all
- end
-
- def blocked_domain
- domain_block.domain
- end
-
- def blocked_domain_accounts
- Account.where(domain: blocked_domain)
- end
-
- def media_from_blocked_domain
- MediaAttachment.joins(:account).merge(blocked_domain_accounts).reorder(nil)
- end
-
- def emojis_from_blocked_domains
- CustomEmoji.where(domain: blocked_domain)
- end
-end
diff --git a/app/services/concerns/author_extractor.rb b/app/services/concerns/author_extractor.rb
deleted file mode 100644
index c2419e9e..00000000
--- a/app/services/concerns/author_extractor.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module AuthorExtractor
- def author_from_xml(xml, update_profile = true)
- return nil if xml.nil?
-
- # Try for acct
- acct = xml.at_xpath('./xmlns:author/xmlns:email', xmlns: OStatus::TagManager::XMLNS)&.content
-
- # Try +
- if acct.blank?
- username = xml.at_xpath('./xmlns:author/xmlns:name', xmlns: OStatus::TagManager::XMLNS)&.content
- uri = xml.at_xpath('./xmlns:author/xmlns:uri', xmlns: OStatus::TagManager::XMLNS)&.content
-
- return nil if username.blank? || uri.blank?
-
- domain = Addressable::URI.parse(uri).normalized_host
- acct = "#{username}@#{domain}"
- end
-
- ResolveAccountService.new.call(acct, update_profile: update_profile)
- end
-end
diff --git a/app/services/concerns/stream_entry_renderer.rb b/app/services/concerns/stream_entry_renderer.rb
deleted file mode 100644
index 9f6c8a08..00000000
--- a/app/services/concerns/stream_entry_renderer.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module StreamEntryRenderer
- def stream_entry_to_xml(stream_entry)
- OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.entry(stream_entry, true))
- end
-end
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index 38fdb11f..93a88fae 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -1,31 +1,9 @@
# frozen_string_literal: true
class FanOutOnWriteService < BaseService
- # Push a status into home and mentions feeds
- # @param [Status] status
+
def call(status)
- raise GabSocial::RaceConditionError if status.visibility.nil?
-
- render_anonymous_payload(status)
-
- if status.direct_visibility?
- deliver_to_own_conversation(status)
- elsif status.limited_visibility?
- deliver_to_mentioned_followers(status)
- else
- deliver_to_self(status) if status.account.local?
- deliver_to_followers(status)
- deliver_to_lists(status)
- end
-
- return if status.account.silenced? || !status.public_visibility? || status.reblog?
-
- return if status.reply? && status.in_reply_to_account_id != status.account_id
-
-
- if status.account.is_pro || status.account.is_donor || status.account.is_investor || status.account.is_verified
- deliver_to_pro(status)
- end
+ deliver_to_self(status) if status.account.local?
end
private
@@ -35,46 +13,4 @@ class FanOutOnWriteService < BaseService
FeedManager.instance.push_to_home(status.account, status)
end
- def deliver_to_followers(status)
- Rails.logger.debug "Delivering status #{status.id} to followers"
-
- status.account.followers_for_local_distribution.select(:id).reorder(nil).find_in_batches do |followers|
- FeedInsertWorker.push_bulk(followers) do |follower|
- [status.id, follower.id, :home]
- end
- end
- end
-
- def deliver_to_lists(status)
- Rails.logger.debug "Delivering status #{status.id} to lists"
-
- status.account.lists_for_local_distribution.select(:id).reorder(nil).find_in_batches do |lists|
- FeedInsertWorker.push_bulk(lists) do |list|
- [status.id, list.id, :list]
- end
- end
- end
-
- def deliver_to_mentioned_followers(status)
- Rails.logger.debug "Delivering status #{status.id} to limited followers"
-
- FeedInsertWorker.push_bulk(status.mentions.includes(:account).map(&:account).select { |mentioned_account| mentioned_account.local? && mentioned_account.following?(status.account) }) do |follower|
- [status.id, follower.id, :home]
- end
- end
-
- def render_anonymous_payload(status)
- @payload = InlineRenderer.render(status, nil, :status)
- @payload = Oj.dump(event: :update, payload: @payload)
- end
-
- def deliver_to_pro(status)
- Rails.logger.debug "Delivering status #{status.id} to pro timeline"
-
- Redis.current.publish('timeline:pro', @payload)
- end
-
- def deliver_to_own_conversation(status)
- AccountConversation.add_status(status.account, status)
- end
end
diff --git a/app/services/fetch_atom_service.rb b/app/services/fetch_atom_service.rb
deleted file mode 100644
index d6508a98..00000000
--- a/app/services/fetch_atom_service.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-class FetchAtomService < BaseService
- include JsonLdHelper
-
- def call(url)
- return if url.blank?
-
- result = process(url)
-
- # retry without ActivityPub
- result ||= process(url) if @unsupported_activity
-
- result
- rescue OpenSSL::SSL::SSLError => e
- Rails.logger.debug "SSL error: #{e}"
- nil
- rescue HTTP::ConnectionError => e
- Rails.logger.debug "HTTP ConnectionError: #{e}"
- nil
- end
-
- private
-
- def process(url, terminal = false)
- @url = url
- perform_request { |response| process_response(response, terminal) }
- end
-
- def perform_request(&block)
- accept = 'text/html'
- accept = 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams", application/atom+xml, ' + accept unless @unsupported_activity
-
- Request.new(:get, @url).add_headers('Accept' => accept).perform(&block)
- end
-
- def process_response(response, terminal = false)
- return nil if response.code != 200
-
- if response.mime_type == 'application/atom+xml'
- [@url, { prefetched_body: response.body_with_limit }, :ostatus]
- elsif ['application/activity+json', 'application/ld+json'].include?(response.mime_type)
- body = response.body_with_limit
- json = body_to_json(body)
- if supported_context?(json) && equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) && json['inbox'].present?
- [json['id'], { prefetched_body: body, id: true }, :activitypub]
- elsif supported_context?(json) && expected_type?(json)
- [json['id'], { prefetched_body: body, id: true }, :activitypub]
- else
- @unsupported_activity = true
- nil
- end
- elsif !terminal
- link_header = response['Link'] && parse_link_header(response)
-
- if link_header&.find_link(%w(rel alternate))
- process_link_headers(link_header)
- elsif response.mime_type == 'text/html'
- process_html(response)
- end
- end
- end
-
- def expected_type?(json)
- equals_or_includes_any?(json['type'], ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES)
- end
-
- def process_html(response)
- page = Nokogiri::HTML(response.body_with_limit)
-
- json_link = page.xpath('//link[@rel="alternate"]').find { |link| ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(link['type']) }
- atom_link = page.xpath('//link[@rel="alternate"]').find { |link| link['type'] == 'application/atom+xml' }
-
- result ||= process(json_link['href'], terminal: true) unless json_link.nil? || @unsupported_activity
- result ||= process(atom_link['href'], terminal: true) unless atom_link.nil?
-
- result
- end
-
- def process_link_headers(link_header)
- json_link = link_header.find_link(%w(rel alternate), %w(type application/activity+json)) || link_header.find_link(%w(rel alternate), ['type', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'])
- atom_link = link_header.find_link(%w(rel alternate), %w(type application/atom+xml))
-
- result ||= process(json_link.href, terminal: true) unless json_link.nil? || @unsupported_activity
- result ||= process(atom_link.href, terminal: true) unless atom_link.nil?
-
- result
- end
-
- def parse_link_header(response)
- LinkHeader.parse(response['Link'].is_a?(Array) ? response['Link'].first : response['Link'])
- end
-end
diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb
index 1ea589e7..e52eec6e 100644
--- a/app/services/fetch_link_card_service.rb
+++ b/app/services/fetch_link_card_service.rb
@@ -78,6 +78,7 @@ class FetchLinkCardService < BaseService
end
def parse_urls
+ # : todo :
if @status.local?
urls = @status.text.scan(URL_PATTERN).map { |array| Addressable::URI.parse(array[0]).normalize }
else
@@ -114,8 +115,6 @@ class FetchLinkCardService < BaseService
@card.type = embed[:type]
@card.title = embed[:title] || ''
- @card.author_name = embed[:author_name] || ''
- @card.author_url = embed[:author_url].present? ? (url + embed[:author_url]).to_s : ''
@card.provider_name = embed[:provider_name] || ''
@card.provider_url = embed[:provider_url].present? ? (url + embed[:provider_url]).to_s : ''
@card.width = 0
diff --git a/app/services/fetch_remote_account_service.rb b/app/services/fetch_remote_account_service.rb
deleted file mode 100644
index cfc56002..00000000
--- a/app/services/fetch_remote_account_service.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-class FetchRemoteAccountService < BaseService
- include AuthorExtractor
-
- def call(url, prefetched_body = nil, protocol = :ostatus)
- if prefetched_body.nil?
- resource_url, resource_options, protocol = FetchAtomService.new.call(url)
- else
- resource_url = url
- resource_options = { prefetched_body: prefetched_body }
- end
-
- case protocol
- when :ostatus
- process_atom(resource_url, **resource_options)
- when :activitypub
- ActivityPub::FetchRemoteAccountService.new.call(resource_url, **resource_options)
- end
- end
-
- private
-
- def process_atom(url, prefetched_body:)
- xml = Nokogiri::XML(prefetched_body)
- xml.encoding = 'utf-8'
-
- account = author_from_xml(xml.at_xpath('/xmlns:feed', xmlns: OStatus::TagManager::XMLNS), false)
-
- UpdateRemoteProfileService.new.call(xml, account) if account.present? && trusted_domain?(url, account)
-
- account
- rescue TypeError
- Rails.logger.debug "Unparseable URL given: #{url}"
- nil
- rescue Nokogiri::XML::XPath::SyntaxError
- Rails.logger.debug 'Invalid XML or missing namespace'
- nil
- end
-
- def trusted_domain?(url, account)
- domain = Addressable::URI.parse(url).normalized_host
- domain.casecmp(account.domain).zero? || domain.casecmp(Addressable::URI.parse(account.remote_url.presence || account.uri).normalized_host).zero?
- end
-end
diff --git a/app/services/fetch_remote_status_service.rb b/app/services/fetch_remote_status_service.rb
deleted file mode 100644
index 9c300803..00000000
--- a/app/services/fetch_remote_status_service.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-class FetchRemoteStatusService < BaseService
- include AuthorExtractor
-
- def call(url, prefetched_body = nil, protocol = :ostatus)
- if prefetched_body.nil?
- resource_url, resource_options, protocol = FetchAtomService.new.call(url)
- else
- resource_url = url
- resource_options = { prefetched_body: prefetched_body }
- end
-
- case protocol
- when :ostatus
- process_atom(resource_url, **resource_options)
- when :activitypub
- ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options)
- end
- end
-
- private
-
- def process_atom(url, prefetched_body:)
- Rails.logger.debug "Processing Atom for remote status at #{url}"
-
- xml = Nokogiri::XML(prefetched_body)
- xml.encoding = 'utf-8'
-
- account = author_from_xml(xml.at_xpath('/xmlns:entry', xmlns: OStatus::TagManager::XMLNS))
- domain = Addressable::URI.parse(url).normalized_host
-
- return nil unless !account.nil? && confirmed_domain?(domain, account)
-
- statuses = ProcessFeedService.new.call(prefetched_body, account)
- statuses.first
- rescue Nokogiri::XML::XPath::SyntaxError
- Rails.logger.debug 'Invalid XML or missing namespace'
- nil
- end
-
- def confirmed_domain?(domain, account)
- account.domain.nil? || domain.casecmp(account.domain).zero? || domain.casecmp(Addressable::URI.parse(account.remote_url.presence || account.uri).normalized_host).zero?
- end
-end
diff --git a/app/services/follow_service.rb b/app/services/follow_service.rb
index ca9237e2..39c9b9bf 100644
--- a/app/services/follow_service.rb
+++ b/app/services/follow_service.rb
@@ -9,7 +9,6 @@ class FollowService < BaseService
# @param [true, false, nil] reblogs Whether or not to show reblogs, defaults to true
def call(source_account, target_account, reblogs: nil)
reblogs = true if reblogs.nil?
- target_account = ResolveAccountService.new.call(target_account, skip_webfinger: true)
raise ActiveRecord::RecordNotFound if target_account.nil? || target_account.id == source_account.id || target_account.suspended?
raise GabSocial::NotPermittedError if target_account.blocking?(source_account) || source_account.blocking?(target_account) || target_account.moved?
@@ -29,9 +28,9 @@ class FollowService < BaseService
ActivityTracker.increment('activity:interactions')
- if target_account.locked? || target_account.activitypub?
+ if target_account.locked?
request_follow(source_account, target_account, reblogs: reblogs)
- else
+ elsif target_account.local?
direct_follow(source_account, target_account, reblogs: reblogs)
end
end
diff --git a/app/services/import_service.rb b/app/services/import_service.rb
deleted file mode 100644
index 212597bc..00000000
--- a/app/services/import_service.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-require 'csv'
-
-class ImportService < BaseService
- ROWS_PROCESSING_LIMIT = 20_000
-
- def call(import)
- @import = import
- @account = @import.account
-
- case @import.type
- when 'following'
- import_follows!
- when 'blocking'
- import_blocks!
- when 'muting'
- import_mutes!
- when 'domain_blocking'
- import_domain_blocks!
- end
- end
-
- private
-
- def import_follows!
- parse_import_data!(['Account address'])
- import_relationships!('follow', 'unfollow', @account.following, follow_limit, reblogs: 'Show reposts')
- end
-
- def import_blocks!
- parse_import_data!(['Account address'])
- import_relationships!('block', 'unblock', @account.blocking, ROWS_PROCESSING_LIMIT)
- end
-
- def import_mutes!
- parse_import_data!(['Account address'])
- import_relationships!('mute', 'unmute', @account.muting, ROWS_PROCESSING_LIMIT, notifications: 'Hide notifications')
- end
-
- def import_domain_blocks!
- parse_import_data!(['#domain'])
- items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#domain'].strip }
-
- if @import.overwrite?
- presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true }
-
- @account.domain_blocks.find_each do |domain_block|
- if presence_hash[domain_block.domain]
- items.delete(domain_block.domain)
- else
- @account.unblock_domain!(domain_block.domain)
- end
- end
- end
-
- items.each do |domain|
- @account.block_domain!(domain)
- end
-
- AfterAccountDomainBlockWorker.push_bulk(items) do |domain|
- [@account.id, domain]
- end
- end
-
- def import_relationships!(action, undo_action, overwrite_scope, limit, extra_fields = {})
- items = @data.take(limit).map { |row| [row['Account address']&.strip, Hash[extra_fields.map { |key, header| [key, row[header]&.strip] }]] }.reject { |(id, _)| id.blank? }
-
- if @import.overwrite?
- presence_hash = items.each_with_object({}) { |(id, extra), mapping| mapping[id] = [true, extra] }
-
- overwrite_scope.find_each do |target_account|
- if presence_hash[target_account.acct]
- items.delete(target_account.acct)
- extra = presence_hash[target_account.acct][1]
- Import::RelationshipWorker.perform_async(@account.id, target_account.acct, action, extra)
- else
- Import::RelationshipWorker.perform_async(@account.id, target_account.acct, undo_action)
- end
- end
- end
-
- Import::RelationshipWorker.push_bulk(items) do |acct, extra|
- [@account.id, acct, action, extra]
- end
- end
-
- def parse_import_data!(default_headers)
- data = CSV.parse(import_data, headers: true)
- data = CSV.parse(import_data, headers: default_headers) unless data.headers&.first&.strip&.include?(' ')
- @data = data.reject(&:blank?)
- end
-
- def import_data
- Paperclip.io_adapters.for(@import.data).read
- end
-
- def follow_limit
- FollowLimitValidator.limit_for_account(@account)
- end
-end
diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb
index b5c72158..a2a1ef6a 100644
--- a/app/services/notify_service.rb
+++ b/app/services/notify_service.rb
@@ -10,7 +10,6 @@ class NotifyService < BaseService
create_notification!
push_notification! if @notification.browserable?
- push_to_conversation! if direct_message?
send_email! if email_enabled?
rescue ActiveRecord::RecordInvalid
return
@@ -59,25 +58,10 @@ class NotifyService < BaseService
@notification.type == :mention
end
- def direct_message?
- message? && @notification.target_status.direct_visibility?
- end
-
- def response_to_recipient?
- @notification.target_status.in_reply_to_account_id == @recipient.id && @notification.target_status.thread&.direct_visibility?
- end
-
def from_staff?
@notification.from_account.local? && @notification.from_account.user.present? && @notification.from_account.user.staff?
end
- def optional_non_following_and_direct?
- direct_message? &&
- @recipient.user.settings.interactions['must_be_following_dm'] &&
- !following_sender? &&
- !response_to_recipient?
- end
-
def hellbanned?
@notification.from_account.silenced? && !following_sender?
end
@@ -86,36 +70,21 @@ class NotifyService < BaseService
@recipient.id == @notification.from_account.id
end
- def domain_blocking?
- @recipient.domain_blocking?(@notification.from_account.domain) && !following_sender?
- end
-
def blocked?
blocked = @recipient.suspended? # Skip if the recipient account is suspended anyway
blocked ||= from_self? && @notification.type != :poll # Skip for interactions with self
return blocked if message? && from_staff?
- blocked ||= domain_blocking? # Skip for domain blocked accounts
blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts
blocked ||= @recipient.muting_notifications?(@notification.from_account)
blocked ||= hellbanned? # Hellban
blocked ||= optional_non_follower? # Options
blocked ||= optional_non_following? # Options
- blocked ||= optional_non_following_and_direct? # Options
- blocked ||= conversation_muted?
blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters
blocked
end
- def conversation_muted?
- if @notification.target_status
- @recipient.muting_conversation?(@notification.target_status.conversation)
- else
- false
- end
- end
-
def create_notification!
@notification.save!
end
@@ -127,11 +96,6 @@ class NotifyService < BaseService
send_push_notifications!
end
- def push_to_conversation!
- return if @notification.activity.nil?
- AccountConversation.add_status(@recipient, @notification.target_status)
- end
-
def send_push_notifications!
subscriptions_ids = ::Web::PushSubscription.where(user_id: @recipient.user.id)
.select { |subscription| subscription.pushable?(@notification) }
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index 0f150bc6..6b77aa9f 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -100,8 +100,6 @@ class PostStatusService < BaseService
def postprocess_status!
LinkCrawlWorker.perform_async(@status.id) unless @status.spoiler_text?
DistributionWorker.perform_async(@status.id)
- # Pubsubhubbub::DistributionWorker.perform_async(@status.stream_entry.id)
- # ActivityPub::DistributionWorker.perform_async(@status.id)
ExpiringStatusWorker.perform_at(@status.expires_at, @status.id) if @status.expires_at && @account.is_pro
PollExpirationNotifyWorker.perform_at(@status.poll.expires_at, @status.poll.id) if @status.poll
end
diff --git a/app/services/process_feed_service.rb b/app/services/process_feed_service.rb
deleted file mode 100644
index 30a9dd85..00000000
--- a/app/services/process_feed_service.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class ProcessFeedService < BaseService
- def call(body, account, **options)
- @options = options
-
- xml = Nokogiri::XML(body)
- xml.encoding = 'utf-8'
-
- update_author(body, account)
- process_entries(xml, account)
- end
-
- private
-
- def update_author(body, account)
- RemoteProfileUpdateWorker.perform_async(account.id, body.force_encoding('UTF-8'), true)
- end
-
- def process_entries(xml, account)
- xml.xpath('//xmlns:entry', xmlns: OStatus::TagManager::XMLNS).reverse_each.map { |entry| process_entry(entry, account) }.compact
- end
-
- def process_entry(xml, account)
- activity = OStatus::Activity::General.new(xml, account, @options)
- activity.specialize&.perform if activity.status?
- rescue ActiveRecord::RecordInvalid => e
- Rails.logger.debug "Nothing was saved for #{activity.id} because: #{e}"
- nil
- end
-end
diff --git a/app/services/process_interaction_service.rb b/app/services/process_interaction_service.rb
deleted file mode 100644
index 7625ade0..00000000
--- a/app/services/process_interaction_service.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# frozen_string_literal: true
-
-class ProcessInteractionService < BaseService
- include AuthorExtractor
- include Authorization
-
- # Record locally the remote interaction with our user
- # @param [String] envelope Salmon envelope
- # @param [Account] target_account Account the Salmon was addressed to
- def call(envelope, target_account)
- body = salmon.unpack(envelope)
-
- xml = Nokogiri::XML(body)
- xml.encoding = 'utf-8'
-
- account = author_from_xml(xml.at_xpath('/xmlns:entry', xmlns: OStatus::TagManager::XMLNS))
-
- return if account.nil? || account.suspended?
-
- if salmon.verify(envelope, account.keypair)
- RemoteProfileUpdateWorker.perform_async(account.id, body.force_encoding('UTF-8'), true)
-
- case verb(xml)
- when :follow
- follow!(account, target_account) unless target_account.locked? || target_account.blocking?(account) || target_account.domain_blocking?(account.domain)
- when :request_friend
- follow_request!(account, target_account) unless !target_account.locked? || target_account.blocking?(account) || target_account.domain_blocking?(account.domain)
- when :authorize
- authorize_follow_request!(account, target_account)
- when :reject
- reject_follow_request!(account, target_account)
- when :unfollow
- unfollow!(account, target_account)
- when :favorite
- favourite!(xml, account)
- when :unfavorite
- unfavourite!(xml, account)
- when :post
- add_post!(body, account) if mentions_account?(xml, target_account)
- when :share
- add_post!(body, account) unless status(xml).nil?
- when :delete
- delete_post!(xml, account)
- when :block
- reflect_block!(account, target_account)
- when :unblock
- reflect_unblock!(account, target_account)
- end
- end
- rescue HTTP::Error, OStatus2::BadSalmonError, GabSocial::NotPermittedError
- nil
- end
-
- private
-
- def mentions_account?(xml, account)
- xml.xpath('/xmlns:entry/xmlns:link[@rel="mentioned"]', xmlns: OStatus::TagManager::XMLNS).each { |mention_link| return true if [OStatus::TagManager.instance.uri_for(account), OStatus::TagManager.instance.url_for(account)].include?(mention_link.attribute('href').value) }
- false
- end
-
- def verb(xml)
- raw = xml.at_xpath('//activity:verb', activity: OStatus::TagManager::AS_XMLNS).content
- OStatus::TagManager::VERBS.key(raw)
- rescue
- :post
- end
-
- def follow!(account, target_account)
- follow = account.follow!(target_account)
- FollowRequest.find_by(account: account, target_account: target_account)&.destroy
- NotifyService.new.call(target_account, follow)
- end
-
- def follow_request!(account, target_account)
- return if account.requested?(target_account)
-
- follow_request = FollowRequest.create!(account: account, target_account: target_account)
- NotifyService.new.call(target_account, follow_request)
- end
-
- def authorize_follow_request!(account, target_account)
- follow_request = FollowRequest.find_by(account: target_account, target_account: account)
- follow_request&.authorize!
- Pubsubhubbub::SubscribeWorker.perform_async(account.id) unless account.subscribed?
- end
-
- def reject_follow_request!(account, target_account)
- follow_request = FollowRequest.find_by(account: target_account, target_account: account)
- follow_request&.reject!
- end
-
- def unfollow!(account, target_account)
- account.unfollow!(target_account)
- FollowRequest.find_by(account: account, target_account: target_account)&.destroy
- end
-
- def reflect_block!(account, target_account)
- UnfollowService.new.call(target_account, account) if target_account.following?(account)
- account.block!(target_account)
- end
-
- def reflect_unblock!(account, target_account)
- UnblockService.new.call(account, target_account)
- end
-
- def delete_post!(xml, account)
- status = Status.find(xml.at_xpath('//xmlns:id', xmlns: OStatus::TagManager::XMLNS).content)
-
- return if status.nil?
-
- authorize_with account, status, :destroy?
-
- RemovalWorker.perform_async(status.id)
- end
-
- def favourite!(xml, from_account)
- current_status = status(xml)
-
- return if current_status.nil?
-
- favourite = current_status.favourites.where(account: from_account).first_or_create!(account: from_account)
- NotifyService.new.call(current_status.account, favourite)
- end
-
- def unfavourite!(xml, from_account)
- current_status = status(xml)
-
- return if current_status.nil?
-
- favourite = current_status.favourites.where(account: from_account).first
- favourite&.destroy
- end
-
- def add_post!(body, account)
- ProcessingWorker.perform_async(account.id, body.force_encoding('UTF-8'))
- end
-
- def status(xml)
- uri = activity_id(xml)
- return nil unless OStatus::TagManager.instance.local_id?(uri)
- Status.find(OStatus::TagManager.instance.unique_tag_to_local_id(uri, 'Status'))
- end
-
- def activity_id(xml)
- xml.at_xpath('//activity:object', activity: OStatus::TagManager::AS_XMLNS).at_xpath('./xmlns:id', xmlns: OStatus::TagManager::XMLNS).content
- end
-
- def salmon
- @salmon ||= OStatus2::Salmon.new
- end
-end
diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb
index 3c6d177f..eb6b8d80 100644
--- a/app/services/process_mentions_service.rb
+++ b/app/services/process_mentions_service.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class ProcessMentionsService < BaseService
- include StreamEntryRenderer
-
# Scan status for mentions and fetch remote mentioned users, create
# local mention pointers, send Salmon notifications to mentioned
# remote users
@@ -15,17 +13,9 @@ class ProcessMentionsService < BaseService
status.text = status.text.gsub(Account::MENTION_RE) do |match|
username, domain = Regexp.last_match(1).split('@')
- mentioned_account = Account.find_remote(username, domain)
+ mentioned_account = Account.find_local(username)
- if mention_undeliverable?(mentioned_account)
- begin
- mentioned_account = resolve_account_service.call(Regexp.last_match(1))
- rescue Goldfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, GabSocial::UnexpectedResponseError
- mentioned_account = nil
- end
- end
-
- next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended?
+ next match if mentioned_account.nil? || mentioned_account&.suspended?
mentions << mentioned_account.mentions.where(status: status).first_or_create(status: status)
@@ -39,10 +29,6 @@ class ProcessMentionsService < BaseService
private
- def mention_undeliverable?(mentioned_account)
- mentioned_account.nil? || (!mentioned_account.local? && mentioned_account.ostatus? && @status.stream_entry.hidden?)
- end
-
def create_notification(mention)
mentioned_account = mention.account
@@ -51,7 +37,4 @@ class ProcessMentionsService < BaseService
end
end
- def resolve_account_service
- ResolveAccountService.new
- end
end
diff --git a/app/services/process_quote_service.rb b/app/services/process_quote_service.rb
index aa2d344f..fc0ca193 100644
--- a/app/services/process_quote_service.rb
+++ b/app/services/process_quote_service.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class ProcessQuoteService < BaseService
- include StreamEntryRenderer
-
# Create notification for a quote
# @param [Status] status Quoting status
# @return [Status]
diff --git a/app/services/pubsubhubbub/subscribe_service.rb b/app/services/pubsubhubbub/subscribe_service.rb
deleted file mode 100644
index 550da632..00000000
--- a/app/services/pubsubhubbub/subscribe_service.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::SubscribeService < BaseService
- URL_PATTERN = /\A#{URI.regexp(%w(http https))}\z/
-
- attr_reader :account, :callback, :secret,
- :lease_seconds, :domain
-
- def call(account, callback, secret, lease_seconds, verified_domain = nil)
- @account = account
- @callback = Addressable::URI.parse(callback).normalize.to_s
- @secret = secret
- @lease_seconds = lease_seconds
- @domain = verified_domain
-
- process_subscribe
- end
-
- private
-
- def process_subscribe
- if account.nil?
- ['Invalid topic URL', 422]
- elsif !valid_callback?
- ['Invalid callback URL', 422]
- elsif blocked_domain?
- ['Callback URL not allowed', 403]
- else
- confirm_subscription
- ['', 202]
- end
- end
-
- def confirm_subscription
- subscription = locate_subscription
- Pubsubhubbub::ConfirmationWorker.perform_async(subscription.id, 'subscribe', secret, lease_seconds)
- end
-
- def valid_callback?
- callback.present? && callback =~ URL_PATTERN
- end
-
- def blocked_domain?
- DomainBlock.blocked? Addressable::URI.parse(callback).host
- end
-
- def locate_subscription
- subscription = Subscription.find_or_initialize_by(account: account, callback_url: callback)
- subscription.domain = domain
- subscription.save!
- subscription
- end
-end
diff --git a/app/services/pubsubhubbub/unsubscribe_service.rb b/app/services/pubsubhubbub/unsubscribe_service.rb
deleted file mode 100644
index 646150f7..00000000
--- a/app/services/pubsubhubbub/unsubscribe_service.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::UnsubscribeService < BaseService
- attr_reader :account, :callback
-
- def call(account, callback)
- @account = account
- @callback = Addressable::URI.parse(callback).normalize.to_s
-
- process_unsubscribe
- end
-
- private
-
- def process_unsubscribe
- if account.nil?
- ['Invalid topic URL', 422]
- else
- confirm_unsubscribe unless subscription.nil?
- ['', 202]
- end
- end
-
- def confirm_unsubscribe
- Pubsubhubbub::ConfirmationWorker.perform_async(subscription.id, 'unsubscribe')
- end
-
- def subscription
- @_subscription ||= Subscription.find_by(account: account, callback_url: callback)
- end
-end
diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb
index 9909a888..80f67cca 100644
--- a/app/services/reblog_service.rb
+++ b/app/services/reblog_service.rb
@@ -2,7 +2,6 @@
class ReblogService < BaseService
include Authorization
- include StreamEntryRenderer
# Reblog a status and notify its remote author
# @param [Account] account Account to reblog from
@@ -24,8 +23,6 @@ class ReblogService < BaseService
reblog = account.statuses.create!(reblog: reblogged_status, text: text, visibility: visibility)
DistributionWorker.perform_async(reblog.id)
- # Pubsubhubbub::DistributionWorker.perform_async(reblog.stream_entry.id)
- # ActivityPub::DistributionWorker.perform_async(reblog.id)
create_notification(reblog)
bump_potential_friendship(account, reblog)
diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb
index 43d9787d..55315703 100644
--- a/app/services/remove_status_service.rb
+++ b/app/services/remove_status_service.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
class RemoveStatusService < BaseService
- include StreamEntryRenderer
include Redisable
def call(status, **options)
@@ -11,7 +10,6 @@ class RemoveStatusService < BaseService
@tags = status.tags.pluck(:name).to_a
@mentions = status.active_mentions.includes(:account).to_a
@reblogs = status.reblogs.includes(:account).to_a
- @stream_entry = status.stream_entry
@options = options
RedisLock.acquire(lock_options) do |lock|
@@ -36,9 +34,6 @@ class RemoveStatusService < BaseService
# of it. The Delete activity of the original is forwarded
# separately.
return if !@account.local? || @options[:original_removed]
-
- remove_from_remote_followers
- remove_from_remote_affected
end
private
@@ -65,66 +60,6 @@ class RemoveStatusService < BaseService
end
end
- def remove_from_remote_affected
- # People who got mentioned in the status, or who
- # reblogged it from someone else might not follow
- # the author and wouldn't normally receive the
- # delete notification - so here, we explicitly
- # send it to them
-
- target_accounts = (@mentions.map(&:account).reject(&:local?) + @reblogs.map(&:account).reject(&:local?))
- target_accounts << @status.reblog.account if @status.reblog? && !@status.reblog.account.local?
- target_accounts.uniq!(&:id)
-
- # Ostatus
- NotificationWorker.push_bulk(target_accounts.select(&:ostatus?).uniq(&:domain)) do |target_account|
- [salmon_xml, @account.id, target_account.id]
- end
-
- # ActivityPub
- ActivityPub::DeliveryWorker.push_bulk(target_accounts.select(&:activitypub?).uniq(&:preferred_inbox_url)) do |target_account|
- [signed_activity_json, @account.id, target_account.preferred_inbox_url]
- end
- end
-
- def remove_from_remote_followers
- # OStatus
- Pubsubhubbub::RawDistributionWorker.perform_async(salmon_xml, @account.id)
-
- # ActivityPub
- ActivityPub::DeliveryWorker.push_bulk(@account.followers.inboxes) do |inbox_url|
- [signed_activity_json, @account.id, inbox_url]
- end
-
- relay! if relayable?
- end
-
- def relayable?
- @status.public_visibility?
- end
-
- def relay!
- ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
- [signed_activity_json, @account.id, inbox_url]
- end
- end
-
- def salmon_xml
- @salmon_xml ||= stream_entry_to_xml(@stream_entry)
- end
-
- def signed_activity_json
- @signed_activity_json ||= Oj.dump(ActivityPub::LinkedDataSignature.new(activity_json).sign!(@account))
- end
-
- def activity_json
- @activity_json ||= ActiveModelSerializers::SerializableResource.new(
- @status,
- serializer: @status.reblog? ? ActivityPub::UndoAnnounceSerializer : ActivityPub::DeleteSerializer,
- adapter: ActivityPub::Adapter
- ).as_json
- end
-
def remove_reblogs
# We delete reblogs of the status before the original status,
# because once original status is gone, reblogs will disappear
diff --git a/app/services/report_service.rb b/app/services/report_service.rb
index d8c55eac..68938d7a 100644
--- a/app/services/report_service.rb
+++ b/app/services/report_service.rb
@@ -9,7 +9,6 @@ class ReportService < BaseService
@options = options
create_report!
- forward_to_origin! if !@target_account.local? && ActiveModel::Type::Boolean.new.cast(@options[:forward])
@report
end
@@ -25,24 +24,4 @@ class ReportService < BaseService
)
end
- def forward_to_origin!
- ActivityPub::DeliveryWorker.perform_async(
- payload,
- some_local_account.id,
- @target_account.inbox_url
- )
- end
-
- def payload
- Oj.dump(ActiveModelSerializers::SerializableResource.new(
- @report,
- serializer: ActivityPub::FlagSerializer,
- adapter: ActivityPub::Adapter,
- account: some_local_account
- ).as_json)
- end
-
- def some_local_account
- @some_local_account ||= Account.representative
- end
end
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
deleted file mode 100644
index b8d4cd9d..00000000
--- a/app/services/resolve_account_service.rb
+++ /dev/null
@@ -1,220 +0,0 @@
-# frozen_string_literal: true
-
-class ResolveAccountService < BaseService
- include OStatus2::MagicKey
- include JsonLdHelper
-
- DFRN_NS = 'http://purl.org/macgirvin/dfrn/1.0'
-
- # Find or create a local account for a remote user.
- # When creating, look up the user's webfinger and fetch all
- # important information from their feed
- # @param [String, Account] uri User URI in the form of username@domain
- # @param [Hash] options
- # @return [Account]
- def call(uri, options = {})
- @options = options
-
- if uri.is_a?(Account)
- @account = uri
- @username = @account.username
- @domain = @account.domain
- uri = "#{@username}@#{@domain}"
-
- return @account if @account.local? || !webfinger_update_due?
- else
- @username, @domain = uri.split('@')
-
- return Account.find_local(@username) if TagManager.instance.local_domain?(@domain)
-
- @account = Account.find_remote(@username, @domain)
-
- return @account unless webfinger_update_due?
- end
-
- Rails.logger.debug "Looking up webfinger for #{uri}"
-
- @webfinger = Goldfinger.finger("acct:#{uri}")
-
- confirmed_username, confirmed_domain = @webfinger.subject.gsub(/\Aacct:/, '').split('@')
-
- if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?
- @username = confirmed_username
- @domain = confirmed_domain
- elsif options[:redirected].nil?
- return call("#{confirmed_username}@#{confirmed_domain}", options.merge(redirected: true))
- else
- Rails.logger.debug 'Requested and returned acct URIs do not match'
- return
- end
-
- return if links_missing?
- return Account.find_local(@username) if TagManager.instance.local_domain?(@domain)
-
- RedisLock.acquire(lock_options) do |lock|
- if lock.acquired?
- @account = Account.find_remote(@username, @domain)
-
- if activitypub_ready? || @account&.activitypub?
- handle_activitypub
- else
- handle_ostatus
- end
- else
- raise GabSocial::RaceConditionError
- end
- end
-
- @account
- rescue Goldfinger::Error => e
- Rails.logger.debug "Webfinger query for #{uri} unsuccessful: #{e}"
- nil
- end
-
- private
-
- def links_missing?
- !(activitypub_ready? || ostatus_ready?)
- end
-
- def ostatus_ready?
- !(@webfinger.link('http://schemas.google.com/g/2010#updates-from').nil? ||
- @webfinger.link('salmon').nil? ||
- @webfinger.link('http://webfinger.net/rel/profile-page').nil? ||
- @webfinger.link('magic-public-key').nil? ||
- canonical_uri.nil? ||
- hub_url.nil?)
- end
-
- def webfinger_update_due?
- @account.nil? || ((!@options[:skip_webfinger] || @account.ostatus?) && @account.possibly_stale?)
- end
-
- def activitypub_ready?
- !@webfinger.link('self').nil? &&
- ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(@webfinger.link('self').type) &&
- !actor_json.nil? &&
- actor_json['inbox'].present?
- end
-
- def handle_ostatus
- create_account if @account.nil?
- update_account
- update_account_profile if update_profile?
- end
-
- def update_profile?
- @options[:update_profile]
- end
-
- def handle_activitypub
- return if actor_json.nil?
-
- @account = ActivityPub::ProcessAccountService.new.call(@username, @domain, actor_json)
- rescue Oj::ParseError
- nil
- end
-
- def create_account
- Rails.logger.debug "Creating new remote account for #{@username}@#{@domain}"
-
- @account = Account.new(username: @username, domain: @domain)
- @account.suspended_at = domain_block.created_at if auto_suspend?
- @account.silenced_at = domain_block.created_at if auto_silence?
- @account.private_key = nil
- end
-
- def update_account
- @account.last_webfingered_at = Time.now.utc
- @account.protocol = :ostatus
- @account.remote_url = atom_url
- @account.salmon_url = salmon_url
- @account.url = url
- @account.public_key = public_key
- @account.uri = canonical_uri
- @account.hub_url = hub_url
- @account.save!
- end
-
- def auto_suspend?
- domain_block&.suspend?
- end
-
- def auto_silence?
- domain_block&.silence?
- end
-
- def domain_block
- return @domain_block if defined?(@domain_block)
- @domain_block = DomainBlock.find_by(domain: @domain)
- end
-
- def atom_url
- @atom_url ||= @webfinger.link('http://schemas.google.com/g/2010#updates-from').href
- end
-
- def salmon_url
- @salmon_url ||= @webfinger.link('salmon').href
- end
-
- def actor_url
- @actor_url ||= @webfinger.link('self').href
- end
-
- def url
- @url ||= @webfinger.link('http://webfinger.net/rel/profile-page').href
- end
-
- def public_key
- @public_key ||= magic_key_to_pem(@webfinger.link('magic-public-key').href)
- end
-
- def canonical_uri
- return @canonical_uri if defined?(@canonical_uri)
-
- author_uri = atom.at_xpath('/xmlns:feed/xmlns:author/xmlns:uri')
-
- if author_uri.nil?
- owner = atom.at_xpath('/xmlns:feed').at_xpath('./dfrn:owner', dfrn: DFRN_NS)
- author_uri = owner.at_xpath('./xmlns:uri') unless owner.nil?
- end
-
- @canonical_uri = author_uri.nil? ? nil : author_uri.content
- end
-
- def hub_url
- return @hub_url if defined?(@hub_url)
-
- hubs = atom.xpath('//xmlns:link[@rel="hub"]')
- @hub_url = hubs.empty? || hubs.first['href'].nil? ? nil : hubs.first['href']
- end
-
- def atom_body
- return @atom_body if defined?(@atom_body)
-
- @atom_body = Request.new(:get, atom_url).perform do |response|
- raise GabSocial::UnexpectedResponseError, response unless response.code == 200
- response.body_with_limit
- end
- end
-
- def actor_json
- return @actor_json if defined?(@actor_json)
-
- json = fetch_resource(actor_url, false)
- @actor_json = supported_context?(json) && equals_or_includes_any?(json['type'], ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) ? json : nil
- end
-
- def atom
- return @atom if defined?(@atom)
- @atom = Nokogiri::XML(atom_body)
- end
-
- def update_account_profile
- RemoteProfileUpdateWorker.perform_async(@account.id, atom_body.force_encoding('UTF-8'), false)
- end
-
- def lock_options
- { redis: Redis.current, key: "resolve:#{@username}@#{@domain}" }
- end
-end
diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb
deleted file mode 100644
index a9e7af58..00000000
--- a/app/services/resolve_url_service.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: true
-
-class ResolveURLService < BaseService
- include JsonLdHelper
- include Authorization
-
- attr_reader :url
-
- def call(url, on_behalf_of: nil)
- @url = url
- @on_behalf_of = on_behalf_of
-
- return process_local_url if local_url?
-
- process_url unless fetched_atom_feed.nil?
- end
-
- private
-
- def process_url
- if equals_or_includes_any?(type, %w(Application Group Organization Person Service))
- FetchRemoteAccountService.new.call(atom_url, body, protocol)
- elsif equals_or_includes_any?(type, %w(Note Article Image Video Page Question))
- FetchRemoteStatusService.new.call(atom_url, body, protocol)
- end
- end
-
- def fetched_atom_feed
- @_fetched_atom_feed ||= FetchAtomService.new.call(url)
- end
-
- def atom_url
- fetched_atom_feed.first
- end
-
- def body
- fetched_atom_feed.second[:prefetched_body]
- end
-
- def protocol
- fetched_atom_feed.third
- end
-
- def type
- return json_data['type'] if protocol == :activitypub
-
- case xml_root
- when 'feed'
- 'Person'
- when 'entry'
- 'Note'
- end
- end
-
- def json_data
- @_json_data ||= body_to_json(body)
- end
-
- def xml_root
- xml_data.root.name
- end
-
- def xml_data
- @_xml_data ||= Nokogiri::XML(body, nil, 'utf-8')
- end
-
- def local_url?
- TagManager.instance.local_url?(@url)
- end
-
- def process_local_url
- recognized_params = Rails.application.routes.recognize_path(@url)
-
- return unless recognized_params[:action] == 'show'
-
- if recognized_params[:controller] == 'stream_entries'
- status = StreamEntry.find_by(id: recognized_params[:id])&.status
- check_local_status(status)
- elsif recognized_params[:controller] == 'statuses'
- status = Status.find_by(id: recognized_params[:id])
- check_local_status(status)
- elsif recognized_params[:controller] == 'accounts'
- Account.find_local(recognized_params[:username])
- end
- end
-
- def check_local_status(status)
- return if status.nil?
- authorize_with @on_behalf_of, status, :show?
- status
- rescue GabSocial::NotPermittedError
- # Do not disclose the existence of status the user is not authorized to see
- nil
- end
-end
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 57e2c99d..ffc95022 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -13,12 +13,9 @@ class SearchService < BaseService
default_results.tap do |results|
next if @query.blank? || @limit.zero?
- if url_query?
- results.merge!(url_resource_results) unless url_resource.nil? || @offset.positive? || (@options[:type].present? && url_resource_symbol != @options[:type].to_sym)
- elsif @query.present?
+ if @query.present?
results[:accounts] = perform_accounts_search! if account_searchable?
results[:statuses] = perform_statuses_search! if full_text_searchable? && !account.nil?
- results[:hashtags] = perform_hashtags_search! if hashtag_searchable? && !account.nil?
results[:links] = [] # perform_links_search! if !account.nil?
results[:groups] = perform_groups_search!
end
@@ -77,31 +74,8 @@ class SearchService < BaseService
[]
end
- def perform_hashtags_search!
- Tag.search_for(
- @query.gsub(/\A#/, ''),
- @offset
- )
- end
-
def default_results
- { accounts: [], hashtags: [], statuses: [], links: [], groups: [] }
- end
-
- def url_query?
- @resolve && @query =~ /\Ahttps?:\/\//
- end
-
- def url_resource_results
- { url_resource_symbol => [url_resource] }
- end
-
- def url_resource
- @_url_resource ||= ResolveURLService.new.call(@query, on_behalf_of: @account)
- end
-
- def url_resource_symbol
- url_resource.class.name.downcase.pluralize.to_sym
+ { accounts: [], statuses: [], links: [], groups: [] }
end
def full_text_searchable?
@@ -114,18 +88,10 @@ class SearchService < BaseService
account_search? && !(@query.include?('@') && @query.include?(' '))
end
- def hashtag_searchable?
- hashtag_search? && !@query.include?('@')
- end
-
def account_search?
@options[:type].blank? || @options[:type] == 'accounts'
end
- def hashtag_search?
- @options[:type].blank? || @options[:type] == 'hashtags'
- end
-
def statuses_search?
@options[:type].blank? || @options[:type] == 'statuses'
end
@@ -136,7 +102,6 @@ class SearchService < BaseService
blocked_by: Account.blocked_by_map(account_ids, account.id),
muting: Account.muting_map(account_ids, account.id),
following: Account.following_map(account_ids, account.id),
- domain_blocking_by_domain: Account.domain_blocking_map_by_domain(domains, account.id),
}
end
end
diff --git a/app/services/send_interaction_service.rb b/app/services/send_interaction_service.rb
deleted file mode 100644
index 9d6ac8f5..00000000
--- a/app/services/send_interaction_service.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-class SendInteractionService < BaseService
- # Send an Atom representation of an interaction to a remote Salmon endpoint
- # @param [String] Entry XML
- # @param [Account] source_account
- # @param [Account] target_account
- def call(xml, source_account, target_account)
- @xml = xml
- @source_account = source_account
- @target_account = target_account
-
- return if !target_account.ostatus? || block_notification?
-
- build_request.perform do |delivery|
- raise GabSocial::UnexpectedResponseError, delivery unless delivery.code > 199 && delivery.code < 300
- end
- end
-
- private
-
- def build_request
- request = Request.new(:post, @target_account.salmon_url, body: envelope)
- request.add_headers('Content-Type' => 'application/magic-envelope+xml')
- request
- end
-
- def envelope
- salmon.pack(@xml, @source_account.keypair)
- end
-
- def block_notification?
- DomainBlock.blocked?(@target_account.domain)
- end
-
- def salmon
- @salmon ||= OStatus2::Salmon.new
- end
-end
diff --git a/app/services/subscribe_service.rb b/app/services/subscribe_service.rb
deleted file mode 100644
index af09644b..00000000
--- a/app/services/subscribe_service.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-
-class SubscribeService < BaseService
- def call(account)
- return if account.hub_url.blank?
-
- @account = account
- @account.secret = SecureRandom.hex
-
- build_request.perform do |response|
- if response_failed_permanently? response
- # We're not allowed to subscribe. Fail and move on.
- @account.secret = ''
- @account.save!
- elsif response_successful? response
- # The subscription will be confirmed asynchronously.
- @account.save!
- else
- # The response was either a 429 rate limit, or a 5xx error.
- # We need to retry at a later time. Fail loudly!
- raise GabSocial::UnexpectedResponseError, response
- end
- end
- end
-
- private
-
- def build_request
- request = Request.new(:post, @account.hub_url, form: subscription_params)
- request.on_behalf_of(some_local_account) if some_local_account
- request
- end
-
- def subscription_params
- {
- 'hub.topic': @account.remote_url,
- 'hub.mode': 'subscribe',
- 'hub.callback': api_subscription_url(@account.id),
- 'hub.verify': 'async',
- 'hub.secret': @account.secret,
- 'hub.lease_seconds': 7.days.seconds,
- }
- end
-
- def some_local_account
- @some_local_account ||= Account.local.without_suspended.first
- end
-
- # Any response in the 3xx or 4xx range, except for 429 (rate limit)
- def response_failed_permanently?(response)
- (response.status.redirect? || response.status.client_error?) && !response.status.too_many_requests?
- end
-
- # Any response in the 2xx range
- def response_successful?(response)
- response.status.success?
- end
-end
diff --git a/app/services/suspend_account_service.rb b/app/services/suspend_account_service.rb
index eee089d6..22db5eb6 100644
--- a/app/services/suspend_account_service.rb
+++ b/app/services/suspend_account_service.rb
@@ -2,14 +2,11 @@
class SuspendAccountService < BaseService
ASSOCIATIONS_ON_SUSPEND = %w(
- account_pins
active_relationships
block_relationships
blocked_by_relationships
- conversation_mutes
conversations
custom_filters
- domain_blocks
favourites
follow_requests
list_accounts
@@ -23,7 +20,6 @@ class SuspendAccountService < BaseService
scheduled_statuses
status_bookmarks
status_pins
- stream_entries
subscriptions
).freeze
@@ -42,7 +38,6 @@ class SuspendAccountService < BaseService
@account = account
@options = options
- reject_follows!
purge_user!
purge_profile!
purge_content!
@@ -50,14 +45,6 @@ class SuspendAccountService < BaseService
private
- def reject_follows!
- return if @account.local? || !@account.activitypub?
-
- ActivityPub::DeliveryWorker.push_bulk(Follow.where(account: @account)) do |follow|
- [build_reject_json(follow), follow.target_account_id, follow.account.inbox_url]
- end
- end
-
def purge_user!
return if !@account.local? || @account.user.nil?
@@ -106,34 +93,6 @@ class SuspendAccountService < BaseService
association.in_batches.destroy_all
end
- def delete_actor_json
- return @delete_actor_json if defined?(@delete_actor_json)
-
- payload = ActiveModelSerializers::SerializableResource.new(
- @account,
- serializer: ActivityPub::DeleteActorSerializer,
- adapter: ActivityPub::Adapter
- ).as_json
-
- @delete_actor_json = Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account))
- end
-
- def build_reject_json(follow)
- ActiveModelSerializers::SerializableResource.new(
- follow,
- serializer: ActivityPub::RejectFollowSerializer,
- adapter: ActivityPub::Adapter
- ).to_json
- end
-
- def delivery_inboxes
- @delivery_inboxes ||= @account.followers.inboxes + Relay.enabled.pluck(:inbox_url)
- end
-
- def low_priority_delivery_inboxes
- Account.inboxes - delivery_inboxes
- end
-
def associations_for_destruction
if @options[:destroy]
ASSOCIATIONS_ON_SUSPEND + ASSOCIATIONS_ON_DESTROY
diff --git a/app/services/unblock_domain_service.rb b/app/services/unblock_domain_service.rb
deleted file mode 100644
index 9b8526fb..00000000
--- a/app/services/unblock_domain_service.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class UnblockDomainService < BaseService
- attr_accessor :domain_block
-
- def call(domain_block)
- @domain_block = domain_block
- process_retroactive_updates
- domain_block.destroy
- end
-
- def process_retroactive_updates
- blocked_accounts.in_batches.update_all(update_options) unless domain_block.noop?
- end
-
- def blocked_accounts
- scope = Account.where(domain: domain_block.domain)
- if domain_block.silence?
- scope.where(silenced_at: @domain_block.created_at)
- else
- scope.where(suspended_at: @domain_block.created_at)
- end
- end
-
- def update_options
- { domain_block_impact => nil }
- end
-
- def domain_block_impact
- domain_block.silence? ? :silenced_at : :suspended_at
- end
-end
diff --git a/app/services/unsubscribe_service.rb b/app/services/unsubscribe_service.rb
deleted file mode 100644
index 95c1fb4f..00000000
--- a/app/services/unsubscribe_service.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class UnsubscribeService < BaseService
- def call(account)
- return if account.hub_url.blank?
-
- @account = account
-
- begin
- build_request.perform do |response|
- Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{response.status}" unless response.status.success?
- end
- rescue HTTP::Error, OpenSSL::SSL::SSLError => e
- Rails.logger.debug "PuSH unsubscribe for #{@account.acct} failed: #{e}"
- end
-
- @account.secret = ''
- @account.subscription_expires_at = nil
- @account.save!
- end
-
- private
-
- def build_request
- Request.new(:post, @account.hub_url, form: subscription_params)
- end
-
- def subscription_params
- {
- 'hub.topic': @account.remote_url,
- 'hub.mode': 'unsubscribe',
- 'hub.callback': api_subscription_url(@account.id),
- 'hub.verify': 'async',
- }
- end
-end
diff --git a/app/services/update_account_service.rb b/app/services/update_account_service.rb
index 97562b8f..66ee435a 100644
--- a/app/services/update_account_service.rb
+++ b/app/services/update_account_service.rb
@@ -9,7 +9,6 @@ class UpdateAccountService < BaseService
next unless ret
authorize_all_follow_requests(account) if was_locked && !account.locked
- check_links(account)
process_hashtags(account)
end
rescue GabSocial::DimensionsValidationError => de
@@ -25,10 +24,6 @@ class UpdateAccountService < BaseService
end
end
- def check_links(account)
- VerifyAccountLinksWorker.perform_async(account.id)
- end
-
def process_hashtags(account)
account.tags_as_strings = Extractor.extract_hashtags(account.note)
end
diff --git a/app/services/update_remote_profile_service.rb b/app/services/update_remote_profile_service.rb
deleted file mode 100644
index 68d36add..00000000
--- a/app/services/update_remote_profile_service.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateRemoteProfileService < BaseService
- attr_reader :account, :remote_profile
-
- def call(body, account, resubscribe = false)
- @account = account
- @remote_profile = RemoteProfile.new(body)
-
- return if remote_profile.root.nil?
-
- update_account unless remote_profile.author.nil?
-
- old_hub_url = account.hub_url
- account.hub_url = remote_profile.hub_link if remote_profile.hub_link.present? && remote_profile.hub_link != old_hub_url
-
- account.save_with_optional_media!
-
- Pubsubhubbub::SubscribeWorker.perform_async(account.id) if resubscribe && account.hub_url != old_hub_url
- end
-
- private
-
- def update_account
- account.display_name = remote_profile.display_name || ''
- account.note = remote_profile.note || ''
- account.locked = remote_profile.locked?
-
- if !account.suspended? && !DomainBlock.find_by(domain: account.domain)&.reject_media?
- if remote_profile.avatar.present?
- account.avatar_remote_url = remote_profile.avatar
- else
- account.avatar_remote_url = ''
- account.avatar.destroy
- end
-
- if remote_profile.header.present?
- account.header_remote_url = remote_profile.header
- else
- account.header_remote_url = ''
- account.header.destroy
- end
-
- save_emojis if remote_profile.emojis.present?
- end
- end
-
- def save_emojis
- do_not_download = DomainBlock.find_by(domain: account.domain)&.reject_media?
-
- return if do_not_download
-
- remote_profile.emojis.each do |link|
- next unless link['href'] && link['name']
-
- shortcode = link['name'].delete(':')
- emoji = CustomEmoji.find_by(shortcode: shortcode, domain: account.domain)
-
- next unless emoji.nil?
-
- emoji = CustomEmoji.new(shortcode: shortcode, domain: account.domain)
- emoji.image_remote_url = link['href']
- emoji.save
- end
- end
-end
diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb
deleted file mode 100644
index 6e17f4ef..00000000
--- a/app/services/verify_link_service.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class VerifyLinkService < BaseService
- def call(field)
- @link_back = ActivityPub::TagManager.instance.url_for(field.account)
- @url = field.value_for_verification
-
- perform_request!
-
- return unless link_back_present?
-
- field.mark_verified!
- rescue OpenSSL::SSL::SSLError, HTTP::Error, Addressable::URI::InvalidURIError, GabSocial::HostValidationError, GabSocial::LengthValidationError => e
- Rails.logger.debug "Error fetching link #{@url}: #{e}"
- nil
- end
-
- private
-
- def perform_request!
- @body = Request.new(:get, @url).add_headers('Accept' => 'text/html').perform do |res|
- res.code != 200 ? nil : res.body_with_limit
- end
- end
-
- def link_back_present?
- return false if @body.blank?
-
- links = Nokogiri::HTML(@body).xpath('//a[contains(concat(" ", normalize-space(@rel), " "), " me ")]|//link[contains(concat(" ", normalize-space(@rel), " "), " me ")]')
-
- if links.any? { |link| link['href'] == @link_back }
- true
- elsif links.empty?
- false
- else
- link_redirects_back?(links.first['href'])
- end
- end
-
- def link_redirects_back?(test_url)
- redirect_to_url = Request.new(:head, test_url, follow: false).perform do |res|
- res.headers['Location']
- end
-
- redirect_to_url == @link_back
- end
-end
diff --git a/app/services/verify_salmon_service.rb b/app/services/verify_salmon_service.rb
deleted file mode 100644
index 205b35d8..00000000
--- a/app/services/verify_salmon_service.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-class VerifySalmonService < BaseService
- include AuthorExtractor
-
- def call(payload)
- body = salmon.unpack(payload)
-
- xml = Nokogiri::XML(body)
- xml.encoding = 'utf-8'
-
- account = author_from_xml(xml.at_xpath('/xmlns:entry', xmlns: OStatus::TagManager::XMLNS))
-
- if account.nil?
- false
- else
- salmon.verify(payload, account.keypair)
- end
- end
-
- private
-
- def salmon
- @salmon ||= OStatus2::Salmon.new
- end
-end
diff --git a/app/services/vote_service.rb b/app/services/vote_service.rb
index 81af9ef3..816a61d2 100644
--- a/app/services/vote_service.rb
+++ b/app/services/vote_service.rb
@@ -18,42 +18,6 @@ class VoteService < BaseService
end
ActivityTracker.increment('activity:interactions')
-
- if @poll.account.local?
- distribute_poll!
- else
- deliver_votes!
- queue_final_poll_check!
- end
end
- private
-
- def distribute_poll!
- return if @poll.hide_totals?
- ActivityPub::DistributePollUpdateWorker.perform_in(3.minutes, @poll.status.id)
- end
-
- def queue_final_poll_check!
- return unless @poll.expires?
- PollExpirationNotifyWorker.perform_at(@poll.expires_at + 5.minutes, @poll.id)
- end
-
- def deliver_votes!
- @votes.each do |vote|
- ActivityPub::DeliveryWorker.perform_async(
- build_json(vote),
- @account.id,
- @poll.account.inbox_url
- )
- end
- end
-
- def build_json(vote)
- ActiveModelSerializers::SerializableResource.new(
- vote,
- serializer: ActivityPub::VoteSerializer,
- adapter: ActivityPub::Adapter
- ).to_json
- end
end
diff --git a/app/validators/blacklisted_email_validator.rb b/app/validators/blacklisted_email_validator.rb
index 0d01a1c4..01c59ebd 100644
--- a/app/validators/blacklisted_email_validator.rb
+++ b/app/validators/blacklisted_email_validator.rb
@@ -2,8 +2,6 @@
class BlacklistedEmailValidator < ActiveModel::Validator
def validate(user)
- return if user.valid_invitation?
-
@email = user.email
user.errors.add(:email, I18n.t('users.invalid_email')) if blocked_email?
diff --git a/app/validators/disallowed_hashtags_validator.rb b/app/validators/disallowed_hashtags_validator.rb
deleted file mode 100644
index ee06b20f..00000000
--- a/app/validators/disallowed_hashtags_validator.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class DisallowedHashtagsValidator < ActiveModel::Validator
- def validate(status)
- return unless status.local? && !status.reblog?
-
- @status = status
- tags = select_tags
-
- status.errors.add(:text, I18n.t('statuses.disallowed_hashtags', tags: tags.join(', '), count: tags.size)) unless tags.empty?
- end
-
- private
-
- def select_tags
- tags = Extractor.extract_hashtags(@status.text)
- tags.keep_if { |tag| disallowed_hashtags.include? tag.downcase }
- end
-
- def disallowed_hashtags
- return @disallowed_hashtags if @disallowed_hashtags
-
- @disallowed_hashtags = Setting.disallowed_hashtags.nil? ? [] : Setting.disallowed_hashtags
- @disallowed_hashtags = @disallowed_hashtags.split(' ') if @disallowed_hashtags.is_a? String
- @disallowed_hashtags = @disallowed_hashtags.map(&:downcase)
- end
-end
diff --git a/app/views/about/_registration.html.haml b/app/views/about/_registration.html.haml
index 8d7dfd6d..e5b4e2b3 100644
--- a/app/views/about/_registration.html.haml
+++ b/app/views/about/_registration.html.haml
@@ -4,25 +4,14 @@
.fields-group
= f.simple_fields_for :account do |account_fields|
- = account_fields.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username') }, hint: false, disabled: closed_registrations?
+ = account_fields.input :username, wrapper: :with_label, label: false, required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off', placeholder: t('simple_form.labels.defaults.username') }, hint: false
- = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations?
- = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations?
- = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false, disabled: closed_registrations?
-
- - if approved_registrations?
- .fields-group
- = f.simple_fields_for :invite_request do |invite_request_fields|
- = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false
+ = f.input :email, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email'), :autocomplete => 'off' }, hint: false
+ = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password'), :autocomplete => 'off' }, hint: false
+ = f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }, hint: false
.fields-group
- = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', about_tos_path: about_tos_path), disabled: closed_registrations?
+ = f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', about_tos_path: about_tos_path)
.actions
- = f.button :button, sign_up_message, type: :submit, class: 'button button-primary', disabled: closed_registrations?
-
- - if closed_registrations? && @instance_presenter.closed_registrations_message.present?
- .simple_form__overlay-area__overlay
- .simple_form__overlay-area__overlay__content.rich-formatting
- .block-icon= fa_icon 'warning'
- = @instance_presenter.closed_registrations_message.html_safe
+ = f.button :button, t('auth.register'), type: :submit, class: 'button button-primary'
\ No newline at end of file
diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml
deleted file mode 100644
index f37a3839..00000000
--- a/app/views/about/more.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-- content_for :page_title do
- = site_hostname
-
-- content_for :header_tags do
- = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
- = render partial: 'shared/og'
-
-.content
- .box-widget
- .rich-formatting= @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html')
-
- %br
-
- .box-widget
- .rich-formatting
- %h3 Open Source
- %p At Gab, we believe that the future of online publishing is decentralized and open. We believe that users of social networks should be able to control their social media experience on their own terms, rather than the terms set down by Big Tech.
- %p Gab Social is a fresh take on one of the Internet's most popular applications: social networking. Originally forked from the Mastodon project, Gab's codebase is free and open-source, licensed under the GNU Affero General Public License version 3 (AGPL3).
- %p As a result, you, the user, have a choice when using Gab Social: you can either have an account on Gab.com, or, if you don't like what we're doing on Gab.com or simply want to manage your own experience, you can spin up your own Gab Social server that you control, that allows you to communicate with millions of users on their own federated servers from around the world, including users on Gab.
- %p Gab.com strives to be the home of free speech online. We work on Gab Social 100% of the time as our full-time jobs. We positively encourage you to either join us on Gab.com or to spin up your own Gab Social server that you control to help take back control of the Web for the People.
- = link_to "https://code.gab.com/gab/social/gab-social", "https://code.gab.com/gab/social/gab-social"
diff --git a/app/views/accounts/_meta.html.haml b/app/views/accounts/_meta.html.haml
index 02d6dfa6..53a7d15d 100644
--- a/app/views/accounts/_meta.html.haml
+++ b/app/views/accounts/_meta.html.haml
@@ -5,12 +5,8 @@
- if account.user&.setting_noindex
%meta{ name: 'robots', content: 'noindex' }/
- %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) }/
-
= opengraph 'og:type', 'profile'
- = render 'accounts/og', account: account, url: short_account_url(account, only_path: false)
+ = render 'accounts/og', account: account, url: "https://gab.com/#{account.username}"
- if older_url
%link{ rel: 'next', href: older_url }/
diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml
index 6b97c160..0a8f7070 100644
--- a/app/views/accounts/show.html.haml
+++ b/app/views/accounts/show.html.haml
@@ -8,7 +8,7 @@
%data.p-name{ value: "#{@account.username} on #{site_hostname}" }/
.account-section-headline
- = active_link_to t('accounts.posts_tab_heading'), short_account_url(@account)
+ = active_link_to t('accounts.posts_tab_heading'), "/#{account.username}"
= active_link_to t('accounts.posts_with_replies'), short_account_with_replies_url(@account)
= active_link_to t('accounts.media'), short_account_media_url(@account)
@@ -19,12 +19,12 @@
- else
.activity-stream
- 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
diff --git a/app/views/admin/accounts/_account.html.haml b/app/views/admin/accounts/_account.html.haml
index eba3ad80..6fe9863f 100644
--- a/app/views/admin/accounts/_account.html.haml
+++ b/app/views/admin/accounts/_account.html.haml
@@ -12,11 +12,4 @@
- if account.user_current_sign_in_at
%time.time-ago{ datetime: account.user_current_sign_in_at.iso8601, title: l(account.user_current_sign_in_at) }= l account.user_current_sign_in_at
- else
- \-
- %td
- - if account.local? && account.user_pending?
- = table_link_to 'check', t('admin.accounts.approve'), approve_admin_account_path(account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:approve, account.user)
- = 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)
+ \-
\ No newline at end of file
diff --git a/app/views/admin/accounts/index.html.haml b/app/views/admin/accounts/index.html.haml
index 7e9adb3f..8e19419f 100644
--- a/app/views/admin/accounts/index.html.haml
+++ b/app/views/admin/accounts/index.html.haml
@@ -10,7 +10,6 @@
.filter-subset
%strong= t('admin.accounts.moderation.title')
%ul
- %li= link_to safe_join([t('admin.accounts.moderation.pending'), "(#{number_with_delimiter(User.pending.count)})"], ' '), admin_pending_accounts_path
%li= filter_link_to t('admin.accounts.moderation.active'), silenced: nil, suspended: nil, pending: nil
%li= filter_link_to t('admin.accounts.moderation.silenced'), silenced: '1', suspended: nil, pending: nil
%li= filter_link_to t('admin.accounts.moderation.suspended'), suspended: '1', silenced: nil, pending: nil
diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml
index daaf286b..b1b604f9 100644
--- a/app/views/admin/accounts/show.html.haml
+++ b/app/views/admin/accounts/show.html.haml
@@ -122,12 +122,6 @@
- if @account.user_current_sign_in_at
%time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }= l @account.user_current_sign_in_at
- - if @account.user&.invited?
- %tr
- %th= t('admin.accounts.invited_by')
- %td= admin_account_link_to @account.user.invite.user.account
- %td
-
%tr
%th= t('admin.accounts.is_pro')
%td
@@ -177,18 +171,6 @@
- else
= table_link_to '', t('admin.accounts.add_investor_badge'), add_investor_badge_admin_account_path(@account.id), class: 'button', method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:update_badges, @account)
- - else
- %tr
- %th= t('admin.accounts.inbox_url')
- %td
- = @account.inbox_url
- = fa_icon DeliveryFailureTracker.unavailable?(@account.inbox_url) ? 'times' : 'check'
- %tr
- %th= t('admin.accounts.shared_inbox_url')
- %td
- = @account.shared_inbox_url
- = fa_icon DeliveryFailureTracker.unavailable?(@account.shared_inbox_url) ? 'times' : 'check'
-
%div{ style: 'overflow: hidden' }
%div{ style: 'float: right' }
- if @account.local?
@@ -209,10 +191,6 @@
= link_to t('admin.accounts.silence'), new_admin_account_action_path(@account.id, type: 'silence'), class: 'button button--destructive' if can?(:silence, @account)
- if @account.local?
- - if @account.user_pending?
- = link_to t('admin.accounts.approve'), approve_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button' if can?(:approve, @account.user)
- = link_to t('admin.accounts.reject'), reject_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive' if can?(:reject, @account.user)
-
- unless @account.user_confirmed?
= link_to t('admin.accounts.confirm'), admin_account_confirmation_path(@account.id), method: :post, class: 'button' if can?(:confirm, @account.user)
diff --git a/app/views/admin/custom_emojis/_custom_emoji.html.haml b/app/views/admin/custom_emojis/_custom_emoji.html.haml
index fbaa9a17..c33697b2 100644
--- a/app/views/admin/custom_emojis/_custom_emoji.html.haml
+++ b/app/views/admin/custom_emojis/_custom_emoji.html.haml
@@ -14,15 +14,5 @@
= table_link_to 'eye', t('admin.custom_emojis.listed'), admin_custom_emoji_path(custom_emoji, custom_emoji: { visible_in_picker: false }, page: params[:page], **@filter_params), method: :patch
- else
= table_link_to 'eye-slash', t('admin.custom_emojis.unlisted'), admin_custom_emoji_path(custom_emoji, custom_emoji: { visible_in_picker: true }, page: params[:page], **@filter_params), method: :patch
- - else
- - if custom_emoji.local_counterpart.present?
- = link_to safe_join([custom_emoji_tag(custom_emoji.local_counterpart), t('admin.custom_emojis.overwrite')]), copy_admin_custom_emoji_path(custom_emoji, page: params[:page], **@filter_params), method: :post, class: 'table-action-link'
- - else
- = table_link_to 'copy', t('admin.custom_emojis.copy'), copy_admin_custom_emoji_path(custom_emoji, page: params[:page], **@filter_params), method: :post
- %td
- - if custom_emoji.disabled?
- = table_link_to 'power-off', t('admin.custom_emojis.enable'), enable_admin_custom_emoji_path(custom_emoji, page: params[:page], **@filter_params), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }
- - else
- = table_link_to 'power-off', t('admin.custom_emojis.disable'), disable_admin_custom_emoji_path(custom_emoji, page: params[:page], **@filter_params), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }
%td
= table_link_to 'times', t('admin.custom_emojis.delete'), admin_custom_emoji_path(custom_emoji, page: params[:page], **@filter_params), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') }
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 397ca450..44ce4235 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -35,23 +35,6 @@
- @recent_users.each do |user|
%li= admin_account_link_to(user.account)
- .dashboard__widgets__features
- %div
- %h4= t 'admin.dashboard.features'
- %ul
- %li
- = feature_hint(link_to(t('admin.dashboard.feature_registrations'), edit_admin_settings_path), @registrations_enabled)
- %li
- = feature_hint(link_to(t('admin.dashboard.feature_invites'), edit_admin_settings_path), @invites_enabled)
- %li
- = feature_hint(link_to(t('admin.dashboard.feature_deletions'), edit_admin_settings_path), @deletions_enabled)
- %li
- = feature_hint(link_to(t('admin.dashboard.feature_profile_directory'), edit_admin_settings_path), @profile_directory)
- %li
- = feature_hint(link_to(t('admin.dashboard.feature_timeline_preview'), edit_admin_settings_path), @timeline_preview)
- %li
- = feature_hint(link_to(t('admin.dashboard.feature_relay'), admin_relays_path), @relay_enabled)
-
.dashboard__widgets__versions
%div
%h4= t 'admin.dashboard.software'
@@ -98,12 +81,3 @@
= feature_hint('PAM', @pam_enabled)
%li
= feature_hint(t('admin.dashboard.hidden_service'), @hidden_service)
-
- .dashboard__widgets__trends
- %div
- %h4= t 'admin.dashboard.trends'
- %ul
- - @trending_hashtags.each do |tag|
- %li
- = link_to "##{tag.name}", web_url("tags/#{tag.name}")
- %span.pull-right= number_with_delimiter(tag.history[0][:accounts].to_i)
diff --git a/app/views/admin/domain_blocks/new.html.haml b/app/views/admin/domain_blocks/new.html.haml
deleted file mode 100644
index 055d2fbd..00000000
--- a/app/views/admin/domain_blocks/new.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- content_for :header_tags do
- = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
-
-- content_for :page_title do
- = t('.title')
-
-= simple_form_for @domain_block, url: admin_domain_blocks_path do |f|
- = render 'shared/error_messages', object: @domain_block
-
- .fields-row
- .fields-row__column.fields-row__column-6.fields-group
- = f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('.hint'), required: true
-
- .fields-row__column.fields-row__column-6.fields-group
- = f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| t(".severity.#{type}") }, hint: t('.severity.desc_html')
-
- .fields-group
- = f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
-
- .fields-group
- = f.input :reject_reports, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_reports'), hint: I18n.t('admin.domain_blocks.reject_reports_hint')
-
- .actions
- = f.button :button, t('.create'), type: :submit
diff --git a/app/views/admin/domain_blocks/show.html.haml b/app/views/admin/domain_blocks/show.html.haml
deleted file mode 100644
index dca4dbac..00000000
--- a/app/views/admin/domain_blocks/show.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- content_for :page_title do
- = t('admin.domain_blocks.show.title', domain: @domain_block.domain)
-
-= simple_form_for @domain_block, url: admin_domain_block_path(@domain_block), method: :delete do |f|
-
- - unless (@domain_block.noop?)
- %p= t(".retroactive.#{@domain_block.severity}")
- %p.hint= t(:affected_accounts,
- scope: [:admin, :domain_blocks, :show],
- count: @domain_block.affected_accounts_count)
-
- .actions
- = f.button :button, t('.undo'), type: :submit
diff --git a/app/views/admin/instances/index.html.haml b/app/views/admin/instances/index.html.haml
deleted file mode 100644
index 9574c314..00000000
--- a/app/views/admin/instances/index.html.haml
+++ /dev/null
@@ -1,53 +0,0 @@
-- content_for :page_title do
- = t('admin.instances.title')
-
-.filters
- .filter-subset
- %strong= t('admin.instances.moderation.title')
- %ul
- %li= filter_link_to t('admin.instances.moderation.all'), limited: nil
- %li= filter_link_to t('admin.instances.moderation.limited'), limited: '1'
-
- %div{ style: 'flex: 1 1 auto; text-align: right' }
- = link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path, class: 'button'
-
-= form_tag admin_instances_url, method: 'GET', class: 'simple_form' do
- .fields-group
- - Admin::FilterHelper::INSTANCES_FILTERS.each do |key|
- - if params[key].present?
- = hidden_field_tag key, params[key]
-
- - %i(by_domain).each do |key|
- .input.string.optional
- = text_field_tag key, params[key], class: 'string optional', placeholder: I18n.t("admin.instances.#{key}")
-
- .actions
- %button= t('admin.accounts.search')
- = link_to t('admin.accounts.reset'), admin_instances_path, class: 'button negative'
-
-%hr.spacer/
-
-- @instances.each do |instance|
- .directory__tag
- = link_to admin_instance_path(instance) do
- %h4
- = instance.domain
- %small
- = t('admin.instances.known_accounts', count: instance.cached_accounts_count)
-
- - if instance.domain_block
- - if !instance.domain_block.noop?
- •
- = t("admin.domain_blocks.severity.#{instance.domain_block.severity}")
- - if instance.domain_block.reject_media?
- •
- = t('admin.domain_blocks.rejecting_media')
- - if instance.domain_block.reject_reports?
- •
- = t('admin.domain_blocks.rejecting_reports')
-
- .avatar-stack
- - instance.cached_sample_accounts.each do |account|
- = image_tag current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url, width: 48, height: 48, alt: '', class: 'account__avatar'
-
-= paginate paginated_instances
diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml
deleted file mode 100644
index c7992a49..00000000
--- a/app/views/admin/instances/show.html.haml
+++ /dev/null
@@ -1,44 +0,0 @@
-- content_for :page_title do
- = @instance.domain
-
-.dashboard__counters
- %div
- %div
- .dashboard__counters__num= number_with_delimiter @following_count
- .dashboard__counters__label= t 'admin.instances.total_followed_by_them'
- %div
- %div
- .dashboard__counters__num= number_with_delimiter @followers_count
- .dashboard__counters__label= t 'admin.instances.total_followed_by_us'
- %div
- %div
- .dashboard__counters__num= number_to_human_size @media_storage
- .dashboard__counters__label= t 'admin.instances.total_storage'
- %div
- %div
- .dashboard__counters__num= number_with_delimiter @blocks_count
- .dashboard__counters__label= t 'admin.instances.total_blocked_by_us'
- %div
- %div
- .dashboard__counters__num= number_with_delimiter @reports_count
- .dashboard__counters__label= t 'admin.instances.total_reported'
- %div
- %div
- .dashboard__counters__num
- - if @available
- = fa_icon 'check'
- - else
- = fa_icon 'times'
- .dashboard__counters__label= t 'admin.instances.delivery_available'
-
-%hr.spacer/
-
-%div{ style: 'overflow: hidden' }
- %div{ style: 'float: left' }
- = link_to t('admin.accounts.title'), admin_accounts_path(remote: '1', by_domain: @instance.domain), class: 'button'
-
- %div{ style: 'float: right' }
- - if @domain_block
- = link_to t('admin.domain_blocks.undo'), admin_domain_block_path(@domain_block), class: 'button'
- - else
- = link_to t('admin.domain_blocks.add_new'), new_admin_domain_block_path(_domain: @instance.domain), class: 'button'
diff --git a/app/views/admin/invites/_invite.html.haml b/app/views/admin/invites/_invite.html.haml
deleted file mode 100644
index e6ad9de3..00000000
--- a/app/views/admin/invites/_invite.html.haml
+++ /dev/null
@@ -1,30 +0,0 @@
-%tr
- %td
- .input-copy
- .input-copy__wrapper
- %input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: public_invite_url(invite_code: invite.code) }
- %button{ type: :button }= t('generic.copy')
-
- %td
- .name-tag
- = image_tag invite.user.account.avatar.url(:original), alt: '', width: 16, height: 16, class: 'avatar'
- %span.username= invite.user.account.username
-
- - if invite.valid_for_use?
- %td
- = fa_icon 'user fw'
- = invite.uses
- = " / #{invite.max_uses}" unless invite.max_uses.nil?
- %td
- - if invite.expires_at.nil?
- ∞
- - else
- %time.formatted{ datetime: invite.expires_at.iso8601, title: l(invite.expires_at) }
- = l invite.expires_at
- - else
- %td{ colspan: 2 }
- = t('invites.expired')
-
- %td
- - if invite.valid_for_use? && policy(invite).destroy?
- = table_link_to 'times', t('invites.delete'), admin_invite_path(invite), method: :delete
diff --git a/app/views/admin/invites/index.html.haml b/app/views/admin/invites/index.html.haml
deleted file mode 100644
index ee6ba0f5..00000000
--- a/app/views/admin/invites/index.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-- content_for :page_title do
- = t('admin.invites.title')
-
-.filters
- .filter-subset
- %strong= t('admin.invites.filter.title')
- %ul
- %li= filter_link_to t('admin.invites.filter.all'), available: nil, expired: nil
- %li= filter_link_to t('admin.invites.filter.available'), available: 1, expired: nil
- %li= filter_link_to t('admin.invites.filter.expired'), available: nil, expired: 1
-
-%hr.spacer/
-
-- if policy(:invite).create?
- %p= t('invites.prompt')
-
- = render 'invites/form'
-
- %hr.spacer/
-
-.table-wrapper.simple_form
- %table.table.table--invites
- %thead
- %tr
- %th
- %th
- %th= t('invites.table.uses')
- %th= t('invites.table.expires_at')
- %th
- %tbody
- = render @invites
-
-= paginate @invites
-
-- if policy(:invite).deactivate_all?
- = link_to t('admin.invites.deactivate_all'), deactivate_all_admin_invites_path, method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button'
diff --git a/app/views/admin/pending_accounts/_account.html.haml b/app/views/admin/pending_accounts/_account.html.haml
deleted file mode 100644
index 1ed5dafd..00000000
--- a/app/views/admin/pending_accounts/_account.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-.batch-table__row
- %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox
- = f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id
- .batch-table__row__content.pending-account
- .pending-account__header
- = link_to admin_account_path(account.id) do
- %strong= account.user_email
- = "(@#{account.username})"
- %br/
- = account.user_current_sign_in_ip
-
- - if account.user&.invite_request&.text&.present?
- .pending-account__body
- %p= account.user&.invite_request&.text
diff --git a/app/views/admin/pending_accounts/index.html.haml b/app/views/admin/pending_accounts/index.html.haml
deleted file mode 100644
index 7ce5b821..00000000
--- a/app/views/admin/pending_accounts/index.html.haml
+++ /dev/null
@@ -1,33 +0,0 @@
-- content_for :page_title do
- = t('admin.pending_accounts.title', count: User.pending.count)
-
-- content_for :header_tags do
- = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
-
-= form_for(@form, url: batch_admin_pending_accounts_path) do |f|
- = hidden_field_tag :page, params[:page] || 1
-
- .batch-table
- .batch-table__toolbar
- %label.batch-table__toolbar__select.batch-checkbox-all
- = check_box_tag :batch_checkbox_all, nil, false
- .batch-table__toolbar__actions
- = f.button safe_join([fa_icon('check'), t('admin.accounts.approve')]), name: :approve, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
-
- = f.button safe_join([fa_icon('times'), t('admin.accounts.reject')]), name: :reject, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') }
- .batch-table__body
- - if @accounts.empty?
- = nothing_here 'nothing-here--under-tabs'
- - else
- = render partial: 'account', collection: @accounts, locals: { f: f }
-
-= paginate @accounts
-
-%hr.spacer/
-
-%div{ style: 'overflow: hidden' }
- %div{ style: 'float: right' }
- = link_to t('admin.accounts.reject_all'), reject_all_admin_pending_accounts_path, method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button button--destructive'
-
- %div
- = link_to t('admin.accounts.approve_all'), approve_all_admin_pending_accounts_path, method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button'
diff --git a/app/views/admin/relays/_relay.html.haml b/app/views/admin/relays/_relay.html.haml
deleted file mode 100644
index 66782189..00000000
--- a/app/views/admin/relays/_relay.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-%tr
- %td
- %samp= relay.inbox_url
- %td
- - if relay.accepted?
- %span.positive-hint
- = fa_icon('check')
- = ' '
- = t 'admin.relays.enabled'
- - elsif relay.pending?
- = fa_icon('hourglass')
- = ' '
- = t 'admin.relays.pending'
- - else
- %span.negative-hint
- = fa_icon('times')
- = ' '
- = t 'admin.relays.disabled'
- %td
- - if relay.accepted?
- = table_link_to 'power-off', t('admin.relays.disable'), disable_admin_relay_path(relay), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }
- - elsif !relay.pending?
- = table_link_to 'power-off', t('admin.relays.enable'), enable_admin_relay_path(relay), method: :post, data: { confirm: t('admin.accounts.are_you_sure') }
-
- = table_link_to 'times', t('admin.relays.delete'), admin_relay_path(relay), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') }
diff --git a/app/views/admin/relays/index.html.haml b/app/views/admin/relays/index.html.haml
deleted file mode 100644
index 1636a53f..00000000
--- a/app/views/admin/relays/index.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- content_for :page_title do
- = t('admin.relays.title')
-
-.simple_form
- %p.hint= t('admin.relays.description_html')
- = link_to @relays.empty? ? t('admin.relays.setup') : t('admin.relays.add_new'), new_admin_relay_path, class: 'block-button'
-
-- unless @relays.empty?
- %hr.spacer
-
- .table-wrapper
- %table.table
- %thead
- %tr
- %th= t('admin.relays.inbox_url')
- %th= t('admin.relays.status')
- %th
- %tbody
- = render @relays
-
diff --git a/app/views/admin/relays/new.html.haml b/app/views/admin/relays/new.html.haml
deleted file mode 100644
index 126794ac..00000000
--- a/app/views/admin/relays/new.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- content_for :page_title do
- = t('admin.relays.add_new')
-
-= simple_form_for @relay, url: admin_relays_path do |f|
- = render 'shared/error_messages', object: @relay
-
- .field-group
- = f.input :inbox_url, as: :string, wrapper: :with_block_label
-
- .actions
- = f.button :button, t('admin.relays.save_and_enable'), type: :submit
-
- %p.hint.subtle-hint= t('admin.relays.enable_hint')
diff --git a/app/views/admin/settings/edit.html.haml b/app/views/admin/settings/edit.html.haml
index 912b9c61..3efae021 100644
--- a/app/views/admin/settings/edit.html.haml
+++ b/app/views/admin/settings/edit.html.haml
@@ -26,12 +26,6 @@
.fields-row
.fields-row__column.fields-row__column-6.fields-group
= f.input :thumbnail, as: :file, wrapper: :with_block_label, label: t('admin.settings.thumbnail.title'), hint: t('admin.settings.thumbnail.desc_html')
- .fields-row__column.fields-row__column-6.fields-group
- = f.input :hero, as: :file, wrapper: :with_block_label, label: t('admin.settings.hero.title'), hint: t('admin.settings.hero.desc_html')
-
- .fields-row
- .fields-row__column.fields-row__column-6.fields-group
- = f.input :mascot, as: :file, wrapper: :with_block_label, label: t('admin.settings.mascot.title'), hint: t('admin.settings.mascot.desc_html')
%hr.spacer/
@@ -40,39 +34,13 @@
%hr.spacer/
- .fields-group
- = f.input :timeline_preview, as: :boolean, wrapper: :with_label, label: t('admin.settings.timeline_preview.title'), hint: t('admin.settings.timeline_preview.desc_html')
-
- .fields-group
- = f.input :show_known_fediverse_at_about_page, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_known_fediverse_at_about_page.title'), hint: t('admin.settings.show_known_fediverse_at_about_page.desc_html')
-
- .fields-group
- = f.input :show_staff_badge, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_staff_badge.title'), hint: t('admin.settings.show_staff_badge.desc_html')
-
- .fields-group
- = f.input :open_deletion, as: :boolean, wrapper: :with_label, label: t('admin.settings.registrations.deletion.title'), hint: t('admin.settings.registrations.deletion.desc_html')
-
- .fields-group
- = f.input :activity_api_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.activity_api_enabled.title'), hint: t('admin.settings.activity_api_enabled.desc_html')
-
- .fields-group
- = f.input :peers_api_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.peers_api_enabled.title'), hint: t('admin.settings.peers_api_enabled.desc_html')
-
.fields-group
= f.input :preview_sensitive_media, as: :boolean, wrapper: :with_label, label: t('admin.settings.preview_sensitive_media.title'), hint: t('admin.settings.preview_sensitive_media.desc_html')
- .fields-group
- = f.input :profile_directory, as: :boolean, wrapper: :with_label, label: t('admin.settings.profile_directory.title'), hint: t('admin.settings.profile_directory.desc_html')
-
%hr.spacer/
.fields-group
= f.input :min_invite_role, wrapper: :with_label, collection: %i(disabled user moderator admin), label: t('admin.settings.registrations.min_invite_role.title'), label_method: lambda { |role| role == :disabled ? t('admin.settings.registrations.min_invite_role.disabled') : t("admin.accounts.roles.#{role}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
- .fields-group
- = f.input :closed_registrations_message, as: :text, wrapper: :with_block_label, label: t('admin.settings.registrations.closed_message.title'), hint: t('admin.settings.registrations.closed_message.desc_html'), input_html: { rows: 8 }
- = f.input :site_extended_description, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_description_extended.title'), hint: t('admin.settings.site_description_extended.desc_html'), input_html: { rows: 8 }
- = f.input :site_terms, wrapper: :with_block_label, as: :text, label: t('admin.settings.site_terms.title'), hint: t('admin.settings.site_terms.desc_html'), input_html: { rows: 8 }
-
.actions
= f.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/admin/subscriptions/_subscription.html.haml b/app/views/admin/subscriptions/_subscription.html.haml
deleted file mode 100644
index 1dec8e39..00000000
--- a/app/views/admin/subscriptions/_subscription.html.haml
+++ /dev/null
@@ -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
diff --git a/app/views/admin/subscriptions/index.html.haml b/app/views/admin/subscriptions/index.html.haml
deleted file mode 100644
index 83704c8e..00000000
--- a/app/views/admin/subscriptions/index.html.haml
+++ /dev/null
@@ -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
diff --git a/app/views/admin/tags/_tag.html.haml b/app/views/admin/tags/_tag.html.haml
deleted file mode 100644
index 961b83f9..00000000
--- a/app/views/admin/tags/_tag.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-%tr
- %td
- = link_to explore_hashtag_path(tag) do
- = fa_icon 'hashtag'
- = tag.name
- %td
- = t('directories.people', count: tag.accounts_count)
- %td
- - if tag.hidden?
- = table_link_to 'eye', t('admin.tags.unhide'), unhide_admin_tag_path(tag.id, **@filter_params), method: :post
- - else
- = table_link_to 'eye-slash', t('admin.tags.hide'), hide_admin_tag_path(tag.id, **@filter_params), method: :post
diff --git a/app/views/admin/tags/index.html.haml b/app/views/admin/tags/index.html.haml
deleted file mode 100644
index 4ba39586..00000000
--- a/app/views/admin/tags/index.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-- content_for :page_title do
- = t('admin.tags.title')
-
-.filters
- .filter-subset
- %strong= t('admin.reports.status')
- %ul
- %li= filter_link_to t('admin.tags.visible'), hidden: nil
- %li= filter_link_to t('admin.tags.hidden'), hidden: '1'
-
-.table-wrapper
- %table.table
- %thead
- %tr
- %th= t('admin.tags.name')
- %th= t('admin.tags.accounts')
- %th
- %tbody
- = render @tags
diff --git a/app/views/admin_mailer/new_pending_account.text.erb b/app/views/admin_mailer/new_pending_account.text.erb
deleted file mode 100644
index a466ee2d..00000000
--- a/app/views/admin_mailer/new_pending_account.text.erb
+++ /dev/null
@@ -1,12 +0,0 @@
-<%= raw t('application_mailer.salutation', name: display_name(@me)) %>
-
-<%= raw t('admin_mailer.new_pending_account.body') %>
-
-<%= @account.user_email %> (@<%= @account.username %>)
-<%= @account.user_current_sign_in_ip %>
-<% if @account.user&.invite_request&.text.present? %>
-
-<%= quote_wrap(@account.user&.invite_request&.text) %>
-<% end %>
-
-<%= raw t('application_mailer.view')%> <%= admin_pending_accounts_url %>
diff --git a/app/views/auth/registrations/edit.html.haml b/app/views/auth/registrations/edit.html.haml
index 694461fd..387d8548 100644
--- a/app/views/auth/registrations/edit.html.haml
+++ b/app/views/auth/registrations/edit.html.haml
@@ -27,7 +27,7 @@
= render 'sessions'
-- if open_deletion?
- %hr.spacer/
- %h4= t('auth.delete_account')
- %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path)
+
+%hr.spacer/
+%h4= t('auth.delete_account')
+%p.muted-hint= t('auth.delete_account_html', path: settings_delete_path)
diff --git a/app/views/auth/registrations/new.html.haml b/app/views/auth/registrations/new.html.haml
index 1919d080..54842686 100644
--- a/app/views/auth/registrations/new.html.haml
+++ b/app/views/auth/registrations/new.html.haml
@@ -9,11 +9,6 @@
= render 'shared/error_messages', object: resource
- - if @invite.present? && @invite.autofollow?
- .fields-group{ style: 'margin-bottom: 30px' }
- %p.hint{ style: 'text-align: center' }= t('invites.invited_by')
- = render 'application/card', account: @invite.user.account
-
= f.simple_fields_for :account do |ff|
.fields-group
= ff.input :username, wrapper: :with_label, autofocus: true, label: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' }, hint: t('simple_form.hints.defaults.username', domain: site_hostname)
@@ -27,13 +22,6 @@
.fields-group
= f.input :password_confirmation, wrapper: :with_label, label: t('simple_form.labels.defaults.confirm_password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_password'), :autocomplete => 'off' }
- - if approved_registrations? && !@invite.present?
- .fields-group
- = f.simple_fields_for :invite_request do |invite_request_fields|
- = invite_request_fields.input :text, as: :text, wrapper: :with_block_label, required: false
-
- = f.input :invite_code, as: :hidden
-
.fields-group
= f.input :challenge, wrapper: :with_label, label: "Are you human? What is #{@challenge_add_1} + #{@challenge_add_2} = ", required: true, input_html: { 'aria-label' => "Are you human? What is #{@challenge_add_1} + #{@challenge_add_2}", :autocomplete => 'off' }
@@ -41,6 +29,6 @@
= f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', about_tos_path: about_tos_path)
.actions
- = f.button :button, @invite.present? ? t('auth.register') : sign_up_message, type: :submit
+ = f.button :button, t('auth.register'), type: :submit
.form-footer= render 'auth/shared/links'
diff --git a/app/views/auth/sessions/new.html.haml b/app/views/auth/sessions/new.html.haml
index 9c00e80b..3b470ae0 100644
--- a/app/views/auth/sessions/new.html.haml
+++ b/app/views/auth/sessions/new.html.haml
@@ -18,13 +18,4 @@
.actions
= f.button :button, t('auth.login'), type: :submit
-- if devise_mapping.omniauthable? and resource_class.omniauth_providers.any?
- .simple_form.alternative-login
- %h4= t('auth.or_log_in_with')
-
- .actions
- - resource_class.omniauth_providers.each do |provider|
- = link_to omniauth_authorize_path(resource_name, provider), class: "button button-#{provider}" do
- = t("auth.providers.#{provider}", default: provider.to_s.chomp("_oauth2").capitalize)
-
.form-footer= render 'auth/shared/links'
diff --git a/app/views/authorize_interactions/_post_follow_actions.html.haml b/app/views/authorize_interactions/_post_follow_actions.html.haml
deleted file mode 100644
index 561c6013..00000000
--- a/app/views/authorize_interactions/_post_follow_actions.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-.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= t('authorize_follow.post_follow.close')
diff --git a/app/views/authorize_interactions/error.html.haml b/app/views/authorize_interactions/error.html.haml
deleted file mode 100644
index 88d33b68..00000000
--- a/app/views/authorize_interactions/error.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.form-container
- .flash-message#error_explanation
- = t('authorize_follow.error')
diff --git a/app/views/authorize_interactions/show.html.haml b/app/views/authorize_interactions/show.html.haml
deleted file mode 100644
index 7ca9b98c..00000000
--- a/app/views/authorize_interactions/show.html.haml
+++ /dev/null
@@ -1,18 +0,0 @@
-- content_for :page_title do
- = t('authorize_follow.title', acct: @resource.acct)
-
-.form-container
- .follow-prompt
- = render 'application/card', account: @resource
-
- - if current_account.following?(@resource)
- .flash-message
- %strong
- = t('authorize_follow.already_following')
-
- = render 'post_follow_actions'
- - else
- = form_tag authorize_interaction_path, method: :post, class: 'simple_form' do
- = hidden_field_tag :action, :follow
- = hidden_field_tag :acct, @resource.acct
- = button_tag t('authorize_follow.follow'), type: :submit
diff --git a/app/views/authorize_interactions/success.html.haml b/app/views/authorize_interactions/success.html.haml
deleted file mode 100644
index 47fd0976..00000000
--- a/app/views/authorize_interactions/success.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- content_for :page_title do
- = t('authorize_follow.title', acct: @resource.acct)
-
-.form-container
- .follow-prompt
- - if @resource.locked?
- %h2= t('authorize_follow.follow_request')
- - else
- %h2= t('authorize_follow.following')
-
- = render 'application/card', account: @resource
-
- = render 'post_follow_actions'
diff --git a/app/views/directories/index.html.haml b/app/views/directories/index.html.haml
deleted file mode 100644
index da08d74d..00000000
--- a/app/views/directories/index.html.haml
+++ /dev/null
@@ -1,71 +0,0 @@
-- content_for :page_title do
- = t('directories.explore_gabsocial', title: site_title)
-
-- content_for :header_tags do
- %meta{ name: 'description', content: t('directories.explanation') }
-
- = opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname)
- = opengraph 'og:type', 'website'
- = opengraph 'og:title', t('directories.explore_gabsocial', title: site_title)
- = opengraph 'og:description', t('directories.explanation')
- = opengraph 'og:image', File.join(root_url, 'android-chrome-192x192.png')
-
-.page-header
- %h1= t('directories.explore_gabsocial', title: site_title)
- %p= t('directories.explanation')
-
-.grid
- .column-0
- - if @accounts.empty?
- = nothing_here
- - else
- .directory
- %table.accounts-table
- %tbody
- - @accounts.each do |account|
- %tr
- %td= account_link_to account
- %td.accounts-table__count.optional
- = number_to_human account.statuses_count, strip_insignificant_zeros: true
- %small= t('accounts.posts', count: account.statuses_count).downcase
- %td.accounts-table__count.optional
- = number_to_human account.followers_count, strip_insignificant_zeros: true
- %small= t('accounts.followers', count: account.followers_count).downcase
- %td.accounts-table__count
- - if account.last_status_at.present?
- %time.time-ago{ datetime: account.last_status_at.iso8601, title: l(account.last_status_at) }= l account.last_status_at
- - else
- \-
- %small= t('accounts.last_active')
-
- = paginate @accounts
-
- .column-1
- - if user_signed_in?
- .box-widget.notice-widget
- - if current_account.discoverable?
- - if current_account.followers_count < Account::MIN_FOLLOWERS_DISCOVERY
- %p= t('directories.enabled_but_waiting', min_followers: Account::MIN_FOLLOWERS_DISCOVERY)
- - else
- %p= t('directories.enabled')
- - else
- %p= t('directories.how_to_enable')
-
- = link_to settings_profile_path do
- = t('settings.edit_profile')
- = fa_icon 'chevron-right fw'
-
- - if @tags.empty? && !user_signed_in?
- .nothing-here
- - else
- - @tags.each do |tag|
- .directory__tag{ class: tag.id == @tag&.id ? 'active' : nil }
- = link_to explore_hashtag_path(tag) do
- %h4
- = fa_icon 'hashtag'
- = tag.name
- %small= t('directories.people', count: tag.accounts_count)
-
- .avatar-stack
- - tag.cached_sample_accounts.each do |account|
- = image_tag current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url, width: 48, height: 48, alt: '', class: 'account__avatar'
diff --git a/app/views/follower_accounts/index.html.haml b/app/views/follower_accounts/index.html.haml
deleted file mode 100644
index 645dd2de..00000000
--- a/app/views/follower_accounts/index.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- content_for :page_title do
- = t('accounts.people_who_follow', name: display_name(@account))
-
-- content_for :header_tags do
- %meta{ name: 'robots', content: 'noindex' }/
- = render 'accounts/og', account: @account, url: account_followers_url(@account, only_path: false)
-
-= render 'accounts/header', account: @account
-
-- if @account.user_hides_network?
- .nothing-here= t('accounts.network_hidden')
-- elsif user_signed_in? && @account.blocking?(current_account)
- .nothing-here= t('accounts.unavailable')
-- elsif @follows.empty?
- = nothing_here
-- else
- .card-grid
- = render partial: 'application/card', collection: @follows.map(&:account), as: :account
-
- = paginate @follows
diff --git a/app/views/following_accounts/index.html.haml b/app/views/following_accounts/index.html.haml
deleted file mode 100644
index 17fe7901..00000000
--- a/app/views/following_accounts/index.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- content_for :page_title do
- = t('accounts.people_followed_by', name: display_name(@account))
-
-- content_for :header_tags do
- %meta{ name: 'robots', content: 'noindex' }/
- = render 'accounts/og', account: @account, url: account_followers_url(@account, only_path: false)
-
-= render 'accounts/header', account: @account
-
-- if @account.user_hides_network?
- .nothing-here= t('accounts.network_hidden')
-- elsif user_signed_in? && @account.blocking?(current_account)
- .nothing-here= t('accounts.unavailable')
-- elsif @follows.empty?
- = nothing_here
-- else
- .card-grid
- = render partial: 'application/card', collection: @follows.map(&:target_account), as: :account
-
- = paginate @follows
diff --git a/app/views/invites/_form.html.haml b/app/views/invites/_form.html.haml
deleted file mode 100644
index 3a2a5ef0..00000000
--- a/app/views/invites/_form.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-= simple_form_for(@invite, url: controller.is_a?(Admin::InvitesController) ? admin_invites_path : invites_path) do |f|
- = render 'shared/error_messages', object: @invite
-
- .fields-row
- .fields-row__column.fields-row__column-6.fields-group
- = f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: lambda { |num| I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt')
- .fields-row__column.fields-row__column-6.fields-group
- = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
-
- .fields-group
- = f.input :autofollow, wrapper: :with_label
-
- .actions
- = f.button :button, t('invites.generate'), type: :submit
diff --git a/app/views/invites/_invite.html.haml b/app/views/invites/_invite.html.haml
deleted file mode 100644
index 62799ca5..00000000
--- a/app/views/invites/_invite.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-%tr
- %td
- .input-copy
- .input-copy__wrapper
- %input{ type: :text, maxlength: '999', spellcheck: 'false', readonly: 'true', value: public_invite_url(invite_code: invite.code) }
- %button{ type: :button }= t('generic.copy')
-
- - if invite.valid_for_use?
- %td
- = fa_icon 'user fw'
- = invite.uses
- = " / #{invite.max_uses}" unless invite.max_uses.nil?
- %td
- - if invite.expires_at.nil?
- ∞
- - else
- %time.formatted{ datetime: invite.expires_at.iso8601, title: l(invite.expires_at) }
- = l invite.expires_at
- - else
- %td{ colspan: 2 }
- = t('invites.expired')
-
- %td
- - if invite.valid_for_use? && policy(invite).destroy?
- = table_link_to 'times', t('invites.delete'), invite_path(invite), method: :delete
diff --git a/app/views/invites/index.html.haml b/app/views/invites/index.html.haml
deleted file mode 100644
index 61420ab1..00000000
--- a/app/views/invites/index.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- content_for :page_title do
- = t('invites.title')
-
-- if policy(:invite).create?
- %p= t('invites.prompt')
-
- = render 'form'
-
- %hr.spacer/
-
-.simple_form
- %table.table.table--invites
- %thead
- %tr
- %th
- %th= t('invites.table.uses')
- %th= t('invites.table.expires_at')
- %th
- %tbody
- = render @invites
diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml
index d93cb74f..a7802991 100644
--- a/app/views/layouts/admin.html.haml
+++ b/app/views/layouts/admin.html.haml
@@ -7,8 +7,6 @@
.admin-wrapper
.sidebar-wrapper
.sidebar
- -# = link_to root_path do
- -# homehack
= link_to '/home' do
= image_pack_tag 'logo.png', class: 'logo', alt: 'Gab Social'
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 0329102f..2d93a4f7 100755
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -32,8 +32,8 @@
%meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/
%meta{ name: 'apple-mobile-web-app-status-bar-style', content: 'black-translucent' }/
- - if @stream_entry && @account
- = render 'stream_entries/meta', stream_entry: @stream_entry, account: @account
+ - if @status && @account
+ = render 'statuses/meta', status: @status, account: @account
- elsif @account && @account.local?
= render 'accounts/meta', account: @account, older_url: nil, newer_url: nil
- elsif @group
diff --git a/app/views/public_timelines/show.html.haml b/app/views/public_timelines/show.html.haml
deleted file mode 100644
index 809ecad9..00000000
--- a/app/views/public_timelines/show.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- content_for :page_title do
- = t('about.see_whats_happening')
-
-- content_for :header_tags do
- %meta{ name: 'robots', content: 'noindex' }/
- %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
-
-.page-header
- %h1= t('about.see_whats_happening')
- %p= t('about.browse_public_posts')
-
-#gabsocial-timeline{ data: { props: Oj.dump(default_props) }}
-#modal-container
diff --git a/app/views/relationships/_account.html.haml b/app/views/relationships/_account.html.haml
deleted file mode 100644
index 6c22deb5..00000000
--- a/app/views/relationships/_account.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-.batch-table__row
- %label.batch-table__row__select.batch-table__row__select--aligned.batch-checkbox
- = f.check_box :account_ids, { multiple: true, include_hidden: false }, account.id
- .batch-table__row__content.batch-table__row__content--unpadded
- %table.accounts-table
- %tbody
- %tr
- %td= account_link_to account
- %td.accounts-table__count.optional
- = number_to_human account.statuses_count, strip_insignificant_zeros: true
- %small= t('accounts.posts', count: account.statuses_count).downcase
- %td.accounts-table__count.optional
- = number_to_human account.followers_count, strip_insignificant_zeros: true
- %small= t('accounts.followers', count: account.followers_count).downcase
- %td.accounts-table__count
- - if account.last_status_at.present?
- %time.time-ago{ datetime: account.last_status_at.iso8601, title: l(account.last_status_at) }= l account.last_status_at
- - else
- \-
- %small= t('accounts.last_active')
diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml
deleted file mode 100644
index e6fff0ad..00000000
--- a/app/views/relationships/show.html.haml
+++ /dev/null
@@ -1,57 +0,0 @@
-- content_for :page_title do
- = t('settings.relationships')
-
-- content_for :header_tags do
- = javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'
-
-.filters
- .filter-subset
- %strong= t 'relationships.relationship'
- %ul
- %li= filter_link_to t('accounts.following', count: current_account.following_count), relationship: nil
- %li= filter_link_to t('accounts.followers', count: current_account.followers_count), relationship: 'followed_by'
- %li= filter_link_to t('relationships.mutual'), relationship: 'mutual'
-
- .filter-subset
- %strong= t 'relationships.status'
- %ul
- %li= filter_link_to t('generic.all'), status: nil
- %li= filter_link_to t('relationships.primary'), status: 'primary'
- %li= filter_link_to t('relationships.moved'), status: 'moved'
-
- .filter-subset
- %strong= t 'relationships.activity'
- %ul
- %li= filter_link_to t('generic.all'), activity: nil
- %li= filter_link_to t('relationships.dormant'), activity: 'dormant'
-
- .filter-subset
- %strong= t 'generic.order_by'
- %ul
- %li= filter_link_to t('relationships.most_recent'), order: nil
- %li= filter_link_to t('relationships.last_active'), order: 'active'
-
-= form_for(@form, url: relationships_path, method: :patch) do |f|
- = hidden_field_tag :page, params[:page] || 1
- = hidden_field_tag :relationship, params[:relationship]
- = hidden_field_tag :status, params[:status]
- = hidden_field_tag :activity, params[:activity]
- = hidden_field_tag :order, params[:order]
-
- .batch-table
- .batch-table__toolbar
- %label.batch-table__toolbar__select.batch-checkbox-all
- = check_box_tag :batch_checkbox_all, nil, false
- .batch-table__toolbar__actions
- = f.button safe_join([fa_icon('user-times'), t('relationships.remove_selected_follows')]), name: :unfollow, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless followed_by_relationship?
-
- = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_followers')]), name: :remove_from_followers, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } unless following_relationship?
-
- = f.button safe_join([fa_icon('trash'), t('relationships.remove_selected_domains')]), name: :block_domains, class: 'table-action-link', type: :submit, data: { confirm: t('admin.reports.are_you_sure') } if followed_by_relationship?
- .batch-table__body
- - if @accounts.empty?
- = nothing_here 'nothing-here--under-tabs'
- - else
- = render partial: 'account', collection: @accounts, locals: { f: f }
-
-= paginate @accounts
diff --git a/app/views/remote_follow/new.html.haml b/app/views/remote_follow/new.html.haml
deleted file mode 100644
index 4e9601f6..00000000
--- a/app/views/remote_follow/new.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- content_for :header_tags do
- %meta{ name: 'robots', content: 'noindex' }/
-
-.form-container
- .follow-prompt
- %h2= t('remote_follow.prompt')
-
- = render partial: 'application/card', locals: { account: @account }
-
- = simple_form_for @remote_follow, as: :remote_follow, url: account_remote_follow_path(@account) do |f|
- = render 'shared/error_messages', object: @remote_follow
-
- = f.input :acct, placeholder: t('remote_follow.acct'), input_html: { autocapitalize: 'none', autocorrect: 'off' }
-
- .actions
- = f.button :button, t('remote_follow.proceed'), type: :submit
-
- %p.hint.subtle-hint
- = t('remote_follow.reason_html', instance: site_hostname)
- = t('remote_follow.no_account_html', sign_up_path: available_sign_up_path)
diff --git a/app/views/remote_interaction/new.html.haml b/app/views/remote_interaction/new.html.haml
deleted file mode 100644
index c8c08991..00000000
--- a/app/views/remote_interaction/new.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- content_for :header_tags do
- %meta{ name: 'robots', content: 'noindex' }/
-
-.form-container
- .follow-prompt
- %h2= t("remote_interaction.#{@interaction_type}.prompt")
-
- .public-layout
- .activity-stream.activity-stream--highlighted
- = render 'stream_entries/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
-
- = hidden_field_tag :type, @interaction_type
-
- = f.input :acct, placeholder: t('remote_follow.acct'), input_html: { autocapitalize: 'none', autocorrect: 'off' }
-
- .actions
- = f.button :button, t("remote_interaction.#{@interaction_type}.proceed"), type: :submit
-
- %p.hint.subtle-hint
- = t('remote_follow.reason_html', instance: site_hostname)
- = t('remote_follow.no_account_html', sign_up_path: available_sign_up_path)
diff --git a/app/views/remote_unfollows/_card.html.haml b/app/views/remote_unfollows/_card.html.haml
deleted file mode 100644
index 9abcfd37..00000000
--- a/app/views/remote_unfollows/_card.html.haml
+++ /dev/null
@@ -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)
diff --git a/app/views/remote_unfollows/_post_follow_actions.html.haml b/app/views/remote_unfollows/_post_follow_actions.html.haml
deleted file mode 100644
index 2a9c062e..00000000
--- a/app/views/remote_unfollows/_post_follow_actions.html.haml
+++ /dev/null
@@ -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')
diff --git a/app/views/remote_unfollows/error.html.haml b/app/views/remote_unfollows/error.html.haml
deleted file mode 100644
index cb63f02b..00000000
--- a/app/views/remote_unfollows/error.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.form-container
- .flash-message#error_explanation
- = t('remote_unfollow.error')
diff --git a/app/views/remote_unfollows/success.html.haml b/app/views/remote_unfollows/success.html.haml
deleted file mode 100644
index b007eedc..00000000
--- a/app/views/remote_unfollows/success.html.haml
+++ /dev/null
@@ -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'
diff --git a/app/views/settings/exports/show.html.haml b/app/views/settings/exports/show.html.haml
index b13cea97..2f6876e3 100644
--- a/app/views/settings/exports/show.html.haml
+++ b/app/views/settings/exports/show.html.haml
@@ -32,10 +32,6 @@
%th= t('exports.mutes')
%td= number_with_delimiter @export.total_mutes
%td= table_link_to 'download', t('exports.csv'), settings_exports_mutes_path(format: :csv)
- %tr
- %th= t('exports.domain_blocks')
- %td= number_with_delimiter @export.total_domain_blocks
- %td= table_link_to 'download', t('exports.csv'), settings_exports_domain_blocks_path(format: :csv)
%p.muted-hint= t('exports.archive_takeout.hint_html')
diff --git a/app/views/settings/identity_proofs/_proof.html.haml b/app/views/settings/identity_proofs/_proof.html.haml
deleted file mode 100644
index 524827ad..00000000
--- a/app/views/settings/identity_proofs/_proof.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-%tr
- %td
- = link_to proof.badge.profile_url, class: 'name-tag' do
- = image_tag proof.badge.avatar_url, width: 15, height: 15, alt: '', class: 'avatar'
- %span.username
- = proof.provider_username
- %span= "(#{proof.provider.capitalize})"
-
- %td
- - if proof.live?
- %span.positive-hint
- = fa_icon 'check-circle fw'
- = t('identity_proofs.active')
- - else
- %span.negative-hint
- = fa_icon 'times-circle fw'
- = t('identity_proofs.inactive')
-
- %td
- = table_link_to 'external-link', t('identity_proofs.view_proof'), proof.badge.proof_url if proof.badge.proof_url
diff --git a/app/views/settings/identity_proofs/index.html.haml b/app/views/settings/identity_proofs/index.html.haml
deleted file mode 100644
index d0ea03ec..00000000
--- a/app/views/settings/identity_proofs/index.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- content_for :page_title do
- = t('settings.identity_proofs')
-
-%p= t('identity_proofs.explanation_html')
-
-- unless @proofs.empty?
- %hr.spacer/
-
- .table-wrapper
- %table.table
- %thead
- %tr
- %th= t('identity_proofs.identity')
- %th= t('identity_proofs.status')
- %th
- %tbody
- = render partial: 'settings/identity_proofs/proof', collection: @proofs, as: :proof
diff --git a/app/views/settings/identity_proofs/new.html.haml b/app/views/settings/identity_proofs/new.html.haml
deleted file mode 100644
index 5e4e9895..00000000
--- a/app/views/settings/identity_proofs/new.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-- content_for :page_title do
- = t('identity_proofs.authorize_connection_prompt')
-
-.form-container
- .oauth-prompt
- %h2= t('identity_proofs.authorize_connection_prompt')
-
- = simple_form_for @proof, url: settings_identity_proofs_url, html: { method: :post } do |f|
- = f.input :provider, as: :hidden
- = f.input :provider_username, as: :hidden
- = f.input :token, as: :hidden
-
- = hidden_field_tag :user_agent, params[:user_agent]
-
- .connection-prompt
- .connection-prompt__row.connection-prompt__connection
- .connection-prompt__column
- = image_tag current_account.avatar.url(:original), size: 96, class: 'account__avatar'
-
- %p= t('identity_proofs.i_am_html', username: content_tag(:strong,current_account.username), service: site_hostname)
-
- .connection-prompt__column.connection-prompt__column-sep
- = fa_icon 'link'
-
- .connection-prompt__column
- = image_tag @proof.badge.avatar_url, size: 96, class: 'account__avatar'
-
- %p= t('identity_proofs.i_am_html', username: content_tag(:strong, @proof.provider_username), service: @proof.provider.capitalize)
-
- .connection-prompt__post
- = f.input :post_status, label: t('identity_proofs.publicize_checkbox'), as: :boolean, wrapper: :with_label, :input_html => { checked: true }
-
- = f.input :status_text, as: :text, input_html: { value: t('identity_proofs.publicize_toot', username: @proof.provider_username, service: @proof.provider.capitalize, url: @proof.badge.proof_url), rows: 4 }
-
- = f.button :button, t('identity_proofs.authorize'), type: :submit
- = link_to t('simple_form.no'), settings_identity_proofs_url, class: 'button negative'
diff --git a/app/views/settings/imports/show.html.haml b/app/views/settings/imports/show.html.haml
deleted file mode 100644
index 7bb4beb0..00000000
--- a/app/views/settings/imports/show.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-- content_for :page_title do
- = t('settings.import')
-
-= simple_form_for @import, url: settings_import_path do |f|
- .field-group
- = f.input :type, collection: Import.types.keys, wrapper: :with_block_label, include_blank: false, label_method: lambda { |type| I18n.t("imports.types.#{type}") }, hint: t('imports.preface')
-
- .fields-row
- .fields-group.fields-row__column.fields-row__column-6
- = f.input :data, wrapper: :with_block_label, hint: t('simple_form.hints.imports.data')
- .fields-group.fields-row__column.fields-row__column-6
- = f.input :mode, as: :radio_buttons, collection: Import::MODES, label_method: lambda { |mode| safe_join([I18n.t("imports.modes.#{mode}"), content_tag(:span, I18n.t("imports.modes.#{mode}_long"), class: 'hint')]) }, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
-
- .actions
- = f.button :button, t('imports.upload'), type: :submit
diff --git a/app/views/settings/migrations/show.html.haml b/app/views/settings/migrations/show.html.haml
deleted file mode 100644
index c69061d5..00000000
--- a/app/views/settings/migrations/show.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- content_for :page_title do
- = t('settings.migrate')
-
-= simple_form_for @migration, as: :migration, url: settings_migration_path, html: { method: :put } do |f|
- - if @migration.account
- %p.hint= t('migrations.currently_redirecting')
-
- .fields-group
- = render partial: 'application/card', locals: { account: @migration.account }
-
- = render 'shared/error_messages', object: @migration
-
- .fields-group
- = f.input :acct, placeholder: t('migrations.acct')
-
- .actions
- = f.button :button, t('migrations.proceed'), type: :submit, class: 'negative'
diff --git a/app/views/settings/notifications/show.html.haml b/app/views/settings/notifications/show.html.haml
index b30662e9..e3539dac 100644
--- a/app/views/settings/notifications/show.html.haml
+++ b/app/views/settings/notifications/show.html.haml
@@ -15,7 +15,6 @@
- if current_user.staff?
= ff.input :report, as: :boolean, wrapper: :with_label
- = ff.input :pending_account, as: :boolean, wrapper: :with_label
.fields-group
= f.simple_fields_for :notification_emails, hash_to_object(current_user.settings.notification_emails) do |ff|
diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml
index 98f3aedd..8dde73ed 100644
--- a/app/views/settings/preferences/show.html.haml
+++ b/app/views/settings/preferences/show.html.haml
@@ -35,9 +35,6 @@
.fields-group
= f.input :setting_hide_network, as: :boolean, wrapper: :with_label
- .fields-group
- = f.input :setting_show_application, as: :boolean, wrapper: :with_label
-
%hr#settings_web/
.fields-row
diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml
index 45f3da1e..c17767f7 100644
--- a/app/views/settings/profiles/show.html.haml
+++ b/app/views/settings/profiles/show.html.haml
@@ -49,8 +49,8 @@
%hr/
-- if open_deletion?
- %hr.spacer/
- %h6= t('auth.delete_account')
- %p.muted-hint= t('auth.delete_account_html', path: settings_delete_path)
+%hr.spacer/
+
+%h6= t('auth.delete_account')
+%p.muted-hint= t('auth.delete_account_html', path: settings_delete_path)
diff --git a/app/views/stream_entries/_attachment_list.html.haml b/app/views/statuses/_attachment_list.html.haml
similarity index 100%
rename from app/views/stream_entries/_attachment_list.html.haml
rename to app/views/statuses/_attachment_list.html.haml
diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/statuses/_detailed_status.html.haml
similarity index 79%
rename from app/views/stream_entries/_detailed_status.html.haml
rename to app/views/statuses/_detailed_status.html.haml
index 226ed5f8..347a1d7f 100644
--- a/app/views/stream_entries/_detailed_status.html.haml
+++ b/app/views/statuses/_detailed_status.html.haml
@@ -24,15 +24,15 @@
- 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 }
- elsif !status.media_attachments.empty?
- if status.media_attachments.first.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 }
+ = 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, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
+ = 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
@@ -42,12 +42,6 @@
= link_to 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
- - if status.application.website.blank?
- %strong.detailed-status__application= status.application.name
- - else
- = link_to status.application.name, status.application.website, class: 'detailed-status__application', target: '_blank', rel: 'noopener'
- ·
= link_to remote_interaction_path(status, type: :reply), class: 'modal-button detailed-status__link' do
- if status.in_reply_to_id.nil?
= fa_icon('reply')
@@ -56,10 +50,7 @@
%span.detailed-status__reblogs>= number_to_human status.replies_count, strip_insignificant_zeros: true
= " "
·
- - if status.direct_visibility?
- %span.detailed-status__link<
- = fa_icon('envelope')
- - elsif status.private_visibility? || status.limited_visibility?
+ - if status.private_visibility? || status.limited_visibility?
%span.detailed-status__link<
= fa_icon('lock')
- else
diff --git a/app/views/statuses/_meta.html.haml b/app/views/statuses/_meta.html.haml
new file mode 100644
index 00000000..9050b920
--- /dev/null
+++ b/app/views/statuses/_meta.html.haml
@@ -0,0 +1,16 @@
+- the_title = t('statuses.title', name: display_name(account), quote: truncate(status.spoiler_text.presence || stream_entry.activity.text, length: 50, omission: '…', escape: false))
+
+- content_for :page_title do
+ = the_title
+
+- content_for :header_tags do
+ - if account.user&.setting_noindex
+ %meta{ name: 'robots', content: 'noindex' }/
+
+ = opengraph 'og:site_name', site_title
+ = opengraph 'og:type', 'article'
+ = opengraph 'og:title', the_title
+ = opengraph 'og:url', short_account_status_url(account, status)
+
+ = render 'statuses/og_description', status: status, account: account
+ = render 'statuses/og_image', status: status, account: account
diff --git a/app/views/stream_entries/_og_description.html.haml b/app/views/statuses/_og_description.html.haml
similarity index 100%
rename from app/views/stream_entries/_og_description.html.haml
rename to app/views/statuses/_og_description.html.haml
diff --git a/app/views/stream_entries/_og_image.html.haml b/app/views/statuses/_og_image.html.haml
similarity index 100%
rename from app/views/stream_entries/_og_image.html.haml
rename to app/views/statuses/_og_image.html.haml
diff --git a/app/views/stream_entries/_poll.html.haml b/app/views/statuses/_poll.html.haml
similarity index 100%
rename from app/views/stream_entries/_poll.html.haml
rename to app/views/statuses/_poll.html.haml
diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/statuses/_simple_status.html.haml
similarity index 92%
rename from app/views/stream_entries/_simple_status.html.haml
rename to app/views/statuses/_simple_status.html.haml
index 0df7497e..58516cfd 100644
--- a/app/views/stream_entries/_simple_status.html.haml
+++ b/app/views/statuses/_simple_status.html.haml
@@ -28,15 +28,15 @@
- 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 }
- elsif !status.media_attachments.empty?
- if status.media_attachments.first.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
diff --git a/app/views/stream_entries/_status.html.haml b/app/views/statuses/_status.html.haml
similarity index 83%
rename from app/views/stream_entries/_status.html.haml
rename to app/views/statuses/_status.html.haml
index 83887cd8..af1e5f34 100644
--- a/app/views/stream_entries/_status.html.haml
+++ b/app/views/statuses/_status.html.haml
@@ -19,7 +19,7 @@
.entry{ class: entry_classes }
= link_to_more 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 }
@@ -39,14 +39,14 @@
%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 }
diff --git a/app/views/statuses/show.html.haml b/app/views/statuses/show.html.haml
new file mode 100644
index 00000000..ac6242b0
--- /dev/null
+++ b/app/views/statuses/show.html.haml
@@ -0,0 +1,23 @@
+- 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') }/
+
+ = 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'
\ No newline at end of file
diff --git a/app/views/stream_entries/_meta.html.haml b/app/views/stream_entries/_meta.html.haml
deleted file mode 100644
index 1ee17b41..00000000
--- a/app/views/stream_entries/_meta.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- the_title = 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 :page_title do
- = the_title
-
-- 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', the_title
- = opengraph 'og:url', short_account_status_url(account, stream_entry.activity)
-
- = render 'stream_entries/og_description', activity: stream_entry.activity, account: account
- = render 'stream_entries/og_image', activity: stream_entry.activity, account: account
diff --git a/app/views/stream_entries/embed.html.haml b/app/views/stream_entries/embed.html.haml
deleted file mode 100644
index 4871c101..00000000
--- a/app/views/stream_entries/embed.html.haml
+++ /dev/null
@@ -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
diff --git a/app/views/stream_entries/show.html.haml b/app/views/stream_entries/show.html.haml
deleted file mode 100644
index 55177b47..00000000
--- a/app/views/stream_entries/show.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-= render 'stream_entries/meta', stream_entry: @stream_entry, account: @account
-
-.grid
- .column-0
- .activity-stream.h-entry
- = render partial: "stream_entries/#{@type}", locals: { @type.to_sym => @stream_entry.activity, include_threads: true }
diff --git a/app/views/tags/_meta.html.haml b/app/views/tags/_meta.html.haml
deleted file mode 100644
index ac7bb745..00000000
--- a/app/views/tags/_meta.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-- content_for :page_title do
- = "##{@tag.name} - Hashtag | #{site_hostname}"
-
-- content_for :header_tags do
- %meta{ name: 'robots', content: 'noindex' }/
- %link{ rel: 'alternate', type: 'application/rss+xml', href: tag_url(@tag, format: 'rss') }/
-
- %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json)
- = render 'tags/og'
diff --git a/app/views/tags/_og.html.haml b/app/views/tags/_og.html.haml
deleted file mode 100644
index a7c289bc..00000000
--- a/app/views/tags/_og.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-= opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname)
-= opengraph 'og:url', tag_url(@tag)
-= opengraph 'og:type', 'website'
-= opengraph 'og:title', "##{@tag.name}"
-= opengraph 'og:description', strip_tags(t('about.about_hashtag_html', hashtag: @tag.name))
-= opengraph 'twitter:card', 'summary'
diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml
deleted file mode 100644
index 8b37d229..00000000
--- a/app/views/tags/show.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= render 'tags/meta', tag: @tag, initial_state_json: @initial_state_json
-
-.page-header
- %h1= "##{@tag.name}"
- %p= t('about.about_hashtag_html', hashtag: @tag.name)
-
-#gabsocial-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) }}
-#modal-container
diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb
deleted file mode 100644
index 7e7accf4..00000000
--- a/app/workers/activitypub/delivery_worker.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::DeliveryWorker
- include Sidekiq::Worker
-
- STOPLIGHT_FAILURE_THRESHOLD = 10
- STOPLIGHT_COOLDOWN = 60
-
- sidekiq_options queue: 'push', retry: 0, dead: true
-
- HEADERS = { 'Content-Type' => 'application/activity+json' }.freeze
-
- def perform(json, source_account_id, inbox_url, options = {})
- return if DeliveryFailureTracker.unavailable?(inbox_url)
-
- @options = options.with_indifferent_access
- @json = json
- @source_account = Account.find(source_account_id)
- @inbox_url = inbox_url
-
- perform_request
-
- failure_tracker.track_success!
- rescue => e
- failure_tracker.track_failure!
- raise e.class, "Delivery failed for #{inbox_url}: #{e.message}", e.backtrace[0]
- end
-
- private
-
- def build_request
- request = Request.new(:post, @inbox_url, body: @json)
- request.on_behalf_of(@source_account, :uri, sign_with: @options[:sign_with])
- request.add_headers(HEADERS)
- end
-
- def perform_request
- light = Stoplight(@inbox_url) do
- build_request.perform do |response|
- raise GabSocial::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response)
- end
- end
-
- light.with_threshold(STOPLIGHT_FAILURE_THRESHOLD)
- .with_cool_off_time(STOPLIGHT_COOLDOWN)
- .run
- end
-
- def response_successful?(response)
- (200...300).cover?(response.code)
- end
-
- def response_error_unsalvageable?(response)
- (400...500).cover?(response.code) && ![401, 408, 429].include?(response.code)
- end
-
- def failure_tracker
- @failure_tracker ||= DeliveryFailureTracker.new(@inbox_url)
- end
-end
diff --git a/app/workers/activitypub/distribute_poll_update_worker.rb b/app/workers/activitypub/distribute_poll_update_worker.rb
deleted file mode 100644
index 5eaca6fd..00000000
--- a/app/workers/activitypub/distribute_poll_update_worker.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::DistributePollUpdateWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push', unique: :until_executed, retry: 0
-
- def perform(status_id)
- @status = Status.find(status_id)
- @account = @status.account
-
- return unless @status.preloadable_poll
-
- ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
- [payload, @account.id, inbox_url]
- end
-
- relay! if relayable?
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def relayable?
- @status.public_visibility?
- end
-
- def inboxes
- return @inboxes if defined?(@inboxes)
-
- @inboxes = [@status.mentions, @status.reblogs, @status.preloadable_poll.votes].flat_map do |relation|
- relation.includes(:account).map do |record|
- record.account.preferred_inbox_url if !record.account.local? && record.account.activitypub?
- end
- end
-
- @inboxes.concat(@account.followers.inboxes) unless @status.direct_visibility?
- @inboxes.uniq!
- @inboxes.compact!
- @inboxes
- end
-
- def signed_payload
- Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@account))
- end
-
- def unsigned_payload
- ActiveModelSerializers::SerializableResource.new(
- @status,
- serializer: ActivityPub::UpdatePollSerializer,
- adapter: ActivityPub::Adapter
- ).as_json
- end
-
- def payload
- @payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload)
- end
-
- def relay!
- ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
- [payload, @account.id, inbox_url]
- end
- end
-end
diff --git a/app/workers/activitypub/distribution_worker.rb b/app/workers/activitypub/distribution_worker.rb
deleted file mode 100644
index 144817ec..00000000
--- a/app/workers/activitypub/distribution_worker.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::DistributionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push', retry: 0, dead: true
-
- def perform(status_id)
- @status = Status.find(status_id)
- @account = @status.account
-
- return if skip_distribution?
-
- ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
- [payload, @account.id, inbox_url]
- end
-
- relay! if relayable?
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def skip_distribution?
- @status.direct_visibility? || @status.limited_visibility?
- end
-
- def relayable?
- @status.public_visibility?
- end
-
- def inboxes
- # Deliver the status to all followers.
- # If the status is a reply to another local status, also forward it to that
- # status' authors' followers.
- @inboxes ||= if @status.reply? && @status.thread.account.local? && @status.distributable?
- @account.followers.or(@status.thread.account.followers).inboxes
- else
- @account.followers.inboxes
- end
- end
-
- def signed_payload
- Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@account))
- end
-
- def unsigned_payload
- ActiveModelSerializers::SerializableResource.new(
- @status,
- serializer: ActivityPub::ActivitySerializer,
- adapter: ActivityPub::Adapter
- ).as_json
- end
-
- def payload
- @payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload)
- end
-
- def relay!
- ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
- [payload, @account.id, inbox_url]
- end
- end
-end
diff --git a/app/workers/activitypub/fetch_replies_worker.rb b/app/workers/activitypub/fetch_replies_worker.rb
deleted file mode 100644
index 54d98f22..00000000
--- a/app/workers/activitypub/fetch_replies_worker.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::FetchRepliesWorker
- include Sidekiq::Worker
- include ExponentialBackoff
-
- sidekiq_options queue: 'pull', retry: 3
-
- def perform(parent_status_id, replies_uri)
- ActivityPub::FetchRepliesService.new.call(Status.find(parent_status_id), replies_uri)
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/activitypub/low_priority_delivery_worker.rb b/app/workers/activitypub/low_priority_delivery_worker.rb
deleted file mode 100644
index b62b36d2..00000000
--- a/app/workers/activitypub/low_priority_delivery_worker.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::LowPriorityDeliveryWorker < ActivityPub::DeliveryWorker
- sidekiq_options queue: 'pull', retry: 0, dead: true
-end
diff --git a/app/workers/activitypub/post_upgrade_worker.rb b/app/workers/activitypub/post_upgrade_worker.rb
deleted file mode 100644
index 4154b858..00000000
--- a/app/workers/activitypub/post_upgrade_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::PostUpgradeWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull'
-
- def perform(domain)
- Account.where(domain: domain)
- .where(protocol: :ostatus)
- .where.not(last_webfingered_at: nil)
- .in_batches
- .update_all(last_webfingered_at: nil)
- end
-end
diff --git a/app/workers/activitypub/processing_worker.rb b/app/workers/activitypub/processing_worker.rb
deleted file mode 100644
index 811218cd..00000000
--- a/app/workers/activitypub/processing_worker.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::ProcessingWorker
- include Sidekiq::Worker
-
- sidekiq_options backtrace: true, retry: 0, dead: true
-
- def perform(account_id, body, delivered_to_account_id = nil)
- ActivityPub::ProcessCollectionService.new.call(body, Account.find(account_id), override_timestamps: true, delivered_to_account_id: delivered_to_account_id, delivery: true)
- rescue ActiveRecord::RecordInvalid => e
- Rails.logger.debug "Error processing incoming ActivityPub object: #{e}"
- end
-end
diff --git a/app/workers/activitypub/raw_distribution_worker.rb b/app/workers/activitypub/raw_distribution_worker.rb
deleted file mode 100644
index 41e61132..00000000
--- a/app/workers/activitypub/raw_distribution_worker.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::RawDistributionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push'
-
- def perform(json, source_account_id, exclude_inboxes = [])
- @account = Account.find(source_account_id)
-
- ActivityPub::DeliveryWorker.push_bulk(inboxes - exclude_inboxes) do |inbox_url|
- [json, @account.id, inbox_url]
- end
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def inboxes
- @inboxes ||= @account.followers.inboxes
- end
-end
diff --git a/app/workers/activitypub/reply_distribution_worker.rb b/app/workers/activitypub/reply_distribution_worker.rb
deleted file mode 100644
index d8fea6c4..00000000
--- a/app/workers/activitypub/reply_distribution_worker.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-# Obsolete but kept around to make sure existing jobs do not fail after upgrade.
-# Should be removed in a subsequent release.
-
-class ActivityPub::ReplyDistributionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push'
-
- def perform(status_id)
- @status = Status.find(status_id)
- @account = @status.thread&.account
-
- return unless @account.present? && @status.distributable?
-
- ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
- [payload, @status.account_id, inbox_url]
- end
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def inboxes
- @inboxes ||= @account.followers.inboxes
- end
-
- def signed_payload
- Oj.dump(ActivityPub::LinkedDataSignature.new(unsigned_payload).sign!(@status.account))
- end
-
- def unsigned_payload
- ActiveModelSerializers::SerializableResource.new(
- @status,
- serializer: ActivityPub::ActivitySerializer,
- adapter: ActivityPub::Adapter
- ).as_json
- end
-
- def payload
- @payload ||= @status.distributable? ? signed_payload : Oj.dump(unsigned_payload)
- end
-end
diff --git a/app/workers/activitypub/synchronize_featured_collection_worker.rb b/app/workers/activitypub/synchronize_featured_collection_worker.rb
deleted file mode 100644
index cd744a8a..00000000
--- a/app/workers/activitypub/synchronize_featured_collection_worker.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::SynchronizeFeaturedCollectionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', unique: :until_executed, retry: 0, dead: true
-
- def perform(account_id)
- ActivityPub::FetchFeaturedCollectionService.new.call(Account.find(account_id))
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/activitypub/update_distribution_worker.rb b/app/workers/activitypub/update_distribution_worker.rb
deleted file mode 100644
index 5b40d5c5..00000000
--- a/app/workers/activitypub/update_distribution_worker.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-class ActivityPub::UpdateDistributionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push', retry: 0, dead: true
-
- def perform(account_id, options = {})
- @options = options.with_indifferent_access
- @account = Account.find(account_id)
-
- ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
- [signed_payload, @account.id, inbox_url]
- end
-
- ActivityPub::DeliveryWorker.push_bulk(Relay.enabled.pluck(:inbox_url)) do |inbox_url|
- [signed_payload, @account.id, inbox_url]
- end
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def inboxes
- @inboxes ||= @account.followers.inboxes
- end
-
- def signed_payload
- @signed_payload ||= Oj.dump(ActivityPub::LinkedDataSignature.new(payload).sign!(@account, sign_with: @options[:sign_with]))
- end
-
- def payload
- @payload ||= ActiveModelSerializers::SerializableResource.new(
- @account,
- serializer: ActivityPub::UpdateSerializer,
- adapter: ActivityPub::Adapter
- ).as_json
- end
-end
diff --git a/app/workers/after_account_domain_block_worker.rb b/app/workers/after_account_domain_block_worker.rb
deleted file mode 100644
index 043c3331..00000000
--- a/app/workers/after_account_domain_block_worker.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class AfterAccountDomainBlockWorker
- include Sidekiq::Worker
-
- def perform(account_id, domain)
- AfterBlockDomainFromAccountService.new.call(Account.find(account_id), domain)
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/after_remote_follow_request_worker.rb b/app/workers/after_remote_follow_request_worker.rb
deleted file mode 100644
index 84eb6ade..00000000
--- a/app/workers/after_remote_follow_request_worker.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AfterRemoteFollowRequestWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: 5
-
- attr_reader :follow_request
-
- def perform(follow_request_id)
- @follow_request = FollowRequest.find(follow_request_id)
- process_follow_service if processing_required?
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def process_follow_service
- follow_request.destroy
- FollowService.new.call(follow_request.account, updated_account.acct)
- end
-
- def processing_required?
- !updated_account.nil? && !updated_account.locked?
- end
-
- def updated_account
- @_updated_account ||= FetchRemoteAccountService.new.call(follow_request.target_account.remote_url)
- end
-end
diff --git a/app/workers/after_remote_follow_worker.rb b/app/workers/after_remote_follow_worker.rb
deleted file mode 100644
index edab83f8..00000000
--- a/app/workers/after_remote_follow_worker.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-class AfterRemoteFollowWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: 5
-
- attr_reader :follow
-
- def perform(follow_id)
- @follow = Follow.find(follow_id)
- process_follow_service if processing_required?
- rescue ActiveRecord::RecordNotFound
- true
- end
-
- private
-
- def process_follow_service
- follow.destroy
- FollowService.new.call(follow.account, updated_account.acct)
- end
-
- def updated_account
- @_updated_account ||= FetchRemoteAccountService.new.call(follow.target_account.remote_url)
- end
-
- def processing_required?
- !updated_account.nil? && updated_account.locked?
- end
-end
diff --git a/app/workers/concerns/exponential_backoff.rb b/app/workers/concerns/exponential_backoff.rb
deleted file mode 100644
index f2b931e3..00000000
--- a/app/workers/concerns/exponential_backoff.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module ExponentialBackoff
- extend ActiveSupport::Concern
-
- included do
- sidekiq_retry_in do |count|
- 15 + 10 * (count**4) + rand(10 * (count**4))
- end
- end
-end
diff --git a/app/workers/domain_block_worker.rb b/app/workers/domain_block_worker.rb
deleted file mode 100644
index 88447782..00000000
--- a/app/workers/domain_block_worker.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class DomainBlockWorker
- include Sidekiq::Worker
-
- def perform(domain_block_id)
- BlockDomainService.new.call(DomainBlock.find(domain_block_id))
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/feed_insert_worker.rb b/app/workers/feed_insert_worker.rb
index 1ae3c877..ec0af0cd 100644
--- a/app/workers/feed_insert_worker.rb
+++ b/app/workers/feed_insert_worker.rb
@@ -10,9 +10,6 @@ class FeedInsertWorker
case @type
when :home
@follower = Account.find(id)
- when :list
- @list = List.find(id)
- @follower = @list.account
end
check_and_insert
@@ -36,8 +33,6 @@ class FeedInsertWorker
case @type
when :home
FeedManager.instance.push_to_home(@follower, @status)
- when :list
- FeedManager.instance.push_to_list(@list, @status)
end
end
end
diff --git a/app/workers/fetch_reply_worker.rb b/app/workers/fetch_reply_worker.rb
deleted file mode 100644
index f7aa25e8..00000000
--- a/app/workers/fetch_reply_worker.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class FetchReplyWorker
- include Sidekiq::Worker
- include ExponentialBackoff
-
- sidekiq_options queue: 'pull', retry: 3
-
- def perform(child_url)
- FetchRemoteStatusService.new.call(child_url)
- end
-end
diff --git a/app/workers/import/relationship_worker.rb b/app/workers/import/relationship_worker.rb
deleted file mode 100644
index 616da6da..00000000
--- a/app/workers/import/relationship_worker.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class Import::RelationshipWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: 8, dead: false
-
- def perform(account_id, target_account_uri, relationship, options = {})
- from_account = Account.find(account_id)
- target_account = ResolveAccountService.new.call(target_account_uri)
- options.symbolize_keys!
-
- return if target_account.nil?
-
- case relationship
- when 'follow'
- FollowService.new.call(from_account, target_account, options)
- when 'unfollow'
- UnfollowService.new.call(from_account, target_account)
- when 'block'
- BlockService.new.call(from_account, target_account)
- when 'unblock'
- UnblockService.new.call(from_account, target_account)
- when 'mute'
- MuteService.new.call(from_account, target_account, options)
- when 'unmute'
- UnmuteService.new.call(from_account, target_account)
- end
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/import_worker.rb b/app/workers/import_worker.rb
deleted file mode 100644
index dfa71b29..00000000
--- a/app/workers/import_worker.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class ImportWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: false
-
- def perform(import_id)
- import = Import.find(import_id)
- ImportService.new.call(import)
- ensure
- import&.destroy
- end
-end
diff --git a/app/workers/notification_worker.rb b/app/workers/notification_worker.rb
index da1d6ab4..1c0f001c 100644
--- a/app/workers/notification_worker.rb
+++ b/app/workers/notification_worker.rb
@@ -5,7 +5,5 @@ class NotificationWorker
sidekiq_options queue: 'push', retry: 5
- def perform(xml, source_account_id, target_account_id)
- SendInteractionService.new.call(xml, Account.find(source_account_id), Account.find(target_account_id))
- end
+ def perform(xml, source_account_id, target_account_id); end
end
diff --git a/app/workers/poll_expiration_notify_worker.rb b/app/workers/poll_expiration_notify_worker.rb
index e08f0c24..7f0180c1 100644
--- a/app/workers/poll_expiration_notify_worker.rb
+++ b/app/workers/poll_expiration_notify_worker.rb
@@ -10,7 +10,6 @@ class PollExpirationNotifyWorker
# Notify poll owner and remote voters
if poll.local?
- ActivityPub::DistributePollUpdateWorker.perform_async(poll.status.id)
NotifyService.new.call(poll.account, poll)
end
diff --git a/app/workers/processing_worker.rb b/app/workers/processing_worker.rb
deleted file mode 100644
index 978c3aba..00000000
--- a/app/workers/processing_worker.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class ProcessingWorker
- include Sidekiq::Worker
-
- sidekiq_options backtrace: true
-
- def perform(account_id, body)
- ProcessFeedService.new.call(body, Account.find(account_id), override_timestamps: true)
- end
-end
diff --git a/app/workers/pubsubhubbub/confirmation_worker.rb b/app/workers/pubsubhubbub/confirmation_worker.rb
deleted file mode 100644
index c0e7b677..00000000
--- a/app/workers/pubsubhubbub/confirmation_worker.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::ConfirmationWorker
- include Sidekiq::Worker
- include RoutingHelper
-
- sidekiq_options queue: 'push', retry: false
-
- attr_reader :subscription, :mode, :secret, :lease_seconds
-
- def perform(subscription_id, mode, secret = nil, lease_seconds = nil)
- @subscription = Subscription.find(subscription_id)
- @mode = mode
- @secret = secret
- @lease_seconds = lease_seconds
- process_confirmation
- end
-
- private
-
- def process_confirmation
- prepare_subscription
-
- callback_get_with_params
- logger.debug "Confirming PuSH subscription for #{subscription.callback_url} with challenge #{challenge}: #{@callback_response_body}"
-
- update_subscription
- end
-
- def update_subscription
- if successful_subscribe?
- subscription.save!
- elsif successful_unsubscribe?
- subscription.destroy!
- end
- end
-
- def successful_subscribe?
- subscribing? && response_matches_challenge?
- end
-
- def successful_unsubscribe?
- (unsubscribing? && response_matches_challenge?) || !subscription.confirmed?
- end
-
- def response_matches_challenge?
- @callback_response_body == challenge
- end
-
- def subscribing?
- mode == 'subscribe'
- end
-
- def unsubscribing?
- mode == 'unsubscribe'
- end
-
- def callback_get_with_params
- Request.new(:get, subscription.callback_url, params: callback_params).perform do |response|
- @callback_response_body = response.body_with_limit
- end
- end
-
- def callback_params
- {
- 'hub.topic': account_url(subscription.account, format: :atom),
- 'hub.mode': mode,
- 'hub.challenge': challenge,
- 'hub.lease_seconds': subscription.lease_seconds,
- }
- end
-
- def prepare_subscription
- subscription.secret = secret
- subscription.lease_seconds = lease_seconds
- subscription.confirmed = true
- end
-
- def challenge
- @_challenge ||= SecureRandom.hex
- end
-end
diff --git a/app/workers/pubsubhubbub/delivery_worker.rb b/app/workers/pubsubhubbub/delivery_worker.rb
deleted file mode 100644
index 2770e22c..00000000
--- a/app/workers/pubsubhubbub/delivery_worker.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::DeliveryWorker
- include Sidekiq::Worker
- include RoutingHelper
-
- sidekiq_options queue: 'push', retry: 3, dead: false
-
- sidekiq_retry_in do |count|
- 5 * (count + 1)
- end
-
- attr_reader :subscription, :payload
-
- def perform(subscription_id, payload)
- @subscription = Subscription.find(subscription_id)
- @payload = payload
- process_delivery unless blocked_domain?
- rescue => e
- raise e.class, "Delivery failed for #{subscription&.callback_url}: #{e.message}", e.backtrace[0]
- end
-
- private
-
- def process_delivery
- callback_post_payload do |payload_delivery|
- raise GabSocial::UnexpectedResponseError, payload_delivery unless response_successful? payload_delivery
- end
-
- subscription.touch(:last_successful_delivery_at)
- end
-
- def callback_post_payload(&block)
- request = Request.new(:post, subscription.callback_url, body: payload)
- request.add_headers(headers)
- request.perform(&block)
- end
-
- def blocked_domain?
- DomainBlock.blocked?(host)
- end
-
- def host
- Addressable::URI.parse(subscription.callback_url).normalized_host
- end
-
- def headers
- {
- 'Content-Type' => 'application/atom+xml',
- 'Link' => link_header,
- }.merge(signature_headers.to_h)
- end
-
- def link_header
- LinkHeader.new([hub_link_header, self_link_header]).to_s
- end
-
- def hub_link_header
- [api_push_url, [%w(rel hub)]]
- end
-
- def self_link_header
- [account_url(subscription.account, format: :atom), [%w(rel self)]]
- end
-
- def signature_headers
- { 'X-Hub-Signature' => payload_signature } if subscription.secret?
- end
-
- def payload_signature
- "sha1=#{hmac_payload_digest}"
- end
-
- def hmac_payload_digest
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), subscription.secret, payload)
- end
-
- def response_successful?(payload_delivery)
- payload_delivery.code > 199 && payload_delivery.code < 300
- end
-end
diff --git a/app/workers/pubsubhubbub/distribution_worker.rb b/app/workers/pubsubhubbub/distribution_worker.rb
deleted file mode 100644
index fed5e917..00000000
--- a/app/workers/pubsubhubbub/distribution_worker.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::DistributionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push'
-
- def perform(stream_entry_ids)
- stream_entries = StreamEntry.where(id: stream_entry_ids).includes(:status).reject { |e| e.status.nil? || e.status.hidden? }
-
- return if stream_entries.empty?
-
- @account = stream_entries.first.account
- @subscriptions = active_subscriptions.to_a
-
- distribute_public!(stream_entries)
- end
-
- private
-
- def distribute_public!(stream_entries)
- @payload = OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, stream_entries))
-
- Pubsubhubbub::DeliveryWorker.push_bulk(@subscriptions) do |subscription_id|
- [subscription_id, @payload]
- end
- end
-
- def active_subscriptions
- Subscription.where(account: @account).active.pluck(:id)
- end
-end
diff --git a/app/workers/pubsubhubbub/raw_distribution_worker.rb b/app/workers/pubsubhubbub/raw_distribution_worker.rb
deleted file mode 100644
index 16962a62..00000000
--- a/app/workers/pubsubhubbub/raw_distribution_worker.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::RawDistributionWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push'
-
- def perform(xml, source_account_id)
- @account = Account.find(source_account_id)
- @subscriptions = active_subscriptions.to_a
-
- Pubsubhubbub::DeliveryWorker.push_bulk(@subscriptions) do |subscription|
- [subscription.id, xml]
- end
- end
-
- private
-
- def active_subscriptions
- Subscription.where(account: @account).active.select('id, callback_url, domain')
- end
-end
diff --git a/app/workers/pubsubhubbub/subscribe_worker.rb b/app/workers/pubsubhubbub/subscribe_worker.rb
deleted file mode 100644
index 2e176d1c..00000000
--- a/app/workers/pubsubhubbub/subscribe_worker.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::SubscribeWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false
-
- sidekiq_retry_in do |count|
- case count
- when 0
- 30.minutes.seconds
- when 1
- 2.hours.seconds
- when 2
- 12.hours.seconds
- else
- 24.hours.seconds * (count - 2)
- end
- end
-
- sidekiq_retries_exhausted do |msg, _e|
- account = Account.find(msg['args'].first)
- Sidekiq.logger.error "PuSH subscription attempts for #{account.acct} exhausted. Unsubscribing"
- ::UnsubscribeService.new.call(account)
- end
-
- def perform(account_id)
- account = Account.find(account_id)
- logger.debug "PuSH re-subscribing to #{account.acct}"
- ::SubscribeService.new.call(account)
- rescue => e
- raise e.class, "Subscribe failed for #{account&.acct}: #{e.message}", e.backtrace[0]
- end
-end
diff --git a/app/workers/pubsubhubbub/unsubscribe_worker.rb b/app/workers/pubsubhubbub/unsubscribe_worker.rb
deleted file mode 100644
index a271715b..00000000
--- a/app/workers/pubsubhubbub/unsubscribe_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class Pubsubhubbub::UnsubscribeWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'push', retry: false, unique: :until_executed, dead: false
-
- def perform(account_id)
- account = Account.find(account_id)
- logger.debug "PuSH unsubscribing from #{account.acct}"
- ::UnsubscribeService.new.call(account)
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/push_conversation_worker.rb b/app/workers/push_conversation_worker.rb
deleted file mode 100644
index 77f5895c..00000000
--- a/app/workers/push_conversation_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-class PushConversationWorker
- include Sidekiq::Worker
-
- def perform(conversation_account_id)
- conversation = AccountConversation.find(conversation_account_id)
- message = InlineRenderer.render(conversation, conversation.account, :conversation)
- timeline_id = "timeline:direct:#{conversation.account_id}"
- Redis.current.publish(timeline_id, Oj.dump(event: :conversation, payload: message, queued_at: (Time.now.to_f * 1000.0).to_i))
- true
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/refollow_worker.rb b/app/workers/refollow_worker.rb
deleted file mode 100644
index 2063bba9..00000000
--- a/app/workers/refollow_worker.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-class RefollowWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: false
-
- def perform(target_account_id)
- target_account = Account.find(target_account_id)
- return unless target_account.protocol == :activitypub
-
- target_account.followers.where(domain: nil).reorder(nil).find_each do |follower|
- # Locally unfollow remote account
- follower.unfollow!(target_account)
-
- # Schedule re-follow
- begin
- FollowService.new.call(follower, target_account)
- rescue GabSocial::NotPermittedError, ActiveRecord::RecordNotFound, GabSocial::UnexpectedResponseError, HTTP::Error, OpenSSL::SSL::SSLError
- next
- end
- end
- end
-end
diff --git a/app/workers/remote_profile_update_worker.rb b/app/workers/remote_profile_update_worker.rb
deleted file mode 100644
index 03585ad2..00000000
--- a/app/workers/remote_profile_update_worker.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class RemoteProfileUpdateWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull'
-
- def perform(account_id, body, resubscribe)
- UpdateRemoteProfileService.new.call(body, Account.find(account_id), resubscribe)
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/resolve_account_worker.rb b/app/workers/resolve_account_worker.rb
deleted file mode 100644
index cd7c4d7d..00000000
--- a/app/workers/resolve_account_worker.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class ResolveAccountWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', unique: :until_executed
-
- def perform(uri)
- ResolveAccountService.new.call(uri)
- end
-end
diff --git a/app/workers/salmon_worker.rb b/app/workers/salmon_worker.rb
deleted file mode 100644
index d37d4043..00000000
--- a/app/workers/salmon_worker.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class SalmonWorker
- include Sidekiq::Worker
-
- sidekiq_options backtrace: true
-
- def perform(account_id, body)
- ProcessInteractionService.new.call(body, Account.find(account_id))
- rescue Nokogiri::XML::XPath::SyntaxError, ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/app/workers/scheduler/subscriptions_cleanup_scheduler.rb b/app/workers/scheduler/subscriptions_cleanup_scheduler.rb
deleted file mode 100644
index 5fba120f..00000000
--- a/app/workers/scheduler/subscriptions_cleanup_scheduler.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-class Scheduler::SubscriptionsCleanupScheduler
- include Sidekiq::Worker
-
- sidekiq_options unique: :until_executed, retry: 0
-
- def perform
- Subscription.expired.in_batches.delete_all
- end
-end
diff --git a/app/workers/scheduler/subscriptions_scheduler.rb b/app/workers/scheduler/subscriptions_scheduler.rb
deleted file mode 100644
index d5873bcc..00000000
--- a/app/workers/scheduler/subscriptions_scheduler.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class Scheduler::SubscriptionsScheduler
- include Sidekiq::Worker
-
- sidekiq_options unique: :until_executed, retry: 0
-
- def perform
- Pubsubhubbub::SubscribeWorker.push_bulk(expiring_accounts.pluck(:id))
- end
-
- private
-
- def expiring_accounts
- Account.expiring(1.day.from_now).partitioned
- end
-end
diff --git a/app/workers/scheduler/user_cleanup_scheduler.rb b/app/workers/scheduler/user_cleanup_scheduler.rb
deleted file mode 100644
index 881b911b..00000000
--- a/app/workers/scheduler/user_cleanup_scheduler.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class Scheduler::UserCleanupScheduler
- include Sidekiq::Worker
-
- sidekiq_options unique: :until_executed, retry: 0
-
- def perform
- User.where('confirmed_at is NULL AND confirmation_sent_at <= ?', 2.days.ago).reorder(nil).find_in_batches do |batch|
- Account.where(id: batch.map(&:account_id)).delete_all
- User.where(id: batch.map(&:id)).delete_all
- end
- end
-end
diff --git a/app/workers/thread_resolve_worker.rb b/app/workers/thread_resolve_worker.rb
deleted file mode 100644
index 8bba9ca7..00000000
--- a/app/workers/thread_resolve_worker.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class ThreadResolveWorker
- include Sidekiq::Worker
- include ExponentialBackoff
-
- sidekiq_options queue: 'pull', retry: 3
-
- def perform(child_status_id, parent_url)
- child_status = Status.find(child_status_id)
- parent_status = FetchRemoteStatusService.new.call(parent_url)
-
- return if parent_status.nil?
-
- child_status.thread = parent_status
- child_status.save!
- end
-end
diff --git a/app/workers/unfollow_follow_worker.rb b/app/workers/unfollow_follow_worker.rb
deleted file mode 100644
index 41d560bb..00000000
--- a/app/workers/unfollow_follow_worker.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-class UnfollowFollowWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull'
-
- def perform(follower_account_id, old_target_account_id, new_target_account_id)
- follower_account = Account.find(follower_account_id)
- old_target_account = Account.find(old_target_account_id)
- new_target_account = Account.find(new_target_account_id)
-
- FollowService.new.call(follower_account, new_target_account)
- UnfollowService.new.call(follower_account, old_target_account)
- rescue ActiveRecord::RecordNotFound, GabSocial::NotPermittedError
- true
- end
-end
diff --git a/app/workers/verify_account_links_worker.rb b/app/workers/verify_account_links_worker.rb
deleted file mode 100644
index 90149858..00000000
--- a/app/workers/verify_account_links_worker.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-class VerifyAccountLinksWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: 'pull', retry: false, unique: :until_executed
-
- def perform(account_id)
- account = Account.find(account_id)
-
- account.fields.each do |field|
- next unless !field.verified? && field.verifiable?
- VerifyLinkService.new.call(field)
- end
-
- account.save! if account.changed?
- rescue ActiveRecord::RecordNotFound
- true
- end
-end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 81530ca6..bae1b731 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -271,7 +271,7 @@ Devise.setup do |config|
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
- config.reset_password_within = 24.hours
+ config.reset_password_within = 3.days
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
index bf0cb52a..6831bdb6 100644
--- a/config/initializers/inflections.rb
+++ b/config/initializers/inflections.rb
@@ -10,6 +10,7 @@
# inflect.uncountable %w( fish sheep )
# end
+# : TODO : WTF IS THIS?
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'StatsD'
inflect.acronym 'OEmbed'
diff --git a/config/navigation.rb b/config/navigation.rb
index 414c179d..ac6d5714 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -23,19 +23,13 @@ SimpleNavigation::Configuration.run do |navigation|
n.item :requests, safe_join([fa_icon('id-card-o fw'), t('verifications.requests.title')]), settings_verifications_requests_url
- n.item :data, safe_join([fa_icon('cloud-download fw'), t('settings.import_and_export')]), settings_export_url do |s|
- s.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url
- end
+ n.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url
n.item :development, safe_join([fa_icon('code fw'), t('settings.development')]), settings_applications_url, if: -> { current_user.staff? }
n.item :moderation, safe_join([fa_icon('gavel fw'), t('moderation.title')]), admin_reports_url, if: proc { current_user.staff? } do |s|
s.item :action_logs, safe_join([fa_icon('bars fw'), t('admin.action_logs.title')]), admin_action_logs_url
s.item :reports, safe_join([fa_icon('flag fw'), t('admin.reports.title')]), admin_reports_url, highlights_on: %r{/admin/reports}
- s.item :accounts, safe_join([fa_icon('users fw'), t('admin.accounts.title')]), admin_accounts_url, highlights_on: %r{/admin/accounts|/admin/pending_accounts}
- s.item :invites, safe_join([fa_icon('user-plus fw'), t('admin.invites.title')]), admin_invites_path
- s.item :tags, safe_join([fa_icon('tag fw'), t('admin.tags.title')]), admin_tags_path
- s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url(limited: '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks}, if: -> { current_user.admin? }
s.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}, if: -> { current_user.admin? }
end
@@ -44,8 +38,6 @@ SimpleNavigation::Configuration.run do |navigation|
s.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/settings}
s.item :groups, safe_join([fa_icon('smile-o fw'), t('admin.groups.title')]), admin_groups_url, highlights_on: %r{/admin/groups}
s.item :custom_emojis, safe_join([fa_icon('smile-o fw'), t('admin.custom_emojis.title')]), admin_custom_emojis_url, highlights_on: %r{/admin/custom_emojis}
- s.item :relays, safe_join([fa_icon('exchange fw'), t('admin.relays.title')]), admin_relays_url, if: -> { current_user.admin? }, highlights_on: %r{/admin/relays}
- s.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url, if: -> { current_user.admin? }
s.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }, if: -> { current_user.admin? }
s.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }, if: -> { current_user.admin? }
s.item :moderation, safe_join([fa_icon('id-card-o fw'), t('verifications.moderation.title')]), settings_verifications_moderation_url, if: -> { current_user.admin? }
diff --git a/config/routes.rb b/config/routes.rb
index 8b089dc6..89d51a0e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -25,62 +25,24 @@ Rails.application.routes.draw do
get '.well-known/change-password', to: redirect('/auth/edit')
get 'manifest', to: 'manifests#show', defaults: { format: 'json' }
- get 'intent', to: 'intents#show'
devise_scope :user do
- get '/invite/:invite_code', to: 'auth/registrations#new', as: :public_invite
match '/auth/finish_signup' => 'auth/confirmations#finish_signup', via: [:get, :patch], as: :finish_signup
end
devise_for :users, path: 'auth', controllers: {
- # omniauth_callbacks: 'auth/omniauth_callbacks',
sessions: 'auth/sessions',
registrations: 'auth/registrations',
passwords: 'auth/passwords',
confirmations: 'auth/confirmations',
}
- get '/users/:username', to: redirect('/%{username}'), constraints: html_only, username: username_regex
- get '/users/:username/followers', to: redirect('/%{username}/followers'), constraints: html_only, username: username_regex
- get '/users/:username/following', to: redirect('/%{username}/following'), constraints: html_only, username: username_regex
- get '/users/:username/statuses/:id', to: redirect('/%{username}/posts/%{id}'), constraints: html_only, username: username_regex
-
get '/authorize_follow', to: redirect { |_, request| "/authorize_interaction?#{request.params.to_query}" }
- resources :accounts, path: 'users', only: [:show], param: :username do
- resources :stream_entries, path: 'updates', only: [:show] do
- member do
- get :embed
- end
- end
-
- # get :remote_follow, to: 'remote_follow#new'
- # post :remote_follow, to: 'remote_follow#create'
-
- resources :statuses, only: [:show] do
- member do
- get :activity
- get :embed
- get :replies
- end
- end
-
- resources :followers, only: [:index], controller: :follower_accounts
- resources :following, only: [:index], controller: :following_accounts
- resource :follow, only: [:create], controller: :account_follow
- resource :unfollow, only: [:create], controller: :account_unfollow
- end
-
- # resource :inbox, only: [:create], module: :activitypub
-
- get '/interact/:id', to: 'remote_interaction#new', as: :remote_interaction
- post '/interact/:id', to: 'remote_interaction#create'
-
namespace :settings do
resource :profile, only: [:show, :update]
resource :preferences, only: [:show, :update]
resource :notifications, only: [:show, :update]
- # resource :import, only: [:show, :create]
namespace :billing do
get :upgrade, to: 'upgrade#index', as: :upgrade
@@ -106,7 +68,6 @@ Rails.application.routes.draw do
resources :blocks, only: :index, controller: :blocked_accounts
resources :mutes, only: :index, controller: :muted_accounts
resources :lists, only: :index, controller: :lists
- resources :domain_blocks, only: :index, controller: :blocked_domains
end
resource :two_factor_authentication, only: [:show, :create, :destroy]
@@ -115,8 +76,6 @@ Rails.application.routes.draw do
resource :confirmation, only: [:new, :create]
end
- resources :identity_proofs, only: [:index, :show, :new, :create, :update]
-
resources :applications, except: [:edit] do
member do
post :regenerate
@@ -124,7 +83,6 @@ Rails.application.routes.draw do
end
resource :delete, only: [:show, :destroy]
- # resource :migration, only: [:show, :update]
resources :sessions, only: [:destroy]
resources :scheduled_statuses, only: [:index, :destroy]
@@ -134,44 +92,18 @@ Rails.application.routes.draw do
get :player
end
- resources :emojis, only: [:show]
- # resources :invites, only: [:index, :create, :destroy]
resources :filters, except: [:show]
- # resource :relationships, only: [:show, :update]
- get '/public', to: redirect('/home'), as: :public_timeline # homehack
get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy
- # Remote follow
- # resource :remote_unfollow, only: [:create]
- # resource :authorize_interaction, only: [:show, :create]
- # resource :share, only: [:show, :create]
-
namespace :admin do
get '/dashboard', to: 'dashboard#index'
- resources :subscriptions, only: [:index]
- resources :domain_blocks, only: [:new, :create, :show, :destroy]
resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
resources :action_logs, only: [:index]
resources :warning_presets, except: [:new]
resource :settings, only: [:edit, :update]
- resources :invites, only: [:index, :create, :destroy] do
- collection do
- post :deactivate_all
- end
- end
-
- resources :relays, only: [:index, :new, :create, :destroy] do
- member do
- post :enable
- post :disable
- end
- end
-
- resources :instances, only: [:index, :show], constraints: { id: /[^\/]+/ }
-
resources :reports, only: [:index, :show] do
member do
post :assign_to_self
@@ -187,8 +119,6 @@ Rails.application.routes.draw do
resources :accounts, only: [:index, :show, :edit, :update] do
member do
- post :subscribe
- post :unsubscribe
post :enable
post :unsilence
post :unsuspend
@@ -228,25 +158,11 @@ Rails.application.routes.draw do
end
end
- resources :pending_accounts, only: [:index] do
- collection do
- post :approve_all
- post :reject_all
- post :batch
- end
- end
-
resources :users, only: [] do
resource :two_factor_authentication, only: [:destroy]
end
- resources :custom_emojis, only: [:index, :new, :create, :update, :destroy] do
- member do
- post :copy
- post :enable
- post :disable
- end
- end
+ resources :custom_emojis, only: [:index, :new, :create, :update, :destroy]
resources :groups, only: [:index, :destroy] do
member do
@@ -256,28 +172,9 @@ Rails.application.routes.draw do
end
resources :account_moderation_notes, only: [:create, :destroy]
-
- resources :tags, only: [:index] do
- member do
- post :hide
- post :unhide
- end
- end
end
- get '/admin', to: redirect('/admin/dashboard', status: 302)
-
namespace :api do
- # PubSubHubbub outgoing subscriptions
- resources :subscriptions, only: [:show]
- post '/subscriptions/:id', to: 'subscriptions#update'
-
- # PubSubHubbub incoming subscriptions
- post '/push', to: 'push#update', as: :push
-
- # Salmon
- post '/salmon/:id', to: 'salmon#update', as: :salmon
-
# OEmbed
get '/oembed', to: 'oembed#show', as: :oembed
@@ -296,13 +193,10 @@ Rails.application.routes.draw do
resource :favourite, only: :create
post :unfavourite, to: 'favourites#destroy'
- resource :bookmark, only: :create
+ resource :bookmark, only: [:show, :create]
post :unbookmark, to: 'bookmarks#destroy'
-
- resource :mute, only: :create
- post :unmute, to: 'mutes#destroy'
- resource :pin, only: :create
+ resource :pin, only: [:show, :create]
post :unpin, to: 'pins#destroy'
end
@@ -327,10 +221,8 @@ Rails.application.routes.draw do
resource :explore, only: :show, controller: :explore
end
- resources :gab_trends, only: [:index]
resources :links, only: :show
resource :popular_links, only: :show
- resources :shop, only: [:index]
resources :streaming, only: [:index]
resources :custom_emojis, only: [:index]
resources :suggestions, only: [:index, :destroy]
@@ -338,17 +230,10 @@ Rails.application.routes.draw do
resources :preferences, only: [:index]
resources :group_categories, only: [:index]
- resources :conversations, only: [:index, :destroy] do
- member do
- post :read
- end
- end
-
get '/search', to: 'search#index', as: :search
- resources :promotions, only: [:index]
-
get '/account_by_username/:username', to: 'account_by_username#show', username: username_regex
+ resources :promotions, only: [:index]
resources :follows, only: [:create]
resources :media, only: [:create, :update]
resources :blocks, only: [:index]
@@ -356,7 +241,6 @@ Rails.application.routes.draw do
resources :favourites, only: [:index]
resources :reports, only: [:create]
resources :filters, only: [:index, :create, :show, :update, :destroy]
- resources :endorsements, only: [:index]
resources :shortcuts, only: [:index, :create, :show, :destroy]
resources :bookmarks, only: [:index]
@@ -366,9 +250,6 @@ Rails.application.routes.draw do
resources :apps, only: [:create]
-
- resource :domain_blocks, only: [:show, :create, :destroy]
-
resources :follow_requests, only: [:index] do
member do
post :authorize
@@ -379,13 +260,8 @@ Rails.application.routes.draw do
resources :notifications, only: [:index, :show] do
collection do
post :clear
- post :dismiss # Deprecated
post :mark_read
end
-
- member do
- post :dismiss
- end
end
namespace :accounts do
@@ -410,9 +286,6 @@ Rails.application.routes.draw do
post :mute
post :unmute
end
-
- resource :pin, only: :create, controller: 'accounts/pins'
- post :unpin, to: 'accounts/pins#destroy'
end
resources :lists, only: [:index, :create, :show, :update, :destroy] do
@@ -436,7 +309,7 @@ Rails.application.routes.draw do
post '/join_requests/respond', to: 'groups/requests#respond_to_request'
- resource :pin, only: :create, controller: 'groups/pins'
+ resource :pin, only: [:show, :create], controller: 'groups/pins'
post :unpin, to: 'groups/pins#destroy'
end
@@ -466,34 +339,11 @@ Rails.application.routes.draw do
end
get '/g/:groupSlug', to: 'react#groupBySlug'
- get '/:username/with_replies', to: 'accounts#show', username: username_regex, as: :short_account_with_replies
- get '/:username/comments_only', to: 'accounts#show', username: username_regex, as: :short_account_comments_only
- get '/:username/media', to: 'accounts#show', username: username_regex, as: :short_account_media
- get '/:username/tagged/:tag', to: 'accounts#show', username: username_regex, as: :short_account_tag
- get '/:username/posts/:statusId/reblogs', to: 'statuses#show', username: username_regex
- get '/:account_username/posts/:id', to: 'statuses#show', account_username: username_regex, as: :short_account_status
- get '/:account_username/posts/:id/embed', to: 'statuses#embed', account_username: username_regex, as: :embed_short_account_status
-
get '/(*any)', to: 'react#react', as: :web
- get '/:username', to: 'accounts#show', username: username_regex, as: :short_account
root 'react#react'
get '/', to: 'react#react', as: :homepage
- # Routes that are now to be used within webapp, but still referenced within application
- # TODO : Consolidate
- get '/explore', to: 'directories#index', as: :explore
- get '/explore/:id', to: 'directories#show', as: :explore_hashtag
-
- get '/about', to: 'about#more'
- get '/about/tos', to: 'about#terms'
- get '/about/privacy', to: 'about#privacy'
- get '/about/investors', to: 'about#investors'
- get '/about/dmca', to: 'about#dmca'
- get '/about/sales', to: 'about#sales'
-
- resources :tags, only: [:show]
-
match '*unmatched_route',
via: :all,
to: 'application#raise_not_found',
diff --git a/config/settings.yml b/config/settings.yml
index 4a7eac09..97680526 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -5,17 +5,10 @@ defaults: &defaults
site_title: Gab Social
site_short_description: ''
site_description: ''
- site_extended_description: ''
- site_terms: ''
site_contact_username: ''
site_contact_email: ''
registrations_mode: 'open'
- profile_directory: true
- closed_registrations_message: ''
- open_deletion: true
min_invite_role: 'admin'
- timeline_preview: true
- show_staff_badge: true
default_sensitive: false
hide_network: false
unfollow_modal: false
@@ -25,8 +18,6 @@ defaults: &defaults
display_media: 'default'
expand_spoilers: false
preview_sensitive_media: false
- reduce_motion: false
- show_application: true
group_in_home_feed: true
noindex: false
theme: 'default'
@@ -39,7 +30,6 @@ defaults: &defaults
follow_request: true
digest: true
report: true
- pending_account: true
emails_from_gabcom: true
interactions:
must_be_follower: false
@@ -92,11 +82,7 @@ defaults: &defaults
- links
- messages
- message
- disallowed_hashtags: # space separated string or list of hashtags without the hash
bootstrap_timeline_accounts: ''
- activity_api_enabled: true
- peers_api_enabled: true
- show_known_fediverse_at_about_page: true
development:
<<: *defaults
diff --git a/config/sidekiq.yml b/config/sidekiq.yml
index f0bcba5f..7588ec8b 100644
--- a/config/sidekiq.yml
+++ b/config/sidekiq.yml
@@ -30,12 +30,6 @@
doorkeeper_cleanup_scheduler:
cron: '<%= Random.rand(0..59) %> <%= Random.rand(0..2) %> * * 0'
class: Scheduler::DoorkeeperCleanupScheduler
- user_cleanup_scheduler:
- cron: '<%= Random.rand(0..59) %> <%= Random.rand(4..6) %> * * *'
- class: Scheduler::UserCleanupScheduler
- subscriptions_cleanup_scheduler:
- cron: '<%= Random.rand(0..59) %> <%= Random.rand(1..3) %> * * 0'
- class: Scheduler::SubscriptionsCleanupScheduler
ip_cleanup_scheduler:
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
class: Scheduler::IpCleanupScheduler
diff --git a/db/post_migrate/20201109233203_remove_invite_id_from_users.rb b/db/post_migrate/20201109233203_remove_invite_id_from_users.rb
new file mode 100644
index 00000000..ffbe9152
--- /dev/null
+++ b/db/post_migrate/20201109233203_remove_invite_id_from_users.rb
@@ -0,0 +1,5 @@
+class RemoveInviteIdFromUsers < ActiveRecord::Migration[5.2]
+ def change
+ safety_assured { remove_column :users, :invite_id }
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233204_drop_stream_entries.rb b/db/post_migrate/20201109233204_drop_stream_entries.rb
new file mode 100644
index 00000000..1468f260
--- /dev/null
+++ b/db/post_migrate/20201109233204_drop_stream_entries.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class DropStreamEntries < ActiveRecord::Migration[5.2]
+ disable_ddl_transaction!
+
+ def up
+ drop_table :stream_entries
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233205_drop_subscriptions.rb b/db/post_migrate/20201109233205_drop_subscriptions.rb
new file mode 100644
index 00000000..1c3b3456
--- /dev/null
+++ b/db/post_migrate/20201109233205_drop_subscriptions.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropSubscriptions < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :subscriptions
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233206_drop_user_invite_requests.rb b/db/post_migrate/20201109233206_drop_user_invite_requests.rb
new file mode 100644
index 00000000..e6f2a3a9
--- /dev/null
+++ b/db/post_migrate/20201109233206_drop_user_invite_requests.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropUserInviteRequests < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :user_invite_requests
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233207_drop_relays.rb b/db/post_migrate/20201109233207_drop_relays.rb
new file mode 100644
index 00000000..9d75468e
--- /dev/null
+++ b/db/post_migrate/20201109233207_drop_relays.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropRelays < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :relays
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233208_drop_invites.rb b/db/post_migrate/20201109233208_drop_invites.rb
new file mode 100644
index 00000000..ff9c6e6f
--- /dev/null
+++ b/db/post_migrate/20201109233208_drop_invites.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropInvites < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :invites
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233209_drop_imports.rb b/db/post_migrate/20201109233209_drop_imports.rb
new file mode 100644
index 00000000..f262f551
--- /dev/null
+++ b/db/post_migrate/20201109233209_drop_imports.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropImports < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :imports
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233210_drop_featured_tags.rb b/db/post_migrate/20201109233210_drop_featured_tags.rb
new file mode 100644
index 00000000..024487df
--- /dev/null
+++ b/db/post_migrate/20201109233210_drop_featured_tags.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropFeaturedTags < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :featured_tags
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233211_drop_domain_blocks.rb b/db/post_migrate/20201109233211_drop_domain_blocks.rb
new file mode 100644
index 00000000..416eb61b
--- /dev/null
+++ b/db/post_migrate/20201109233211_drop_domain_blocks.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropDomainBlocks < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :domain_blocks
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233212_drop_account_pins.rb b/db/post_migrate/20201109233212_drop_account_pins.rb
new file mode 100644
index 00000000..79ff46f9
--- /dev/null
+++ b/db/post_migrate/20201109233212_drop_account_pins.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropAccountPins < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :account_pins
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233213_drop_account_identity_proofs.rb b/db/post_migrate/20201109233213_drop_account_identity_proofs.rb
new file mode 100644
index 00000000..dcbbbb99
--- /dev/null
+++ b/db/post_migrate/20201109233213_drop_account_identity_proofs.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropAccountIdentityProofs < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :account_identity_proofs
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233214_drop_account_domain_blocks.rb b/db/post_migrate/20201109233214_drop_account_domain_blocks.rb
new file mode 100644
index 00000000..5530c7c6
--- /dev/null
+++ b/db/post_migrate/20201109233214_drop_account_domain_blocks.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropAccountDomainBlocks < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :account_domain_blocks
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/post_migrate/20201109233215_drop_conversation_mutes.rb b/db/post_migrate/20201109233215_drop_conversation_mutes.rb
new file mode 100644
index 00000000..b067c641
--- /dev/null
+++ b/db/post_migrate/20201109233215_drop_conversation_mutes.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class DropConversationMutes < ActiveRecord::Migration[5.2]
+ def up
+ drop_table :conversation_mutes
+ end
+
+ def down
+ raise ActiveRecord::IrreversibleMigration
+ end
+end
\ No newline at end of file
diff --git a/db/schema.rb b/db/schema.rb
index 6fa418c8..9242e426 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2020_09_08_210104) do
+ActiveRecord::Schema.define(version: 2020_11_09_233215) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
@@ -29,27 +29,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["conversation_id"], name: "index_account_conversations_on_conversation_id"
end
- create_table "account_domain_blocks", force: :cascade do |t|
- t.string "domain"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.bigint "account_id"
- t.index ["account_id", "domain"], name: "index_account_domain_blocks_on_account_id_and_domain", unique: true
- end
-
- create_table "account_identity_proofs", force: :cascade do |t|
- t.bigint "account_id"
- t.string "provider", default: "", null: false
- t.string "provider_username", default: "", null: false
- t.text "token", default: "", null: false
- t.boolean "verified", default: false, null: false
- t.boolean "live", default: false, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.index ["account_id", "provider", "provider_username"], name: "index_account_proofs_on_account_and_provider_and_username", unique: true
- t.index ["account_id"], name: "index_account_identity_proofs_on_account_id"
- end
-
create_table "account_moderation_notes", force: :cascade do |t|
t.text "content", null: false
t.bigint "account_id", null: false
@@ -60,16 +39,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["target_account_id"], name: "index_account_moderation_notes_on_target_account_id"
end
- create_table "account_pins", force: :cascade do |t|
- t.bigint "account_id"
- t.bigint "target_account_id"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.index ["account_id", "target_account_id"], name: "index_account_pins_on_account_id_and_target_account_id", unique: true
- t.index ["account_id"], name: "index_account_pins_on_account_id"
- t.index ["target_account_id"], name: "index_account_pins_on_target_account_id"
- end
-
create_table "account_stats", force: :cascade do |t|
t.bigint "account_id", null: false
t.bigint "statuses_count", default: 0, null: false
@@ -225,12 +194,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.boolean "success", default: false, null: false
end
- create_table "conversation_mutes", force: :cascade do |t|
- t.bigint "conversation_id", null: false
- t.bigint "account_id", null: false
- t.index ["account_id", "conversation_id"], name: "index_conversation_mutes_on_account_id_and_conversation_id", unique: true
- end
-
create_table "conversations", force: :cascade do |t|
t.string "uri"
t.datetime "created_at", null: false
@@ -266,16 +229,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["account_id"], name: "index_custom_filters_on_account_id"
end
- create_table "domain_blocks", force: :cascade do |t|
- t.string "domain", default: "", null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.integer "severity", default: 0
- t.boolean "reject_media", default: false, null: false
- t.boolean "reject_reports", default: false, null: false
- t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true
- end
-
create_table "email_domain_blocks", force: :cascade do |t|
t.string "domain", default: "", null: false
t.datetime "created_at", null: false
@@ -293,17 +246,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["status_id"], name: "index_favourites_on_status_id"
end
- create_table "featured_tags", force: :cascade do |t|
- t.bigint "account_id"
- t.bigint "tag_id"
- t.bigint "statuses_count", default: 0, null: false
- t.datetime "last_status_at"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.index ["account_id"], name: "index_featured_tags_on_account_id"
- t.index ["tag_id"], name: "index_featured_tags_on_tag_id"
- end
-
create_table "follow_requests", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
@@ -406,32 +348,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["user_id"], name: "index_identities_on_user_id"
end
- create_table "imports", force: :cascade do |t|
- t.integer "type", null: false
- t.boolean "approved", default: false, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.string "data_file_name"
- t.string "data_content_type"
- t.integer "data_file_size"
- t.datetime "data_updated_at"
- t.bigint "account_id", null: false
- t.boolean "overwrite", default: false, null: false
- end
-
- create_table "invites", force: :cascade do |t|
- t.bigint "user_id", null: false
- t.string "code", default: "", null: false
- t.datetime "expires_at"
- t.integer "max_uses"
- t.integer "uses", default: 0, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "autofollow", default: false, null: false
- t.index ["code"], name: "index_invites_on_code", unique: true
- t.index ["user_id"], name: "index_invites_on_user_id"
- end
-
create_table "list_accounts", force: :cascade do |t|
t.bigint "list_id", null: false
t.bigint "account_id", null: false
@@ -623,14 +539,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.integer "position", default: 10
end
- create_table "relays", force: :cascade do |t|
- t.string "inbox_url", default: "", null: false
- t.string "follow_activity_id"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.integer "state", default: 0, null: false
- end
-
create_table "report_notes", force: :cascade do |t|
t.text "content", null: false
t.bigint "report_id", null: false
@@ -793,30 +701,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["tag_id", "status_id"], name: "index_statuses_tags_on_tag_id_and_status_id", unique: true
end
- create_table "stream_entries", force: :cascade do |t|
- t.bigint "activity_id"
- t.string "activity_type"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "hidden", default: false, null: false
- t.bigint "account_id"
- t.index ["account_id", "activity_type", "id"], name: "index_stream_entries_on_account_id_and_activity_type_and_id"
- t.index ["activity_id", "activity_type"], name: "index_stream_entries_on_activity_id_and_activity_type"
- end
-
- create_table "subscriptions", force: :cascade do |t|
- t.string "callback_url", default: "", null: false
- t.string "secret"
- t.datetime "expires_at"
- t.boolean "confirmed", default: false, null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.datetime "last_successful_delivery_at"
- t.string "domain"
- t.bigint "account_id", null: false
- t.index ["account_id", "callback_url"], name: "index_subscriptions_on_account_id_and_callback_url", unique: true
- end
-
create_table "tags", force: :cascade do |t|
t.string "name", default: "", null: false
t.datetime "created_at", null: false
@@ -846,14 +730,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.boolean "success", default: false, null: false
end
- create_table "user_invite_requests", force: :cascade do |t|
- t.bigint "user_id"
- t.text "text"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.index ["user_id"], name: "index_user_invite_requests_on_user_id"
- end
-
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.datetime "created_at", null: false
@@ -884,7 +760,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.bigint "account_id", null: false
t.boolean "disabled", default: false, null: false
t.boolean "moderator", default: false, null: false
- t.bigint "invite_id"
t.string "remember_token"
t.string "chosen_languages", array: true
t.bigint "created_by_application_id"
@@ -924,12 +799,8 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
add_foreign_key "account_conversations", "accounts", on_delete: :cascade
add_foreign_key "account_conversations", "conversations", on_delete: :cascade
- add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade
- add_foreign_key "account_identity_proofs", "accounts", on_delete: :cascade
add_foreign_key "account_moderation_notes", "accounts"
add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id"
- add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade
- add_foreign_key "account_pins", "accounts", on_delete: :cascade
add_foreign_key "account_stats", "accounts", on_delete: :cascade
add_foreign_key "account_tag_stats", "tags", on_delete: :cascade
add_foreign_key "account_warnings", "accounts", column: "target_account_id", on_delete: :cascade
@@ -939,13 +810,9 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
add_foreign_key "backups", "users", on_delete: :nullify
add_foreign_key "blocks", "accounts", column: "target_account_id", name: "fk_9571bfabc1", on_delete: :cascade
add_foreign_key "blocks", "accounts", name: "fk_4269e03e65", on_delete: :cascade
- add_foreign_key "conversation_mutes", "accounts", name: "fk_225b4212bb", on_delete: :cascade
- add_foreign_key "conversation_mutes", "conversations", on_delete: :cascade
add_foreign_key "custom_filters", "accounts", on_delete: :cascade
add_foreign_key "favourites", "accounts", name: "fk_5eb6c2b873", on_delete: :cascade
add_foreign_key "favourites", "statuses", name: "fk_b0e856845e", on_delete: :cascade
- add_foreign_key "featured_tags", "accounts", on_delete: :cascade
- add_foreign_key "featured_tags", "tags", on_delete: :cascade
add_foreign_key "follow_requests", "accounts", column: "target_account_id", name: "fk_9291ec025d", on_delete: :cascade
add_foreign_key "follow_requests", "accounts", name: "fk_76d644b0e7", on_delete: :cascade
add_foreign_key "follows", "accounts", column: "target_account_id", name: "fk_745ca29eac", on_delete: :cascade
@@ -960,8 +827,6 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
add_foreign_key "group_removed_accounts", "groups", on_delete: :cascade
add_foreign_key "groups", "group_categories", on_delete: :nullify
add_foreign_key "identities", "users", name: "fk_bea040f377", on_delete: :cascade
- add_foreign_key "imports", "accounts", name: "fk_6db1b6e408", on_delete: :cascade
- add_foreign_key "invites", "users", on_delete: :cascade
add_foreign_key "list_accounts", "accounts", on_delete: :cascade
add_foreign_key "list_accounts", "follows", on_delete: :cascade
add_foreign_key "list_accounts", "lists", on_delete: :cascade
@@ -1007,12 +872,8 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
add_foreign_key "statuses", "statuses", column: "reblog_of_id", on_delete: :cascade
add_foreign_key "statuses_tags", "statuses", on_delete: :cascade
add_foreign_key "statuses_tags", "tags", name: "fk_3081861e21", on_delete: :cascade
- add_foreign_key "stream_entries", "accounts", name: "fk_5659b17554", on_delete: :cascade
- add_foreign_key "subscriptions", "accounts", name: "fk_9847d1cbb5", on_delete: :cascade
add_foreign_key "tombstones", "accounts", on_delete: :cascade
- add_foreign_key "user_invite_requests", "users", on_delete: :cascade
add_foreign_key "users", "accounts", name: "fk_50500f500d", on_delete: :cascade
- add_foreign_key "users", "invites", on_delete: :nullify
add_foreign_key "users", "oauth_applications", column: "created_by_application_id", on_delete: :nullify
add_foreign_key "web_push_subscriptions", "oauth_access_tokens", column: "access_token_id", on_delete: :cascade
add_foreign_key "web_push_subscriptions", "users", on_delete: :cascade
diff --git a/lib/cli.rb b/lib/cli.rb
index 07c69c27..7decd772 100644
--- a/lib/cli.rb
+++ b/lib/cli.rb
@@ -80,7 +80,7 @@ module GabSocial
exit(1) if prompt.no?('Are you sure you want to proceed?')
- inboxes = Account.inboxes
+ inboxes = nil
processed = 0
dry_run = options[:dry_run] ? ' (DRY RUN)' : ''
diff --git a/lib/gabsocial/accounts_cli.rb b/lib/gabsocial/accounts_cli.rb
index eb879464..b04ef20c 100644
--- a/lib/gabsocial/accounts_cli.rb
+++ b/lib/gabsocial/accounts_cli.rb
@@ -297,7 +297,7 @@ module GabSocial
say("Scheduled refreshment of #{queued} accounts", :green, true)
elsif username.present?
username, domain = username.split('@')
- account = Account.find_remote(username, domain)
+ account = Account.find_local(username)
if account.nil?
say('No such account', :red)
@@ -498,7 +498,6 @@ module GabSocial
old_key = account.private_key
new_key = OpenSSL::PKey::RSA.new(2048)
account.update(private_key: new_key.to_pem, public_key: new_key.public_key.to_pem)
- ActivityPub::UpdateDistributionWorker.perform_in(delay, account.id, sign_with: old_key)
end
end
end
diff --git a/lib/gabsocial/settings_cli.rb b/lib/gabsocial/settings_cli.rb
index 17e54973..4b2522e0 100644
--- a/lib/gabsocial/settings_cli.rb
+++ b/lib/gabsocial/settings_cli.rb
@@ -15,12 +15,6 @@ module GabSocial
Setting.registrations_mode = 'open'
say('OK', :green)
end
-
- desc 'close', 'Close registrations'
- def close
- Setting.registrations_mode = 'none'
- say('OK', :green)
- end
end
class SettingsCLI < Thor
diff --git a/package.json b/package.json
index f743aa20..3d56b772 100644
--- a/package.json
+++ b/package.json
@@ -9,10 +9,7 @@
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/webpack",
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack",
"manage:translations": "node ./config/webpack/translationRunner.js",
- "start": "node ./streaming/index.js",
- "test": "${npm_execpath} run test:lint && ${npm_execpath} run test:jest",
- "test:lint": "eslint --ext=js .",
- "test:jest": "cross-env NODE_ENV=test jest --coverage"
+ "start": "node ./streaming/index.js"
},
"repository": {
"type": "git",
@@ -24,37 +21,6 @@
"iOS >= 9",
"not dead"
],
- "jest": {
- "projects": [
- "/app/javascript/gabsocial"
- ],
- "testPathIgnorePatterns": [
- "/node_modules/",
- "/vendor/",
- "/config/",
- "/log/",
- "/public/",
- "/tmp/"
- ],
- "setupFiles": [
- "raf/polyfill"
- ],
- "setupFilesAfterEnv": [
- "/app/javascript/gabsocial/test_setup.js"
- ],
- "collectCoverageFrom": [
- "app/javascript/gabsocial/**/*.js",
- "!app/javascript/gabsocial/components/emoji/emoji_compressed.js",
- "!app/javascript/gabsocial/locales/locale-data/*.js",
- "!app/javascript/gabsocial/service_worker/entry.js",
- "!app/javascript/gabsocial/test_setup.js"
- ],
- "coverageDirectory": "/coverage",
- "moduleDirectories": [
- "/node_modules",
- "/app/javascript"
- ]
- },
"private": true,
"dependencies": {
"@babel/core": "^7.3.4",
@@ -174,16 +140,12 @@
},
"devDependencies": {
"babel-eslint": "^10.0.1",
- "babel-jest": "^24.8.0",
"cssnano": "^4.1.10",
- "enzyme": "^3.8.0",
- "enzyme-adapter-react-16": "^1.7.1",
"eslint": "^5.11.1",
"eslint-plugin-import": "~2.14.0",
"eslint-plugin-jsx-a11y": "~6.2.1",
"eslint-plugin-promise": "~4.1.1",
"eslint-plugin-react": "~7.12.1",
- "jest": "^24.8.0",
"raf": "^3.4.1",
"react-intl-translations-manager": "^5.0.3",
"react-test-renderer": "^16.7.0",
diff --git a/spec/controllers/about_controller_spec.rb b/spec/controllers/about_controller_spec.rb
deleted file mode 100644
index 03dddd8c..00000000
--- a/spec/controllers/about_controller_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AboutController, type: :controller do
- render_views
-
- describe 'GET #show' do
- before do
- get :show
- end
-
- it 'assigns @instance_presenter' do
- expect(assigns(:instance_presenter)).to be_kind_of InstancePresenter
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #more' do
- before do
- get :more
- end
-
- it 'assigns @instance_presenter' do
- expect(assigns(:instance_presenter)).to be_kind_of InstancePresenter
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #terms' do
- before do
- get :terms
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'helper_method :new_user' do
- it 'returns a new User' do
- user = @controller.view_context.new_user
- expect(user).to be_kind_of User
- expect(user.account).to be_kind_of Account
- end
- end
-end
diff --git a/spec/controllers/account_follow_controller_spec.rb b/spec/controllers/account_follow_controller_spec.rb
deleted file mode 100644
index ac15499b..00000000
--- a/spec/controllers/account_follow_controller_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'rails_helper'
-
-describe AccountFollowController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- describe 'POST #create' do
- let(:service) { double }
-
- subject { post :create, params: { account_username: alice.username } }
-
- before do
- allow(FollowService).to receive(:new).and_return(service)
- allow(service).to receive(:call)
- end
-
- it 'does not create for user who is not signed in' do
- subject
- expect(FollowService).not_to receive(:new)
- end
-
- it 'redirects to account path' do
- sign_in(user)
- subject
-
- expect(service).to have_received(:call).with(user.account, 'alice')
- expect(response).to redirect_to(account_path(alice))
- end
- end
-end
diff --git a/spec/controllers/account_unfollow_controller_spec.rb b/spec/controllers/account_unfollow_controller_spec.rb
deleted file mode 100644
index bdebcfa9..00000000
--- a/spec/controllers/account_unfollow_controller_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'rails_helper'
-
-describe AccountUnfollowController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- describe 'POST #create' do
- let(:service) { double }
-
- subject { post :create, params: { account_username: alice.username } }
-
- before do
- allow(UnfollowService).to receive(:new).and_return(service)
- allow(service).to receive(:call)
- end
-
- it 'does not create for user who is not signed in' do
- subject
- expect(UnfollowService).not_to receive(:new)
- end
-
- it 'redirects to account path' do
- sign_in(user)
- subject
-
- expect(service).to have_received(:call).with(user.account, alice)
- expect(response).to redirect_to(account_path(alice))
- end
- end
-end
diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb
deleted file mode 100644
index b85f748b..00000000
--- a/spec/controllers/accounts_controller_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AccountsController, type: :controller do
- render_views
-
- let(:alice) { Fabricate(:account, username: 'alice', user: Fabricate(:user)) }
- let(:eve) { Fabricate(:user) }
-
- describe 'GET #show' do
- let!(:status1) { Status.create!(account: alice, text: 'Hello world') }
- let!(:status2) { Status.create!(account: alice, text: 'Boop', thread: status1) }
- let!(:status3) { Status.create!(account: alice, text: 'Picture!') }
- let!(:status4) { Status.create!(account: alice, text: 'Mentioning @alice') }
- let!(:status5) { Status.create!(account: alice, text: 'Kitsune') }
- let!(:status6) { Status.create!(account: alice, text: 'Neko') }
- let!(:status7) { Status.create!(account: alice, text: 'Tanuki') }
-
- let!(:status_pin1) { StatusPin.create!(account: alice, status: status5, created_at: 5.days.ago) }
- let!(:status_pin2) { StatusPin.create!(account: alice, status: status6, created_at: 2.years.ago) }
- let!(:status_pin3) { StatusPin.create!(account: alice, status: status7, created_at: 10.minutes.ago) }
-
- before do
- alice.block!(eve.account)
- status3.media_attachments.create!(account: alice, file: fixture_file_upload('files/attachment.jpg', 'image/jpeg'))
- end
-
- shared_examples 'responses' do
- before do
- sign_in(current_user) if defined? current_user
- get :show, params: {
- username: alice.username,
- max_id: (max_id if defined? max_id),
- since_id: (since_id if defined? since_id),
- current_user: (current_user if defined? current_user),
- }, format: format
- end
-
- it 'assigns @account' do
- expect(assigns(:account)).to eq alice
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns correct format' do
- expect(response.content_type).to eq content_type
- end
- end
-
- context 'atom' do
- let(:format) { 'atom' }
- let(:content_type) { 'application/atom+xml' }
-
- shared_examples 'responsed streams' do
- it 'assigns @entries' do
- entries = assigns(:entries).to_a
- expect(entries.size).to eq expected_statuses.size
- entries.each.zip(expected_statuses.each) do |entry, expected_status|
- expect(entry.status).to eq expected_status
- end
- end
- end
-
- include_examples 'responses'
- end
-
- context 'activitystreams2' do
- let(:format) { 'json' }
- let(:content_type) { 'application/activity+json' }
-
- include_examples 'responses'
- end
-
- context 'html' do
- let(:format) { nil }
- let(:content_type) { 'text/html' }
-
-
- include_examples 'responses'
- end
- end
-end
diff --git a/spec/controllers/activitypub/collections_controller_spec.rb b/spec/controllers/activitypub/collections_controller_spec.rb
deleted file mode 100644
index 34114cc8..00000000
--- a/spec/controllers/activitypub/collections_controller_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe ActivityPub::CollectionsController, type: :controller do
- describe 'POST #show' do
- let(:account) { Fabricate(:account) }
-
- context 'id is "featured"' do
- it 'returns 200 with "application/activity+json"' do
- post :show, params: { id: 'featured', account_username: account.username }
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/activity+json'
- end
- end
-
- context 'id is not "featured"' do
- it 'returns 404' do
- post :show, params: { id: 'hoge', account_username: account.username }
- expect(response).to have_http_status(404)
- end
- end
- end
-end
diff --git a/spec/controllers/activitypub/inboxes_controller_spec.rb b/spec/controllers/activitypub/inboxes_controller_spec.rb
deleted file mode 100644
index eab4b8c3..00000000
--- a/spec/controllers/activitypub/inboxes_controller_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe ActivityPub::InboxesController, type: :controller do
- describe 'POST #create' do
- context 'if signed_request_account' do
- it 'returns 202' do
- allow(controller).to receive(:signed_request_account) do
- Fabricate(:account)
- end
-
- post :create, body: '{}'
- expect(response).to have_http_status(202)
- end
- end
-
- context 'not signed_request_account' do
- it 'returns 401' do
- allow(controller).to receive(:signed_request_account) do
- false
- end
-
- post :create, body: '{}'
- expect(response).to have_http_status(401)
- end
- end
- end
-end
diff --git a/spec/controllers/activitypub/outboxes_controller_spec.rb b/spec/controllers/activitypub/outboxes_controller_spec.rb
deleted file mode 100644
index 47460b22..00000000
--- a/spec/controllers/activitypub/outboxes_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::OutboxesController, type: :controller do
- let!(:account) { Fabricate(:account) }
-
- before do
- Fabricate(:status, account: account)
- end
-
- describe 'GET #show' do
- before do
- get :show, params: { account_username: account.username }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns application/activity+json' do
- expect(response.content_type).to eq 'application/activity+json'
- end
- end
-end
diff --git a/spec/controllers/admin/account_moderation_notes_controller_spec.rb b/spec/controllers/admin/account_moderation_notes_controller_spec.rb
deleted file mode 100644
index 410ce654..00000000
--- a/spec/controllers/admin/account_moderation_notes_controller_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::AccountModerationNotesController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
- let(:target_account) { Fabricate(:account) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'POST #create' do
- subject { post :create, params: params }
-
- context 'when parameters are valid' do
- let(:params) { { account_moderation_note: { target_account_id: target_account.id, content: 'test content' } } }
-
- it 'successfully creates a note' do
- expect { subject }.to change { AccountModerationNote.count }.by(1)
- expect(subject).to redirect_to admin_account_path(target_account.id)
- end
- end
-
- context 'when parameters are invalid' do
- let(:params) { { account_moderation_note: { target_account_id: target_account.id, content: '' } } }
-
- it 'falls to create a note' do
- expect { subject }.not_to change { AccountModerationNote.count }
- expect(subject).to render_template 'admin/accounts/show'
- end
- end
- end
-
- describe 'DELETE #destroy' do
- subject { delete :destroy, params: { id: note.id } }
-
- let!(:note) { Fabricate(:account_moderation_note, account: account, target_account: target_account) }
- let(:account) { Fabricate(:account) }
-
- it 'destroys note' do
- expect { subject }.to change { AccountModerationNote.count }.by(-1)
- expect(subject).to redirect_to admin_account_path(target_account.id)
- end
- end
-end
diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb
deleted file mode 100644
index a348ab3d..00000000
--- a/spec/controllers/admin/accounts_controller_spec.rb
+++ /dev/null
@@ -1,239 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::AccountsController, type: :controller do
- render_views
-
- before { sign_in current_user, scope: :user }
-
- describe 'GET #index' do
- let(:current_user) { Fabricate(:user, admin: true) }
-
- around do |example|
- default_per_page = Account.default_per_page
- Account.paginates_per 1
- example.run
- Account.paginates_per default_per_page
- end
-
- it 'filters with parameters' do
- new = AccountFilter.method(:new)
-
- expect(AccountFilter).to receive(:new) do |params|
- h = params.to_h
-
- expect(h[:local]).to eq '1'
- expect(h[:remote]).to eq '1'
- expect(h[:by_domain]).to eq 'domain'
- expect(h[:active]).to eq '1'
- expect(h[:silenced]).to eq '1'
- expect(h[:suspended]).to eq '1'
- expect(h[:username]).to eq 'username'
- expect(h[:display_name]).to eq 'display name'
- expect(h[:email]).to eq 'local-part@domain'
- expect(h[:ip]).to eq '0.0.0.42'
-
- new.call({})
- end
-
- get :index, params: {
- local: '1',
- remote: '1',
- by_domain: 'domain',
- active: '1',
- silenced: '1',
- suspended: '1',
- username: 'username',
- display_name: 'display name',
- email: 'local-part@domain',
- ip: '0.0.0.42'
- }
- end
-
- it 'paginates accounts' do
- Fabricate(:account)
-
- get :index, params: { page: 2 }
-
- accounts = assigns(:accounts)
- expect(accounts.count).to eq 1
- expect(accounts.klass).to be Account
- end
-
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #show' do
- let(:current_user) { Fabricate(:user, admin: true) }
- let(:account) { Fabricate(:account, username: 'bob') }
-
- it 'returns http success' do
- get :show, params: { id: account.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #subscribe' do
- subject { post :subscribe, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: admin) }
- let(:account) { Fabricate(:account) }
-
- context 'when user is admin' do
- let(:admin) { true }
-
- it { is_expected.to redirect_to admin_account_path(account.id) }
- end
-
- context 'when user is not admin' do
- let(:admin) { false }
-
- it { is_expected.to have_http_status :forbidden }
- end
- end
-
- describe 'POST #unsubscribe' do
- subject { post :unsubscribe, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: admin) }
- let(:account) { Fabricate(:account) }
-
- context 'when user is admin' do
- let(:admin) { true }
-
- it { is_expected.to redirect_to admin_account_path(account.id) }
- end
-
- context 'when user is not admin' do
- let(:admin) { false }
-
- it { is_expected.to have_http_status :forbidden }
- end
- end
-
- describe 'POST #memorialize' do
- subject { post :memorialize, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: current_user_admin) }
- let(:account) { Fabricate(:account, user: user) }
- let(:user) { Fabricate(:user, admin: target_user_admin) }
-
- context 'when user is admin' do
- let(:current_user_admin) { true }
-
- context 'when target user is admin' do
- let(:target_user_admin) { true }
-
- it 'fails to memorialize account' do
- is_expected.to have_http_status :forbidden
- expect(account.reload).not_to be_memorial
- end
- end
-
- context 'when target user is not admin' do
- let(:target_user_admin) { false }
-
- it 'succeeds in memorializing account' do
- is_expected.to redirect_to admin_account_path(account.id)
- expect(account.reload).to be_memorial
- end
- end
- end
-
- context 'when user is not admin' do
- let(:current_user_admin) { false }
-
- context 'when target user is admin' do
- let(:target_user_admin) { true }
-
- it 'fails to memorialize account' do
- is_expected.to have_http_status :forbidden
- expect(account.reload).not_to be_memorial
- end
- end
-
- context 'when target user is not admin' do
- let(:target_user_admin) { false }
-
- it 'fails to memorialize account' do
- is_expected.to have_http_status :forbidden
- expect(account.reload).not_to be_memorial
- end
- end
- end
- end
-
- describe 'POST #enable' do
- subject { post :enable, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: admin) }
- let(:account) { Fabricate(:account, user: user) }
- let(:user) { Fabricate(:user, disabled: true) }
-
- context 'when user is admin' do
- let(:admin) { true }
-
- it 'succeeds in enabling account' do
- is_expected.to redirect_to admin_account_path(account.id)
- expect(user.reload).not_to be_disabled
- end
- end
-
- context 'when user is not admin' do
- let(:admin) { false }
-
- it 'fails to enable account' do
- is_expected.to have_http_status :forbidden
- expect(user.reload).to be_disabled
- end
- end
- end
-
- describe 'POST #redownload' do
- subject { post :redownload, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: admin) }
- let(:account) { Fabricate(:account) }
-
- context 'when user is admin' do
- let(:admin) { true }
-
- it 'succeeds in redownloadin' do
- is_expected.to redirect_to admin_account_path(account.id)
- end
- end
-
- context 'when user is not admin' do
- let(:admin) { false }
-
- it 'fails to redownload' do
- is_expected.to have_http_status :forbidden
- end
- end
- end
-
- describe 'POST #remove_avatar' do
- subject { post :remove_avatar, params: { id: account.id } }
-
- let(:current_user) { Fabricate(:user, admin: admin) }
- let(:account) { Fabricate(:account) }
-
- context 'when user is admin' do
- let(:admin) { true }
-
- it 'succeeds in removing avatar' do
- is_expected.to redirect_to admin_account_path(account.id)
- end
- end
-
- context 'when user is not admin' do
- let(:admin) { false }
-
- it 'fails to remove avatar' do
- is_expected.to have_http_status :forbidden
- end
- end
- end
-end
diff --git a/spec/controllers/admin/action_logs_controller_spec.rb b/spec/controllers/admin/action_logs_controller_spec.rb
deleted file mode 100644
index 4720ed2e..00000000
--- a/spec/controllers/admin/action_logs_controller_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::ActionLogsController, type: :controller do
- describe 'GET #index' do
- it 'returns 200' do
- sign_in Fabricate(:user, admin: true)
- get :index, params: { page: 1 }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/admin/base_controller_spec.rb b/spec/controllers/admin/base_controller_spec.rb
deleted file mode 100644
index 9ac83362..00000000
--- a/spec/controllers/admin/base_controller_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::BaseController, type: :controller do
- controller do
- def success
- render 'admin/reports/show'
- end
- end
-
- it 'requires administrator or moderator' do
- routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, admin: false, moderator: false))
- get :success
-
- expect(response).to have_http_status(:forbidden)
- end
-
- it 'renders admin layout as a moderator' do
- routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, moderator: true))
- get :success
- expect(response).to render_template layout: 'admin'
- end
-
- it 'renders admin layout as an admin' do
- routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, admin: true))
- get :success
- expect(response).to render_template layout: 'admin'
- end
-end
diff --git a/spec/controllers/admin/change_email_controller_spec.rb b/spec/controllers/admin/change_email_controller_spec.rb
deleted file mode 100644
index 31df0f0f..00000000
--- a/spec/controllers/admin/change_email_controller_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::ChangeEmailsController, type: :controller do
- render_views
-
- let(:admin) { Fabricate(:user, admin: true) }
-
- before do
- sign_in admin
- end
-
- describe "GET #show" do
- it "returns http success" do
- account = Fabricate(:account)
- user = Fabricate(:user, account: account)
-
- get :show, params: { account_id: account.id }
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe "GET #update" do
- before do
- allow(UserMailer).to receive(:confirmation_instructions).and_return(double('email', deliver_later: nil))
- end
-
- it "returns http success" do
- account = Fabricate(:account)
- user = Fabricate(:user, account: account)
-
- previous_email = user.email
-
- post :update, params: { account_id: account.id, user: { unconfirmed_email: 'test@example.com' } }
-
- user.reload
-
- expect(user.email).to eq previous_email
- expect(user.unconfirmed_email).to eq 'test@example.com'
- expect(user.confirmation_token).not_to be_nil
-
- expect(UserMailer).to have_received(:confirmation_instructions).with(user, user.confirmation_token, { to: 'test@example.com' })
-
- expect(response).to redirect_to(admin_account_path(account.id))
- end
- end
-end
diff --git a/spec/controllers/admin/confirmations_controller_spec.rb b/spec/controllers/admin/confirmations_controller_spec.rb
deleted file mode 100644
index eec2b2f5..00000000
--- a/spec/controllers/admin/confirmations_controller_spec.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::ConfirmationsController, type: :controller do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'POST #create' do
- it 'confirms the user' do
- account = Fabricate(:account)
- user = Fabricate(:user, confirmed_at: false, account: account)
- post :create, params: { account_id: account.id }
-
- expect(response).to redirect_to(admin_accounts_path)
- expect(user.reload).to be_confirmed
- end
-
- it 'raises an error when there is no account' do
- post :create, params: { account_id: 'fake' }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises an error when there is no user' do
- account = Fabricate(:account, user: nil)
- post :create, params: { account_id: account.id }
-
- expect(response).to have_http_status(404)
- end
- end
-
- describe 'POST #resernd' do
- subject { post :resend, params: { account_id: account.id } }
-
- let(:account) { Fabricate(:account) }
- let!(:user) { Fabricate(:user, confirmed_at: confirmed_at, account: account) }
-
- before do
- allow(UserMailer).to receive(:confirmation_instructions) { double(:email, deliver_later: nil) }
- end
-
- context 'when email is not confirmed' do
- let(:confirmed_at) { nil }
-
- it 'resends confirmation mail' do
- expect(subject).to redirect_to admin_accounts_path
- expect(flash[:notice]).to eq I18n.t('admin.accounts.resend_confirmation.success')
- expect(UserMailer).to have_received(:confirmation_instructions).once
- end
- end
-
- context 'when email is confirmed' do
- let(:confirmed_at) { Time.zone.now }
-
- it 'does not resend confirmation mail' do
- expect(subject).to redirect_to admin_accounts_path
- expect(flash[:error]).to eq I18n.t('admin.accounts.resend_confirmation.already_confirmed')
- expect(UserMailer).not_to have_received(:confirmation_instructions)
- end
- end
- end
-end
diff --git a/spec/controllers/admin/custom_emojis_controller_spec.rb b/spec/controllers/admin/custom_emojis_controller_spec.rb
deleted file mode 100644
index b7e2894e..00000000
--- a/spec/controllers/admin/custom_emojis_controller_spec.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-require 'rails_helper'
-
-describe Admin::CustomEmojisController do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- subject { get :index }
-
- before do
- Fabricate(:custom_emoji)
- end
-
- it 'renders index page' do
- expect(subject).to have_http_status 200
- expect(subject).to render_template :index
- end
- end
-
- describe 'GET #new' do
- subject { get :new }
-
- it 'renders new page' do
- expect(subject).to have_http_status 200
- expect(subject).to render_template :new
- end
- end
-
- describe 'POST #create' do
- subject { post :create, params: { custom_emoji: params } }
-
- let(:image) { fixture_file_upload(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png'), 'image/png') }
-
- context 'when parameter is valid' do
- let(:params) { { shortcode: 'test', image: image } }
-
- it 'creates custom emoji' do
- expect { subject }.to change { CustomEmoji.count }.by(1)
- end
- end
-
- context 'when parameter is invalid' do
- let(:params) { { shortcode: 't', image: image } }
-
- it 'renders new' do
- expect(subject).to render_template :new
- end
- end
- end
-
- describe 'PUT #update' do
- let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test') }
- let(:image) { fixture_file_upload(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png'), 'image/png') }
-
- before do
- put :update, params: { id: custom_emoji.id, custom_emoji: params }
- end
-
- context 'when parameter is valid' do
- let(:params) { { shortcode: 'updated', image: image } }
-
- it 'succeeds in updating custom emoji' do
- expect(flash[:notice]).to eq I18n.t('admin.custom_emojis.updated_msg')
- expect(custom_emoji.reload).to have_attributes(shortcode: 'updated')
- end
- end
-
- context 'when parameter is invalid' do
- let(:params) { { shortcode: 'u', image: image } }
-
- it 'fails to update custom emoji' do
- expect(flash[:alert]).to eq I18n.t('admin.custom_emojis.update_failed_msg')
- expect(custom_emoji.reload).to have_attributes(shortcode: 'test')
- end
- end
- end
-
- describe 'POST #copy' do
- subject { post :copy, params: { id: custom_emoji.id } }
-
- let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test') }
-
- it 'copies custom emoji' do
- expect { subject }.to change { CustomEmoji.where(shortcode: 'test').count }.by(1)
- expect(flash[:notice]).to eq I18n.t('admin.custom_emojis.copied_msg')
- end
- end
-
- describe 'POST #enable' do
- let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test', disabled: true) }
-
- before { post :enable, params: { id: custom_emoji.id } }
-
- it 'enables custom emoji' do
- expect(response).to redirect_to admin_custom_emojis_path
- expect(custom_emoji.reload).to have_attributes(disabled: false)
- end
- end
-
- describe 'POST #disable' do
- let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: 'test', disabled: false) }
-
- before { post :disable, params: { id: custom_emoji.id } }
-
- it 'enables custom emoji' do
- expect(response).to redirect_to admin_custom_emojis_path
- expect(custom_emoji.reload).to have_attributes(disabled: true)
- end
- end
-end
diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb
deleted file mode 100644
index 73b50e72..00000000
--- a/spec/controllers/admin/dashboard_controller_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::DashboardController, type: :controller do
- describe 'GET #index' do
- it 'returns 200' do
- sign_in Fabricate(:user, admin: true)
- get :index
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/admin/domain_blocks_controller_spec.rb b/spec/controllers/admin/domain_blocks_controller_spec.rb
deleted file mode 100644
index fb23658c..00000000
--- a/spec/controllers/admin/domain_blocks_controller_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::DomainBlocksController, type: :controller do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'GET #new' do
- it 'assigns a new domain block' do
- get :new
-
- expect(assigns(:domain_block)).to be_instance_of(DomainBlock)
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- domain_block = Fabricate(:domain_block)
- get :show, params: { id: domain_block.id }
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- it 'blocks the domain when succeeded to save' do
- allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
-
- post :create, params: { domain_block: { domain: 'example.com', severity: 'silence' } }
-
- expect(DomainBlockWorker).to have_received(:perform_async)
- expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg')
- expect(response).to redirect_to(admin_instances_path(limited: '1'))
- end
-
- it 'renders new when failed to save' do
- Fabricate(:domain_block, domain: 'example.com', severity: 'suspend')
- allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
-
- post :create, params: { domain_block: { domain: 'example.com', severity: 'silence' } }
-
- expect(DomainBlockWorker).not_to have_received(:perform_async)
- expect(response).to render_template :new
- end
-
- it 'allows upgrading a block' do
- Fabricate(:domain_block, domain: 'example.com', severity: 'silence')
- allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
-
- post :create, params: { domain_block: { domain: 'example.com', severity: 'silence', reject_media: true, reject_reports: true } }
-
- expect(DomainBlockWorker).to have_received(:perform_async)
- expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.created_msg')
- expect(response).to redirect_to(admin_instances_path(limited: '1'))
- end
- end
-
- describe 'DELETE #destroy' do
- it 'unblocks the domain' do
- service = double(call: true)
- allow(UnblockDomainService).to receive(:new).and_return(service)
- domain_block = Fabricate(:domain_block)
- delete :destroy, params: { id: domain_block.id }
-
- expect(service).to have_received(:call).with(domain_block)
- expect(flash[:notice]).to eq I18n.t('admin.domain_blocks.destroyed_msg')
- expect(response).to redirect_to(admin_instances_path(limited: '1'))
- end
- end
-end
diff --git a/spec/controllers/admin/email_domain_blocks_controller_spec.rb b/spec/controllers/admin/email_domain_blocks_controller_spec.rb
deleted file mode 100644
index 52db56f4..00000000
--- a/spec/controllers/admin/email_domain_blocks_controller_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::EmailDomainBlocksController, type: :controller do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'GET #index' do
- around do |example|
- default_per_page = EmailDomainBlock.default_per_page
- EmailDomainBlock.paginates_per 1
- example.run
- EmailDomainBlock.paginates_per default_per_page
- end
-
- it 'renders email blacks' do
- 2.times { Fabricate(:email_domain_block) }
-
- get :index, params: { page: 2 }
-
- assigned = assigns(:email_domain_blocks)
- expect(assigned.count).to eq 1
- expect(assigned.klass).to be EmailDomainBlock
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #new' do
- it 'assigns a new email black' do
- get :new
-
- expect(assigns(:email_domain_block)).to be_instance_of(EmailDomainBlock)
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- it 'blocks the domain when succeeded to save' do
- post :create, params: { email_domain_block: { domain: 'example.com' } }
-
- expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.created_msg')
- expect(response).to redirect_to(admin_email_domain_blocks_path)
- end
- end
-
- describe 'DELETE #destroy' do
- it 'unblocks the domain' do
- email_domain_block = Fabricate(:email_domain_block)
- delete :destroy, params: { id: email_domain_block.id }
-
- expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.destroyed_msg')
- expect(response).to redirect_to(admin_email_domain_blocks_path)
- end
- end
-end
diff --git a/spec/controllers/admin/instances_controller_spec.rb b/spec/controllers/admin/instances_controller_spec.rb
deleted file mode 100644
index 412b8144..00000000
--- a/spec/controllers/admin/instances_controller_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::InstancesController, type: :controller do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'GET #index' do
- around do |example|
- default_per_page = Account.default_per_page
- Account.paginates_per 1
- example.run
- Account.paginates_per default_per_page
- end
-
- it 'renders instances' do
- Fabricate(:account, domain: 'popular')
- Fabricate(:account, domain: 'popular')
- Fabricate(:account, domain: 'less.popular')
-
- get :index, params: { page: 2 }
-
- instances = assigns(:instances).to_a
- expect(instances.size).to eq 1
- expect(instances[0].domain).to eq 'less.popular'
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/admin/invites_controller_spec.rb b/spec/controllers/admin/invites_controller_spec.rb
deleted file mode 100644
index 449a699e..00000000
--- a/spec/controllers/admin/invites_controller_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Admin::InvitesController do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- subject { get :index, params: { available: true } }
-
- let!(:invite) { Fabricate(:invite) }
-
- it 'renders index page' do
- expect(subject).to render_template :index
- expect(assigns(:invites)).to include invite
- end
- end
-
- describe 'POST #create' do
- subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
-
- it 'succeeds to create a invite' do
- expect { subject }.to change { Invite.count }.by(1)
- expect(subject).to redirect_to admin_invites_path
- expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
- end
- end
-
- describe 'DELETE #destroy' do
- let!(:invite) { Fabricate(:invite, expires_at: nil) }
-
- subject { delete :destroy, params: { id: invite.id } }
-
- it 'expires invite' do
- expect(subject).to redirect_to admin_invites_path
- expect(invite.reload).to be_expired
- end
- end
-
- describe 'POST #deactivate_all' do
- it 'expires all invites, then redirects to admin_invites_path' do
- invites = Fabricate.times(2, :invite, expires_at: nil)
-
- post :deactivate_all
-
- invites.each do |invite|
- expect(invite.reload).to be_expired
- end
-
- expect(response).to redirect_to admin_invites_path
- end
- end
-end
diff --git a/spec/controllers/admin/report_notes_controller_spec.rb b/spec/controllers/admin/report_notes_controller_spec.rb
deleted file mode 100644
index ec5872c7..00000000
--- a/spec/controllers/admin/report_notes_controller_spec.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-require 'rails_helper'
-
-describe Admin::ReportNotesController do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'POST #create' do
- subject { post :create, params: params }
-
- let(:report) { Fabricate(:report, action_taken: action_taken, action_taken_by_account_id: account_id) }
-
- context 'when parameter is valid' do
- context 'when report is unsolved' do
- let(:action_taken) { false }
- let(:account_id) { nil }
-
- context 'when create_and_resolve flag is on' do
- let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_resolve: nil } }
-
- it 'creates a report note and resolves report' do
- expect { subject }.to change { ReportNote.count }.by(1)
- expect(report.reload).to be_action_taken
- expect(subject).to redirect_to admin_reports_path
- end
- end
-
- context 'when create_and_resolve flag is false' do
- let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
-
- it 'creates a report note and does not resolve report' do
- expect { subject }.to change { ReportNote.count }.by(1)
- expect(report.reload).not_to be_action_taken
- expect(subject).to redirect_to admin_report_path(report)
- end
- end
- end
-
- context 'when report is resolved' do
- let(:action_taken) { true }
- let(:account_id) { user.account.id }
-
- context 'when create_and_unresolve flag is on' do
- let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_unresolve: nil } }
-
- it 'creates a report note and unresolves report' do
- expect { subject }.to change { ReportNote.count }.by(1)
- expect(report.reload).not_to be_action_taken
- expect(subject).to redirect_to admin_report_path(report)
- end
- end
-
- context 'when create_and_unresolve flag is false' do
- let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
-
- it 'creates a report note and does not unresolve report' do
- expect { subject }.to change { ReportNote.count }.by(1)
- expect(report.reload).to be_action_taken
- expect(subject).to redirect_to admin_report_path(report)
- end
- end
- end
- end
-
- context 'when parameter is invalid' do
- let(:params) { { report_note: { content: '', report_id: report.id } } }
- let(:action_taken) { false }
- let(:account_id) { nil }
-
- it 'renders admin/reports/show' do
- expect(subject).to render_template 'admin/reports/show'
- end
- end
- end
-
- describe 'DELETE #destroy' do
- subject { delete :destroy, params: { id: report_note.id } }
-
- let!(:report_note) { Fabricate(:report_note) }
-
- it 'deletes note' do
- expect { subject }.to change { ReportNote.count }.by(-1)
- expect(subject).to redirect_to admin_report_path(report_note.report)
- end
- end
-end
diff --git a/spec/controllers/admin/reported_statuses_controller_spec.rb b/spec/controllers/admin/reported_statuses_controller_spec.rb
deleted file mode 100644
index c358506d..00000000
--- a/spec/controllers/admin/reported_statuses_controller_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require 'rails_helper'
-
-describe Admin::ReportedStatusesController do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
- let(:report) { Fabricate(:report, status_ids: [status.id]) }
- let(:status) { Fabricate(:status) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'POST #create' do
- subject do
- -> { post :create, params: { :report_id => report, action => '', :form_status_batch => { status_ids: status_ids } } }
- end
-
- let(:action) { 'nsfw_on' }
- let(:status_ids) { [status.id] }
- let(:status) { Fabricate(:status, sensitive: !sensitive) }
- let(:sensitive) { true }
- let!(:media_attachment) { Fabricate(:media_attachment, status: status) }
-
- context 'when action is nsfw_on' do
- it 'updates sensitive column' do
- is_expected.to change {
- status.reload.sensitive
- }.from(false).to(true)
- end
- end
-
- context 'when action is nsfw_off' do
- let(:action) { 'nsfw_off' }
- let(:sensitive) { false }
-
- it 'updates sensitive column' do
- is_expected.to change {
- status.reload.sensitive
- }.from(true).to(false)
- end
- end
-
- context 'when action is delete' do
- let(:action) { 'delete' }
-
- it 'removes a status' do
- allow(RemovalWorker).to receive(:perform_async)
- subject.call
- expect(RemovalWorker).to have_received(:perform_async).with(status_ids.first)
- end
- end
-
- it 'redirects to report page' do
- subject.call
- expect(response).to redirect_to(admin_report_path(report))
- end
- end
-end
diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb
deleted file mode 100644
index b428299e..00000000
--- a/spec/controllers/admin/reports_controller_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-require 'rails_helper'
-
-describe Admin::ReportsController do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- it 'returns http success with no filters' do
- specified = Fabricate(:report, action_taken: false)
- Fabricate(:report, action_taken: true)
-
- get :index
-
- reports = assigns(:reports).to_a
- expect(reports.size).to eq 1
- expect(reports[0]).to eq specified
- expect(response).to have_http_status(200)
- end
-
- it 'returns http success with resolved filter' do
- specified = Fabricate(:report, action_taken: true)
- Fabricate(:report, action_taken: false)
-
- get :index, params: { resolved: 1 }
-
- reports = assigns(:reports).to_a
- expect(reports.size).to eq 1
- expect(reports[0]).to eq specified
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #show' do
- it 'renders report' do
- report = Fabricate(:report)
-
- get :show, params: { id: report }
-
- expect(assigns(:report)).to eq report
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #reopen' do
- it 'reopens the report' do
- report = Fabricate(:report)
-
- put :reopen, params: { id: report }
- expect(response).to redirect_to(admin_report_path(report))
- report.reload
- expect(report.action_taken_by_account).to eq nil
- expect(report.action_taken).to eq false
- end
- end
-
- describe 'POST #assign_to_self' do
- it 'reopens the report' do
- report = Fabricate(:report)
-
- put :assign_to_self, params: { id: report }
- expect(response).to redirect_to(admin_report_path(report))
- report.reload
- expect(report.assigned_account).to eq user.account
- end
- end
-
- describe 'POST #unassign' do
- it 'reopens the report' do
- report = Fabricate(:report)
-
- put :unassign, params: { id: report }
- expect(response).to redirect_to(admin_report_path(report))
- report.reload
- expect(report.assigned_account).to eq nil
- end
- end
-end
diff --git a/spec/controllers/admin/resets_controller_spec.rb b/spec/controllers/admin/resets_controller_spec.rb
deleted file mode 100644
index a20a460b..00000000
--- a/spec/controllers/admin/resets_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rails_helper'
-
-describe Admin::ResetsController do
- render_views
-
- let(:account) { Fabricate(:account, user: Fabricate(:user)) }
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'POST #create' do
- it 'redirects to admin accounts page' do
- expect_any_instance_of(User).to receive(:send_reset_password_instructions) do |value|
- expect(value.account_id).to eq account.id
- end
-
- post :create, params: { account_id: account.id }
-
- expect(response).to redirect_to(admin_accounts_path)
- end
- end
-end
diff --git a/spec/controllers/admin/roles_controller_spec.rb b/spec/controllers/admin/roles_controller_spec.rb
deleted file mode 100644
index 8e0de73c..00000000
--- a/spec/controllers/admin/roles_controller_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require 'rails_helper'
-
-describe Admin::RolesController do
- render_views
-
- let(:admin) { Fabricate(:user, admin: true) }
-
- before do
- sign_in admin, scope: :user
- end
-
- describe 'POST #promote' do
- subject { post :promote, params: { account_id: user.account_id } }
-
- let(:user) { Fabricate(:user, moderator: false, admin: false) }
-
- it 'promotes user' do
- expect(subject).to redirect_to admin_account_path(user.account_id)
- expect(user.reload).to be_moderator
- end
- end
-
- describe 'POST #demote' do
- subject { post :demote, params: { account_id: user.account_id } }
-
- let(:user) { Fabricate(:user, moderator: true, admin: false) }
-
- it 'demotes user' do
- expect(subject).to redirect_to admin_account_path(user.account_id)
- expect(user.reload).not_to be_moderator
- end
- end
-end
diff --git a/spec/controllers/admin/settings_controller_spec.rb b/spec/controllers/admin/settings_controller_spec.rb
deleted file mode 100644
index 6cf0ee20..00000000
--- a/spec/controllers/admin/settings_controller_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::SettingsController, type: :controller do
- render_views
-
- describe 'When signed in as an admin' do
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'GET #edit' do
- it 'returns http success' do
- get :edit
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'PUT #update' do
- before do
- allow_any_instance_of(Form::AdminSettings).to receive(:valid?).and_return(true)
- end
-
- describe 'for a record that doesnt exist' do
- around do |example|
- before = Setting.site_extended_description
- Setting.site_extended_description = nil
- example.run
- Setting.site_extended_description = before
- Setting.new_setting_key = nil
- end
-
- it 'cannot create a setting value for a non-admin key' do
- expect(Setting.new_setting_key).to be_blank
-
- patch :update, params: { form_admin_settings: { new_setting_key: 'New key value' } }
-
- expect(response).to redirect_to(edit_admin_settings_path)
- expect(Setting.new_setting_key).to be_nil
- end
-
- it 'creates a settings value that didnt exist before for eligible key' do
- expect(Setting.site_extended_description).to be_blank
-
- patch :update, params: { form_admin_settings: { site_extended_description: 'New key value' } }
-
- expect(response).to redirect_to(edit_admin_settings_path)
- expect(Setting.site_extended_description).to eq 'New key value'
- end
- end
-
- context do
- around do |example|
- site_title = Setting.site_title
- example.run
- Setting.site_title = site_title
- end
-
- it 'updates a settings value' do
- Setting.site_title = 'Original'
- patch :update, params: { form_admin_settings: { site_title: 'New title' } }
-
- expect(response).to redirect_to(edit_admin_settings_path)
- expect(Setting.site_title).to eq 'New title'
- end
- end
- end
- end
-end
diff --git a/spec/controllers/admin/statuses_controller_spec.rb b/spec/controllers/admin/statuses_controller_spec.rb
deleted file mode 100644
index 1a08c10b..00000000
--- a/spec/controllers/admin/statuses_controller_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'rails_helper'
-
-describe Admin::StatusesController do
- render_views
-
- let(:user) { Fabricate(:user, admin: true) }
- let(:account) { Fabricate(:account) }
- let!(:status) { Fabricate(:status, account: account) }
- let(:media_attached_status) { Fabricate(:status, account: account, sensitive: !sensitive) }
- let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: media_attached_status) }
- let(:sensitive) { true }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- it 'returns http success with no media' do
- get :index, params: { account_id: account.id }
-
- statuses = assigns(:statuses).to_a
- expect(statuses.size).to eq 2
- expect(response).to have_http_status(200)
- end
-
- it 'returns http success with media' do
- get :index, params: { account_id: account.id, media: true }
-
- statuses = assigns(:statuses).to_a
- expect(statuses.size).to eq 1
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- subject do
- -> { post :create, params: { :account_id => account.id, action => '', :form_status_batch => { status_ids: status_ids } } }
- end
-
- let(:action) { 'nsfw_on' }
- let(:status_ids) { [media_attached_status.id] }
-
- context 'when action is nsfw_on' do
- it 'updates sensitive column' do
- is_expected.to change {
- media_attached_status.reload.sensitive
- }.from(false).to(true)
- end
- end
-
- context 'when action is nsfw_off' do
- let(:action) { 'nsfw_off' }
- let(:sensitive) { false }
-
- it 'updates sensitive column' do
- is_expected.to change {
- media_attached_status.reload.sensitive
- }.from(true).to(false)
- end
- end
-
- context 'when action is delete' do
- let(:action) { 'delete' }
-
- it 'removes a status' do
- allow(RemovalWorker).to receive(:perform_async)
- subject.call
- expect(RemovalWorker).to have_received(:perform_async).with(status_ids.first)
- end
- end
-
- it 'redirects to account statuses page' do
- subject.call
- expect(response).to redirect_to(admin_account_statuses_path(account.id))
- end
- end
-end
diff --git a/spec/controllers/admin/subscriptions_controller_spec.rb b/spec/controllers/admin/subscriptions_controller_spec.rb
deleted file mode 100644
index 967152ab..00000000
--- a/spec/controllers/admin/subscriptions_controller_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-require 'rails_helper'
-
-RSpec.describe Admin::SubscriptionsController, type: :controller do
- render_views
-
- describe 'GET #index' do
- around do |example|
- default_per_page = Subscription.default_per_page
- Subscription.paginates_per 1
- example.run
- Subscription.paginates_per default_per_page
- end
-
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- it 'renders subscriptions' do
- Fabricate(:subscription)
- specified = Fabricate(:subscription)
-
- get :index
-
- subscriptions = assigns(:subscriptions)
- expect(subscriptions.count).to eq 1
- expect(subscriptions[0]).to eq specified
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/admin/tags_controller_spec.rb b/spec/controllers/admin/tags_controller_spec.rb
deleted file mode 100644
index 3af99407..00000000
--- a/spec/controllers/admin/tags_controller_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::TagsController, type: :controller do
- render_views
-
- before do
- sign_in Fabricate(:user, admin: true)
- end
-
- describe 'GET #index' do
- before do
- account_tag_stat = Fabricate(:tag).account_tag_stat
- account_tag_stat.update(hidden: hidden, accounts_count: 1)
- get :index, params: { hidden: hidden }
- end
-
- context 'with hidden tags' do
- let(:hidden) { true }
-
- it 'returns status 200' do
- expect(response).to have_http_status(200)
- end
- end
-
- context 'without hidden tags' do
- let(:hidden) { false }
-
- it 'returns status 200' do
- expect(response).to have_http_status(200)
- end
- end
- end
-
- describe 'POST #hide' do
- let(:tag) { Fabricate(:tag) }
-
- before do
- tag.account_tag_stat.update(hidden: false)
- post :hide, params: { id: tag.id }
- end
-
- it 'hides tag' do
- tag.reload
- expect(tag).to be_hidden
- end
-
- it 'redirects to admin_tags_path' do
- expect(response).to redirect_to(admin_tags_path(controller.instance_variable_get(:@filter_params)))
- end
- end
-
- describe 'POST #unhide' do
- let(:tag) { Fabricate(:tag) }
-
- before do
- tag.account_tag_stat.update(hidden: true)
- post :unhide, params: { id: tag.id }
- end
-
- it 'unhides tag' do
- tag.reload
- expect(tag).not_to be_hidden
- end
-
- it 'redirects to admin_tags_path' do
- expect(response).to redirect_to(admin_tags_path(controller.instance_variable_get(:@filter_params)))
- end
- end
-end
diff --git a/spec/controllers/admin/two_factor_authentications_controller_spec.rb b/spec/controllers/admin/two_factor_authentications_controller_spec.rb
deleted file mode 100644
index 4c1aa88d..00000000
--- a/spec/controllers/admin/two_factor_authentications_controller_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'rails_helper'
-
-describe Admin::TwoFactorAuthenticationsController do
- render_views
-
- let(:user) { Fabricate(:user, otp_required_for_login: true) }
- before do
- sign_in Fabricate(:user, admin: true), scope: :user
- end
-
- describe 'DELETE #destroy' do
- it 'redirects to admin accounts page' do
- delete :destroy, params: { user_id: user.id }
-
- user.reload
- expect(user.otp_required_for_login).to eq false
- expect(response).to redirect_to(admin_accounts_path)
- end
- end
-end
diff --git a/spec/controllers/api/base_controller_spec.rb b/spec/controllers/api/base_controller_spec.rb
deleted file mode 100644
index ef0e4d90..00000000
--- a/spec/controllers/api/base_controller_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-class FakeService; end
-
-describe Api::BaseController do
- controller do
- def success
- head 200
- end
-
- def error
- FakeService.new
- end
- end
-
- describe 'Forgery protection' do
- before do
- routes.draw { post 'success' => 'api/base#success' }
- end
-
- it 'does not protect from forgery' do
- ActionController::Base.allow_forgery_protection = true
- post 'success'
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'Error handling' do
- ERRORS_WITH_CODES = {
- ActiveRecord::RecordInvalid => 422,
- GabSocial::ValidationError => 422,
- ActiveRecord::RecordNotFound => 404,
- GabSocial::UnexpectedResponseError => 503,
- HTTP::Error => 503,
- OpenSSL::SSL::SSLError => 503,
- GabSocial::NotPermittedError => 403,
- }
-
- before do
- routes.draw { get 'error' => 'api/base#error' }
- end
-
- ERRORS_WITH_CODES.each do |error, code|
- it "Handles error class of #{error}" do
- expect(FakeService).to receive(:new).and_raise(error)
-
- get 'error'
- expect(response).to have_http_status(code)
- end
- end
- end
-end
diff --git a/spec/controllers/api/oembed_controller_spec.rb b/spec/controllers/api/oembed_controller_spec.rb
deleted file mode 100644
index 7fee15a3..00000000
--- a/spec/controllers/api/oembed_controller_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::OEmbedController, type: :controller do
- render_views
-
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:status) { Fabricate(:status, text: 'Hello world', account: alice) }
-
- describe 'GET #show' do
- before do
- request.host = Rails.configuration.x.local_domain
- get :show, params: { url: account_stream_entry_url(alice, status.stream_entry) }, format: :json
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/proofs_controller_spec.rb b/spec/controllers/api/proofs_controller_spec.rb
deleted file mode 100644
index dbde4927..00000000
--- a/spec/controllers/api/proofs_controller_spec.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-require 'rails_helper'
-
-describe Api::ProofsController do
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- before do
- stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_valid.json?domain=cb6e6126.ngrok.io&kb_username=crypto_alice&sig_hash=111111111111111111111111111111111111111111111111111111111111111111&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":false}')
- stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_live.json?domain=cb6e6126.ngrok.io&kb_username=crypto_alice&sig_hash=111111111111111111111111111111111111111111111111111111111111111111&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":true}')
- stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_valid.json?domain=cb6e6126.ngrok.io&kb_username=hidden_alice&sig_hash=222222222222222222222222222222222222222222222222222222222222222222&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":true}')
- stub_request(:get, 'https://keybase.io/_/api/1.0/sig/proof_live.json?domain=cb6e6126.ngrok.io&kb_username=hidden_alice&sig_hash=222222222222222222222222222222222222222222222222222222222222222222&username=alice').to_return(status: 200, body: '{"proof_valid":true,"proof_live":true}')
- end
-
- describe 'GET #index' do
- describe 'with a non-existent username' do
- it '404s' do
- get :index, params: { username: 'nonexistent', provider: 'keybase' }
-
- expect(response).to have_http_status(:not_found)
- end
- end
-
- describe 'with a user that has no proofs' do
- it 'is an empty list of signatures' do
- get :index, params: { username: alice.username, provider: 'keybase' }
-
- expect(body_as_json[:signatures]).to eq []
- end
- end
-
- describe 'with a user that has a live, valid proof' do
- let(:token1) { '111111111111111111111111111111111111111111111111111111111111111111' }
- let(:kb_name1) { 'crypto_alice' }
-
- before do
- Fabricate(:account_identity_proof, account: alice, verified: true, live: true, token: token1, provider_username: kb_name1)
- end
-
- it 'is a list with that proof in it' do
- get :index, params: { username: alice.username, provider: 'keybase' }
-
- expect(body_as_json[:signatures]).to eq [
- { kb_username: kb_name1, sig_hash: token1 },
- ]
- end
-
- describe 'add one that is neither live nor valid' do
- let(:token2) { '222222222222222222222222222222222222222222222222222222222222222222' }
- let(:kb_name2) { 'hidden_alice' }
-
- before do
- Fabricate(:account_identity_proof, account: alice, verified: false, live: false, token: token2, provider_username: kb_name2)
- end
-
- it 'is a list with both proofs' do
- get :index, params: { username: alice.username, provider: 'keybase' }
-
- expect(body_as_json[:signatures]).to eq [
- { kb_username: kb_name1, sig_hash: token1 },
- { kb_username: kb_name2, sig_hash: token2 },
- ]
- end
- end
- end
-
- describe 'a user that has an avatar' do
- let(:alice) { Fabricate(:account, username: 'alice', avatar: attachment_fixture('avatar.gif')) }
-
- context 'and a proof' do
- let(:token1) { '111111111111111111111111111111111111111111111111111111111111111111' }
- let(:kb_name1) { 'crypto_alice' }
-
- before do
- Fabricate(:account_identity_proof, account: alice, verified: true, live: true, token: token1, provider_username: kb_name1)
- get :index, params: { username: alice.username, provider: 'keybase' }
- end
-
- it 'has two keys: signatures and avatar' do
- expect(body_as_json.keys).to match_array [:signatures, :avatar]
- end
-
- it 'has the correct signatures' do
- expect(body_as_json[:signatures]).to eq [
- { kb_username: kb_name1, sig_hash: token1 },
- ]
- end
-
- it 'has the correct avatar url' do
- first_part = 'https://cb6e6126.ngrok.io/system/accounts/avatars/'
- last_part = 'original/avatar.gif'
-
- expect(body_as_json[:avatar]).to match /#{Regexp.quote(first_part)}(?:\d{3,5}\/){3}#{Regexp.quote(last_part)}/
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/push_controller_spec.rb b/spec/controllers/api/push_controller_spec.rb
deleted file mode 100644
index d769d855..00000000
--- a/spec/controllers/api/push_controller_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::PushController, type: :controller do
- describe 'POST #update' do
- context 'with hub.mode=subscribe' do
- it 'creates a subscription' do
- service = double(call: ['', 202])
- allow(Pubsubhubbub::SubscribeService).to receive(:new).and_return(service)
- account = Fabricate(:account)
- account_topic_url = "https://#{Rails.configuration.x.local_domain}/users/#{account.username}.atom"
- post :update, params: {
- 'hub.mode' => 'subscribe',
- 'hub.topic' => account_topic_url,
- 'hub.callback' => 'https://callback.host/api',
- 'hub.lease_seconds' => '3600',
- 'hub.secret' => 'as1234df',
- }
-
- expect(service).to have_received(:call).with(
- account,
- 'https://callback.host/api',
- 'as1234df',
- '3600',
- nil
- )
- expect(response).to have_http_status(202)
- end
- end
-
- context 'with hub.mode=unsubscribe' do
- it 'unsubscribes the account' do
- service = double(call: ['', 202])
- allow(Pubsubhubbub::UnsubscribeService).to receive(:new).and_return(service)
- account = Fabricate(:account)
- account_topic_url = "https://#{Rails.configuration.x.local_domain}/users/#{account.username}.atom"
- post :update, params: {
- 'hub.mode' => 'unsubscribe',
- 'hub.topic' => account_topic_url,
- 'hub.callback' => 'https://callback.host/api',
- }
-
- expect(service).to have_received(:call).with(
- account,
- 'https://callback.host/api',
- )
- expect(response).to have_http_status(202)
- end
- end
-
- context 'with unknown mode' do
- it 'returns an unknown mode error' do
- post :update, params: { 'hub.mode' => 'fake' }
-
- expect(response).to have_http_status(422)
- expect(response.body).to match(/Unknown mode/)
- end
- end
- end
-end
diff --git a/spec/controllers/api/salmon_controller_spec.rb b/spec/controllers/api/salmon_controller_spec.rb
deleted file mode 100644
index f78fd7c8..00000000
--- a/spec/controllers/api/salmon_controller_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::SalmonController, type: :controller do
- render_views
-
- let(:account) { Fabricate(:user, account: Fabricate(:account, username: 'catsrgr8')).account }
-
- before do
- stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt'))
- stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:robcolbert@quitter.no").to_return(request_fixture('webfinger.txt'))
- stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
- stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
- end
-
- describe 'POST #update' do
- context 'with valid post data' do
- before do
- post :update, params: { id: account.id }, body: File.read(Rails.root.join('spec', 'fixtures', 'salmon', 'mention.xml'))
- end
-
- it 'contains XML in the request body' do
- expect(request.body.read).to be_a String
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(202)
- end
-
- it 'creates remote account' do
- expect(Account.find_by(username: 'robcolbert', domain: 'quitter.no')).to_not be_nil
- end
-
- it 'creates status' do
- expect(Status.find_by(uri: 'tag:quitter.no,2016-03-20:noticeId=1276923:objectType=note')).to_not be_nil
- end
-
- it 'creates mention for target account' do
- expect(account.mentions.count).to eq 1
- end
- end
-
- context 'with empty post data' do
- before do
- post :update, params: { id: account.id }, body: ''
- end
-
- it 'returns http client error' do
- expect(response).to have_http_status(400)
- end
- end
-
- context 'with invalid post data' do
- before do
- service = double(call: false)
- allow(VerifySalmonService).to receive(:new).and_return(service)
-
- post :update, params: { id: account.id }, body: File.read(Rails.root.join('spec', 'fixtures', 'salmon', 'mention.xml'))
- end
-
- it 'returns http client error' do
- expect(response).to have_http_status(401)
- end
- end
- end
-end
diff --git a/spec/controllers/api/subscriptions_controller_spec.rb b/spec/controllers/api/subscriptions_controller_spec.rb
deleted file mode 100644
index 894122ba..00000000
--- a/spec/controllers/api/subscriptions_controller_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::SubscriptionsController, type: :controller do
- render_views
-
- let(:account) { Fabricate(:account, username: 'robcolbert', domain: 'quitter.no', remote_url: 'topic_url', secret: 'abc') }
-
- describe 'GET #show' do
- context 'with valid subscription' do
- before do
- get :show, params: { :id => account.id, 'hub.topic' => 'topic_url', 'hub.challenge' => '456', 'hub.lease_seconds' => "#{86400 * 30}" }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'echoes back the challenge' do
- expect(response.body).to match '456'
- end
- end
-
- context 'with invalid subscription' do
- before do
- expect_any_instance_of(Account).to receive_message_chain(:subscription, :valid?).and_return(false)
- get :show, params: { :id => account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(404)
- end
- end
- end
-
- describe 'POST #update' do
- let(:feed) { File.read(Rails.root.join('spec', 'fixtures', 'push', 'feed.atom')) }
-
- before do
- stub_request(:post, "https://quitter.no/main/push/hub").to_return(:status => 200, :body => "", :headers => {})
- stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
- stub_request(:get, "https://quitter.no/notice/1269244").to_return(status: 404)
- stub_request(:get, "https://quitter.no/notice/1265331").to_return(status: 404)
- stub_request(:get, "https://community.highlandarrow.com/notice/54411").to_return(status: 404)
- stub_request(:get, "https://community.highlandarrow.com/notice/53857").to_return(status: 404)
- stub_request(:get, "https://community.highlandarrow.com/notice/51852").to_return(status: 404)
- stub_request(:get, "https://social.umeahackerspace.se/notice/424348").to_return(status: 404)
- stub_request(:get, "https://community.highlandarrow.com/notice/50467").to_return(status: 404)
- stub_request(:get, "https://quitter.no/notice/1243309").to_return(status: 404)
- stub_request(:get, "https://quitter.no/user/7477").to_return(status: 404)
- stub_request(:any, "https://community.highlandarrow.com/user/1").to_return(status: 404)
- stub_request(:any, "https://social.umeahackerspace.se/user/2").to_return(status: 404)
- stub_request(:any, "https://gs.kawa-kun.com/user/2").to_return(status: 404)
- stub_request(:any, "https://mastodon.social/users/Gargron").to_return(status: 404)
-
- request.env['HTTP_X_HUB_SIGNATURE'] = "sha1=#{OpenSSL::HMAC.hexdigest('sha1', 'abc', feed)}"
-
- post :update, params: { id: account.id }, body: feed
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates statuses for feed' do
- expect(account.statuses.count).to_not eq 0
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
deleted file mode 100644
index 19ac3261..00000000
--- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Accounts::CredentialsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:accounts' }
-
- it 'returns http success' do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'PATCH #update' do
- let(:scopes) { 'write:accounts' }
-
- describe 'with valid data' do
- before do
- allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
-
- patch :update, params: {
- display_name: "Alice Isn't Dead",
- note: "Hi!\n\nToot toot!",
- avatar: fixture_file_upload('files/avatar.gif', 'image/gif'),
- header: fixture_file_upload('files/attachment.jpg', 'image/jpeg'),
- source: {
- privacy: 'unlisted',
- sensitive: true,
- }
- }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates account info' do
- user.account.reload
-
- expect(user.account.display_name).to eq("Alice Isn't Dead")
- expect(user.account.note).to eq("Hi!\n\nToot toot!")
- expect(user.account.avatar).to exist
- expect(user.account.header).to exist
- expect(user.setting_default_privacy).to eq('unlisted')
- expect(user.setting_default_sensitive).to eq(true)
- end
-
- it 'queues up an account update distribution' do
- expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(user.account_id)
- end
- end
-
- describe 'with invalid data' do
- before do
- patch :update, params: { note: 'This is too long. ' * 30 }
- end
-
- it 'returns http unprocessable entity' do
- expect(response).to have_http_status(:unprocessable_entity)
- end
- end
- end
- end
-
- context 'without an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { nil }
- end
-
- describe 'GET #show' do
- it 'returns http unauthorized' do
- get :show
- expect(response).to have_http_status(:unauthorized)
- end
- end
-
- describe 'PATCH #update' do
- it 'returns http unauthorized' do
- patch :update, params: { note: 'Foo' }
- expect(response).to have_http_status(:unauthorized)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb
deleted file mode 100644
index 75e0570e..00000000
--- a/spec/controllers/api/v1/accounts/follower_accounts_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Accounts::FollowerAccountsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
-
- before do
- Fabricate(:follow, target_account: user.account)
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: user.account.id, limit: 1 }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb b/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb
deleted file mode 100644
index 7f7105ad..00000000
--- a/spec/controllers/api/v1/accounts/following_accounts_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Accounts::FollowingAccountsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
-
- before do
- Fabricate(:follow, account: user.account)
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: user.account.id, limit: 1 }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/lists_controller_spec.rb b/spec/controllers/api/v1/accounts/lists_controller_spec.rb
deleted file mode 100644
index baafea8e..00000000
--- a/spec/controllers/api/v1/accounts/lists_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Accounts::ListsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:lists') }
- let(:account) { Fabricate(:account) }
- let(:list) { Fabricate(:list, account: user.account) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- user.account.follow!(account)
- list.accounts << account
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: account.id }
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/pins_controller_spec.rb b/spec/controllers/api/v1/accounts/pins_controller_spec.rb
deleted file mode 100644
index c71935df..00000000
--- a/spec/controllers/api/v1/accounts/pins_controller_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::Accounts::PinsController, type: :controller do
- let(:john) { Fabricate(:user, account: Fabricate(:account, username: 'john')) }
- let(:kevin) { Fabricate(:user, account: Fabricate(:account, username: 'kevin')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: john.id, scopes: 'write:accounts') }
-
- before do
- kevin.account.followers << john.account
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- subject { post :create, params: { account_id: kevin.account.id } }
-
- it 'returns 200' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates account_pin' do
- expect do
- subject
- end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(1)
- end
- end
-
- describe 'DELETE #destroy' do
- subject { delete :destroy, params: { account_id: kevin.account.id } }
-
- before do
- Fabricate(:account_pin, account: john.account, target_account: kevin.account)
- end
-
- it 'returns 200' do
- expect(response).to have_http_status(200)
- end
-
- it 'destroys account_pin' do
- expect do
- subject
- end.to change { AccountPin.where(account: john.account, target_account: kevin.account).count }.by(-1)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/relationships_controller_spec.rb b/spec/controllers/api/v1/accounts/relationships_controller_spec.rb
deleted file mode 100644
index fe715ff6..00000000
--- a/spec/controllers/api/v1/accounts/relationships_controller_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Accounts::RelationshipsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:follows') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:simon) { Fabricate(:user, email: 'simon@example.com', account: Fabricate(:account, username: 'simon')).account }
- let(:lewis) { Fabricate(:user, email: 'lewis@example.com', account: Fabricate(:account, username: 'lewis')).account }
-
- before do
- user.account.follow!(simon)
- lewis.follow!(user.account)
- end
-
- context 'provided only one ID' do
- before do
- get :index, params: { id: simon.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns JSON with correct data' do
- json = body_as_json
-
- expect(json).to be_a Enumerable
- expect(json.first[:following]).to be true
- expect(json.first[:followed_by]).to be false
- end
- end
-
- context 'provided multiple IDs' do
- before do
- get :index, params: { id: [simon.id, lewis.id] }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns JSON with correct data' do
- json = body_as_json
-
- expect(json).to be_a Enumerable
- expect(json.first[:id]).to eq simon.id.to_s
- expect(json.first[:following]).to be true
- expect(json.first[:showing_reblogs]).to be true
- expect(json.first[:followed_by]).to be false
- expect(json.first[:muting]).to be false
- expect(json.first[:requested]).to be false
- expect(json.first[:domain_blocking]).to be false
-
- expect(json.second[:id]).to eq lewis.id.to_s
- expect(json.second[:following]).to be false
- expect(json.second[:showing_reblogs]).to be false
- expect(json.second[:followed_by]).to be true
- expect(json.second[:muting]).to be false
- expect(json.second[:requested]).to be false
- expect(json.second[:domain_blocking]).to be false
- end
-
- it 'returns JSON with correct data on cached requests too' do
- get :index, params: { id: [simon.id] }
-
- json = body_as_json
-
- expect(json).to be_a Enumerable
- expect(json.first[:following]).to be true
- expect(json.first[:showing_reblogs]).to be true
- end
-
- it 'returns JSON with correct data after change too' do
- user.account.unfollow!(simon)
-
- get :index, params: { id: [simon.id] }
-
- json = body_as_json
-
- expect(json).to be_a Enumerable
- expect(json.first[:following]).to be false
- expect(json.first[:showing_reblogs]).to be false
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/search_controller_spec.rb b/spec/controllers/api/v1/accounts/search_controller_spec.rb
deleted file mode 100644
index 8ff2b17d..00000000
--- a/spec/controllers/api/v1/accounts/search_controller_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::Accounts::SearchController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { q: 'query' }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb b/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
deleted file mode 100644
index 693cd1ac..00000000
--- a/spec/controllers/api/v1/accounts/statuses_controller_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Accounts::StatusesController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- Fabricate(:status, account: user.account)
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { account_id: user.account.id, limit: 1 }
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
-
- context 'with only media' do
- it 'returns http success' do
- get :index, params: { account_id: user.account.id, only_media: true }
-
- expect(response).to have_http_status(200)
- end
- end
-
- context 'with exclude replies' do
- before do
- Fabricate(:status, account: user.account, thread: Fabricate(:status))
- end
-
- it 'returns http success' do
- get :index, params: { account_id: user.account.id, exclude_replies: true }
-
- expect(response).to have_http_status(200)
- end
- end
-
- context 'with only pinned' do
- before do
- Fabricate(:status_pin, account: user.account, status: Fabricate(:status, account: user.account))
- end
-
- it 'returns http success' do
- get :index, params: { account_id: user.account.id, pinned: true }
-
- expect(response).to have_http_status(200)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb
deleted file mode 100644
index f5f65c00..00000000
--- a/spec/controllers/api/v1/accounts_controller_spec.rb
+++ /dev/null
@@ -1,260 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::AccountsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:scopes) { '' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- shared_examples 'forbidden for wrong scope' do |wrong_scope|
- let(:scopes) { wrong_scope }
-
- it 'returns http forbidden' do
- expect(response).to have_http_status(403)
- end
- end
-
- describe 'POST #create' do
- let(:app) { Fabricate(:application) }
- let(:token) { Doorkeeper::AccessToken.find_or_create_for(app, nil, 'read write', nil, false) }
- let(:agreement) { nil }
-
- before do
- post :create, params: { username: 'test', password: '12345678', email: 'hello@world.tld', agreement: agreement }
- end
-
- context 'given truthy agreement' do
- let(:agreement) { 'true' }
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns a new access token as JSON' do
- expect(body_as_json[:access_token]).to_not be_blank
- end
-
- it 'creates a user' do
- user = User.find_by(email: 'hello@world.tld')
- expect(user).to_not be_nil
- expect(user.created_by_application_id).to eq app.id
- end
- end
-
- context 'given no agreement' do
- it 'returns http unprocessable entity' do
- expect(response).to have_http_status(422)
- end
- end
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:accounts' }
-
- before do
- get :show, params: { id: user.account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- end
-
- describe 'POST #follow' do
- let(:scopes) { 'write:follows' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', locked: locked)).account }
-
- before do
- post :follow, params: { id: other_account.id }
- end
-
- context 'with unlocked account' do
- let(:locked) { false }
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns JSON with following=true and requested=false' do
- json = body_as_json
-
- expect(json[:following]).to be true
- expect(json[:requested]).to be false
- end
-
- it 'creates a following relation between user and target user' do
- expect(user.account.following?(other_account)).to be true
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-
- context 'with locked account' do
- let(:locked) { true }
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns JSON with following=false and requested=true' do
- json = body_as_json
-
- expect(json[:following]).to be false
- expect(json[:requested]).to be true
- end
-
- it 'creates a follow request relation between user and target user' do
- expect(user.account.requested?(other_account)).to be true
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
- end
-
- describe 'POST #unfollow' do
- let(:scopes) { 'write:follows' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- user.account.follow!(other_account)
- post :unfollow, params: { id: other_account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes the following relation between user and target user' do
- expect(user.account.following?(other_account)).to be false
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-
- describe 'POST #block' do
- let(:scopes) { 'write:blocks' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- user.account.follow!(other_account)
- post :block, params: { id: other_account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes the following relation between user and target user' do
- expect(user.account.following?(other_account)).to be false
- end
-
- it 'creates a blocking relation' do
- expect(user.account.blocking?(other_account)).to be true
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-
- describe 'POST #unblock' do
- let(:scopes) { 'write:blocks' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- user.account.block!(other_account)
- post :unblock, params: { id: other_account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes the blocking relation between user and target user' do
- expect(user.account.blocking?(other_account)).to be false
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-
- describe 'POST #mute' do
- let(:scopes) { 'write:mutes' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- user.account.follow!(other_account)
- post :mute, params: { id: other_account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'does not remove the following relation between user and target user' do
- expect(user.account.following?(other_account)).to be true
- end
-
- it 'creates a muting relation' do
- expect(user.account.muting?(other_account)).to be true
- end
-
- it 'mutes notifications' do
- expect(user.account.muting_notifications?(other_account)).to be true
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-
- describe 'POST #mute with notifications set to false' do
- let(:scopes) { 'write:mutes' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- user.account.follow!(other_account)
- post :mute, params: { id: other_account.id, notifications: false }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'does not remove the following relation between user and target user' do
- expect(user.account.following?(other_account)).to be true
- end
-
- it 'creates a muting relation' do
- expect(user.account.muting?(other_account)).to be true
- end
-
- it 'does not mute notifications' do
- expect(user.account.muting_notifications?(other_account)).to be false
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-
- describe 'POST #unmute' do
- let(:scopes) { 'write:mutes' }
- let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- user.account.mute!(other_account)
- post :unmute, params: { id: other_account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes the muting relation between user and target user' do
- expect(user.account.muting?(other_account)).to be false
- end
-
- it_behaves_like 'forbidden for wrong scope', 'read:accounts'
- end
-end
diff --git a/spec/controllers/api/v1/apps/credentials_controller_spec.rb b/spec/controllers/api/v1/apps/credentials_controller_spec.rb
deleted file mode 100644
index 0f811d5f..00000000
--- a/spec/controllers/api/v1/apps/credentials_controller_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Apps::CredentialsController do
- render_views
-
- let(:token) { Fabricate(:accessible_access_token, scopes: 'read', application: Fabricate(:application)) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- before do
- get :show
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'does not contain client credentials' do
- json = body_as_json
-
- expect(json).to_not have_key(:client_secret)
- expect(json).to_not have_key(:client_id)
- end
- end
- end
-
- context 'without an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { nil }
- end
-
- describe 'GET #show' do
- it 'returns http unauthorized' do
- get :show
- expect(response).to have_http_status(:unauthorized)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/apps_controller_spec.rb b/spec/controllers/api/v1/apps_controller_spec.rb
deleted file mode 100644
index 60a4c3b4..00000000
--- a/spec/controllers/api/v1/apps_controller_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::AppsController, type: :controller do
- render_views
-
- describe 'POST #create' do
- before do
- post :create, params: { client_name: 'Test app', redirect_uris: 'urn:ietf:wg:oauth:2.0:oob' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates an OAuth app' do
- expect(Doorkeeper::Application.find_by(name: 'Test app')).to_not be nil
- end
-
- it 'returns client ID and client secret' do
- json = body_as_json
-
- expect(json[:client_id]).to_not be_blank
- expect(json[:client_secret]).to_not be_blank
- end
- end
-end
diff --git a/spec/controllers/api/v1/blocks_controller_spec.rb b/spec/controllers/api/v1/blocks_controller_spec.rb
deleted file mode 100644
index 818f76c9..00000000
--- a/spec/controllers/api/v1/blocks_controller_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::BlocksController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:scopes) { 'read:blocks' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before { allow(controller).to receive(:doorkeeper_token) { token } }
-
- describe 'GET #index' do
- it 'limits according to limit parameter' do
- 2.times.map { Fabricate(:block, account: user.account) }
- get :index, params: { limit: 1 }
- expect(body_as_json.size).to eq 1
- end
-
- it 'queries blocks in range according to max_id' do
- blocks = 2.times.map { Fabricate(:block, account: user.account) }
-
- get :index, params: { max_id: blocks[1] }
-
- expect(body_as_json.size).to eq 1
- expect(body_as_json[0][:id]).to eq blocks[0].target_account_id.to_s
- end
-
- it 'queries blocks in range according to since_id' do
- blocks = 2.times.map { Fabricate(:block, account: user.account) }
-
- get :index, params: { since_id: blocks[0] }
-
- expect(body_as_json.size).to eq 1
- expect(body_as_json[0][:id]).to eq blocks[1].target_account_id.to_s
- end
-
- it 'sets pagination header for next path' do
- blocks = 2.times.map { Fabricate(:block, account: user.account) }
- get :index, params: { limit: 1, since_id: blocks[0] }
- expect(response.headers['Link'].find_link(['rel', 'next']).href).to eq api_v1_blocks_url(limit: 1, max_id: blocks[1])
- end
-
- it 'sets pagination header for previous path' do
- block = Fabricate(:block, account: user.account)
- get :index
- expect(response.headers['Link'].find_link(['rel', 'prev']).href).to eq api_v1_blocks_url(since_id: block)
- end
-
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
-
- context 'with wrong scopes' do
- let(:scopes) { 'write:blocks' }
-
- it 'returns http forbidden' do
- get :index
- expect(response).to have_http_status(403)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/conversations_controller_spec.rb b/spec/controllers/api/v1/conversations_controller_spec.rb
deleted file mode 100644
index 070f6506..00000000
--- a/spec/controllers/api/v1/conversations_controller_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::ConversationsController, type: :controller do
- render_views
-
- let!(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
- let(:other) { Fabricate(:user, account: Fabricate(:account, username: 'bob')) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:scopes) { 'read:statuses' }
-
- before do
- PostStatusService.new.call(other.account, text: 'Hey @alice', visibility: 'direct')
- end
-
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
-
- it 'returns pagination headers' do
- get :index, params: { limit: 1 }
- expect(response.headers['Link'].links.size).to eq(2)
- end
-
- it 'returns conversations' do
- get :index
- json = body_as_json
- expect(json.size).to eq 1
- end
- end
-end
diff --git a/spec/controllers/api/v1/custom_emojis_controller_spec.rb b/spec/controllers/api/v1/custom_emojis_controller_spec.rb
deleted file mode 100644
index fe8daa7c..00000000
--- a/spec/controllers/api/v1/custom_emojis_controller_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::CustomEmojisController, type: :controller do
- render_views
-
- describe 'GET #index' do
- before do
- Fabricate(:custom_emoji)
- get :index
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/domain_blocks_controller_spec.rb b/spec/controllers/api/v1/domain_blocks_controller_spec.rb
deleted file mode 100644
index 6a7a35c7..00000000
--- a/spec/controllers/api/v1/domain_blocks_controller_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::DomainBlocksController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before do
- user.account.block_domain!('example.com')
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- shared_examples 'forbidden for wrong scope' do |wrong_scope|
- let(:scopes) { wrong_scope }
-
- it 'returns http forbidden' do
- expect(response).to have_http_status(403)
- end
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:blocks' }
-
- before do
- get :show, params: { limit: 1 }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns blocked domains' do
- expect(body_as_json.first).to eq 'example.com'
- end
-
- it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- end
-
- describe 'POST #create' do
- let(:scopes) { 'write:blocks' }
-
- before do
- post :create, params: { domain: 'example.org' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a domain block' do
- expect(user.account.domain_blocking?('example.org')).to be true
- end
-
- it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- end
-
- describe 'DELETE #destroy' do
- let(:scopes) { 'write:blocks' }
-
- before do
- delete :destroy, params: { domain: 'example.com' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'deletes a domain block' do
- expect(user.account.domain_blocking?('example.com')).to be false
- end
-
- it_behaves_like 'forbidden for wrong scope', 'write:statuses'
- end
-end
diff --git a/spec/controllers/api/v1/endorsements_controller_spec.rb b/spec/controllers/api/v1/endorsements_controller_spec.rb
deleted file mode 100644
index ad5ff400..00000000
--- a/spec/controllers/api/v1/endorsements_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::EndorsementsController, type: :controller do
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:accounts') }
-
- describe 'GET #index' do
- it 'returns 200' do
- allow(controller).to receive(:doorkeeper_token) { token }
- get :index
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/favourites_controller_spec.rb b/spec/controllers/api/v1/favourites_controller_spec.rb
deleted file mode 100644
index 231f7650..00000000
--- a/spec/controllers/api/v1/favourites_controller_spec.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::FavouritesController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') }
-
- describe 'GET #index' do
- context 'without token' do
- it 'returns http unauthorized' do
- get :index
- expect(response).to have_http_status :unauthorized
- end
- end
-
- context 'with token' do
- context 'without read scope' do
- before do
- allow(controller).to receive(:doorkeeper_token) do
- Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: '')
- end
- end
-
- it 'returns http forbidden' do
- get :index
- expect(response).to have_http_status :forbidden
- end
- end
-
- context 'without valid resource owner' do
- before do
- token = Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read')
- user.destroy!
-
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- it 'returns http unprocessable entity' do
- get :index
- expect(response).to have_http_status :unprocessable_entity
- end
- end
-
- context 'with read scope and valid resource owner' do
- before do
- allow(controller).to receive(:doorkeeper_token) do
- Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:favourites')
- end
- end
-
- it 'shows favourites owned by the user' do
- favourite_by_user = Fabricate(:favourite, account: user.account)
- favourite_by_others = Fabricate(:favourite)
-
- get :index
-
- expect(assigns(:statuses)).to match_array [favourite_by_user.status]
- end
-
- it 'adds pagination headers if necessary' do
- favourite = Fabricate(:favourite, account: user.account)
-
- get :index, params: { limit: 1 }
-
- expect(response.headers['Link'].find_link(['rel', 'next']).href).to eq "http://test.host/api/v1/favourites?limit=1&max_id=#{favourite.id}"
- expect(response.headers['Link'].find_link(['rel', 'prev']).href).to eq "http://test.host/api/v1/favourites?limit=1&min_id=#{favourite.id}"
- end
-
- it 'does not add pagination headers if not necessary' do
- get :index
-
- expect(response.headers['Link']).to eq nil
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/filters_controller_spec.rb b/spec/controllers/api/v1/filters_controller_spec.rb
deleted file mode 100644
index 5948809e..00000000
--- a/spec/controllers/api/v1/filters_controller_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::FiltersController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:scopes) { 'read:filters' }
- let!(:filter) { Fabricate(:custom_filter, account: user.account) }
-
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- let(:scopes) { 'write:filters' }
-
- before do
- post :create, params: { phrase: 'magic', context: %w(home), irreversible: true }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a filter' do
- filter = user.account.custom_filters.first
- expect(filter).to_not be_nil
- expect(filter.phrase).to eq 'magic'
- expect(filter.context).to eq %w(home)
- expect(filter.irreversible?).to be true
- expect(filter.expires_at).to be_nil
- end
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:filters' }
- let(:filter) { Fabricate(:custom_filter, account: user.account) }
-
- it 'returns http success' do
- get :show, params: { id: filter.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'PUT #update' do
- let(:scopes) { 'write:filters' }
- let(:filter) { Fabricate(:custom_filter, account: user.account) }
-
- before do
- put :update, params: { id: filter.id, phrase: 'updated' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the filter' do
- expect(filter.reload.phrase).to eq 'updated'
- end
- end
-
- describe 'DELETE #destroy' do
- let(:scopes) { 'write:filters' }
- let(:filter) { Fabricate(:custom_filter, account: user.account) }
-
- before do
- delete :destroy, params: { id: filter.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes the filter' do
- expect { filter.reload }.to raise_error ActiveRecord::RecordNotFound
- end
- end
-end
diff --git a/spec/controllers/api/v1/follow_requests_controller_spec.rb b/spec/controllers/api/v1/follow_requests_controller_spec.rb
deleted file mode 100644
index 87292d9c..00000000
--- a/spec/controllers/api/v1/follow_requests_controller_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::FollowRequestsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice', locked: true)) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
- let(:follower) { Fabricate(:account, username: 'bob') }
-
- before do
- FollowService.new.call(follower, user.account.acct)
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:scopes) { 'read:follows' }
-
- before do
- get :index, params: { limit: 1 }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #authorize' do
- let(:scopes) { 'write:follows' }
-
- before do
- post :authorize, params: { id: follower.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'allows follower to follow' do
- expect(follower.following?(user.account)).to be true
- end
- end
-
- describe 'POST #reject' do
- let(:scopes) { 'write:follows' }
-
- before do
- post :reject, params: { id: follower.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes follow request' do
- expect(FollowRequest.where(target_account: user.account, account: follower).count).to eq 0
- end
- end
-end
diff --git a/spec/controllers/api/v1/follows_controller_spec.rb b/spec/controllers/api/v1/follows_controller_spec.rb
deleted file mode 100644
index 626190f1..00000000
--- a/spec/controllers/api/v1/follows_controller_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::FollowsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:follows') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- before do
- stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt'))
- stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:robcolbert@quitter.no").to_return(request_fixture('webfinger.txt'))
- stub_request(:head, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(:status => 405, :body => "", :headers => {})
- stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
- stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
- stub_request(:post, "https://quitter.no/main/push/hub").to_return(:status => 200, :body => "", :headers => {})
- stub_request(:post, "https://quitter.no/main/salmon/user/7477").to_return(:status => 200, :body => "", :headers => {})
-
- post :create, params: { uri: 'robcolbert@quitter.no' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates account for remote user' do
- expect(Account.find_by(username: 'robcolbert', domain: 'quitter.no')).to_not be_nil
- end
-
- it 'creates a follow relation between user and remote user' do
- expect(user.account.following?(Account.find_by(username: 'robcolbert', domain: 'quitter.no'))).to be true
- end
-
- it 'sends a salmon slap to the remote user' do
- expect(a_request(:post, "https://quitter.no/main/salmon/user/7477")).to have_been_made
- end
-
- it 'subscribes to remote hub' do
- expect(a_request(:post, "https://quitter.no/main/push/hub")).to have_been_made
- end
-
- it 'returns http success if already following, too' do
- post :create, params: { uri: 'robcolbert@quitter.no' }
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/instances/activity_controller_spec.rb b/spec/controllers/api/v1/instances/activity_controller_spec.rb
deleted file mode 100644
index 159792ee..00000000
--- a/spec/controllers/api/v1/instances/activity_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::Instances::ActivityController, type: :controller do
- describe 'GET #show' do
- it 'returns 200' do
- get :show
- expect(response).to have_http_status(200)
- end
-
- context '!Setting.activity_api_enabled' do
- it 'returns 404' do
- Setting.activity_api_enabled = false
-
- get :show
- expect(response).to have_http_status(404)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/instances/peers_controller_spec.rb b/spec/controllers/api/v1/instances/peers_controller_spec.rb
deleted file mode 100644
index 12a214a8..00000000
--- a/spec/controllers/api/v1/instances/peers_controller_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::Instances::PeersController, type: :controller do
- describe 'GET #index' do
- it 'returns 200' do
- get :index
- expect(response).to have_http_status(200)
- end
-
- context '!Setting.peers_api_enabled' do
- it 'returns 404' do
- Setting.peers_api_enabled = false
-
- get :index
- expect(response).to have_http_status(404)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/instances_controller_spec.rb b/spec/controllers/api/v1/instances_controller_spec.rb
deleted file mode 100644
index 7397d25d..00000000
--- a/spec/controllers/api/v1/instances_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::InstancesController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/lists/accounts_controller_spec.rb b/spec/controllers/api/v1/lists/accounts_controller_spec.rb
deleted file mode 100644
index 08c22de5..00000000
--- a/spec/controllers/api/v1/lists/accounts_controller_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require 'rails_helper'
-
-describe Api::V1::Lists::AccountsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
- let(:list) { Fabricate(:list, account: user.account) }
-
- before do
- follow = Fabricate(:follow, account: user.account)
- list.accounts << follow.target_account
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:scopes) { 'read:lists' }
-
- it 'returns http success' do
- get :show, params: { list_id: list.id }
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- let(:scopes) { 'write:lists' }
- let(:bob) { Fabricate(:account, username: 'bob') }
-
- before do
- user.account.follow!(bob)
- post :create, params: { list_id: list.id, account_ids: [bob.id] }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'adds account to the list' do
- expect(list.accounts.include?(bob)).to be true
- end
- end
-
- describe 'DELETE #destroy' do
- let(:scopes) { 'write:lists' }
-
- before do
- delete :destroy, params: { list_id: list.id, account_ids: [list.accounts.first.id] }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes account from the list' do
- expect(list.accounts.count).to eq 0
- end
- end
-end
diff --git a/spec/controllers/api/v1/lists_controller_spec.rb b/spec/controllers/api/v1/lists_controller_spec.rb
deleted file mode 100644
index e9221378..00000000
--- a/spec/controllers/api/v1/lists_controller_spec.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::ListsController, type: :controller do
- render_views
-
- let!(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let!(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
- let!(:list) { Fabricate(:list, account: user.account) }
-
- before { allow(controller).to receive(:doorkeeper_token) { token } }
-
- describe 'GET #index' do
- let(:scopes) { 'read:lists' }
-
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:lists' }
-
- it 'returns http success' do
- get :show, params: { id: list.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- let(:scopes) { 'write:lists' }
-
- before do
- post :create, params: { title: 'Foo bar' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates list' do
- expect(List.where(account: user.account).count).to eq 2
- expect(List.last.title).to eq 'Foo bar'
- end
- end
-
- describe 'PUT #update' do
- let(:scopes) { 'write:lists' }
-
- before do
- put :update, params: { id: list.id, title: 'Updated title' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the list' do
- expect(list.reload.title).to eq 'Updated title'
- end
- end
-
- describe 'DELETE #destroy' do
- let(:scopes) { 'write:lists' }
-
- before do
- delete :destroy, params: { id: list.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'deletes the list' do
- expect(List.find_by(id: list.id)).to be_nil
- end
- end
-end
diff --git a/spec/controllers/api/v1/media_controller_spec.rb b/spec/controllers/api/v1/media_controller_spec.rb
deleted file mode 100644
index 4e303720..00000000
--- a/spec/controllers/api/v1/media_controller_spec.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::MediaController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:media') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- describe 'with paperclip errors' do
- context 'when imagemagick cant identify the file type' do
- before do
- expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
- post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
- end
-
- it 'returns http 422' do
- expect(response).to have_http_status(:unprocessable_entity)
- end
- end
-
- context 'when there is a generic error' do
- before do
- expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error)
- post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
- end
-
- it 'returns http 422' do
- expect(response).to have_http_status(500)
- end
- end
- end
-
- context 'image/jpeg' do
- before do
- post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a media attachment' do
- expect(MediaAttachment.first).to_not be_nil
- end
-
- it 'uploads a file' do
- expect(MediaAttachment.first).to have_attached_file(:file)
- end
-
- it 'returns media ID in JSON' do
- expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
- end
- end
-
- context 'image/gif' do
- before do
- post :create, params: { file: fixture_file_upload('files/attachment.gif', 'image/gif') }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a media attachment' do
- expect(MediaAttachment.first).to_not be_nil
- end
-
- it 'uploads a file' do
- expect(MediaAttachment.first).to have_attached_file(:file)
- end
-
- it 'returns media ID in JSON' do
- expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
- end
- end
-
- context 'video/webm' do
- before do
- post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') }
- end
-
- it do
- # returns http success
- expect(response).to have_http_status(200)
-
- # creates a media attachment
- expect(MediaAttachment.first).to_not be_nil
-
- # uploads a file
- expect(MediaAttachment.first).to have_attached_file(:file)
-
- # returns media ID in JSON
- expect(body_as_json[:id]).to eq MediaAttachment.first.id.to_s
- end
- end
- end
-
- describe 'PUT #update' do
- context 'when somebody else\'s' do
- let(:media) { Fabricate(:media_attachment, status: nil) }
-
- it 'returns http not found' do
- put :update, params: { id: media.id, description: 'Lorem ipsum!!!' }
- expect(response).to have_http_status(:not_found)
- end
- end
-
- context 'when not attached to a status' do
- let(:media) { Fabricate(:media_attachment, status: nil, account: user.account) }
-
- it 'updates the description' do
- put :update, params: { id: media.id, description: 'Lorem ipsum!!!' }
- expect(media.reload.description).to eq 'Lorem ipsum!!!'
- end
- end
-
- context 'when attached to a status' do
- let(:media) { Fabricate(:media_attachment, status: Fabricate(:status), account: user.account) }
-
- it 'returns http not found' do
- put :update, params: { id: media.id, description: 'Lorem ipsum!!!' }
- expect(response).to have_http_status(:not_found)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/mutes_controller_spec.rb b/spec/controllers/api/v1/mutes_controller_spec.rb
deleted file mode 100644
index a2b814a6..00000000
--- a/spec/controllers/api/v1/mutes_controller_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::MutesController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:scopes) { 'read:mutes' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before { allow(controller).to receive(:doorkeeper_token) { token } }
-
- describe 'GET #index' do
- it 'limits according to limit parameter' do
- 2.times.map { Fabricate(:mute, account: user.account) }
- get :index, params: { limit: 1 }
- expect(body_as_json.size).to eq 1
- end
-
- it 'queries mutes in range according to max_id' do
- mutes = 2.times.map { Fabricate(:mute, account: user.account) }
-
- get :index, params: { max_id: mutes[1] }
-
- expect(body_as_json.size).to eq 1
- expect(body_as_json[0][:id]).to eq mutes[0].target_account_id.to_s
- end
-
- it 'queries mutes in range according to since_id' do
- mutes = 2.times.map { Fabricate(:mute, account: user.account) }
-
- get :index, params: { since_id: mutes[0] }
-
- expect(body_as_json.size).to eq 1
- expect(body_as_json[0][:id]).to eq mutes[1].target_account_id.to_s
- end
-
- it 'sets pagination header for next path' do
- mutes = 2.times.map { Fabricate(:mute, account: user.account) }
- get :index, params: { limit: 1, since_id: mutes[0] }
- expect(response.headers['Link'].find_link(['rel', 'next']).href).to eq api_v1_mutes_url(limit: 1, max_id: mutes[1])
- end
-
- it 'sets pagination header for previous path' do
- mute = Fabricate(:mute, account: user.account)
- get :index
- expect(response.headers['Link'].find_link(['rel', 'prev']).href).to eq api_v1_mutes_url(since_id: mute)
- end
-
- it 'returns http success' do
- get :index
- expect(response).to have_http_status(200)
- end
-
- context 'with wrong scopes' do
- let(:scopes) { 'write:mutes' }
-
- it 'returns http forbidden' do
- get :index
- expect(response).to have_http_status(403)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/notifications_controller_spec.rb b/spec/controllers/api/v1/notifications_controller_spec.rb
deleted file mode 100644
index db3f4b78..00000000
--- a/spec/controllers/api/v1/notifications_controller_spec.rb
+++ /dev/null
@@ -1,179 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::NotificationsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
- let(:other) { Fabricate(:user, account: Fabricate(:account, username: 'bob')) }
- let(:third) { Fabricate(:user, account: Fabricate(:account, username: 'carol')) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:notifications' }
-
- it 'returns http success' do
- notification = Fabricate(:notification, account: user.account)
- get :show, params: { id: notification.id }
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #dismiss' do
- let(:scopes) { 'write:notifications' }
-
- it 'destroys the notification' do
- notification = Fabricate(:notification, account: user.account)
- post :dismiss, params: { id: notification.id }
-
- expect(response).to have_http_status(200)
- expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- describe 'POST #clear' do
- let(:scopes) { 'write:notifications' }
-
- it 'clears notifications for the account' do
- notification = Fabricate(:notification, account: user.account)
- post :clear
-
- expect(notification.account.reload.notifications).to be_empty
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #index' do
- let(:scopes) { 'read:notifications' }
-
- before do
- first_status = PostStatusService.new.call(user.account, text: 'Test')
- @reblog_of_first_status = ReblogService.new.call(other.account, first_status)
- mentioning_status = PostStatusService.new.call(other.account, text: 'Hello @alice')
- @mention_from_status = mentioning_status.mentions.first
- @favourite = FavouriteService.new.call(other.account, first_status)
- @second_favourite = FavouriteService.new.call(third.account, first_status)
- @follow = FollowService.new.call(other.account, 'alice')
- end
-
- describe 'with no options' do
- before do
- get :index
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'includes reblog' do
- expect(assigns(:notifications).map(&:activity)).to include(@reblog_of_first_status)
- end
-
- it 'includes mention' do
- expect(assigns(:notifications).map(&:activity)).to include(@mention_from_status)
- end
-
- it 'includes favourite' do
- expect(assigns(:notifications).map(&:activity)).to include(@favourite)
- end
-
- it 'includes follow' do
- expect(assigns(:notifications).map(&:activity)).to include(@follow)
- end
- end
-
- describe 'from specified user' do
- before do
- get :index, params: { account_id: third.account.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'includes favourite' do
- expect(assigns(:notifications).map(&:activity)).to include(@second_favourite)
- end
-
- it 'excludes favourite' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@favourite)
- end
-
- it 'excludes mention' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
- end
-
- it 'excludes reblog' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@reblog_of_first_status)
- end
-
- it 'excludes follow' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@follow)
- end
- end
-
- describe 'from nonexistent user' do
- before do
- get :index, params: { account_id: 'foo' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'excludes favourite' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@favourite)
- end
-
- it 'excludes second favourite' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@second_favourite)
- end
-
- it 'excludes mention' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
- end
-
- it 'excludes reblog' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@reblog_of_first_status)
- end
-
- it 'excludes follow' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@follow)
- end
- end
-
- describe 'with excluded mentions' do
- before do
- get :index, params: { exclude_types: ['mention'] }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'includes reblog' do
- expect(assigns(:notifications).map(&:activity)).to include(@reblog_of_first_status)
- end
-
- it 'excludes mention' do
- expect(assigns(:notifications).map(&:activity)).to_not include(@mention_from_status)
- end
-
- it 'includes favourite' do
- expect(assigns(:notifications).map(&:activity)).to include(@favourite)
- end
-
- it 'includes third favourite' do
- expect(assigns(:notifications).map(&:activity)).to include(@second_favourite)
- end
-
- it 'includes follow' do
- expect(assigns(:notifications).map(&:activity)).to include(@follow)
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/polls/votes_controller_spec.rb b/spec/controllers/api/v1/polls/votes_controller_spec.rb
deleted file mode 100644
index 0ee3aa04..00000000
--- a/spec/controllers/api/v1/polls/votes_controller_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::Polls::VotesController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:scopes) { 'write:statuses' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before { allow(controller).to receive(:doorkeeper_token) { token } }
-
- describe 'POST #create' do
- let(:poll) { Fabricate(:poll) }
-
- before do
- post :create, params: { poll_id: poll.id, choices: %w(1) }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a vote' do
- vote = poll.votes.where(account: user.account).first
-
- expect(vote).to_not be_nil
- expect(vote.choice).to eq 1
- end
-
- it 'updates poll tallies' do
- expect(poll.reload.cached_tallies).to eq [0, 1]
- end
- end
-end
diff --git a/spec/controllers/api/v1/polls_controller_spec.rb b/spec/controllers/api/v1/polls_controller_spec.rb
deleted file mode 100644
index 2b8d5f3e..00000000
--- a/spec/controllers/api/v1/polls_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::PollsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:scopes) { 'read:statuses' }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before { allow(controller).to receive(:doorkeeper_token) { token } }
-
- describe 'GET #show' do
- let(:poll) { Fabricate(:poll) }
-
- before do
- get :show, params: { id: poll.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/push/subscriptions_controller_spec.rb b/spec/controllers/api/v1/push/subscriptions_controller_spec.rb
deleted file mode 100644
index 01146294..00000000
--- a/spec/controllers/api/v1/push/subscriptions_controller_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Push::SubscriptionsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'push') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- let(:create_payload) do
- {
- subscription: {
- endpoint: 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX',
- keys: {
- p256dh: 'BEm_a0bdPDhf0SOsrnB2-ategf1hHoCnpXgQsFj5JCkcoMrMt2WHoPfEYOYPzOIs9mZE8ZUaD7VA5vouy0kEkr8=',
- auth: 'eH_C8rq2raXqlcBVDa1gLg==',
- },
- }
- }.with_indifferent_access
- end
-
- let(:alerts_payload) do
- {
- data: {
- alerts: {
- follow: true,
- favourite: false,
- reblog: true,
- mention: false,
- }
- }
- }.with_indifferent_access
- end
-
- describe 'POST #create' do
- it 'saves push subscriptions' do
- post :create, params: create_payload
-
- push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
-
- expect(push_subscription.endpoint).to eq(create_payload[:subscription][:endpoint])
- expect(push_subscription.key_p256dh).to eq(create_payload[:subscription][:keys][:p256dh])
- expect(push_subscription.key_auth).to eq(create_payload[:subscription][:keys][:auth])
- expect(push_subscription.user_id).to eq user.id
- expect(push_subscription.access_token_id).to eq token.id
- end
-
- it 'replaces old subscription on repeat calls' do
- post :create, params: create_payload
- post :create, params: create_payload
-
- expect(Web::PushSubscription.where(endpoint: create_payload[:subscription][:endpoint]).count).to eq 1
- end
- end
-
- describe 'PUT #update' do
- it 'changes alert settings' do
- post :create, params: create_payload
- put :update, params: alerts_payload
-
- push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
-
- expect(push_subscription.data.dig('alerts', 'follow')).to eq(alerts_payload[:data][:alerts][:follow].to_s)
- expect(push_subscription.data.dig('alerts', 'favourite')).to eq(alerts_payload[:data][:alerts][:favourite].to_s)
- expect(push_subscription.data.dig('alerts', 'reblog')).to eq(alerts_payload[:data][:alerts][:reblog].to_s)
- expect(push_subscription.data.dig('alerts', 'mention')).to eq(alerts_payload[:data][:alerts][:mention].to_s)
- end
- end
-
- describe 'DELETE #destroy' do
- it 'removes the subscription' do
- post :create, params: create_payload
- delete :destroy
-
- expect(Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])).to be_nil
- end
- end
-end
diff --git a/spec/controllers/api/v1/reports_controller_spec.rb b/spec/controllers/api/v1/reports_controller_spec.rb
deleted file mode 100644
index a3596cf8..00000000
--- a/spec/controllers/api/v1/reports_controller_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::ReportsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- let(:scopes) { 'write:reports' }
- let!(:status) { Fabricate(:status) }
- let!(:admin) { Fabricate(:user, admin: true) }
-
- before do
- allow(AdminMailer).to receive(:new_report).and_return(double('email', deliver_later: nil))
- post :create, params: { status_ids: [status.id], account_id: status.account.id, comment: 'reasons' }
- end
-
- it 'creates a report' do
- expect(status.reload.account.targeted_reports).not_to be_empty
- expect(response).to have_http_status(200)
- end
-
- it 'sends e-mails to admins' do
- expect(AdminMailer).to have_received(:new_report).with(admin.account, Report)
- end
- end
-end
diff --git a/spec/controllers/api/v1/search_controller_spec.rb b/spec/controllers/api/v1/search_controller_spec.rb
deleted file mode 100644
index c9e544cc..00000000
--- a/spec/controllers/api/v1/search_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::SearchController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { q: 'test' }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb
deleted file mode 100644
index 40f75c70..00000000
--- a/spec/controllers/api/v1/statuses/favourited_by_accounts_controller_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::Statuses::FavouritedByAccountsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- Fabricate(:favourite, status: status)
- end
-
- it 'returns http success' do
- get :index, params: { status_id: status.id, limit: 1 }
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
-
- context 'without an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { nil }
- end
-
- context 'with a private status' do
- let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
-
- describe 'GET #index' do
- before do
- Fabricate(:favourite, status: status)
- end
-
- it 'returns http unautharized' do
- get :index, params: { status_id: status.id }
- expect(response).to have_http_status(404)
- end
- end
- end
-
- context 'with a public status' do
- let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
-
- describe 'GET #index' do
- before do
- Fabricate(:favourite, status: status)
- end
-
- it 'returns http success' do
- get :index, params: { status_id: status.id }
- expect(response).to have_http_status(200)
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/favourites_controller_spec.rb b/spec/controllers/api/v1/statuses/favourites_controller_spec.rb
deleted file mode 100644
index 24a760e2..00000000
--- a/spec/controllers/api/v1/statuses/favourites_controller_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Statuses::FavouritesController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:favourites', application: app) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- post :create, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the favourites count' do
- expect(status.favourites.count).to eq 1
- end
-
- it 'updates the favourited attribute' do
- expect(user.account.favourited?(status)).to be true
- end
-
- it 'return json with updated attributes' do
- hash_body = body_as_json
-
- expect(hash_body[:id]).to eq status.id.to_s
- expect(hash_body[:favourites_count]).to eq 1
- expect(hash_body[:favourited]).to be true
- end
- end
-
- describe 'POST #destroy' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- FavouriteService.new.call(user.account, status)
- post :destroy, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the favourites count' do
- expect(status.favourites.count).to eq 0
- end
-
- it 'updates the favourited attribute' do
- expect(user.account.favourited?(status)).to be false
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/mutes_controller_spec.rb b/spec/controllers/api/v1/statuses/mutes_controller_spec.rb
deleted file mode 100644
index 96639858..00000000
--- a/spec/controllers/api/v1/statuses/mutes_controller_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Statuses::MutesController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:mutes', application: app) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- post :create, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'creates a conversation mute' do
- expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to_not be_nil
- end
- end
-
- describe 'POST #destroy' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- user.account.mute_conversation!(status.conversation)
- post :destroy, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'destroys the conversation mute' do
- expect(ConversationMute.find_by(account: user.account, conversation_id: status.conversation_id)).to be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/pins_controller_spec.rb b/spec/controllers/api/v1/statuses/pins_controller_spec.rb
deleted file mode 100644
index 13405d28..00000000
--- a/spec/controllers/api/v1/statuses/pins_controller_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Statuses::PinsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:accounts', application: app) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- post :create, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the pinned attribute' do
- expect(user.account.pinned?(status)).to be true
- end
-
- it 'return json with updated attributes' do
- hash_body = body_as_json
-
- expect(hash_body[:id]).to eq status.id.to_s
- expect(hash_body[:pinned]).to be true
- end
- end
-
- describe 'POST #destroy' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- Fabricate(:status_pin, status: status, account: user.account)
- post :destroy, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the pinned attribute' do
- expect(user.account.pinned?(status)).to be false
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb
deleted file mode 100644
index d758786d..00000000
--- a/spec/controllers/api/v1/statuses/reblogged_by_accounts_controller_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::Statuses::RebloggedByAccountsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: 'read:accounts') }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- Fabricate(:status, reblog_of_id: status.id)
- end
-
- it 'returns http success' do
- get :index, params: { status_id: status.id, limit: 1 }
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
-
- context 'without an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { nil }
- end
-
- context 'with a private status' do
- let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
-
- describe 'GET #index' do
- before do
- Fabricate(:status, reblog_of_id: status.id)
- end
-
- it 'returns http unautharized' do
- get :index, params: { status_id: status.id }
- expect(response).to have_http_status(404)
- end
- end
- end
-
- context 'with a public status' do
- let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
-
- describe 'GET #index' do
- before do
- Fabricate(:status, reblog_of_id: status.id)
- end
-
- it 'returns http success' do
- get :index, params: { status_id: status.id }
- expect(response).to have_http_status(200)
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb b/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
deleted file mode 100644
index d14ca3e8..00000000
--- a/spec/controllers/api/v1/statuses/reblogs_controller_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Statuses::ReblogsController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:statuses', application: app) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'POST #create' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- post :create, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the reblogs count' do
- expect(status.reblogs.count).to eq 1
- end
-
- it 'updates the reblogged attribute' do
- expect(user.account.reblogged?(status)).to be true
- end
-
- it 'return json with updated attributes' do
- hash_body = body_as_json
-
- expect(hash_body[:reblog][:id]).to eq status.id.to_s
- expect(hash_body[:reblog][:reblogs_count]).to eq 1
- expect(hash_body[:reblog][:reblogged]).to be true
- end
- end
-
- describe 'POST #destroy' do
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- ReblogService.new.call(user.account, status)
- post :destroy, params: { status_id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'updates the reblogs count' do
- expect(status.reblogs.count).to eq 0
- end
-
- it 'updates the reblogged attribute' do
- expect(user.account.reblogged?(status)).to be false
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/statuses_controller_spec.rb b/spec/controllers/api/v1/statuses_controller_spec.rb
deleted file mode 100644
index 8bc3b0c6..00000000
--- a/spec/controllers/api/v1/statuses_controller_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::StatusesController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, application: app, scopes: scopes) }
-
- context 'with an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #show' do
- let(:scopes) { 'read:statuses' }
- let(:status) { Fabricate(:status, account: user.account) }
-
- it 'returns http success' do
- get :show, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #context' do
- let(:scopes) { 'read:statuses' }
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- Fabricate(:status, account: user.account, thread: status)
- end
-
- it 'returns http success' do
- get :context, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- let(:scopes) { 'write:statuses' }
-
- before do
- post :create, params: { status: 'Hello world' }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'DELETE #destroy' do
- let(:scopes) { 'write:statuses' }
- let(:status) { Fabricate(:status, account: user.account) }
-
- before do
- post :destroy, params: { id: status.id }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'removes the status' do
- expect(Status.find_by(id: status.id)).to be nil
- end
- end
- end
-
- context 'without an oauth token' do
- before do
- allow(controller).to receive(:doorkeeper_token) { nil }
- end
-
- context 'with a private status' do
- let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
-
- describe 'GET #show' do
- it 'returns http unautharized' do
- get :show, params: { id: status.id }
- expect(response).to have_http_status(404)
- end
- end
-
- describe 'GET #context' do
- before do
- Fabricate(:status, account: user.account, thread: status)
- end
-
- it 'returns http unautharized' do
- get :context, params: { id: status.id }
- expect(response).to have_http_status(404)
- end
- end
-
- describe 'GET #card' do
- it 'returns http unautharized' do
- get :card, params: { id: status.id }
- expect(response).to have_http_status(404)
- end
- end
- end
-
- context 'with a public status' do
- let(:status) { Fabricate(:status, account: user.account, visibility: :public) }
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #context' do
- before do
- Fabricate(:status, account: user.account, thread: status)
- end
-
- it 'returns http success' do
- get :context, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #card' do
- it 'returns http success' do
- get :card, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/streaming_controller_spec.rb b/spec/controllers/api/v1/streaming_controller_spec.rb
deleted file mode 100644
index 4ab409a5..00000000
--- a/spec/controllers/api/v1/streaming_controller_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::StreamingController do
- around(:each) do |example|
- before = Rails.configuration.x.streaming_api_base_url
- Rails.configuration.x.streaming_api_base_url = Rails.configuration.x.web_domain
- example.run
- Rails.configuration.x.streaming_api_base_url = before
- end
-
- before(:each) do
- request.headers.merge! Host: Rails.configuration.x.web_domain
- end
-
- context 'with streaming api on same host' do
- describe 'GET #index' do
- it 'raises ActiveRecord::RecordNotFound' do
- get :index
- expect(response).to have_http_status(404)
- end
- end
- end
-
- context 'with streaming api on different host' do
- before(:each) do
- Rails.configuration.x.streaming_api_base_url = 'wss://streaming-' + Rails.configuration.x.web_domain
- @streaming_host = URI.parse(Rails.configuration.x.streaming_api_base_url).host
- end
-
- describe 'GET #index' do
- it 'redirects to streaming host' do
- get :index, params: { access_token: 'deadbeef', stream: 'public' }
- expect(response).to have_http_status(301)
- request_uri = URI.parse(request.url)
- redirect_to_uri = URI.parse(response.location)
- [:scheme, :path, :query, :fragment].each do |part|
- expect(redirect_to_uri.send(part)).to eq(request_uri.send(part)), "redirect target #{part}"
- end
- expect(redirect_to_uri.host).to eq(@streaming_host), "redirect target host"
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/suggestions_controller_spec.rb b/spec/controllers/api/v1/suggestions_controller_spec.rb
deleted file mode 100644
index 17f10b04..00000000
--- a/spec/controllers/api/v1/suggestions_controller_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Api::V1::SuggestionsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read write') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- let(:bob) { Fabricate(:account) }
- let(:jeff) { Fabricate(:account) }
-
- before do
- PotentialFriendshipTracker.record(user.account_id, bob.id, :reblog)
- PotentialFriendshipTracker.record(user.account_id, jeff.id, :favourite)
-
- get :index
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'returns accounts' do
- json = body_as_json
-
- expect(json.size).to be >= 1
- expect(json.map { |i| i[:id] }).to include *[bob, jeff].map { |i| i.id.to_s }
- end
- end
-end
diff --git a/spec/controllers/api/v1/timelines/direct_controller_spec.rb b/spec/controllers/api/v1/timelines/direct_controller_spec.rb
deleted file mode 100644
index a22c2cbe..00000000
--- a/spec/controllers/api/v1/timelines/direct_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V1::Timelines::DirectController, type: :controller do
- let(:user) { Fabricate(:user) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
-
- describe 'GET #show' do
- it 'returns 200' do
- allow(controller).to receive(:doorkeeper_token) { token }
- get :show
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/v1/timelines/home_controller_spec.rb b/spec/controllers/api/v1/timelines/home_controller_spec.rb
deleted file mode 100644
index e953e464..00000000
--- a/spec/controllers/api/v1/timelines/home_controller_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Timelines::HomeController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice'), current_sign_in_at: 1.day.ago) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- context 'with a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
-
- describe 'GET #show' do
- before do
- follow = Fabricate(:follow, account: user.account)
- PostStatusService.new.call(follow.target_account, text: 'New status for user home timeline.')
- end
-
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
-
- context 'without a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read') }
-
- describe 'GET #show' do
- it 'returns http unprocessable entity' do
- get :show
-
- expect(response).to have_http_status(:unprocessable_entity)
- expect(response.headers['Link']).to be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/timelines/list_controller_spec.rb b/spec/controllers/api/v1/timelines/list_controller_spec.rb
deleted file mode 100644
index 45e4bf34..00000000
--- a/spec/controllers/api/v1/timelines/list_controller_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Timelines::ListController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:list) { Fabricate(:list, account: user.account) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- context 'with a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:lists') }
-
- describe 'GET #show' do
- before do
- follow = Fabricate(:follow, account: user.account)
- list.accounts << follow.target_account
- PostStatusService.new.call(follow.target_account, text: 'New status for user home timeline.')
- end
-
- it 'returns http success' do
- get :show, params: { id: list.id }
- expect(response).to have_http_status(200)
- end
- end
- end
-
- context 'with the wrong user context' do
- let(:other_user) { Fabricate(:user, account: Fabricate(:account, username: 'bob')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: other_user.id, scopes: 'read') }
-
- describe 'GET #show' do
- it 'returns http not found' do
- get :show, params: { id: list.id }
- expect(response).to have_http_status(:not_found)
- end
- end
- end
-
- context 'without a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read') }
-
- describe 'GET #show' do
- it 'returns http unprocessable entity' do
- get :show, params: { id: list.id }
-
- expect(response).to have_http_status(:unprocessable_entity)
- expect(response.headers['Link']).to be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/timelines/public_controller_spec.rb b/spec/controllers/api/v1/timelines/public_controller_spec.rb
deleted file mode 100644
index 737aedba..00000000
--- a/spec/controllers/api/v1/timelines/public_controller_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Timelines::PublicController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- context 'with a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
-
- describe 'GET #show' do
- before do
- PostStatusService.new.call(user.account, text: 'New status from user for federated public timeline.')
- end
-
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
-
- describe 'GET #show with local only' do
- before do
- PostStatusService.new.call(user.account, text: 'New status from user for local public timeline.')
- end
-
- it 'returns http success' do
- get :show, params: { local: true }
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
-
- context 'without a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil) }
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
-
- expect(response).to have_http_status(200)
- expect(response.headers['Link']).to be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/api/v1/timelines/tag_controller_spec.rb b/spec/controllers/api/v1/timelines/tag_controller_spec.rb
deleted file mode 100644
index f71ca2a3..00000000
--- a/spec/controllers/api/v1/timelines/tag_controller_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::V1::Timelines::TagController do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- context 'with a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
-
- describe 'GET #show' do
- before do
- PostStatusService.new.call(user.account, text: 'It is a #test')
- end
-
- it 'returns http success' do
- get :show, params: { id: 'test' }
- expect(response).to have_http_status(200)
- expect(response.headers['Link'].links.size).to eq(2)
- end
- end
- end
-
- context 'without a user context' do
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil) }
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { id: 'test' }
- expect(response).to have_http_status(200)
- expect(response.headers['Link']).to be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/api/v2/search_controller_spec.rb b/spec/controllers/api/v2/search_controller_spec.rb
deleted file mode 100644
index 8ee8753d..00000000
--- a/spec/controllers/api/v2/search_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Api::V2::SearchController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:search') }
-
- before do
- allow(controller).to receive(:doorkeeper_token) { token }
- end
-
- describe 'GET #index' do
- it 'returns http success' do
- get :index, params: { q: 'test' }
-
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/api/web/embeds_controller_spec.rb b/spec/controllers/api/web/embeds_controller_spec.rb
deleted file mode 100644
index a8fc1718..00000000
--- a/spec/controllers/api/web/embeds_controller_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::Web::EmbedsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- before { sign_in user }
-
- describe 'POST #create' do
- subject(:response) { post :create, params: { url: url } }
- subject(:body) { JSON.parse(response.body, symbolize_names: true) }
-
- context 'when successfully finds status' do
- let(:status) { Fabricate(:status) }
- let(:url) { "http://#{Rails.configuration.x.web_domain}/@#{status.account.username}/#{status.id}" }
-
- it 'returns a right response' do
- expect(response).to have_http_status :ok
- expect(body[:author_name]).to eq status.account.username
- end
- end
-
- context 'when fails to find status' do
- let(:url) { 'https://host.test/oembed.html' }
- let(:service_instance) { double('fetch_oembed_service') }
-
- before do
- allow(FetchOEmbedService).to receive(:new) { service_instance }
- allow(service_instance).to receive(:call) { call_result }
- end
-
- context 'when successfully fetching oembed' do
- let(:call_result) { { result: :ok } }
-
- it 'returns a right response' do
- expect(response).to have_http_status :ok
- expect(body[:result]).to eq 'ok'
- end
- end
-
- context 'when fails to fetch oembed' do
- let(:call_result) { nil }
-
- it 'returns a right response' do
- expect(response).to have_http_status :not_found
- end
- end
- end
- end
-end
diff --git a/spec/controllers/api/web/push_subscriptions_controller_spec.rb b/spec/controllers/api/web/push_subscriptions_controller_spec.rb
deleted file mode 100644
index 381cdeab..00000000
--- a/spec/controllers/api/web/push_subscriptions_controller_spec.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::Web::PushSubscriptionsController do
- render_views
-
- let(:user) { Fabricate(:user) }
-
- let(:create_payload) do
- {
- subscription: {
- endpoint: 'https://fcm.googleapis.com/fcm/send/fiuH06a27qE:APA91bHnSiGcLwdaxdyqVXNDR9w1NlztsHb6lyt5WDKOC_Z_Q8BlFxQoR8tWFSXUIDdkyw0EdvxTu63iqamSaqVSevW5LfoFwojws8XYDXv_NRRLH6vo2CdgiN4jgHv5VLt2A8ah6lUX',
- keys: {
- p256dh: 'BEm_a0bdPDhf0SOsrnB2-ategf1hHoCnpXgQsFj5JCkcoMrMt2WHoPfEYOYPzOIs9mZE8ZUaD7VA5vouy0kEkr8=',
- auth: 'eH_C8rq2raXqlcBVDa1gLg==',
- },
- }
- }
- end
-
- let(:alerts_payload) do
- {
- data: {
- alerts: {
- follow: true,
- favourite: false,
- reblog: true,
- mention: false,
- }
- }
- }
- end
-
- describe 'POST #create' do
- it 'saves push subscriptions' do
- sign_in(user)
-
- stub_request(:post, create_payload[:subscription][:endpoint]).to_return(status: 200)
-
- post :create, format: :json, params: create_payload
-
- user.reload
-
- push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
-
- expect(push_subscription['endpoint']).to eq(create_payload[:subscription][:endpoint])
- expect(push_subscription['key_p256dh']).to eq(create_payload[:subscription][:keys][:p256dh])
- expect(push_subscription['key_auth']).to eq(create_payload[:subscription][:keys][:auth])
- end
-
- context 'with initial data' do
- it 'saves alert settings' do
- sign_in(user)
-
- stub_request(:post, create_payload[:subscription][:endpoint]).to_return(status: 200)
-
- post :create, format: :json, params: create_payload.merge(alerts_payload)
-
- push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
-
- expect(push_subscription.data['alerts']['follow']).to eq(alerts_payload[:data][:alerts][:follow].to_s)
- expect(push_subscription.data['alerts']['favourite']).to eq(alerts_payload[:data][:alerts][:favourite].to_s)
- expect(push_subscription.data['alerts']['reblog']).to eq(alerts_payload[:data][:alerts][:reblog].to_s)
- expect(push_subscription.data['alerts']['mention']).to eq(alerts_payload[:data][:alerts][:mention].to_s)
- end
- end
- end
-
- describe 'PUT #update' do
- it 'changes alert settings' do
- sign_in(user)
-
- stub_request(:post, create_payload[:subscription][:endpoint]).to_return(status: 200)
-
- post :create, format: :json, params: create_payload
-
- alerts_payload[:id] = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint]).id
-
- put :update, format: :json, params: alerts_payload
-
- push_subscription = Web::PushSubscription.find_by(endpoint: create_payload[:subscription][:endpoint])
-
- expect(push_subscription.data['alerts']['follow']).to eq(alerts_payload[:data][:alerts][:follow].to_s)
- expect(push_subscription.data['alerts']['favourite']).to eq(alerts_payload[:data][:alerts][:favourite].to_s)
- expect(push_subscription.data['alerts']['reblog']).to eq(alerts_payload[:data][:alerts][:reblog].to_s)
- expect(push_subscription.data['alerts']['mention']).to eq(alerts_payload[:data][:alerts][:mention].to_s)
- end
- end
-end
diff --git a/spec/controllers/api/web/settings_controller_spec.rb b/spec/controllers/api/web/settings_controller_spec.rb
deleted file mode 100644
index 815da04c..00000000
--- a/spec/controllers/api/web/settings_controller_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Api::Web::SettingsController do
- render_views
-
- let!(:user) { Fabricate(:user) }
-
- describe 'PATCH #update' do
- it 'redirects to about page' do
- sign_in(user)
- patch :update, format: :json, params: { data: { 'onboarded' => true } }
-
- user.reload
- expect(response).to have_http_status(200)
- expect(user_web_setting.data['onboarded']).to eq('true')
- end
-
- def user_web_setting
- Web::Setting.where(user: user).first
- end
- end
-end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
deleted file mode 100644
index a93be917..00000000
--- a/spec/controllers/application_controller_spec.rb
+++ /dev/null
@@ -1,368 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- def success
- head 200
- end
-
- def routing_error
- raise ActionController::RoutingError, ''
- end
-
- def record_not_found
- raise ActiveRecord::RecordNotFound, ''
- end
-
- def invalid_authenticity_token
- raise ActionController::InvalidAuthenticityToken, ''
- end
- end
-
- shared_examples 'respond_with_error' do |code|
- it "returns http #{code} for any" do
- subject
- expect(response).to have_http_status(code)
- end
-
- it "returns http #{code} for http" do
- subject
- expect(response).to have_http_status(code)
- end
-
- it "renders template for http" do
- is_expected.to render_template("errors/#{code}", layout: 'error')
- end
- end
-
- context 'forgery' do
- subject do
- ActionController::Base.allow_forgery_protection = true
- routes.draw { post 'success' => 'anonymous#success' }
- post 'success'
- end
-
- include_examples 'respond_with_error', 422
- end
-
- it "does not force ssl if Rails.env.production? is not 'true'" do
- routes.draw { get 'success' => 'anonymous#success' }
- allow(Rails.env).to receive(:production?).and_return(false)
- get 'success'
- expect(response).to have_http_status(200)
- end
-
- it "forces ssl if Rails.env.production? is 'true'" do
- routes.draw { get 'success' => 'anonymous#success' }
- allow(Rails.env).to receive(:production?).and_return(true)
- get 'success'
- expect(response).to redirect_to('https://test.host/success')
- end
-
- describe 'helper_method :current_account' do
- it 'returns nil if not signed in' do
- expect(controller.view_context.current_account).to be_nil
- end
-
- it 'returns account if signed in' do
- account = Fabricate(:account)
- sign_in(Fabricate(:user, account: account))
- expect(controller.view_context.current_account).to eq account
- end
- end
-
- describe 'helper_method :single_user_mode?' do
- it 'returns false if it is in single_user_mode but there is no account' do
- allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
- expect(controller.view_context.single_user_mode?).to eq false
- end
-
- it 'returns false if there is an account but it is not in single_user_mode' do
- allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
- Fabricate(:account)
- expect(controller.view_context.single_user_mode?).to eq false
- end
-
- it 'returns true if it is in single_user_mode and there is an account' do
- allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
- Fabricate(:account)
- expect(controller.view_context.single_user_mode?).to eq true
- end
- end
-
- describe 'helper_method :current_theme' do
- it 'returns "default" when theme wasn\'t changed in admin settings' do
- allow(Setting).to receive(:default_settings).and_return({ 'theme' => 'default' })
-
- expect(controller.view_context.current_theme).to eq 'default'
- end
-
- it 'returns instances\'s theme when user is not signed in' do
- allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
-
- expect(controller.view_context.current_theme).to eq 'contrast'
- end
-
- it 'returns instances\'s default theme when user didn\'t set theme' do
- current_user = Fabricate(:user)
- sign_in current_user
-
- allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
-
- expect(controller.view_context.current_theme).to eq 'contrast'
- end
-
- it 'returns user\'s theme when it is set' do
- current_user = Fabricate(:user)
- current_user.settings['theme'] = 'gabsocial-light'
- sign_in current_user
-
- allow(Setting).to receive(:[]).with('theme').and_return 'contrast'
-
- expect(controller.view_context.current_theme).to eq 'gabsocial-light'
- end
- end
-
- context 'ActionController::RoutingError' do
- subject do
- routes.draw { get 'routing_error' => 'anonymous#routing_error' }
- get 'routing_error'
- end
-
- include_examples 'respond_with_error', 404
- end
-
- context 'ActiveRecord::RecordNotFound' do
- subject do
- routes.draw { get 'record_not_found' => 'anonymous#record_not_found' }
- get 'record_not_found'
- end
-
- include_examples 'respond_with_error', 404
- end
-
- context 'ActionController::InvalidAuthenticityToken' do
- subject do
- routes.draw { get 'invalid_authenticity_token' => 'anonymous#invalid_authenticity_token' }
- get 'invalid_authenticity_token'
- end
-
- include_examples 'respond_with_error', 422
- end
-
- describe 'before_action :store_current_location' do
- it 'stores location for user if it is not devise controller' do
- routes.draw { get 'success' => 'anonymous#success' }
- get 'success'
- expect(controller.stored_location_for(:user)).to eq '/success'
- end
-
- context do
- controller Devise::SessionsController do
- end
-
- it 'does not store location for user if it is devise controller' do
- @request.env["devise.mapping"] = Devise.mappings[:user]
- get 'create'
- expect(controller.stored_location_for(:user)).to be_nil
- end
- end
- end
-
- describe 'before_action :check_suspension' do
- before do
- routes.draw { get 'success' => 'anonymous#success' }
- end
-
- it 'does nothing if not signed in' do
- get 'success'
- expect(response).to have_http_status(200)
- end
-
- it 'does nothing if user who signed in is not suspended' do
- sign_in(Fabricate(:user, account: Fabricate(:account, suspended: false)))
- get 'success'
- expect(response).to have_http_status(200)
- end
-
- it 'returns http 403 if user who signed in is suspended' do
- sign_in(Fabricate(:user, account: Fabricate(:account, suspended: true)))
- get 'success'
- expect(response).to have_http_status(403)
- end
- end
-
- describe 'raise_not_found' do
- it 'raises error' do
- controller.params[:unmatched_route] = 'unmatched'
- expect { controller.raise_not_found }.to raise_error(ActionController::RoutingError, 'No route matches unmatched')
- end
- end
-
- describe 'require_admin!' do
- controller do
- before_action :require_admin!
-
- def sucesss
- head 200
- end
- end
-
- before do
- routes.draw { get 'sucesss' => 'anonymous#sucesss' }
- end
-
- it 'returns a 403 if current user is not admin' do
- sign_in(Fabricate(:user, admin: false))
- get 'sucesss'
- expect(response).to have_http_status(403)
- end
-
- it 'returns a 403 if current user is only a moderator' do
- sign_in(Fabricate(:user, moderator: true))
- get 'sucesss'
- expect(response).to have_http_status(403)
- end
-
- it 'does nothing if current user is admin' do
- sign_in(Fabricate(:user, admin: true))
- get 'sucesss'
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'require_staff!' do
- controller do
- before_action :require_staff!
-
- def sucesss
- head 200
- end
- end
-
- before do
- routes.draw { get 'sucesss' => 'anonymous#sucesss' }
- end
-
- it 'returns a 403 if current user is not admin or moderator' do
- sign_in(Fabricate(:user, admin: false, moderator: false))
- get 'sucesss'
- expect(response).to have_http_status(403)
- end
-
- it 'does nothing if current user is moderator' do
- sign_in(Fabricate(:user, moderator: true))
- get 'sucesss'
- expect(response).to have_http_status(200)
- end
-
- it 'does nothing if current user is admin' do
- sign_in(Fabricate(:user, admin: true))
- get 'sucesss'
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'forbidden' do
- controller do
- def route_forbidden
- forbidden
- end
- end
-
- subject do
- routes.draw { get 'route_forbidden' => 'anonymous#route_forbidden' }
- get 'route_forbidden'
- end
-
- include_examples 'respond_with_error', 403
- end
-
- describe 'not_found' do
- controller do
- def route_not_found
- not_found
- end
- end
-
- subject do
- routes.draw { get 'route_not_found' => 'anonymous#route_not_found' }
- get 'route_not_found'
- end
-
- include_examples 'respond_with_error', 404
- end
-
- describe 'gone' do
- controller do
- def route_gone
- gone
- end
- end
-
- subject do
- routes.draw { get 'route_gone' => 'anonymous#route_gone' }
- get 'route_gone'
- end
-
- include_examples 'respond_with_error', 410
- end
-
- describe 'unprocessable_entity' do
- controller do
- def route_unprocessable_entity
- unprocessable_entity
- end
- end
-
- subject do
- routes.draw { get 'route_unprocessable_entity' => 'anonymous#route_unprocessable_entity' }
- get 'route_unprocessable_entity'
- end
-
- include_examples 'respond_with_error', 422
- end
-
- describe 'cache_collection' do
- class C < ApplicationController
- public :cache_collection
- end
-
- shared_examples 'receives :with_includes' do |fabricator, klass|
- it 'uses raw if it is not an ActiveRecord::Relation' do
- record = Fabricate(fabricator)
- expect(C.new.cache_collection([record], klass)).to eq [record]
- end
- end
-
- shared_examples 'cacheable' do |fabricator, klass|
- include_examples 'receives :with_includes', fabricator, klass
-
- it 'calls cache_ids of raw if it is an ActiveRecord::Relation' do
- record = Fabricate(fabricator)
- relation = klass.none
- allow(relation).to receive(:cache_ids).and_return([record])
- expect(C.new.cache_collection(relation, klass)).to eq [record]
- end
- end
-
- it 'returns raw unless class responds to :with_includes' do
- raw = Object.new
- expect(C.new.cache_collection(raw, Object)).to eq raw
- end
-
- context 'Notification' do
- include_examples 'cacheable', :notification, Notification
- end
-
- context 'Status' do
- include_examples 'cacheable', :status, Status
- end
-
- context 'StreamEntry' do
- include_examples 'receives :with_includes', :stream_entry, StreamEntry
- end
- end
-end
diff --git a/spec/controllers/auth/confirmations_controller_spec.rb b/spec/controllers/auth/confirmations_controller_spec.rb
deleted file mode 100644
index e9a471fc..00000000
--- a/spec/controllers/auth/confirmations_controller_spec.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Auth::ConfirmationsController, type: :controller do
- render_views
-
- describe 'GET #new' do
- it 'returns http success' do
- @request.env['devise.mapping'] = Devise.mappings[:user]
- get :new
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #show' do
- context 'when user is unconfirmed' do
- let!(:user) { Fabricate(:user, confirmation_token: 'foobar', confirmed_at: nil) }
-
- before do
- allow(BootstrapTimelineWorker).to receive(:perform_async)
- @request.env['devise.mapping'] = Devise.mappings[:user]
- get :show, params: { confirmation_token: 'foobar' }
- end
-
- it 'redirects to login' do
- expect(response).to redirect_to(new_user_session_path)
- end
-
- it 'queues up bootstrapping of home timeline' do
- expect(BootstrapTimelineWorker).to have_received(:perform_async).with(user.account_id)
- end
- end
-
- context 'when user is updating email' do
- let!(:user) { Fabricate(:user, confirmation_token: 'foobar', unconfirmed_email: 'new-email@example.com') }
-
- before do
- allow(BootstrapTimelineWorker).to receive(:perform_async)
- @request.env['devise.mapping'] = Devise.mappings[:user]
- get :show, params: { confirmation_token: 'foobar' }
- end
-
- it 'redirects to login' do
- expect(response).to redirect_to(new_user_session_path)
- end
-
- it 'does not queue up bootstrapping of home timeline' do
- expect(BootstrapTimelineWorker).to_not have_received(:perform_async)
- end
- end
- end
-
- describe 'GET #finish_signup' do
- subject { get :finish_signup }
-
- let(:user) { Fabricate(:user) }
- before do
- sign_in user, scope: :user
- @request.env['devise.mapping'] = Devise.mappings[:user]
- end
-
- it 'renders finish_signup' do
- is_expected.to render_template :finish_signup
- expect(assigns(:user)).to have_attributes id: user.id
- end
- end
-
- describe 'PATCH #finish_signup' do
- subject { patch :finish_signup, params: { user: { email: email } } }
-
- let(:user) { Fabricate(:user) }
- before do
- sign_in user, scope: :user
- @request.env['devise.mapping'] = Devise.mappings[:user]
- end
-
- context 'when email is valid' do
- let(:email) { 'new_' + user.email }
-
- it 'redirects to root_path' do
- is_expected.to redirect_to root_path
- end
- end
-
- context 'when email is invalid' do
- let(:email) { '' }
-
- it 'renders finish_signup' do
- is_expected.to render_template :finish_signup
- end
- end
- end
-end
diff --git a/spec/controllers/auth/passwords_controller_spec.rb b/spec/controllers/auth/passwords_controller_spec.rb
deleted file mode 100644
index dcfdebb1..00000000
--- a/spec/controllers/auth/passwords_controller_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Auth::PasswordsController, type: :controller do
- include Devise::Test::ControllerHelpers
-
- describe 'GET #new' do
- it 'returns http success' do
- @request.env['devise.mapping'] = Devise.mappings[:user]
- get :new
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #edit' do
- let(:user) { Fabricate(:user) }
-
- before do
- request.env['devise.mapping'] = Devise.mappings[:user]
- @token = user.send_reset_password_instructions
- end
-
- context 'with valid reset_password_token' do
- it 'returns http success' do
- get :edit, params: { reset_password_token: @token }
- expect(response).to have_http_status(200)
- end
- end
-
- context 'with invalid reset_password_token' do
- it 'redirects to #new' do
- get :edit, params: { reset_password_token: 'some_invalid_value' }
- expect(response).to redirect_to subject.new_password_path(subject.send(:resource_name))
- end
- end
- end
-end
diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb
deleted file mode 100644
index a4337039..00000000
--- a/spec/controllers/auth/registrations_controller_spec.rb
+++ /dev/null
@@ -1,218 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Auth::RegistrationsController, type: :controller do
- render_views
-
- shared_examples 'checks for enabled registrations' do |path|
- around do |example|
- registrations_mode = Setting.registrations_mode
- example.run
- Setting.registrations_mode = registrations_mode
- end
-
- it 'redirects if it is in single user mode while it is open for registration' do
- Fabricate(:account)
- Setting.registrations_mode = 'open'
- expect(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
-
- get path
-
- expect(response).to redirect_to '/'
- end
-
- it 'redirects if it is not open for registration while it is not in single user mode' do
- Setting.registrations_mode = 'none'
- expect(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
-
- get path
-
- expect(response).to redirect_to '/'
- end
- end
-
- describe 'GET #edit' do
- it 'returns http success' do
- request.env["devise.mapping"] = Devise.mappings[:user]
- sign_in(Fabricate(:user))
- get :edit
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #update' do
- it 'returns http success' do
- request.env["devise.mapping"] = Devise.mappings[:user]
- sign_in(Fabricate(:user), scope: :user)
- post :update
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #new' do
- before do
- request.env["devise.mapping"] = Devise.mappings[:user]
- end
-
- context do
- around do |example|
- registrations_mode = Setting.registrations_mode
- example.run
- Setting.registrations_mode = registrations_mode
- end
-
- it 'returns http success' do
- Setting.registrations_mode = 'open'
- get :new
- expect(response).to have_http_status(200)
- end
- end
-
- include_examples 'checks for enabled registrations', :new
- end
-
- describe 'POST #create' do
- let(:accept_language) { Rails.application.config.i18n.available_locales.sample.to_s }
-
- around do |example|
- current_locale = I18n.locale
- example.run
- I18n.locale = current_locale
- end
-
- before { request.env["devise.mapping"] = Devise.mappings[:user] }
-
- context do
- around do |example|
- registrations_mode = Setting.registrations_mode
- example.run
- Setting.registrations_mode = registrations_mode
- end
-
- subject do
- Setting.registrations_mode = 'open'
- request.headers["Accept-Language"] = accept_language
- post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
- end
-
- it 'redirects to login page' do
- subject
- expect(response).to redirect_to new_user_session_path
- end
-
- it 'creates user' do
- subject
- user = User.find_by(email: 'test@example.com')
- expect(user).to_not be_nil
- expect(user.locale).to eq(accept_language)
- end
- end
-
- context 'approval-based registrations without invite' do
- around do |example|
- registrations_mode = Setting.registrations_mode
- example.run
- Setting.registrations_mode = registrations_mode
- end
-
- subject do
- Setting.registrations_mode = 'approved'
- request.headers["Accept-Language"] = accept_language
- post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678' } }
- end
-
- it 'redirects to login page' do
- subject
- expect(response).to redirect_to new_user_session_path
- end
-
- it 'creates user' do
- subject
- user = User.find_by(email: 'test@example.com')
- expect(user).to_not be_nil
- expect(user.locale).to eq(accept_language)
- expect(user.approved).to eq(false)
- end
- end
-
- context 'approval-based registrations with expired invite' do
- around do |example|
- registrations_mode = Setting.registrations_mode
- example.run
- Setting.registrations_mode = registrations_mode
- end
-
- subject do
- Setting.registrations_mode = 'approved'
- request.headers["Accept-Language"] = accept_language
- invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.ago)
- post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
- end
-
- it 'redirects to login page' do
- subject
- expect(response).to redirect_to new_user_session_path
- end
-
- it 'creates user' do
- subject
- user = User.find_by(email: 'test@example.com')
- expect(user).to_not be_nil
- expect(user.locale).to eq(accept_language)
- expect(user.approved).to eq(false)
- end
- end
-
- context 'approval-based registrations with valid invite' do
- around do |example|
- registrations_mode = Setting.registrations_mode
- example.run
- Setting.registrations_mode = registrations_mode
- end
-
- subject do
- Setting.registrations_mode = 'approved'
- request.headers["Accept-Language"] = accept_language
- invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.from_now)
- post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', 'invite_code': invite.code } }
- end
-
- it 'redirects to login page' do
- subject
- expect(response).to redirect_to new_user_session_path
- end
-
- it 'creates user' do
- subject
- user = User.find_by(email: 'test@example.com')
- expect(user).to_not be_nil
- expect(user.locale).to eq(accept_language)
- expect(user.approved).to eq(true)
- end
- end
-
- it 'does nothing if user already exists' do
- Fabricate(:user, account: Fabricate(:account, username: 'test'))
- subject
- end
-
- include_examples 'checks for enabled registrations', :create
- end
-
- describe 'DELETE #destroy' do
- let(:user) { Fabricate(:user) }
-
- before do
- request.env['devise.mapping'] = Devise.mappings[:user]
- sign_in(user, scope: :user)
- delete :destroy
- end
-
- it 'returns http not found' do
- expect(response).to have_http_status(:not_found)
- end
-
- it 'does not delete user' do
- expect(User.find(user.id)).to_not be_nil
- end
- end
-end
diff --git a/spec/controllers/auth/sessions_controller_spec.rb b/spec/controllers/auth/sessions_controller_spec.rb
deleted file mode 100644
index 71fcc1a6..00000000
--- a/spec/controllers/auth/sessions_controller_spec.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Auth::SessionsController, type: :controller do
- render_views
-
- describe 'GET #new' do
- before do
- request.env['devise.mapping'] = Devise.mappings[:user]
- end
-
- it 'returns http success' do
- get :new
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'DELETE #destroy' do
- let(:user) { Fabricate(:user) }
-
- before do
- request.env['devise.mapping'] = Devise.mappings[:user]
- end
-
- context 'with a regular user' do
- it 'redirects to home after sign out' do
- sign_in(user, scope: :user)
- delete :destroy
-
- expect(response).to redirect_to(new_user_session_path)
- end
-
- it 'does not delete redirect location with continue=true' do
- sign_in(user, scope: :user)
- controller.store_location_for(:user, '/authorize')
- delete :destroy, params: { continue: 'true' }
- expect(controller.stored_location_for(:user)).to eq '/authorize'
- end
- end
-
- context 'with a suspended user' do
- it 'redirects to home after sign out' do
- Fabricate(:account, user: user, suspended: true)
- sign_in(user, scope: :user)
- delete :destroy
-
- expect(response).to redirect_to(new_user_session_path)
- end
- end
- end
-
- describe 'POST #create' do
- before do
- request.env['devise.mapping'] = Devise.mappings[:user]
- end
-
- context 'using PAM authentication', if: ENV['PAM_ENABLED'] == 'true' do
- context 'using a valid password' do
- before do
- post :create, params: { user: { email: "pam_user1", password: '123456' } }
- end
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
-
- it 'logs the user in' do
- expect(controller.current_user).to be_instance_of(User)
- end
- end
-
- context 'using an invalid password' do
- before do
- post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } }
- end
-
- it 'shows a login error' do
- expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
- end
-
- it "doesn't log the user in" do
- expect(controller.current_user).to be_nil
- end
- end
-
- context 'using a valid email and existing user' do
- let(:user) do
- account = Fabricate.build(:account, username: 'pam_user1')
- account.save!(validate: false)
- user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account)
- user
- end
-
- before do
- post :create, params: { user: { email: user.email, password: '123456' } }
- end
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
-
- it 'logs the user in' do
- expect(controller.current_user).to eq user
- end
- end
- end
-
- context 'using password authentication' do
- let(:user) { Fabricate(:user, email: 'foo@bar.com', password: 'abcdefgh') }
-
- context 'using a valid password' do
- before do
- post :create, params: { user: { email: user.email, password: user.password } }
- end
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
-
- it 'logs the user in' do
- expect(controller.current_user).to eq user
- end
- end
-
- context 'using email with uppercase letters' do
- before do
- post :create, params: { user: { email: user.email.upcase, password: user.password } }
- end
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
-
- it 'logs the user in' do
- expect(controller.current_user).to eq user
- end
- end
-
- context 'using an invalid password' do
- before do
- post :create, params: { user: { email: user.email, password: 'wrongpw' } }
- end
-
- it 'shows a login error' do
- expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
- end
-
- it "doesn't log the user in" do
- expect(controller.current_user).to be_nil
- end
- end
-
- context 'using an unconfirmed password' do
- before do
- request.headers['Accept-Language'] = accept_language
- post :create, params: { user: { email: unconfirmed_user.email, password: unconfirmed_user.password } }
- end
-
- let(:unconfirmed_user) { user.tap { |u| u.update!(confirmed_at: nil) } }
- let(:accept_language) { 'fr' }
-
- it 'shows a translated login error' do
- expect(flash[:alert]).to eq(I18n.t('devise.failure.unconfirmed', locale: accept_language))
- end
- end
-
- context "logging in from the user's page" do
- before do
- allow(controller).to receive(:single_user_mode?).and_return(single_user_mode)
- allow(controller).to receive(:stored_location_for).with(:user).and_return("/@#{user.account.username}")
- post :create, params: { user: { email: user.email, password: user.password } }
- end
-
- context "in single user mode" do
- let(:single_user_mode) { true }
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
- end
-
- context "in non-single user mode" do
- let(:single_user_mode) { false }
-
- it "redirects back to the user's page" do
- expect(response).to redirect_to(short_account_path(username: user.account))
- end
- end
- end
- end
-
- context 'using two-factor authentication' do
- let(:user) do
- Fabricate(:user, email: 'x@y.com', password: 'abcdefgh',
- otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
- end
- let(:recovery_codes) do
- codes = user.generate_otp_backup_codes!
- user.save
- return codes
- end
-
- context 'using email and password' do
- before do
- post :create, params: { user: { email: user.email, password: user.password } }
- end
-
- it 'renders two factor authentication page' do
- expect(controller).to render_template("two_factor")
- end
- end
-
- context 'using upcase email and password' do
- before do
- post :create, params: { user: { email: user.email.upcase, password: user.password } }
- end
-
- it 'renders two factor authentication page' do
- expect(controller).to render_template("two_factor")
- end
- end
-
- context 'using a valid OTP' do
- before do
- post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
- end
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
-
- it 'logs the user in' do
- expect(controller.current_user).to eq user
- end
- end
-
- context 'when the server has an decryption error' do
- before do
- allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError)
- post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
- end
-
- it 'shows a login error' do
- expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
- end
-
- it "doesn't log the user in" do
- expect(controller.current_user).to be_nil
- end
- end
-
- context 'using a valid recovery code' do
- before do
- post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { otp_user_id: user.id }
- end
-
- it 'redirects to home' do
- expect(response).to redirect_to(root_path)
- end
-
- it 'logs the user in' do
- expect(controller.current_user).to eq user
- end
- end
-
- context 'using an invalid OTP' do
- before do
- post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { otp_user_id: user.id }
- end
-
- it 'shows a login error' do
- expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
- end
-
- it "doesn't log the user in" do
- expect(controller.current_user).to be_nil
- end
- end
- end
- end
-end
diff --git a/spec/controllers/authorize_interactions_controller_spec.rb b/spec/controllers/authorize_interactions_controller_spec.rb
deleted file mode 100644
index ce4257b6..00000000
--- a/spec/controllers/authorize_interactions_controller_spec.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe AuthorizeInteractionsController do
- render_views
-
- describe 'GET #show' do
- describe 'when signed out' do
- it 'redirects to sign in page' do
- get :show
-
- expect(response).to redirect_to(new_user_session_path)
- end
- end
-
- describe 'when signed in' do
- let(:user) { Fabricate(:user) }
- let(:account) { Fabricate(:account, user: user) }
-
- before do
- sign_in(user)
- end
-
- it 'renders error without acct param' do
- get :show
-
- expect(response).to render_template(:error)
- end
-
- it 'renders error when account cant be found' do
- service = double
- allow(ResolveAccountService).to receive(:new).and_return(service)
- allow(service).to receive(:call).with('missing@hostname').and_return(nil)
-
- get :show, params: { acct: 'acct:missing@hostname' }
-
- expect(response).to render_template(:error)
- expect(service).to have_received(:call).with('missing@hostname')
- end
-
- it 'sets resource from url' do
- account = Account.new
- service = double
- allow(ResolveURLService).to receive(:new).and_return(service)
- allow(service).to receive(:call).with('http://example.com').and_return(account)
-
- get :show, params: { acct: 'http://example.com' }
-
- expect(response).to have_http_status(200)
- expect(assigns(:resource)).to eq account
- end
-
- it 'sets resource from acct uri' do
- account = Account.new
- service = double
- allow(ResolveAccountService).to receive(:new).and_return(service)
- allow(service).to receive(:call).with('found@hostname').and_return(account)
-
- get :show, params: { acct: 'acct:found@hostname' }
-
- expect(response).to have_http_status(200)
- expect(assigns(:resource)).to eq account
- end
- end
- end
-
- describe 'POST #create' do
- describe 'when signed out' do
- it 'redirects to sign in page' do
- post :create
-
- expect(response).to redirect_to(new_user_session_path)
- end
- end
-
- describe 'when signed in' do
- let!(:user) { Fabricate(:user) }
- let!(:account) { user.account }
-
- before do
- sign_in(user)
- end
-
- it 'shows error when account not found' do
- service = double
-
- allow(ResolveAccountService).to receive(:new).and_return(service)
- allow(service).to receive(:call).with('user@hostname').and_return(nil)
-
- post :create, params: { acct: 'acct:user@hostname' }
-
- expect(response).to render_template(:error)
- end
-
- it 'follows account when found' do
- target_account = Fabricate(:account)
- service = double
-
- allow(ResolveAccountService).to receive(:new).and_return(service)
- allow(service).to receive(:call).with('user@hostname').and_return(target_account)
- allow(service).to receive(:call).with(target_account, skip_webfinger: true).and_return(target_account)
-
-
- post :create, params: { acct: 'acct:user@hostname' }
-
- expect(service).to have_received(:call).with(target_account, skip_webfinger: true)
- expect(account.following?(target_account)).to be true
- expect(response).to render_template(:success)
- end
- end
- end
-end
diff --git a/spec/controllers/concerns/account_controller_concern_spec.rb b/spec/controllers/concerns/account_controller_concern_spec.rb
deleted file mode 100644
index ea2b4a2a..00000000
--- a/spec/controllers/concerns/account_controller_concern_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- include AccountControllerConcern
-
- def success
- head 200
- end
- end
-
- before do
- routes.draw { get 'success' => 'anonymous#success' }
- end
-
- context 'when account is suspended' do
- it 'returns http gone' do
- account = Fabricate(:account, suspended: true, user: Fabricate(:user))
- get 'success', params: { account_username: account.username }
- expect(response).to have_http_status(410)
- end
- end
-
- context 'when account is deleted by owner' do
- it 'returns http gone' do
- account = Fabricate(:account, suspended: true, user: nil)
- get 'success', params: { account_username: account.username }
- expect(response).to have_http_status(410)
- end
- end
-
- context 'when account is not suspended' do
- it 'assigns @account' do
- account = Fabricate(:account, user: Fabricate(:user))
- get 'success', params: { account_username: account.username }
- expect(assigns(:account)).to eq account
- end
-
- it 'sets link headers' do
- account = Fabricate(:account, username: 'username', user: Fabricate(:user))
- get 'success', params: { account_username: 'username' }
- expect(response.headers['Link'].to_s).to eq '; rel="lrdd"; type="application/xrd+xml", ; rel="alternate"; type="application/atom+xml", ; rel="alternate"; type="application/activity+json"'
- end
-
- it 'returns http success' do
- account = Fabricate(:account, user: Fabricate(:user))
- get 'success', params: { account_username: account.username }
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/concerns/accountable_concern_spec.rb b/spec/controllers/concerns/accountable_concern_spec.rb
deleted file mode 100644
index e3c06b49..00000000
--- a/spec/controllers/concerns/accountable_concern_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe AccountableConcern do
- class Hoge
- include AccountableConcern
- attr_reader :current_account
-
- def initialize(current_account)
- @current_account = current_account
- end
- end
-
- let(:user) { Fabricate(:user, account: Fabricate(:account)) }
- let(:target) { Fabricate(:user, account: Fabricate(:account)) }
- let(:hoge) { Hoge.new(user.account) }
-
- describe '#log_action' do
- it 'creates Admin::ActionLog' do
- expect do
- hoge.log_action(:create, target.account)
- end.to change { Admin::ActionLog.count }.by(1)
- end
- end
-end
diff --git a/spec/controllers/concerns/export_controller_concern_spec.rb b/spec/controllers/concerns/export_controller_concern_spec.rb
deleted file mode 100644
index e5861c80..00000000
--- a/spec/controllers/concerns/export_controller_concern_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- include ExportControllerConcern
- def index
- send_export_file
- end
-
- def export_data
- @export.account.username
- end
- end
-
- describe 'GET #index' do
- it 'returns a csv of the exported data when signed in' do
- user = Fabricate(:user)
- sign_in user
- get :index, format: :csv
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'text/csv'
- expect(response.headers['Content-Disposition']).to eq 'attachment; filename="anonymous.csv"'
- expect(response.body).to eq user.account.username
- end
-
- it 'returns unauthorized when not signed in' do
- get :index, format: :csv
- expect(response).to have_http_status(:unauthorized)
- end
- end
-end
diff --git a/spec/controllers/concerns/localized_spec.rb b/spec/controllers/concerns/localized_spec.rb
deleted file mode 100644
index 76c3de11..00000000
--- a/spec/controllers/concerns/localized_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- include Localized
-
- def success
- head 200
- end
- end
-
- around do |example|
- current_locale = I18n.locale
- example.run
- I18n.locale = current_locale
- end
-
- before do
- routes.draw { get 'success' => 'anonymous#success' }
- end
-
- shared_examples 'default locale' do
- it 'sets available and preferred language' do
- request.headers['Accept-Language'] = 'ca-ES, fa'
- get 'success'
- expect(I18n.locale).to eq :fa
- end
-
- it 'sets available and compatible language if none of available languages are preferred' do
- request.headers['Accept-Language'] = 'fa-IR'
- get 'success'
- expect(I18n.locale).to eq :fa
- end
-
- it 'sets default locale if none of available languages are compatible' do
- request.headers['Accept-Language'] = ''
- get 'success'
- expect(I18n.locale).to eq :en
- end
- end
-
- context 'user with valid locale has signed in' do
- it "sets user's locale" do
- user = Fabricate(:user, locale: :ca)
-
- sign_in(user)
- get 'success'
-
- expect(I18n.locale).to eq :ca
- end
- end
-
- context 'user with invalid locale has signed in' do
- before do
- user = Fabricate.build(:user, locale: :invalid)
- user.save!(validate: false)
- sign_in(user)
- end
-
- include_examples 'default locale'
- end
-
- context 'user has not signed in' do
- include_examples 'default locale'
- end
-end
diff --git a/spec/controllers/concerns/obfuscate_filename_spec.rb b/spec/controllers/concerns/obfuscate_filename_spec.rb
deleted file mode 100644
index e06d53c0..00000000
--- a/spec/controllers/concerns/obfuscate_filename_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- include ObfuscateFilename
-
- obfuscate_filename :file
-
- def file
- render plain: params[:file]&.original_filename
- end
- end
-
- before do
- routes.draw { get 'file' => 'anonymous#file' }
- end
-
- it 'obfusticates filename if the given parameter is specified' do
- file = fixture_file_upload('files/imports.txt', 'text/plain')
- post 'file', params: { file: file }
- expect(response.body).to end_with '.txt'
- expect(response.body).not_to include 'imports'
- end
-
- it 'does nothing if the given parameter is not specified' do
- post 'file'
- end
-end
diff --git a/spec/controllers/concerns/rate_limit_headers_spec.rb b/spec/controllers/concerns/rate_limit_headers_spec.rb
deleted file mode 100644
index 00a9a208..00000000
--- a/spec/controllers/concerns/rate_limit_headers_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController do
- controller do
- include RateLimitHeaders
-
- def show
- head 200
- end
- end
-
- before do
- routes.draw { get 'show' => 'anonymous#show' }
- end
-
- describe 'rate limiting' do
- context 'throttling is off' do
- before do
- request.env['rack.attack.throttle_data'] = nil
- end
-
- it 'does not apply rate limiting' do
- get 'show'
-
- expect(response.headers['X-RateLimit-Limit']).to be_nil
- expect(response.headers['X-RateLimit-Remaining']).to be_nil
- expect(response.headers['X-RateLimit-Reset']).to be_nil
- end
- end
-
- context 'throttling is on' do
- let(:start_time) { DateTime.new(2017, 1, 1, 12, 0, 0).utc }
-
- before do
- request.env['rack.attack.throttle_data'] = { 'throttle_authenticated_api' => { limit: 100, count: 20, period: 10 } }
- travel_to start_time do
- get 'show'
- end
- end
-
- it 'applies rate limiting limit header' do
- expect(response.headers['X-RateLimit-Limit']).to eq '100'
- end
-
- it 'applies rate limiting remaining header' do
- expect(response.headers['X-RateLimit-Remaining']).to eq '80'
- end
-
- it 'applies rate limiting reset header' do
- expect(response.headers['X-RateLimit-Reset']).to eq (start_time + 10.seconds).iso8601(6)
- end
- end
- end
-end
diff --git a/spec/controllers/concerns/signature_verification_spec.rb b/spec/controllers/concerns/signature_verification_spec.rb
deleted file mode 100644
index 72069009..00000000
--- a/spec/controllers/concerns/signature_verification_spec.rb
+++ /dev/null
@@ -1,138 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- include SignatureVerification
-
- def success
- head 200
- end
-
- def alternative_success
- head 200
- end
- end
-
- before do
- routes.draw { match via: [:get, :post], 'success' => 'anonymous#success' }
- end
-
- context 'without signature header' do
- before do
- get :success
- end
-
- describe '#signed_request?' do
- it 'returns false' do
- expect(controller.signed_request?).to be false
- end
- end
-
- describe '#signed_request_account' do
- it 'returns nil' do
- expect(controller.signed_request_account).to be_nil
- end
- end
- end
-
- context 'with signature header' do
- let!(:author) { Fabricate(:account) }
-
- context 'without body' do
- before do
- get :success
-
- fake_request = Request.new(:get, request.url)
- fake_request.on_behalf_of(author)
-
- request.headers.merge!(fake_request.headers)
- end
-
- describe '#signed_request?' do
- it 'returns true' do
- expect(controller.signed_request?).to be true
- end
- end
-
- describe '#signed_request_account' do
- it 'returns an account' do
- expect(controller.signed_request_account).to eq author
- end
-
- it 'returns nil when path does not match' do
- request.path = '/alternative-path'
- expect(controller.signed_request_account).to be_nil
- end
-
- it 'returns nil when method does not match' do
- post :success
- expect(controller.signed_request_account).to be_nil
- end
- end
- end
-
- context 'with request older than a day' do
- before do
- get :success
-
- fake_request = Request.new(:get, request.url)
- fake_request.add_headers({ 'Date' => 2.days.ago.utc.httpdate })
- fake_request.on_behalf_of(author)
-
- request.headers.merge!(fake_request.headers)
- end
-
- describe '#signed_request?' do
- it 'returns true' do
- expect(controller.signed_request?).to be true
- end
- end
-
- describe '#signed_request_account' do
- it 'returns nil' do
- expect(controller.signed_request_account).to be_nil
- end
- end
- end
-
- context 'with body' do
- before do
- post :success, body: 'Hello world'
-
- fake_request = Request.new(:post, request.url, body: 'Hello world')
- fake_request.on_behalf_of(author)
-
- request.headers.merge!(fake_request.headers)
- end
-
- describe '#signed_request?' do
- it 'returns true' do
- expect(controller.signed_request?).to be true
- end
- end
-
- describe '#signed_request_account' do
- it 'returns an account' do
- expect(controller.signed_request_account).to eq author
- end
-
- it 'returns nil when path does not match' do
- request.path = '/alternative-path'
- expect(controller.signed_request_account).to be_nil
- end
-
- it 'returns nil when method does not match' do
- get :success
- expect(controller.signed_request_account).to be_nil
- end
-
- it 'returns nil when body has been tampered' do
- post :success, body: 'doo doo doo'
- expect(controller.signed_request_account).to be_nil
- end
- end
- end
- end
-end
diff --git a/spec/controllers/concerns/user_tracking_concern_spec.rb b/spec/controllers/concerns/user_tracking_concern_spec.rb
deleted file mode 100644
index 1e562022..00000000
--- a/spec/controllers/concerns/user_tracking_concern_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ApplicationController, type: :controller do
- controller do
- include UserTrackingConcern
-
- def show
- render plain: 'show'
- end
- end
-
- before do
- routes.draw { get 'show' => 'anonymous#show' }
- end
-
- describe 'when signed in' do
- let(:user) { Fabricate(:user) }
-
- it 'does not track when there is a recent sign in' do
- user.update(current_sign_in_at: 60.minutes.ago)
- prior = user.current_sign_in_at
- sign_in user, scope: :user
- get :show
-
- expect(user.reload.current_sign_in_at).to be_within(1.0).of(prior)
- end
-
- it 'tracks when sign in is nil' do
- user.update(current_sign_in_at: nil)
- sign_in user, scope: :user
- get :show
-
- expect_updated_sign_in_at(user)
- end
-
- it 'tracks when sign in is older than one day' do
- user.update(current_sign_in_at: 2.days.ago)
- sign_in user, scope: :user
- get :show
-
- expect_updated_sign_in_at(user)
- end
-
- describe 'feed regeneration' do
- before do
- alice = Fabricate(:account)
- bob = Fabricate(:account)
-
- user.account.follow!(alice)
- user.account.follow!(bob)
-
- Fabricate(:status, account: alice, text: 'hello world')
- Fabricate(:status, account: bob, text: 'yes hello')
- Fabricate(:status, account: user.account, text: 'test')
-
- user.update(last_sign_in_at: 'Tue, 04 Jul 2017 14:45:56 UTC +00:00', current_sign_in_at: 'Wed, 05 Jul 2017 22:10:52 UTC +00:00')
-
- sign_in user, scope: :user
- end
-
- it 'sets a regeneration marker while regenerating' do
- allow(RegenerationWorker).to receive(:perform_async)
- get :show
-
- expect_updated_sign_in_at(user)
- expect(Redis.current.get("account:#{user.account_id}:regeneration")).to eq 'true'
- expect(RegenerationWorker).to have_received(:perform_async)
- end
-
- it 'sets the regeneration marker to expire' do
- allow(RegenerationWorker).to receive(:perform_async)
- get :show
- expect(Redis.current.ttl("account:#{user.account_id}:regeneration")).to be >= 0
- end
-
- it 'regenerates feed when sign in is older than two weeks' do
- get :show
-
- expect_updated_sign_in_at(user)
- expect(Redis.current.zcard(FeedManager.instance.key(:home, user.account_id))).to eq 3
- expect(Redis.current.get("account:#{user.account_id}:regeneration")).to be_nil
- end
- end
-
- def expect_updated_sign_in_at(user)
- expect(user.reload.current_sign_in_at).to be_within(1.0).of(Time.now.utc)
- end
- end
-end
diff --git a/spec/controllers/emojis_controller_spec.rb b/spec/controllers/emojis_controller_spec.rb
deleted file mode 100644
index fbbd11f6..00000000
--- a/spec/controllers/emojis_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'rails_helper'
-
-describe EmojisController do
- render_views
-
- let(:emoji) { Fabricate(:custom_emoji) }
-
- describe 'GET #show' do
- subject(:response) { get :show, params: { id: emoji.id, format: :json } }
- subject(:body) { JSON.parse(response.body, symbolize_names: true) }
-
- it 'returns the right response' do
- expect(response).to have_http_status 200
- expect(body[:name]).to eq ':coolcat:'
- end
- end
-end
diff --git a/spec/controllers/follower_accounts_controller_spec.rb b/spec/controllers/follower_accounts_controller_spec.rb
deleted file mode 100644
index 83032ab6..00000000
--- a/spec/controllers/follower_accounts_controller_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'rails_helper'
-
-describe FollowerAccountsController do
- render_views
-
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:follower0) { Fabricate(:account) }
- let(:follower1) { Fabricate(:account) }
-
- describe 'GET #index' do
- let!(:follow0) { follower0.follow!(alice) }
- let!(:follow1) { follower1.follow!(alice) }
-
- context 'when format is html' do
- subject(:response) { get :index, params: { account_username: alice.username, format: :html } }
-
- it 'assigns follows' do
- expect(response).to have_http_status(200)
-
- assigned = assigns(:follows).to_a
- expect(assigned.size).to eq 2
- expect(assigned[0]).to eq follow1
- expect(assigned[1]).to eq follow0
- end
- end
-
- context 'when format is json' do
- subject(:response) { get :index, params: { account_username: alice.username, page: page, format: :json } }
- subject(:body) { JSON.parse(response.body) }
-
- context 'with page' do
- let(:page) { 1 }
-
- it 'returns followers' do
- expect(response).to have_http_status(200)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_present
- end
- end
-
- context 'without page' do
- let(:page) { nil }
-
- it 'returns followers' do
- expect(response).to have_http_status(200)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_blank
- end
- end
- end
- end
-end
diff --git a/spec/controllers/following_accounts_controller_spec.rb b/spec/controllers/following_accounts_controller_spec.rb
deleted file mode 100644
index d5e4ee58..00000000
--- a/spec/controllers/following_accounts_controller_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'rails_helper'
-
-describe FollowingAccountsController do
- render_views
-
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:followee0) { Fabricate(:account) }
- let(:followee1) { Fabricate(:account) }
-
- describe 'GET #index' do
- let!(:follow0) { alice.follow!(followee0) }
- let!(:follow1) { alice.follow!(followee1) }
-
- context 'when format is html' do
- subject(:response) { get :index, params: { account_username: alice.username, format: :html } }
-
- it 'assigns follows' do
- expect(response).to have_http_status(200)
-
- assigned = assigns(:follows).to_a
- expect(assigned.size).to eq 2
- expect(assigned[0]).to eq follow1
- expect(assigned[1]).to eq follow0
- end
- end
-
- context 'when format is json' do
- subject(:response) { get :index, params: { account_username: alice.username, page: page, format: :json } }
- subject(:body) { JSON.parse(response.body) }
-
- context 'with page' do
- let(:page) { 1 }
-
- it 'returns followers' do
- expect(response).to have_http_status(200)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_present
- end
- end
-
- context 'without page' do
- let(:page) { nil }
-
- it 'returns followers' do
- expect(response).to have_http_status(200)
- expect(body['totalItems']).to eq 2
- expect(body['partOf']).to be_blank
- end
- end
- end
- end
-end
diff --git a/spec/controllers/intents_controller_spec.rb b/spec/controllers/intents_controller_spec.rb
deleted file mode 100644
index d3709d12..00000000
--- a/spec/controllers/intents_controller_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe IntentsController, type: :controller do
- render_views
-
- let(:user) { Fabricate(:user) }
- before { sign_in user, scope: :user }
-
- describe 'GET #show' do
- subject { get :show, params: { uri: uri } }
-
- context 'when schema is web+gabsocial' do
- context 'when host is follow' do
- let(:uri) { 'web+gabsocial://follow?uri=test' }
-
- it { is_expected.to redirect_to authorize_interaction_path(uri: 'test') }
- end
-
- context 'when host is share' do
- let(:uri) { 'web+gabsocial://share?text=test' }
-
- it { is_expected.to redirect_to share_path(text: 'test') }
- end
-
- context 'when host is none of the above' do
- let(:uri) { 'web+gabsocial://test' }
-
- it { is_expected.to have_http_status 404 }
- end
- end
-
- context 'when schema is not web+gabsocial' do
- let(:uri) { 'api+gabsocial://test.com' }
-
- it { is_expected.to have_http_status 404 }
- end
-
- context 'when uri param is blank' do
- let(:uri) { '' }
-
- it { is_expected.to have_http_status 404 }
- end
-
- context 'when uri is invalid' do
- let(:uri) { 'invalid uri://test.com' }
-
- it { is_expected.to have_http_status 404 }
- end
- end
-end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
deleted file mode 100644
index 76e617e6..00000000
--- a/spec/controllers/invites_controller_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-require 'rails_helper'
-
-describe InvitesController do
- render_views
-
- before do
- sign_in user
- end
-
- around do |example|
- min_invite_role = Setting.min_invite_role
- example.run
- Setting.min_invite_role = min_invite_role
- end
-
- describe 'GET #index' do
- subject { get :index }
-
- let(:user) { Fabricate(:user, moderator: false, admin: false) }
- let!(:invite) { Fabricate(:invite, user: user) }
-
- context 'when user is a staff' do
- it 'renders index page' do
- Setting.min_invite_role = 'user'
- expect(subject).to render_template :index
- expect(assigns(:invites)).to include invite
- expect(assigns(:invites).count).to eq 1
- end
- end
-
- context 'when user is not a staff' do
- it 'returns 403' do
- Setting.min_invite_role = 'modelator'
- expect(subject).to have_http_status 403
- end
- end
- end
-
- describe 'POST #create' do
- subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
-
- context 'when user is an admin' do
- let(:user) { Fabricate(:user, moderator: false, admin: true) }
-
- it 'succeeds to create a invite' do
- expect { subject }.to change { Invite.count }.by(1)
- expect(subject).to redirect_to invites_path
- expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
- end
- end
-
- context 'when user is not an admin' do
- let(:user) { Fabricate(:user, moderator: true, admin: false) }
-
- it 'returns 403' do
- expect(subject).to have_http_status 403
- end
- end
- end
-
- describe 'DELETE #create' do
- subject { delete :destroy, params: { id: invite.id } }
-
- let!(:invite) { Fabricate(:invite, user: user, expires_at: nil) }
- let(:user) { Fabricate(:user, moderator: false, admin: true) }
-
- it 'expires invite' do
- expect(subject).to redirect_to invites_path
- expect(invite.reload).to be_expired
- end
- end
-end
diff --git a/spec/controllers/manifests_controller_spec.rb b/spec/controllers/manifests_controller_spec.rb
deleted file mode 100644
index a549adef..00000000
--- a/spec/controllers/manifests_controller_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe ManifestsController do
- render_views
-
- describe 'GET #show' do
- before do
- get :show, format: :json
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
- end
-end
diff --git a/spec/controllers/media_controller_spec.rb b/spec/controllers/media_controller_spec.rb
deleted file mode 100644
index ac44a76f..00000000
--- a/spec/controllers/media_controller_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe MediaController do
- render_views
-
- describe '#show' do
- it 'redirects to the file url when attached to a status' do
- status = Fabricate(:status)
- media_attachment = Fabricate(:media_attachment, status: status)
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to redirect_to(media_attachment.file.url(:original))
- end
-
- it 'responds with missing when there is not an attached status' do
- media_attachment = Fabricate(:media_attachment, status: nil)
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises when shortcode cant be found' do
- get :show, params: { id: 'missing' }
-
- expect(response).to have_http_status(404)
- end
-
- it 'raises when not permitted to view' do
- status = Fabricate(:status)
- media_attachment = Fabricate(:media_attachment, status: status)
- allow_any_instance_of(MediaController).to receive(:authorize).and_raise(ActiveRecord::RecordNotFound)
- get :show, params: { id: media_attachment.to_param }
-
- expect(response).to have_http_status(404)
- end
- end
-end
diff --git a/spec/controllers/oauth/authorizations_controller_spec.rb b/spec/controllers/oauth/authorizations_controller_spec.rb
deleted file mode 100644
index a84260a5..00000000
--- a/spec/controllers/oauth/authorizations_controller_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Oauth::AuthorizationsController, type: :controller do
- render_views
-
- let(:app) { Doorkeeper::Application.create!(name: 'test', redirect_uri: 'http://localhost/', scopes: 'read') }
-
- describe 'GET #new' do
- subject do
- get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read' }
- end
-
- shared_examples 'stores location for user' do
- it 'stores location for user' do
- subject
- expect(controller.stored_location_for(:user)).to eq "/oauth/authorize?client_id=#{app.uid}&redirect_uri=http%3A%2F%2Flocalhost%2F&response_type=code&scope=read"
- end
- end
-
- context 'when signed in' do
- let!(:user) { Fabricate(:user) }
-
- before do
- sign_in user, scope: :user
- end
-
- it 'returns http success' do
- subject
- expect(response).to have_http_status(200)
- end
-
- it 'gives options to authorize and deny' do
- subject
- expect(response.body).to match(/Authorize/)
- end
-
- include_examples 'stores location for user'
-
- context 'when app is already authorized' do
- before do
- Doorkeeper::AccessToken.find_or_create_for(
- app,
- user.id,
- app.scopes,
- Doorkeeper.configuration.access_token_expires_in,
- Doorkeeper.configuration.refresh_token_enabled?
- )
- end
-
- it 'redirects to callback' do
- subject
- expect(response).to redirect_to(/\A#{app.redirect_uri}/)
- end
-
- it 'does not redirect to callback with force_login=true' do
- get :new, params: { client_id: app.uid, response_type: 'code', redirect_uri: 'http://localhost/', scope: 'read', force_login: 'true' }
- expect(response.body).to match(/Authorize/)
- end
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- subject
- expect(response).to redirect_to '/auth/sign_in'
- end
-
- include_examples 'stores location for user'
- end
- end
-end
diff --git a/spec/controllers/oauth/authorized_applications_controller_spec.rb b/spec/controllers/oauth/authorized_applications_controller_spec.rb
deleted file mode 100644
index 901e538e..00000000
--- a/spec/controllers/oauth/authorized_applications_controller_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Oauth::AuthorizedApplicationsController do
- render_views
-
- describe 'GET #index' do
- subject do
- get :index
- end
-
- shared_examples 'stores location for user' do
- it 'stores location for user' do
- subject
- expect(controller.stored_location_for(:user)).to eq "/oauth/authorized_applications"
- end
- end
-
- context 'when signed in' do
- before do
- sign_in Fabricate(:user), scope: :user
- end
-
- it 'returns http success' do
- subject
- expect(response).to have_http_status(200)
- end
-
- include_examples 'stores location for user'
- end
-
- context 'when not signed in' do
- it 'redirects' do
- subject
- expect(response).to redirect_to '/auth/sign_in'
- end
-
- include_examples 'stores location for user'
- end
- end
-
- describe 'DELETE #destroy' do
- let!(:user) { Fabricate(:user) }
- let!(:application) { Fabricate(:application) }
- let!(:access_token) { Fabricate(:accessible_access_token, application: application, resource_owner_id: user.id) }
- let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) }
-
- before do
- sign_in user, scope: :user
- post :destroy, params: { id: application.id }
- end
-
- it 'revokes access tokens for the application' do
- expect(Doorkeeper::AccessToken.where(application: application).first.revoked_at).to_not be_nil
- end
-
- it 'removes subscriptions for the application\'s access tokens' do
- expect(Web::PushSubscription.where(user: user).count).to eq 0
- end
- end
-end
diff --git a/spec/controllers/oauth/tokens_controller_spec.rb b/spec/controllers/oauth/tokens_controller_spec.rb
deleted file mode 100644
index ba8e367a..00000000
--- a/spec/controllers/oauth/tokens_controller_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Oauth::TokensController, type: :controller do
- describe 'POST #revoke' do
- let!(:user) { Fabricate(:user) }
- let!(:access_token) { Fabricate(:accessible_access_token, resource_owner_id: user.id) }
- let!(:web_push_subscription) { Fabricate(:web_push_subscription, user: user, access_token: access_token) }
-
- before do
- post :revoke, params: { token: access_token.token }
- end
-
- it 'revokes the token' do
- expect(access_token.reload.revoked_at).to_not be_nil
- end
-
- it 'removes web push subscription for token' do
- expect(Web::PushSubscription.where(access_token: access_token).count).to eq 0
- end
- end
-end
diff --git a/spec/controllers/react_controller_spec.rb b/spec/controllers/react_controller_spec.rb
deleted file mode 100644
index 6b7da2ec..00000000
--- a/spec/controllers/react_controller_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ReactController, type: :controller do
- render_views
-
- describe 'GET #react' do
- subject { get :react }
-
- context 'when not signed in' do
- context 'when requested path is tag timeline' do
- # : TODO :
- before { @request.path = '/web/timelines/tag/name' }
- it { is_expected.to redirect_to '/tags/name' }
- end
-
- it 'redirects to about page' do
- @request.path = '/'
- is_expected.to redirect_to(about_path)
- end
- end
-
- context 'when signed in' do
- let(:user) { Fabricate(:user) }
-
- before { sign_in(user) }
-
- it 'assigns @body_classes' do
- subject
- expect(assigns(:body_classes)).to eq 'app-body'
- end
-
- it 'assigns @initial_state_json' do
- subject
- initial_state_json = json_str_to_hash(assigns(:initial_state_json))
- expect(initial_state_json[:meta]).to_not be_nil
- expect(initial_state_json[:compose]).to_not be_nil
- expect(initial_state_json[:accounts]).to_not be_nil
- expect(initial_state_json[:settings]).to_not be_nil
- expect(initial_state_json[:media_attachments]).to_not be_nil
- end
- end
- end
-end
diff --git a/spec/controllers/relationships_controller_spec.rb b/spec/controllers/relationships_controller_spec.rb
deleted file mode 100644
index 16e255af..00000000
--- a/spec/controllers/relationships_controller_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'rails_helper'
-
-describe RelationshipsController do
- render_views
-
- let(:user) { Fabricate(:user) }
-
- shared_examples 'authenticate user' do
- it 'redirects when not signed in' do
- is_expected.to redirect_to '/auth/sign_in'
- end
- end
-
- describe 'GET #show' do
- subject { get :show, params: { page: 2, relationship: 'followed_by' } }
-
- it 'assigns @accounts' do
- Fabricate(:account, domain: 'old').follow!(user.account)
- Fabricate(:account, domain: 'recent').follow!(user.account)
-
- sign_in user, scope: :user
- subject
-
- assigned = assigns(:accounts).per(1).to_a
- expect(assigned.size).to eq 1
- expect(assigned[0].domain).to eq 'old'
- end
-
- it 'returns http success' do
- sign_in user, scope: :user
- subject
- expect(response).to have_http_status(200)
- end
-
- include_examples 'authenticate user'
- end
-
- describe 'PATCH #update' do
- let(:poopfeast) { Fabricate(:account, username: 'poopfeast', domain: 'example.com', salmon_url: 'http://example.com/salmon') }
-
- before do
- stub_request(:post, 'http://example.com/salmon').to_return(status: 200)
- end
-
- shared_examples 'redirects back to followers page' do
- it 'redirects back to followers page' do
- poopfeast.follow!(user.account)
-
- sign_in user, scope: :user
- subject
-
- expect(response).to redirect_to(relationships_path)
- end
- end
-
- context 'when select parameter is not provided' do
- subject { patch :update }
- include_examples 'redirects back to followers page'
- end
-
- context 'when select parameter is provided' do
- subject { patch :update, params: { form_account_batch: { account_ids: [poopfeast.id] }, block_domains: '' } }
-
- it 'soft-blocks followers from selected domains' do
- poopfeast.follow!(user.account)
-
- sign_in user, scope: :user
- subject
-
- expect(poopfeast.following?(user.account)).to be false
- end
-
- include_examples 'authenticate user'
- include_examples 'redirects back to followers page'
- end
- end
-end
diff --git a/spec/controllers/remote_follow_controller_spec.rb b/spec/controllers/remote_follow_controller_spec.rb
deleted file mode 100644
index 5088c2e6..00000000
--- a/spec/controllers/remote_follow_controller_spec.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe RemoteFollowController do
- render_views
-
- describe '#new' do
- it 'returns success when session is empty' do
- account = Fabricate(:account)
- get :new, params: { account_username: account.to_param }
-
- expect(response).to have_http_status(200)
- expect(response).to render_template(:new)
- expect(assigns(:remote_follow).acct).to be_nil
- end
-
- it 'populates the remote follow with session data when session exists' do
- session[:remote_follow] = 'user@example.com'
- account = Fabricate(:account)
- get :new, params: { account_username: account.to_param }
-
- expect(response).to have_http_status(200)
- expect(response).to render_template(:new)
- expect(assigns(:remote_follow).acct).to eq 'user@example.com'
- end
- end
-
- describe '#create' do
- before do
- @account = Fabricate(:account, username: 'test_user')
- end
-
- context 'with a valid acct' do
- context 'when webfinger values are wrong' do
- it 'renders new when redirect url is nil' do
- resource_with_nil_link = double(link: nil)
- allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_return(resource_with_nil_link)
- post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
-
- expect(response).to render_template(:new)
- expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
- end
-
- it 'renders new when template is nil' do
- link_with_nil_template = double(template: nil)
- resource_with_link = double(link: link_with_nil_template)
- allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_return(resource_with_link)
- post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
-
- expect(response).to render_template(:new)
- expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
- end
- end
-
- context 'when webfinger values are good' do
- before do
- link_with_template = double(template: 'http://example.com/follow_me?acct={uri}')
- resource_with_link = double(link: link_with_template)
- allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_return(resource_with_link)
- post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
- end
-
- it 'saves the session' do
- expect(session[:remote_follow]).to eq 'user@example.com'
- end
-
- it 'redirects to the remote location' do
- address = "http://example.com/follow_me?acct=test_user%40#{Rails.configuration.x.local_domain}"
-
- expect(response).to redirect_to(address)
- end
- end
- end
-
- context 'with an invalid acct' do
- it 'renders new when acct is missing' do
- post :create, params: { account_username: @account.to_param, remote_follow: { acct: '' } }
-
- expect(response).to render_template(:new)
- end
-
- it 'renders new with error when goldfinger fails' do
- allow(Goldfinger).to receive(:finger).with('acct:user@example.com').and_raise(Goldfinger::Error)
- post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@example.com' } }
-
- expect(response).to render_template(:new)
- expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
- end
-
- it 'renders new when occur HTTP::ConnectionError' do
- allow(Goldfinger).to receive(:finger).with('acct:user@unknown').and_raise(HTTP::ConnectionError)
- post :create, params: { account_username: @account.to_param, remote_follow: { acct: 'user@unknown' } }
-
- expect(response).to render_template(:new)
- expect(response.body).to include(I18n.t('remote_follow.missing_resource'))
- end
- end
- end
-
- describe 'with a suspended account' do
- before do
- @account = Fabricate(:account, suspended: true)
- end
-
- it 'returns 410 gone on GET to #new' do
- get :new, params: { account_username: @account.to_param }
-
- expect(response).to have_http_status(:gone)
- end
-
- it 'returns 410 gone on POST to #create' do
- post :create, params: { account_username: @account.to_param }
-
- expect(response).to have_http_status(:gone)
- end
- end
-end
diff --git a/spec/controllers/remote_interaction_controller_spec.rb b/spec/controllers/remote_interaction_controller_spec.rb
deleted file mode 100644
index bb0074b1..00000000
--- a/spec/controllers/remote_interaction_controller_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe RemoteInteractionController, type: :controller do
- render_views
-
- let(:status) { Fabricate(:status) }
-
- describe 'GET #new' do
- it 'returns 200' do
- get :new, params: { id: status.id }
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- context '@remote_follow is valid' do
- it 'returns 302' do
- allow_any_instance_of(RemoteFollow).to receive(:valid?) { true }
- allow_any_instance_of(RemoteFollow).to receive(:addressable_template) do
- Addressable::Template.new('https://hoge.com')
- end
-
- post :create, params: { id: status.id, remote_follow: { acct: '@hoge' } }
- expect(response).to have_http_status(302)
- end
- end
-
- context '@remote_follow is invalid' do
- it 'returns 200' do
- allow_any_instance_of(RemoteFollow).to receive(:valid?) { false }
- post :create, params: { id: status.id, remote_follow: { acct: '@hoge' } }
-
- expect(response).to have_http_status(200)
- end
- end
- end
-end
diff --git a/spec/controllers/remote_unfollows_controller_spec.rb b/spec/controllers/remote_unfollows_controller_spec.rb
deleted file mode 100644
index a1a55ede..00000000
--- a/spec/controllers/remote_unfollows_controller_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe RemoteUnfollowsController do
- render_views
-
- describe '#create' do
- subject { post :create, params: { acct: acct } }
-
- let(:current_user) { Fabricate(:user, account: current_account) }
- let(:current_account) { Fabricate(:account) }
- let(:remote_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox')).account }
- before do
- sign_in current_user
- current_account.follow!(remote_account)
- stub_request(:post, 'http://example.com/inbox') { { status: 200 } }
- end
-
- context 'when successfully unfollow remote account' do
- let(:acct) { "acct:#{remote_account.username}@#{remote_account.domain}" }
-
- it do
- is_expected.to render_template :success
- expect(current_account.following?(remote_account)).to be false
- end
- end
-
- context 'when fails to unfollow remote account' do
- let(:acct) { "acct:#{remote_account.username + '_test'}@#{remote_account.domain}" }
-
- it do
- is_expected.to render_template :error
- expect(current_account.following?(remote_account)).to be true
- end
- end
- end
-end
diff --git a/spec/controllers/settings/applications_controller_spec.rb b/spec/controllers/settings/applications_controller_spec.rb
deleted file mode 100644
index 29c27814..00000000
--- a/spec/controllers/settings/applications_controller_spec.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-require 'rails_helper'
-
-describe Settings::ApplicationsController do
- render_views
-
- let!(:user) { Fabricate(:user) }
- let!(:app) { Fabricate(:application, owner: user) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #index' do
- let!(:other_app) { Fabricate(:application) }
-
- it 'shows apps' do
- get :index
- expect(response).to have_http_status(200)
- expect(assigns(:applications)).to include(app)
- expect(assigns(:applications)).to_not include(other_app)
- end
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, params: { id: app.id }
- expect(response).to have_http_status(200)
- expect(assigns[:application]).to eql(app)
- end
-
- it 'returns 404 if you dont own app' do
- app.update!(owner: nil)
-
- get :show, params: { id: app.id }
- expect(response.status).to eq 404
- end
- end
-
- describe 'GET #new' do
- it 'works' do
- get :new
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- context 'success (passed scopes as a String)' do
- def call_create
- post :create, params: {
- doorkeeper_application: {
- name: 'My New App',
- redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
- website: 'http://google.com',
- scopes: 'read write follow'
- }
- }
- response
- end
-
- it 'creates an entry in the database' do
- expect { call_create }.to change(Doorkeeper::Application, :count)
- end
-
- it 'redirects back to applications page' do
- expect(call_create).to redirect_to(settings_applications_path)
- end
- end
-
- context 'success (passed scopes as an Array)' do
- def call_create
- post :create, params: {
- doorkeeper_application: {
- name: 'My New App',
- redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
- website: 'http://google.com',
- scopes: [ 'read', 'write', 'follow' ]
- }
- }
- response
- end
-
- it 'creates an entry in the database' do
- expect { call_create }.to change(Doorkeeper::Application, :count)
- end
-
- it 'redirects back to applications page' do
- expect(call_create).to redirect_to(settings_applications_path)
- end
- end
-
- context 'failure' do
- before do
- post :create, params: {
- doorkeeper_application: {
- name: '',
- redirect_uri: '',
- website: '',
- scopes: []
- }
- }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'renders form again' do
- expect(response).to render_template(:new)
- end
- end
- end
-
- describe 'PATCH #update' do
- context 'success' do
- let(:opts) {
- {
- website: 'https://foo.bar/'
- }
- }
-
- def call_update
- patch :update, params: {
- id: app.id,
- doorkeeper_application: opts
- }
- response
- end
-
- it 'updates existing application' do
- call_update
- expect(app.reload.website).to eql(opts[:website])
- end
-
- it 'redirects back to applications page' do
- expect(call_update).to redirect_to(settings_applications_path)
- end
- end
-
- context 'failure' do
- before do
- patch :update, params: {
- id: app.id,
- doorkeeper_application: {
- name: '',
- redirect_uri: '',
- website: '',
- scopes: []
- }
- }
- end
-
- it 'returns http success' do
- expect(response).to have_http_status(200)
- end
-
- it 'renders form again' do
- expect(response).to render_template(:show)
- end
- end
- end
-
- describe 'destroy' do
- before do
- post :destroy, params: { id: app.id }
- end
-
- it 'redirects back to applications page' do
- expect(response).to redirect_to(settings_applications_path)
- end
-
- it 'removes the app' do
- expect(Doorkeeper::Application.find_by(id: app.id)).to be_nil
- end
- end
-
- describe 'regenerate' do
- let(:token) { user.token_for_app(app) }
- before do
- expect(token).to_not be_nil
- post :regenerate, params: { id: app.id }
- end
-
- it 'should create new token' do
- expect(user.token_for_app(app)).to_not eql(token)
- end
- end
-end
diff --git a/spec/controllers/settings/deletes_controller_spec.rb b/spec/controllers/settings/deletes_controller_spec.rb
deleted file mode 100644
index 35fd64e9..00000000
--- a/spec/controllers/settings/deletes_controller_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-require 'rails_helper'
-
-describe Settings::DeletesController do
- render_views
-
- describe 'GET #show' do
- context 'when signed in' do
- let(:user) { Fabricate(:user) }
-
- before do
- sign_in user, scope: :user
- end
-
- it 'renders confirmation page' do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- get :show
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
- end
-
- describe 'DELETE #destroy' do
- context 'when signed in' do
- let(:user) { Fabricate(:user, password: 'petsmoldoggos') }
-
- before do
- sign_in user, scope: :user
- end
-
- context 'with correct password' do
- before do
- delete :destroy, params: { form_delete_confirmation: { password: 'petsmoldoggos' } }
- end
-
- it 'redirects to sign in page' do
- expect(response).to redirect_to '/auth/sign_in'
- end
-
- it 'removes user record' do
- expect(User.find_by(id: user.id)).to be_nil
- end
-
- it 'marks account as suspended' do
- expect(user.account.reload).to be_suspended
- end
- end
-
- context 'with incorrect password' do
- before do
- delete :destroy, params: { form_delete_confirmation: { password: 'blaze420' } }
- end
-
- it 'redirects back to confirmation page' do
- expect(response).to redirect_to settings_delete_path
- end
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- delete :destroy
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
-
- context do
- around do |example|
- open_deletion = Setting.open_deletion
- example.run
- Setting.open_deletion = open_deletion
- end
-
- it 'redirects' do
- Setting.open_deletion = false
- delete :destroy
- expect(response).to redirect_to root_path
- end
- end
- end
-end
diff --git a/spec/controllers/settings/exports/blocked_accounts_controller_spec.rb b/spec/controllers/settings/exports/blocked_accounts_controller_spec.rb
deleted file mode 100644
index 5ff41b7f..00000000
--- a/spec/controllers/settings/exports/blocked_accounts_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'rails_helper'
-
-describe Settings::Exports::BlockedAccountsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the blocking accounts' do
- user = Fabricate(:user)
- user.account.block!(Fabricate(:account, username: 'username', domain: 'domain'))
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "username@domain\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports/following_accounts_controller_spec.rb b/spec/controllers/settings/exports/following_accounts_controller_spec.rb
deleted file mode 100644
index 8be547eb..00000000
--- a/spec/controllers/settings/exports/following_accounts_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'rails_helper'
-
-describe Settings::Exports::FollowingAccountsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the following accounts' do
- user = Fabricate(:user)
- user.account.follow!(Fabricate(:account, username: 'username', domain: 'domain'))
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "Account address,Show reposts\nusername@domain,true\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports/muted_accounts_controller_spec.rb b/spec/controllers/settings/exports/muted_accounts_controller_spec.rb
deleted file mode 100644
index 642f0a9b..00000000
--- a/spec/controllers/settings/exports/muted_accounts_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'rails_helper'
-
-describe Settings::Exports::MutedAccountsController do
- render_views
-
- describe 'GET #index' do
- it 'returns a csv of the muting accounts' do
- user = Fabricate(:user)
- user.account.mute!(Fabricate(:account, username: 'username', domain: 'domain'))
-
- sign_in user, scope: :user
- get :index, format: :csv
-
- expect(response.body).to eq "Account address,Hide notifications\nusername@domain,true\n"
- end
- end
-end
diff --git a/spec/controllers/settings/exports_controller_spec.rb b/spec/controllers/settings/exports_controller_spec.rb
deleted file mode 100644
index a46fe095..00000000
--- a/spec/controllers/settings/exports_controller_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::ExportsController do
- render_views
-
- describe 'GET #show' do
- context 'when signed in' do
- let(:user) { Fabricate(:user) }
-
- before do
- sign_in user, scope: :user
- end
-
- it 'renders export' do
- get :show
-
- export = assigns(:export)
- expect(export).to be_instance_of Export
- expect(export.account).to eq user.account
- expect(response).to have_http_status(200)
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- get :show
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
- end
-
- describe 'POST #create' do
- before do
- sign_in Fabricate(:user), scope: :user
- end
-
- it 'redirects to settings_export_path' do
- post :create
- expect(response).to redirect_to(settings_export_path)
- end
-
- it 'queues BackupWorker job by 1' do
- Sidekiq::Testing.fake! do
- expect do
- post :create
- end.to change(BackupWorker.jobs, :size).by(1)
- end
- end
- end
-end
diff --git a/spec/controllers/settings/identity_proofs_controller_spec.rb b/spec/controllers/settings/identity_proofs_controller_spec.rb
deleted file mode 100644
index 2a0f9108..00000000
--- a/spec/controllers/settings/identity_proofs_controller_spec.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-require 'rails_helper'
-
-describe Settings::IdentityProofsController do
- include RoutingHelper
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:valid_token) { '1'*66 }
- let(:kbname) { 'kbuser' }
- let(:provider) { 'keybase' }
- let(:findable_id) { Faker::Number.number(5) }
- let(:unfindable_id) { Faker::Number.number(5) }
- let(:new_proof_params) do
- { provider: provider, provider_username: kbname, token: valid_token, username: user.account.username }
- end
- let(:status_text) { "i just proved that i am also #{kbname} on #{provider}." }
- let(:status_posting_params) do
- { post_status: '0', status_text: status_text }
- end
- let(:postable_params) do
- { account_identity_proof: new_proof_params.merge(status_posting_params) }
- end
-
- before do
- allow_any_instance_of(ProofProvider::Keybase::Verifier).to receive(:status) { { 'proof_valid' => true, 'proof_live' => true } }
- sign_in user, scope: :user
- end
-
- describe 'new proof creation' do
- context 'GET #new' do
- before do
- allow_any_instance_of(ProofProvider::Keybase::Badge).to receive(:avatar_url) { full_pack_url('media/images/void.png') }
- end
-
- context 'with all of the correct params' do
- it 'renders the template' do
- get :new, params: new_proof_params
- expect(response).to render_template(:new)
- end
- end
-
- context 'without any params' do
- it 'redirects to :index' do
- get :new, params: {}
- expect(response).to redirect_to settings_identity_proofs_path
- end
- end
-
- context 'with params to prove a different, not logged-in user' do
- let(:wrong_user_params) { new_proof_params.merge(username: 'someone_else') }
-
- it 'shows a helpful alert' do
- get :new, params: wrong_user_params
- expect(flash[:alert]).to eq I18n.t('identity_proofs.errors.wrong_user', proving: 'someone_else', current: user.account.username)
- end
- end
-
- context 'with params to prove the same username cased differently' do
- let(:capitalized_username) { new_proof_params.merge(username: user.account.username.upcase) }
-
- it 'renders the new template' do
- get :new, params: capitalized_username
- expect(response).to render_template(:new)
- end
- end
- end
-
- context 'POST #create' do
- context 'when saving works' do
- before do
- allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
- allow_any_instance_of(ProofProvider::Keybase::Verifier).to receive(:valid?) { true }
- allow_any_instance_of(AccountIdentityProof).to receive(:on_success_path) { root_url }
- end
-
- it 'serializes a ProofProvider::Keybase::Worker' do
- expect(ProofProvider::Keybase::Worker).to receive(:perform_async)
- post :create, params: postable_params
- end
-
- it 'delegates redirection to the proof provider' do
- expect_any_instance_of(AccountIdentityProof).to receive(:on_success_path)
- post :create, params: postable_params
- expect(response).to redirect_to root_url
- end
-
- it 'does not post a status' do
- expect(PostStatusService).not_to receive(:new)
- post :create, params: postable_params
- end
-
- context 'and the user has requested to post a status' do
- let(:postable_params_with_status) do
- postable_params.tap { |p| p[:account_identity_proof][:post_status] = '1' }
- end
-
- it 'posts a status' do
- expect_any_instance_of(PostStatusService).to receive(:call).with(user.account, text: status_text)
-
- post :create, params: postable_params_with_status
- end
- end
- end
-
- context 'when saving fails' do
- before do
- allow_any_instance_of(ProofProvider::Keybase::Verifier).to receive(:valid?) { false }
- end
-
- it 'redirects to :index' do
- post :create, params: postable_params
- expect(response).to redirect_to settings_identity_proofs_path
- end
-
- it 'flashes a helpful message' do
- post :create, params: postable_params
- expect(flash[:alert]).to eq I18n.t('identity_proofs.errors.failed', provider: 'Keybase')
- end
- end
-
- context 'it can also do an update if the provider and username match an existing proof' do
- before do
- allow_any_instance_of(ProofProvider::Keybase::Verifier).to receive(:valid?) { true }
- allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
- Fabricate(:account_identity_proof, account: user.account, provider: provider, provider_username: kbname)
- allow_any_instance_of(AccountIdentityProof).to receive(:on_success_path) { root_url }
- end
-
- it 'calls update with the new token' do
- expect_any_instance_of(AccountIdentityProof).to receive(:save) do |proof|
- expect(proof.token).to eq valid_token
- end
-
- post :create, params: postable_params
- end
- end
- end
- end
-
- describe 'GET #index' do
- context 'with no existing proofs' do
- it 'shows the helpful explanation' do
- get :index
- expect(response.body).to match I18n.t('identity_proofs.explanation_html')
- end
- end
-
- context 'with two proofs' do
- before do
- allow_any_instance_of(ProofProvider::Keybase::Verifier).to receive(:valid?) { true }
- @proof1 = Fabricate(:account_identity_proof, account: user.account)
- @proof2 = Fabricate(:account_identity_proof, account: user.account)
- allow_any_instance_of(AccountIdentityProof).to receive(:badge) { double(avatar_url: '', profile_url: '', proof_url: '') }
- allow_any_instance_of(AccountIdentityProof).to receive(:refresh!) { }
- end
-
- it 'has the first proof username on the page' do
- get :index
- expect(response.body).to match /#{Regexp.quote(@proof1.provider_username)}/
- end
-
- it 'has the second proof username on the page' do
- get :index
- expect(response.body).to match /#{Regexp.quote(@proof2.provider_username)}/
- end
- end
- end
-end
diff --git a/spec/controllers/settings/imports_controller_spec.rb b/spec/controllers/settings/imports_controller_spec.rb
deleted file mode 100644
index 7a9b0219..00000000
--- a/spec/controllers/settings/imports_controller_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Settings::ImportsController, type: :controller do
- render_views
-
- before do
- sign_in Fabricate(:user), scope: :user
- end
-
- describe "GET #show" do
- it "returns http success" do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'POST #create' do
- it 'redirects to settings path with successful following import' do
- service = double(call: nil)
- allow(ResolveAccountService).to receive(:new).and_return(service)
- post :create, params: {
- import: {
- type: 'following',
- data: fixture_file_upload('files/imports.txt')
- }
- }
-
- expect(response).to redirect_to(settings_import_path)
- end
-
- it 'redirects to settings path with successful blocking import' do
- service = double(call: nil)
- allow(ResolveAccountService).to receive(:new).and_return(service)
- post :create, params: {
- import: {
- type: 'blocking',
- data: fixture_file_upload('files/imports.txt')
- }
- }
-
- expect(response).to redirect_to(settings_import_path)
- end
- end
-end
diff --git a/spec/controllers/settings/migrations_controller_spec.rb b/spec/controllers/settings/migrations_controller_spec.rb
deleted file mode 100644
index 4d814a45..00000000
--- a/spec/controllers/settings/migrations_controller_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'rails_helper'
-
-describe Settings::MigrationsController do
- render_views
-
- shared_examples 'authenticate user' do
- it 'redirects to sign_in page' do
- is_expected.to redirect_to new_user_session_path
- end
- end
-
- describe 'GET #show' do
- context 'when user is not sign in' do
- subject { get :show }
-
- it_behaves_like 'authenticate user'
- end
-
- context 'when user is sign in' do
- subject { get :show }
-
- let(:user) { Fabricate(:user, account: account) }
- let(:account) { Fabricate(:account, moved_to_account: moved_to_account) }
- before { sign_in user, scope: :user }
-
- context 'when user does not have moved to account' do
- let(:moved_to_account) { nil }
-
- it 'renders show page' do
- is_expected.to have_http_status 200
- is_expected.to render_template :show
- end
- end
-
- context 'when user does not have moved to account' do
- let(:moved_to_account) { Fabricate(:account) }
-
- it 'renders show page' do
- is_expected.to have_http_status 200
- is_expected.to render_template :show
- end
- end
- end
- end
-
- describe 'PUT #update' do
- context 'when user is not sign in' do
- subject { put :update }
-
- it_behaves_like 'authenticate user'
- end
-
- context 'when user is sign in' do
- subject { put :update, params: { migration: { acct: acct } } }
-
- let(:user) { Fabricate(:user) }
- before { sign_in user, scope: :user }
-
- context 'when migration account is changed' do
- let(:acct) { Fabricate(:account) }
-
- it 'updates moved to account' do
- is_expected.to redirect_to settings_migration_path
- expect(user.account.reload.moved_to_account_id).to eq acct.id
- end
- end
-
- context 'when acct is a current account' do
- let(:acct) { user.account }
-
- it 'renders show' do
- is_expected.to render_template :show
- end
- end
- end
- end
-end
diff --git a/spec/controllers/settings/notifications_controller_spec.rb b/spec/controllers/settings/notifications_controller_spec.rb
deleted file mode 100644
index 981ef674..00000000
--- a/spec/controllers/settings/notifications_controller_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'rails_helper'
-
-describe Settings::NotificationsController do
- render_views
-
- let(:user) { Fabricate(:user) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'PUT #update' do
- it 'updates notifications settings' do
- user.settings['notification_emails'] = user.settings['notification_emails'].merge('follow' => false)
- user.settings['interactions'] = user.settings['interactions'].merge('must_be_follower' => true)
-
- put :update, params: {
- user: {
- notification_emails: { follow: '1' },
- interactions: { must_be_follower: '0' },
- }
- }
-
- expect(response).to redirect_to(settings_notifications_path)
- user.reload
- expect(user.settings['notification_emails']['follow']).to be true
- expect(user.settings['interactions']['must_be_follower']).to be false
- end
- end
-end
diff --git a/spec/controllers/settings/preferences_controller_spec.rb b/spec/controllers/settings/preferences_controller_spec.rb
deleted file mode 100644
index f2028cf3..00000000
--- a/spec/controllers/settings/preferences_controller_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'rails_helper'
-
-describe Settings::PreferencesController do
- render_views
-
- let(:user) { Fabricate(:user, filtered_languages: []) }
-
- before do
- sign_in user, scope: :user
- end
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the user record' do
- put :update, params: { user: { locale: 'en', chosen_languages: ['es', 'fr', ''] } }
-
- expect(response).to redirect_to(settings_preferences_path)
- user.reload
- expect(user.locale).to eq 'en'
- expect(user.chosen_languages).to eq ['es', 'fr']
- end
-
- it 'updates user settings' do
- user.settings['boost_modal'] = false
- user.settings['delete_modal'] = true
-
- put :update, params: {
- user: {
- setting_boost_modal: '1',
- setting_delete_modal: '0',
- }
- }
-
- expect(response).to redirect_to(settings_preferences_path)
- user.reload
- expect(user.settings['boost_modal']).to be true
- expect(user.settings['delete_modal']).to be false
- end
- end
-end
diff --git a/spec/controllers/settings/profiles_controller_spec.rb b/spec/controllers/settings/profiles_controller_spec.rb
deleted file mode 100644
index 5b1fe3ac..00000000
--- a/spec/controllers/settings/profiles_controller_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Settings::ProfilesController, type: :controller do
- render_views
-
- before do
- @user = Fabricate(:user)
- sign_in @user, scope: :user
- end
-
- describe "GET #show" do
- it "returns http success" do
- get :show
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'PUT #update' do
- it 'updates the user profile' do
- allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
- account = Fabricate(:account, user: @user, display_name: 'Old name')
-
- put :update, params: { account: { display_name: 'New name' } }
- expect(account.reload.display_name).to eq 'New name'
- expect(response).to redirect_to(settings_profile_path)
- expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
- end
- end
-
- describe 'PUT #update with new profile image' do
- it 'updates profile image' do
- allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
- account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
- expect(account.avatar.instance.avatar_file_name).to be_nil
-
- put :update, params: { account: { avatar: fixture_file_upload('files/avatar.gif', 'image/gif') } }
- expect(response).to redirect_to(settings_profile_path)
- expect(account.reload.avatar.instance.avatar_file_name).not_to be_nil
- expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
- end
- end
-
- describe 'PUT #update with oversized image' do
- it 'gives the user an error message' do
- allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
- account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
- put :update, params: { account: { avatar: fixture_file_upload('files/4096x4097.png', 'image/png') } }
- expect(response.body).to include('images are not supported')
- end
- end
-end
diff --git a/spec/controllers/settings/sessions_controller_spec.rb b/spec/controllers/settings/sessions_controller_spec.rb
deleted file mode 100644
index 52b204a6..00000000
--- a/spec/controllers/settings/sessions_controller_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'rails_helper'
-
-describe Settings::SessionsController do
- render_views
-
- let(:user) { Fabricate(:user) }
- let(:session_activation) { Fabricate(:session_activation, user: user) }
- before { sign_in user, scope: :user }
-
- describe 'DELETE #destroy' do
- subject { delete :destroy, params: { id: id } }
-
- context 'when session activation exists' do
- let(:id) { session_activation.id }
-
- it 'destroys session activation' do
- is_expected.to redirect_to edit_user_registration_path
- expect(SessionActivation.find_by(id: id)).to be_nil
- end
- end
-
- context 'when session activation does not exist' do
- let(:id) { session_activation.id + 1000 }
-
- it 'destroys session activation' do
- is_expected.to have_http_status :not_found
- end
- end
- end
-end
diff --git a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
deleted file mode 100644
index 478f2458..00000000
--- a/spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::TwoFactorAuthentication::ConfirmationsController do
- render_views
-
- let(:user) { Fabricate(:user, email: 'local-part@domain', otp_secret: 'thisisasecretforthespecofnewview') }
- let(:user_without_otp_secret) { Fabricate(:user, email: 'local-part@domain') }
-
- shared_examples 'renders :new' do
- it 'renders the new view' do
- subject
-
- expect(assigns(:confirmation)).to be_instance_of Form::TwoFactorConfirmation
- expect(assigns(:provision_url)).to eq 'otpauth://totp/local-part@domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
- expect(assigns(:qrcode)).to be_instance_of RQRCode::QRCode
- expect(response).to have_http_status(200)
- expect(response).to render_template(:new)
- end
- end
-
- describe 'GET #new' do
- context 'when signed in' do
- subject do
- sign_in user, scope: :user
- get :new
- end
-
- include_examples 'renders :new'
- end
-
- it 'redirects if not signed in' do
- get :new
- expect(response).to redirect_to('/auth/sign_in')
- end
-
- it 'redirects if user do not have otp_secret' do
- sign_in user_without_otp_secret, scope: :user
- get :new
- expect(response).to redirect_to('/settings/two_factor_authentication')
- end
- end
-
- describe 'POST #create' do
- context 'when signed in' do
- before do
- sign_in user, scope: :user
- end
-
- describe 'when form_two_factor_confirmation parameter is not provided' do
- it 'raises ActionController::ParameterMissing' do
- expect { post :create, params: {} }.to raise_error(ActionController::ParameterMissing)
- end
- end
-
- describe 'when creation succeeds' do
- it 'renders page with success' do
- otp_backup_codes = user.generate_otp_backup_codes!
- expect_any_instance_of(User).to receive(:generate_otp_backup_codes!) do |value|
- expect(value).to eq user
- otp_backup_codes
- end
- expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg|
- expect(value).to eq user
- expect(arg).to eq '123456'
- true
- end
-
- post :create, params: { form_two_factor_confirmation: { code: '123456' } }
-
- expect(assigns(:recovery_codes)).to eq otp_backup_codes
- expect(flash[:notice]).to eq 'Two-factor authentication successfully enabled'
- expect(response).to have_http_status(200)
- expect(response).to render_template('settings/two_factor_authentication/recovery_codes/index')
- end
- end
-
- describe 'when creation fails' do
- subject do
- expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg|
- expect(value).to eq user
- expect(arg).to eq '123456'
- false
- end
-
- post :create, params: { form_two_factor_confirmation: { code: '123456' } }
- end
-
- it 'renders the new view' do
- subject
- expect(response.body).to include 'The entered code was invalid! Are server time and device time correct?'
- end
-
- include_examples 'renders :new'
- end
- end
-
- context 'when not signed in' do
- it 'redirects if not signed in' do
- post :create, params: { form_two_factor_confirmation: { code: '123456' } }
- expect(response).to redirect_to('/auth/sign_in')
- end
- end
- end
-end
diff --git a/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb b/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb
deleted file mode 100644
index c04760e5..00000000
--- a/spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::TwoFactorAuthentication::RecoveryCodesController do
- render_views
-
- describe 'POST #create' do
- it 'updates the codes and shows them on a view when signed in' do
- user = Fabricate(:user)
- otp_backup_codes = user.generate_otp_backup_codes!
- expect_any_instance_of(User).to receive(:generate_otp_backup_codes!) do |value|
- expect(value).to eq user
- otp_backup_codes
- end
-
- sign_in user, scope: :user
- post :create
-
- expect(assigns(:recovery_codes)).to eq otp_backup_codes
- expect(flash[:notice]).to eq 'Recovery codes successfully regenerated'
- expect(response).to have_http_status(200)
- expect(response).to render_template(:index)
- end
-
- it 'redirects when not signed in' do
- post :create
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
-end
diff --git a/spec/controllers/settings/two_factor_authentications_controller_spec.rb b/spec/controllers/settings/two_factor_authentications_controller_spec.rb
deleted file mode 100644
index 9f27222a..00000000
--- a/spec/controllers/settings/two_factor_authentications_controller_spec.rb
+++ /dev/null
@@ -1,124 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Settings::TwoFactorAuthenticationsController do
- render_views
-
- let(:user) { Fabricate(:user) }
-
- describe 'GET #show' do
- context 'when signed in' do
- before do
- sign_in user, scope: :user
- end
-
- describe 'when user requires otp for login already' do
- it 'returns http success' do
- user.update(otp_required_for_login: true)
- get :show
-
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'when user does not require otp for login' do
- it 'returns http success' do
- user.update(otp_required_for_login: false)
- get :show
-
- expect(response).to have_http_status(200)
- end
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- get :show
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
- end
-
- describe 'POST #create' do
- context 'when signed in' do
- before do
- sign_in user, scope: :user
- end
-
- describe 'when user requires otp for login already' do
- it 'redirects to show page' do
- user.update(otp_required_for_login: true)
- post :create
-
- expect(response).to redirect_to(settings_two_factor_authentication_path)
- end
- end
-
- describe 'when creation succeeds' do
- it 'updates user secret' do
- before = user.otp_secret
- post :create
-
- expect(user.reload.otp_secret).not_to eq(before)
- expect(response).to redirect_to(new_settings_two_factor_authentication_confirmation_path)
- end
- end
- end
-
- context 'when not signed in' do
- it 'redirects' do
- get :show
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
- end
-
- describe 'POST #destroy' do
- before do
- user.update(otp_required_for_login: true)
- end
-
- context 'when signed in' do
- before do
- sign_in user, scope: :user
- end
-
- it 'turns off otp requirement with correct code' do
- expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg|
- expect(value).to eq user
- expect(arg).to eq '123456'
- true
- end
-
- post :destroy, params: { form_two_factor_confirmation: { code: '123456' } }
-
- expect(response).to redirect_to(settings_two_factor_authentication_path)
- user.reload
- expect(user.otp_required_for_login).to eq(false)
- end
-
- it 'does not turn off otp if code is incorrect' do
- expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, arg|
- expect(value).to eq user
- expect(arg).to eq '057772'
- false
- end
-
- post :destroy, params: { form_two_factor_confirmation: { code: '057772' } }
-
- user.reload
- expect(user.otp_required_for_login).to eq(true)
- end
-
- it 'raises ActionController::ParameterMissing if code is missing' do
- expect { post :destroy }.to raise_error(ActionController::ParameterMissing)
- end
- end
-
- it 'redirects if not signed in' do
- get :show
- expect(response).to redirect_to '/auth/sign_in'
- end
- end
-end
diff --git a/spec/controllers/shares_controller_spec.rb b/spec/controllers/shares_controller_spec.rb
deleted file mode 100644
index a74e9af5..00000000
--- a/spec/controllers/shares_controller_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rails_helper'
-
-describe SharesController do
- render_views
-
- let(:user) { Fabricate(:user) }
- before { sign_in user }
-
- describe 'GTE #show' do
- subject(:initial_state_json) { JSON.parse(assigns(:initial_state_json), symbolize_names: true) }
- subject(:body_classes) { assigns(:body_classes) }
-
- before { get :show, params: { title: 'test title', text: 'test text', url: 'url1 url2' } }
-
- it 'assigns json' do
- expect(response).to have_http_status :ok
- expect(initial_state_json[:compose][:text]).to eq 'test title test text url1 url2'
- expect(initial_state_json[:meta][:me]).to eq user.account.id.to_s
- expect(body_classes).to eq 'modal-layout compose-standalone'
- end
- end
-end
diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb
deleted file mode 100644
index 3425b66b..00000000
--- a/spec/controllers/statuses_controller_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe StatusesController do
- render_views
-
- describe '#show' do
- context 'account is suspended' do
- it 'returns gone' do
- account = Fabricate(:account, suspended: true)
- status = Fabricate(:status, account: account)
-
- get :show, params: { account_username: account.username, id: status.id }
-
- expect(response).to have_http_status(410)
- end
- end
-
- context 'status is not permitted' do
- it 'raises ActiveRecord::RecordNotFound' do
- user = Fabricate(:user)
- status = Fabricate(:status)
- status.account.block!(user.account)
-
- sign_in(user)
- get :show, params: { account_username: status.account.username, id: status.id }
-
- expect(response).to have_http_status(404)
- end
- end
-
- context 'status is a reblog' do
- it 'redirects to the original status' do
- original_account = Fabricate(:account, domain: 'example.com')
- original_status = Fabricate(:status, account: original_account, uri: 'tag:example.com,2017:foo', url: 'https://example.com/123')
- status = Fabricate(:status, reblog: original_status)
-
- get :show, params: { account_username: status.account.username, id: status.id }
-
- expect(response).to redirect_to(original_status.url)
- end
- end
-
- context 'account is not suspended and status is permitted' do
- it 'assigns @account' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.id }
- expect(assigns(:account)).to eq status.account
- end
-
- it 'assigns @status' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.id }
- expect(assigns(:status)).to eq status
- end
-
- it 'assigns @stream_entry' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.id }
- expect(assigns(:stream_entry)).to eq status.stream_entry
- end
-
- it 'assigns @type' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.id }
- expect(assigns(:type)).to eq 'status'
- end
-
- it 'returns a success' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.id }
- expect(response).to have_http_status(200)
- end
-
- it 'renders the React front-end' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.id }
- expect(response).to render_template 'react/react'
- end
- end
- end
-end
diff --git a/spec/controllers/stream_entries_controller_spec.rb b/spec/controllers/stream_entries_controller_spec.rb
deleted file mode 100644
index eb7fdf9d..00000000
--- a/spec/controllers/stream_entries_controller_spec.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe StreamEntriesController, type: :controller do
- render_views
-
- shared_examples 'before_action' do |route|
- context 'when account is not suspended and stream_entry is available' do
- it 'assigns instance variables' do
- status = Fabricate(:status)
-
- get route, params: { account_username: status.account.username, id: status.stream_entry.id }
-
- expect(assigns(:account)).to eq status.account
- expect(assigns(:stream_entry)).to eq status.stream_entry
- expect(assigns(:type)).to eq 'status'
- end
-
- it 'sets Link headers' do
- alice = Fabricate(:account, username: 'alice')
- status = Fabricate(:status, account: alice)
-
- get route, params: { account_username: alice.username, id: status.stream_entry.id }
-
- expect(response.headers['Link'].to_s).to eq "; rel=\"alternate\"; type=\"application/atom+xml\", ; rel=\"alternate\"; type=\"application/activity+json\""
- end
- end
-
- context 'when account is suspended' do
- it 'returns http status 410' do
- account = Fabricate(:account, suspended: true)
- status = Fabricate(:status, account: account)
-
- get route, params: { account_username: account.username, id: status.stream_entry.id }
-
- expect(response).to have_http_status(410)
- end
- end
-
- context 'when activity is nil' do
- it 'raises ActiveRecord::RecordNotFound' do
- account = Fabricate(:account)
- stream_entry = Fabricate.build(:stream_entry, account: account, activity: nil, activity_type: 'Status')
- stream_entry.save!(validate: false)
-
- get route, params: { account_username: account.username, id: stream_entry.id }
-
- expect(response).to have_http_status(404)
- end
- end
-
- context 'when it is hidden and it is not permitted' do
- it 'raises ActiveRecord::RecordNotFound' do
- status = Fabricate(:status)
- user = Fabricate(:user)
- status.account.block!(user.account)
- status.stream_entry.update!(hidden: true)
-
- sign_in(user)
- get route, params: { account_username: status.account.username, id: status.stream_entry.id }
-
- expect(response).to have_http_status(404)
- end
- end
- end
-
- describe 'GET #show' do
- include_examples 'before_action', :show
-
- it 'redirects to status page' do
- status = Fabricate(:status)
-
- get :show, params: { account_username: status.account.username, id: status.stream_entry.id }
-
- expect(response).to redirect_to(short_account_status_url(status.account, status))
- end
-
- it 'returns http success with Atom' do
- status = Fabricate(:status)
- get :show, params: { account_username: status.account.username, id: status.stream_entry.id }, format: 'atom'
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'GET #embed' do
- include_examples 'before_action', :embed
-
- it 'redirects to new embed page' do
- status = Fabricate(:status)
-
- get :embed, params: { account_username: status.account.username, id: status.stream_entry.id }
-
- expect(response).to redirect_to(embed_short_account_status_url(status.account, status))
- end
- end
-end
diff --git a/spec/controllers/tags_controller_spec.rb b/spec/controllers/tags_controller_spec.rb
deleted file mode 100644
index 69def90c..00000000
--- a/spec/controllers/tags_controller_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe TagsController, type: :controller do
- render_views
-
- describe 'GET #show' do
- let!(:tag) { Fabricate(:tag, name: 'test') }
- let!(:local) { Fabricate(:status, tags: [tag], text: 'local #test') }
- let!(:remote) { Fabricate(:status, tags: [tag], text: 'remote #test', account: Fabricate(:account, domain: 'remote')) }
- let!(:late) { Fabricate(:status, tags: [tag], text: 'late #test') }
-
- context 'when tag exists' do
- it 'returns http success' do
- get :show, params: { id: 'test', max_id: late.id }
- expect(response).to have_http_status(200)
- end
-
- it 'renders application layout' do
- get :show, params: { id: 'test', max_id: late.id }
- expect(response).to render_template layout: 'public'
- end
- end
-
- context 'when tag does not exist' do
- it 'returns http missing for non-existent tag' do
- get :show, params: { id: 'none' }
-
- expect(response).to have_http_status(404)
- end
- end
- end
-end
diff --git a/spec/controllers/well_known/host_meta_controller_spec.rb b/spec/controllers/well_known/host_meta_controller_spec.rb
deleted file mode 100644
index b43ae19d..00000000
--- a/spec/controllers/well_known/host_meta_controller_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'rails_helper'
-
-describe WellKnown::HostMetaController, type: :controller do
- render_views
-
- describe 'GET #show' do
- it 'returns http success' do
- get :show, format: :xml
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/xrd+xml'
- expect(response.body).to eq <
-
-
-
-XML
- end
- end
-end
diff --git a/spec/controllers/well_known/keybase_proof_config_controller_spec.rb b/spec/controllers/well_known/keybase_proof_config_controller_spec.rb
deleted file mode 100644
index 9067e676..00000000
--- a/spec/controllers/well_known/keybase_proof_config_controller_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe WellKnown::KeybaseProofConfigController, type: :controller do
- render_views
-
- describe 'GET #show' do
- it 'renders json' do
- get :show
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/json'
- expect { JSON.parse(response.body) }.not_to raise_exception
- end
- end
-end
diff --git a/spec/controllers/well_known/webfinger_controller_spec.rb b/spec/controllers/well_known/webfinger_controller_spec.rb
deleted file mode 100644
index b05745ea..00000000
--- a/spec/controllers/well_known/webfinger_controller_spec.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-require 'rails_helper'
-
-describe WellKnown::WebfingerController, type: :controller do
- render_views
-
- describe 'GET #show' do
- let(:alice) do
- Fabricate(:account, username: 'alice')
- end
-
- before do
- alice.private_key = <<-PEM
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQDHgPoPJlrfMZrVcuF39UbVssa8r4ObLP3dYl9Y17Mgp5K4mSYD
-R/Y2ag58tSi6ar2zM3Ze3QYsNfTq0NqN1g89eAu0MbSjWqpOsgntRPJiFuj3hai2
-X2Im8TBrkiM/UyfTRgn8q8WvMoKbXk8Lu6nqv420eyqhhLxfUoCpxuem1QIDAQAB
-AoGBAIKsOh2eM7spVI8mdgQKheEG/iEsnPkQ2R8ehfE9JzjmSbXbqghQJDaz9NU+
-G3Uu4R31QT0VbCudE9SSA/UPFl82GeQG4QLjrSE+PSjSkuslgSXelJHfAJ+ycGax
-ajtPyiQD0e4c2loagHNHPjqK9OhHx9mFnZWmoagjlZ+mQGEpAkEA8GtqfS65IaRQ
-uVhMzpp25rF1RWOwaaa+vBPkd7pGdJEQGFWkaR/a9UkU+2C4ZxGBkJDP9FApKVQI
-RANEwN3/hwJBANRuw5+es6BgBv4PD387IJvuruW2oUtYP+Lb2Z5k77J13hZTr0db
-Oo9j1UbbR0/4g+vAcsDl4JD9c/9LrGYEpcMCQBon9Yvs+2M3lziy7JhFoc3zXIjS
-Ea1M4M9hcqe78lJYPeIH3z04o/+vlcLLgQRlmSz7NESmO/QtGkEcAezhuh0CQHji
-pzO4LeO/gXslut3eGcpiYuiZquOjToecMBRwv+5AIKd367Che4uJdh6iPcyGURvh
-IewfZFFdyZqnx20ui90CQQC1W2rK5Y30wAunOtSLVA30TLK/tKrTppMC3corjKlB
-FTX8IvYBNTbpEttc1VCf/0ccnNpfb0CrFNSPWxRj7t7D
------END RSA PRIVATE KEY-----
-PEM
-
- alice.public_key = <<-PEM
------BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHgPoPJlrfMZrVcuF39UbVssa8
-r4ObLP3dYl9Y17Mgp5K4mSYDR/Y2ag58tSi6ar2zM3Ze3QYsNfTq0NqN1g89eAu0
-MbSjWqpOsgntRPJiFuj3hai2X2Im8TBrkiM/UyfTRgn8q8WvMoKbXk8Lu6nqv420
-eyqhhLxfUoCpxuem1QIDAQAB
------END PUBLIC KEY-----
-PEM
-
- alice.save!
- end
-
- around(:each) do |example|
- before = Rails.configuration.x.alternate_domains
- example.run
- Rails.configuration.x.alternate_domains = before
- end
-
- it 'returns JSON when account can be found' do
- get :show, params: { resource: alice.to_webfinger_s }, format: :json
-
- json = body_as_json
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/jrd+json'
- expect(json[:subject]).to eq 'acct:alice@cb6e6126.ngrok.io'
- expect(json[:aliases]).to include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice')
- end
-
- it 'returns JSON when account can be found' do
- get :show, params: { resource: alice.to_webfinger_s }, format: :xml
-
- xml = Nokogiri::XML(response.body)
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/xrd+xml'
- expect(xml.at_xpath('//xmlns:Subject').content).to eq 'acct:alice@cb6e6126.ngrok.io'
- expect(xml.xpath('//xmlns:Alias').map(&:content)).to include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice')
- end
-
- it 'returns http not found when account cannot be found' do
- get :show, params: { resource: 'acct:not@existing.com' }, format: :json
-
- expect(response).to have_http_status(:not_found)
- end
-
- it 'returns JSON when account can be found with alternate domains' do
- Rails.configuration.x.alternate_domains = ['foo.org']
- username, = alice.to_webfinger_s.split('@')
-
- get :show, params: { resource: "#{username}@foo.org" }, format: :json
-
- json = body_as_json
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/jrd+json'
- expect(json[:subject]).to eq 'acct:alice@cb6e6126.ngrok.io'
- expect(json[:aliases]).to include('https://cb6e6126.ngrok.io/@alice', 'https://cb6e6126.ngrok.io/users/alice')
- end
-
- it 'returns http not found when account can not be found with alternate domains' do
- Rails.configuration.x.alternate_domains = ['foo.org']
- username, = alice.to_webfinger_s.split('@')
-
- get :show, params: { resource: "#{username}@bar.org" }, format: :json
-
- expect(response).to have_http_status(:not_found)
- end
- end
-end
diff --git a/spec/fabricators/access_token_fabricator.rb b/spec/fabricators/access_token_fabricator.rb
deleted file mode 100644
index 1856a8eb..00000000
--- a/spec/fabricators/access_token_fabricator.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-Fabricator :access_token, from: 'Doorkeeper::AccessToken' do
-end
diff --git a/spec/fabricators/accessible_access_token_fabricator.rb b/spec/fabricators/accessible_access_token_fabricator.rb
deleted file mode 100644
index 4b7e99b2..00000000
--- a/spec/fabricators/accessible_access_token_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator :accessible_access_token, from: :access_token do
- expires_in { nil }
- revoked_at { nil }
-end
diff --git a/spec/fabricators/account_domain_block_fabricator.rb b/spec/fabricators/account_domain_block_fabricator.rb
deleted file mode 100644
index 2ad4b67a..00000000
--- a/spec/fabricators/account_domain_block_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:account_domain_block) do
- account
- domain 'example.com'
-end
diff --git a/spec/fabricators/account_fabricator.rb b/spec/fabricators/account_fabricator.rb
deleted file mode 100644
index f12464ef..00000000
--- a/spec/fabricators/account_fabricator.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-keypair = OpenSSL::PKey::RSA.new(2048)
-public_key = keypair.public_key.to_pem
-private_key = keypair.to_pem
-
-Fabricator(:account) do
- transient :suspended, :silenced
- username { sequence(:username) { |i| "#{Faker::Internet.user_name(nil, %w(_))}#{i}" } }
- last_webfingered_at { Time.now.utc }
- public_key { public_key }
- private_key { private_key }
- suspended_at { |attrs| attrs[:suspended] ? Time.now.utc : nil }
- silenced_at { |attrs| attrs[:silenced] ? Time.now.utc : nil }
-end
diff --git a/spec/fabricators/account_identity_proof_fabricator.rb b/spec/fabricators/account_identity_proof_fabricator.rb
deleted file mode 100644
index 94f40dfd..00000000
--- a/spec/fabricators/account_identity_proof_fabricator.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-Fabricator(:account_identity_proof) do
- account
- provider 'keybase'
- provider_username { sequence(:provider_username) { |i| "#{Faker::Lorem.characters(15)}" } }
- token { sequence(:token) { |i| "#{i}#{Faker::Crypto.sha1()*2}"[0..65] } }
- verified false
- live false
-end
diff --git a/spec/fabricators/account_moderation_note_fabricator.rb b/spec/fabricators/account_moderation_note_fabricator.rb
deleted file mode 100644
index 9277af16..00000000
--- a/spec/fabricators/account_moderation_note_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:account_moderation_note) do
- content "MyText"
- account nil
-end
diff --git a/spec/fabricators/account_pin_fabricator.rb b/spec/fabricators/account_pin_fabricator.rb
deleted file mode 100644
index c0f8b8af..00000000
--- a/spec/fabricators/account_pin_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:account_pin) do
- account nil
- target_account nil
-end
diff --git a/spec/fabricators/account_stat_fabricator.rb b/spec/fabricators/account_stat_fabricator.rb
deleted file mode 100644
index 2b06b479..00000000
--- a/spec/fabricators/account_stat_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:account_stat) do
- account nil
- statuses_count ""
- following_count ""
- followers_count ""
-end
diff --git a/spec/fabricators/account_tag_stat_fabricator.rb b/spec/fabricators/account_tag_stat_fabricator.rb
deleted file mode 100644
index 9edb550b..00000000
--- a/spec/fabricators/account_tag_stat_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:account_tag_stat) do
- accounts_count ""
-end
diff --git a/spec/fabricators/account_warning_fabricator.rb b/spec/fabricators/account_warning_fabricator.rb
deleted file mode 100644
index db161d44..00000000
--- a/spec/fabricators/account_warning_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:account_warning) do
- account nil
- target_account nil
- text "MyText"
-end
diff --git a/spec/fabricators/account_warning_preset_fabricator.rb b/spec/fabricators/account_warning_preset_fabricator.rb
deleted file mode 100644
index 6c0b87e7..00000000
--- a/spec/fabricators/account_warning_preset_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:account_warning_preset) do
- text "MyText"
-end
diff --git a/spec/fabricators/admin_action_log_fabricator.rb b/spec/fabricators/admin_action_log_fabricator.rb
deleted file mode 100644
index 2f44e953..00000000
--- a/spec/fabricators/admin_action_log_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator('Admin::ActionLog') do
- account nil
- action "MyString"
- target nil
-end
diff --git a/spec/fabricators/application_fabricator.rb b/spec/fabricators/application_fabricator.rb
deleted file mode 100644
index 42b7009d..00000000
--- a/spec/fabricators/application_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:application, from: Doorkeeper::Application) do
- name 'Example'
- website 'http://example.com'
- redirect_uri 'http://example.com/callback'
-end
diff --git a/spec/fabricators/assets/TEAPOT b/spec/fabricators/assets/TEAPOT
deleted file mode 100644
index e624ecb4..00000000
--- a/spec/fabricators/assets/TEAPOT
+++ /dev/null
@@ -1,6 +0,0 @@
-This "Utah teapot" photograph is licensed under the Creative Commons
-Attribution-Share Alike 3.0 Unported license:
- https://creativecommons.org/licenses/by-sa/3.0/deed.en
-
-Original source of work:
- https://commons.wikimedia.org/wiki/File:Utah_teapot_simple_2.png
diff --git a/spec/fabricators/assets/utah_teapot.png b/spec/fabricators/assets/utah_teapot.png
deleted file mode 100644
index 6708361e..00000000
Binary files a/spec/fabricators/assets/utah_teapot.png and /dev/null differ
diff --git a/spec/fabricators/backup_fabricator.rb b/spec/fabricators/backup_fabricator.rb
deleted file mode 100644
index 99a5bdcd..00000000
--- a/spec/fabricators/backup_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:backup) do
- user
-end
diff --git a/spec/fabricators/block_fabricator.rb b/spec/fabricators/block_fabricator.rb
deleted file mode 100644
index 379931ba..00000000
--- a/spec/fabricators/block_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:block) do
- account
- target_account { Fabricate(:account) }
-end
diff --git a/spec/fabricators/conversation_account_fabricator.rb b/spec/fabricators/conversation_account_fabricator.rb
deleted file mode 100644
index f57ffd53..00000000
--- a/spec/fabricators/conversation_account_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:conversation_account) do
- account nil
- conversation nil
- participant_account_ids ""
- last_status nil
-end
diff --git a/spec/fabricators/conversation_fabricator.rb b/spec/fabricators/conversation_fabricator.rb
deleted file mode 100644
index b4fadb46..00000000
--- a/spec/fabricators/conversation_fabricator.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-Fabricator(:conversation) do
-end
diff --git a/spec/fabricators/conversation_mute_fabricator.rb b/spec/fabricators/conversation_mute_fabricator.rb
deleted file mode 100644
index 84f131c2..00000000
--- a/spec/fabricators/conversation_mute_fabricator.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-Fabricator(:conversation_mute) do
-end
diff --git a/spec/fabricators/custom_emoji_fabricator.rb b/spec/fabricators/custom_emoji_fabricator.rb
deleted file mode 100644
index 18a7d23d..00000000
--- a/spec/fabricators/custom_emoji_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:custom_emoji) do
- shortcode 'coolcat'
- domain nil
- image { File.open(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png')) }
-end
diff --git a/spec/fabricators/custom_filter_fabricator.rb b/spec/fabricators/custom_filter_fabricator.rb
deleted file mode 100644
index 64297a7e..00000000
--- a/spec/fabricators/custom_filter_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:custom_filter) do
- account
- expires_at nil
- phrase 'discourse'
- context %w(home notifications)
-end
diff --git a/spec/fabricators/domain_block_fabricator.rb b/spec/fabricators/domain_block_fabricator.rb
deleted file mode 100644
index cc1f928e..00000000
--- a/spec/fabricators/domain_block_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:domain_block) do
- domain { sequence(:domain) { |i| "#{i}#{Faker::Internet.domain_name}" } }
-end
diff --git a/spec/fabricators/email_domain_block_fabricator.rb b/spec/fabricators/email_domain_block_fabricator.rb
deleted file mode 100644
index d18af643..00000000
--- a/spec/fabricators/email_domain_block_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:email_domain_block) do
- domain { sequence(:domain) { |i| "#{i}#{Faker::Internet.domain_name}" } }
-end
diff --git a/spec/fabricators/favourite_fabricator.rb b/spec/fabricators/favourite_fabricator.rb
deleted file mode 100644
index 464ac8d7..00000000
--- a/spec/fabricators/favourite_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:favourite) do
- account
- status
-end
diff --git a/spec/fabricators/featured_tag_fabricator.rb b/spec/fabricators/featured_tag_fabricator.rb
deleted file mode 100644
index 25cbdaac..00000000
--- a/spec/fabricators/featured_tag_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:featured_tag) do
- account
- tag
- statuses_count 1_337
- last_status_at Time.now.utc
-end
diff --git a/spec/fabricators/follow_fabricator.rb b/spec/fabricators/follow_fabricator.rb
deleted file mode 100644
index 9b25dc54..00000000
--- a/spec/fabricators/follow_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:follow) do
- account
- target_account { Fabricate(:account) }
-end
diff --git a/spec/fabricators/follow_request_fabricator.rb b/spec/fabricators/follow_request_fabricator.rb
deleted file mode 100644
index c00ddf84..00000000
--- a/spec/fabricators/follow_request_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:follow_request) do
- account
- target_account { Fabricate(:account, locked: true) }
-end
diff --git a/spec/fabricators/group_removed_account_fabricator.rb b/spec/fabricators/group_removed_account_fabricator.rb
deleted file mode 100644
index c01c2df3..00000000
--- a/spec/fabricators/group_removed_account_fabricator.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-Fabricator(:group_removed_account) do
-end
diff --git a/spec/fabricators/identity_fabricator.rb b/spec/fabricators/identity_fabricator.rb
deleted file mode 100644
index bc832df9..00000000
--- a/spec/fabricators/identity_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:identity) do
- user nil
- provider "MyString"
- uid "MyString"
-end
diff --git a/spec/fabricators/import_fabricator.rb b/spec/fabricators/import_fabricator.rb
deleted file mode 100644
index e2eb1e0d..00000000
--- a/spec/fabricators/import_fabricator.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-Fabricator(:import) do
-end
diff --git a/spec/fabricators/invite_fabricator.rb b/spec/fabricators/invite_fabricator.rb
deleted file mode 100644
index 62b9b390..00000000
--- a/spec/fabricators/invite_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:invite) do
- user
- expires_at nil
- max_uses nil
- uses 0
-end
diff --git a/spec/fabricators/list_account_fabricator.rb b/spec/fabricators/list_account_fabricator.rb
deleted file mode 100644
index 30e4004a..00000000
--- a/spec/fabricators/list_account_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:list_account) do
- list nil
- account nil
- follow nil
-end
diff --git a/spec/fabricators/list_fabricator.rb b/spec/fabricators/list_fabricator.rb
deleted file mode 100644
index c3db690f..00000000
--- a/spec/fabricators/list_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:list) do
- account
- title "MyString"
-end
diff --git a/spec/fabricators/media_attachment_fabricator.rb b/spec/fabricators/media_attachment_fabricator.rb
deleted file mode 100644
index bb938e36..00000000
--- a/spec/fabricators/media_attachment_fabricator.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-Fabricator(:media_attachment) do
- account
- file do |attrs|
- [
- case attrs[:type]
- when :gifv
- attachment_fixture ['attachment.gif', 'attachment.webm'].sample
- when :image
- attachment_fixture 'attachment.jpg'
- when nil
- attachment_fixture ['attachment.gif', 'attachment.jpg', 'attachment.webm'].sample
- end,
- nil
- ].sample
- end
-end
diff --git a/spec/fabricators/mention_fabricator.rb b/spec/fabricators/mention_fabricator.rb
deleted file mode 100644
index cb5fe429..00000000
--- a/spec/fabricators/mention_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:mention) do
- account
- status
-end
diff --git a/spec/fabricators/mute_fabricator.rb b/spec/fabricators/mute_fabricator.rb
deleted file mode 100644
index 30d20e87..00000000
--- a/spec/fabricators/mute_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:mute) do
- account
- target_account { Fabricate(:account) }
-end
diff --git a/spec/fabricators/notification_fabricator.rb b/spec/fabricators/notification_fabricator.rb
deleted file mode 100644
index 638844e0..00000000
--- a/spec/fabricators/notification_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:notification) do
- activity fabricator: [:mention, :status, :follow, :follow_request, :favourite].sample
- account
-end
diff --git a/spec/fabricators/poll_fabricator.rb b/spec/fabricators/poll_fabricator.rb
deleted file mode 100644
index 746610f7..00000000
--- a/spec/fabricators/poll_fabricator.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-Fabricator(:poll) do
- account
- status
- expires_at { 7.days.from_now }
- options %w(Foo Bar)
- multiple false
- hide_totals false
-end
diff --git a/spec/fabricators/poll_vote_fabricator.rb b/spec/fabricators/poll_vote_fabricator.rb
deleted file mode 100644
index 51f9b006..00000000
--- a/spec/fabricators/poll_vote_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:poll_vote) do
- account
- poll
- choice 0
-end
diff --git a/spec/fabricators/relay_fabricator.rb b/spec/fabricators/relay_fabricator.rb
deleted file mode 100644
index 488913f7..00000000
--- a/spec/fabricators/relay_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:relay) do
- inbox_url "https://example.com/inbox"
- state :idle
-end
diff --git a/spec/fabricators/report_fabricator.rb b/spec/fabricators/report_fabricator.rb
deleted file mode 100644
index 5bd4a63f..00000000
--- a/spec/fabricators/report_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:report) do
- account
- target_account { Fabricate(:account) }
- comment "You nasty"
- action_taken false
-end
diff --git a/spec/fabricators/report_note_fabricator.rb b/spec/fabricators/report_note_fabricator.rb
deleted file mode 100644
index e139efff..00000000
--- a/spec/fabricators/report_note_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:report_note) do
- report
- account { Fabricate(:account) }
- content "Test Content"
-end
diff --git a/spec/fabricators/scheduled_status_fabricator.rb b/spec/fabricators/scheduled_status_fabricator.rb
deleted file mode 100644
index 52384d13..00000000
--- a/spec/fabricators/scheduled_status_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:scheduled_status) do
- account
- scheduled_at { 20.hours.from_now }
-end
diff --git a/spec/fabricators/session_activation_fabricator.rb b/spec/fabricators/session_activation_fabricator.rb
deleted file mode 100644
index 526faaec..00000000
--- a/spec/fabricators/session_activation_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:session_activation) do
- user
- session_id "MyString"
-end
diff --git a/spec/fabricators/setting_fabricator.rb b/spec/fabricators/setting_fabricator.rb
deleted file mode 100644
index 336d7c35..00000000
--- a/spec/fabricators/setting_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-Fabricator(:setting) do
-end
diff --git a/spec/fabricators/site_upload_fabricator.rb b/spec/fabricators/site_upload_fabricator.rb
deleted file mode 100644
index 2efc57e2..00000000
--- a/spec/fabricators/site_upload_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:site_upload) do
- file { File.open(File.join(Rails.root, 'spec', 'fabricators', 'assets', 'utah_teapot.png')) }
-end
diff --git a/spec/fabricators/status_fabricator.rb b/spec/fabricators/status_fabricator.rb
deleted file mode 100644
index 04bbbcf4..00000000
--- a/spec/fabricators/status_fabricator.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-Fabricator(:status) do
- account
- text "Lorem ipsum dolor sit amet"
-
- after_build do |status|
- status.uri = Faker::Internet.device_token if !status.account.local? && status.uri.nil?
- end
-end
diff --git a/spec/fabricators/status_pin_fabricator.rb b/spec/fabricators/status_pin_fabricator.rb
deleted file mode 100644
index 6a9006c9..00000000
--- a/spec/fabricators/status_pin_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:status_pin) do
- account
- status
-end
diff --git a/spec/fabricators/status_stat_fabricator.rb b/spec/fabricators/status_stat_fabricator.rb
deleted file mode 100644
index 9c67fd40..00000000
--- a/spec/fabricators/status_stat_fabricator.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-Fabricator(:status_stat) do
- status_id nil
- replies_count ""
- reblogs_count ""
- favourites_count ""
-end
diff --git a/spec/fabricators/stream_entry_fabricator.rb b/spec/fabricators/stream_entry_fabricator.rb
deleted file mode 100644
index f33822c7..00000000
--- a/spec/fabricators/stream_entry_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:stream_entry) do
- account
- activity { Fabricate(:status) }
- hidden { [true, false].sample }
-end
diff --git a/spec/fabricators/subscription_fabricator.rb b/spec/fabricators/subscription_fabricator.rb
deleted file mode 100644
index 347dab5d..00000000
--- a/spec/fabricators/subscription_fabricator.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-Fabricator(:subscription) do
- account
- callback_url "http://example.com/callback"
- secret "foobar"
- expires_at "2016-11-28 11:30:07"
- confirmed false
-end
diff --git a/spec/fabricators/tag_fabricator.rb b/spec/fabricators/tag_fabricator.rb
deleted file mode 100644
index 33d57c92..00000000
--- a/spec/fabricators/tag_fabricator.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-Fabricator(:tag) do
- name { sequence(:hashtag) { |i| "#{Faker::Lorem.word}#{i}" } }
-end
diff --git a/spec/fabricators/user_fabricator.rb b/spec/fabricators/user_fabricator.rb
deleted file mode 100644
index 8f595650..00000000
--- a/spec/fabricators/user_fabricator.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-Fabricator(:user) do
- account
- email { sequence(:email) { |i| "#{i}#{Faker::Internet.email}" } }
- password "123456789"
- confirmed_at { Time.zone.now }
- agreement true
-end
diff --git a/spec/fabricators/user_invite_request_fabricator.rb b/spec/fabricators/user_invite_request_fabricator.rb
deleted file mode 100644
index 5cc6ae56..00000000
--- a/spec/fabricators/user_invite_request_fabricator.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-Fabricator(:user_invite_request) do
- user
- text { Faker::Lorem.sentence }
-end
diff --git a/spec/fabricators/web_push_subscription_fabricator.rb b/spec/fabricators/web_push_subscription_fabricator.rb
deleted file mode 100644
index 97f90675..00000000
--- a/spec/fabricators/web_push_subscription_fabricator.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-Fabricator(:web_push_subscription, from: Web::PushSubscription) do
- endpoint Faker::Internet.url
- key_p256dh Faker::Internet.password
- key_auth Faker::Internet.password
-end
diff --git a/spec/fabricators/web_setting_fabricator.rb b/spec/fabricators/web_setting_fabricator.rb
deleted file mode 100644
index 369b86bc..00000000
--- a/spec/fabricators/web_setting_fabricator.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-Fabricator(:web_setting, from: Web::Setting) do
-end
diff --git a/spec/features/log_in_spec.rb b/spec/features/log_in_spec.rb
deleted file mode 100644
index 53a1f9b1..00000000
--- a/spec/features/log_in_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require "rails_helper"
-
-feature "Log in" do
- given(:email) { "test@examle.com" }
- given(:password) { "password" }
- given(:confirmed_at) { Time.zone.now }
-
- background do
- Fabricate(:user, email: email, password: password, confirmed_at: confirmed_at)
- visit new_user_session_path
- end
-
- subject { page }
-
- scenario "A valid email and password user is able to log in" do
- fill_in "user_email", with: email
- fill_in "user_password", with: password
- click_on I18n.t('auth.login')
-
- is_expected.to have_css("div.app-holder")
- end
-
- scenario "A invalid email and password user is not able to log in" do
- fill_in "user_email", with: "invalid_email"
- fill_in "user_password", with: "invalid_password"
- click_on I18n.t('auth.login')
-
- is_expected.to have_css(".flash-message", text: failure_message("invalid"))
- end
-
- context do
- given(:confirmed_at) { nil }
-
- scenario "A unconfirmed user is not able to log in" do
- fill_in "user_email", with: email
- fill_in "user_password", with: password
- click_on I18n.t('auth.login')
-
- is_expected.to have_css(".flash-message", text: failure_message("unconfirmed"))
- end
- end
-
- def failure_message(message)
- keys = User.authentication_keys.map { |key| User.human_attribute_name(key) }
- I18n.t("devise.failure.#{message}", authentication_keys: keys.join("support.array.words_connector"))
- end
-end
diff --git a/spec/fixtures/files/4096x4097.png b/spec/fixtures/files/4096x4097.png
deleted file mode 100644
index d1110cc2..00000000
Binary files a/spec/fixtures/files/4096x4097.png and /dev/null differ
diff --git a/spec/fixtures/files/attachment.gif b/spec/fixtures/files/attachment.gif
deleted file mode 100644
index 2937f5ab..00000000
Binary files a/spec/fixtures/files/attachment.gif and /dev/null differ
diff --git a/spec/fixtures/files/attachment.jpg b/spec/fixtures/files/attachment.jpg
deleted file mode 100644
index f1d40539..00000000
Binary files a/spec/fixtures/files/attachment.jpg and /dev/null differ
diff --git a/spec/fixtures/files/attachment.webm b/spec/fixtures/files/attachment.webm
deleted file mode 100644
index 3babe5cf..00000000
Binary files a/spec/fixtures/files/attachment.webm and /dev/null differ
diff --git a/spec/fixtures/files/avatar.gif b/spec/fixtures/files/avatar.gif
deleted file mode 100644
index d929801e..00000000
Binary files a/spec/fixtures/files/avatar.gif and /dev/null differ
diff --git a/spec/fixtures/files/emojo.png b/spec/fixtures/files/emojo.png
deleted file mode 100644
index cb599349..00000000
Binary files a/spec/fixtures/files/emojo.png and /dev/null differ
diff --git a/spec/fixtures/files/imports.txt b/spec/fixtures/files/imports.txt
deleted file mode 100644
index dac295c4..00000000
--- a/spec/fixtures/files/imports.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-user@example.com
-
-user@test.com
diff --git a/spec/fixtures/files/mini-static.gif b/spec/fixtures/files/mini-static.gif
deleted file mode 100644
index fe597b21..00000000
Binary files a/spec/fixtures/files/mini-static.gif and /dev/null differ
diff --git a/spec/fixtures/files/mute-imports.txt b/spec/fixtures/files/mute-imports.txt
deleted file mode 100644
index 125cbd38..00000000
--- a/spec/fixtures/files/mute-imports.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-bob
-
-eve@example.com
-
diff --git a/spec/fixtures/files/new-following-imports.txt b/spec/fixtures/files/new-following-imports.txt
deleted file mode 100644
index a2a787fd..00000000
--- a/spec/fixtures/files/new-following-imports.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Account address,Show reposts
-bob,true
-eve@example.com,false
-
diff --git a/spec/fixtures/files/new-mute-imports.txt b/spec/fixtures/files/new-mute-imports.txt
deleted file mode 100644
index c1c9bca9..00000000
--- a/spec/fixtures/files/new-mute-imports.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Account address,Hide notifications
-bob,true
-eve@example.com,false
-
diff --git a/spec/fixtures/push/feed.atom b/spec/fixtures/push/feed.atom
deleted file mode 100644
index 8606b0a7..00000000
--- a/spec/fixtures/push/feed.atom
+++ /dev/null
@@ -1,424 +0,0 @@
-
-
- GNU social
- https://quitter.no/api/statuses/user_timeline/7477.atom
- robcolbert timeline
- Updates from robcolbert on Quitter.no!
- https://quitter.no/avatar/7477-96-20160211190340.png
- 2016-03-20T12:42:58+01:00
-
- http://activitystrea.ms/schema/1.0/person
- https://quitter.no/user/7477
- robcolbert
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
-
-
-
- robcolbert
- DIGITAL CAT
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
- Germany
-
-
- homepage
- https://zeonfederated.com
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-20:noticeId=1276923:objectType=note
- New note by robcolbert
- @<a href="https://cb6e6126.ngrok.io/users/catsrgr8" class="h-card mention">catsrgr8</a> this is a mention
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-20T11:05:31+00:00
- 2016-03-20T11:05:31+00:00
-
- tag:quitter.no,2016-03-20:objectType=thread:nonce=7c998112e39a6685
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-19:noticeId=1273635:objectType=note
- New note by robcolbert
- Just testing a thing.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-19T20:35:53+00:00
- 2016-03-19T20:35:53+00:00
-
- tag:quitter.no,2016-03-19:objectType=thread:nonce=c4a61886d5cad4c2
-
-
-
-
-
-
-
- tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note
- Delete
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> deleted notice <a href="https://quitter.no/notice/1272988">{{tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note}}</a>.
-
- delete
- 2016-03-19T18:16:58+00:00
- 2016-03-19T18:16:58+00:00
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note
-
-
- tag:quitter.no,2016-03-19:objectType=thread:nonce=7913e6b6256b6d0b
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-19:noticeId=1269381:objectType=comment
- New comment by robcolbert
- @<a href="https://gab.com/users/robcolbert" class="h-card mention" title="Eugen">robcolbert</a> I have to wonder if this will appear as a reply to the right status, and not just a mention.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-19T00:10:14+00:00
- 2016-03-19T00:10:14+00:00
-
-
-
- tag:quitter.no,2016-03-18:objectType=thread:nonce=d05c6330fbe23fb9
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-18:noticeId=1265337:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> Plus, Android can hardly be considered free software given how many proprietary blobs are used. I'm speaking as a disappointed Android user.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-18T10:01:50+00:00
- 2016-03-18T10:01:50+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-18:objectType=thread:nonce=d61438407b882959
-
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-18:noticeId=1265331:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> Well as it turns out, Apple software is better than Android in terms of security, and Apple is fighting FBI while Google promised to build a messaging app that facilitates wire tapping. The whole free software thing should imo be considered a bonus and not overshadow other factors.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-18T10:01:01+00:00
- 2016-03-18T10:01:01+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-18:objectType=thread:nonce=d61438407b882959
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-17:noticeId=1261358:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> @<a href="https://gs.kawa-kun.com/user/2" class="h-card mention" title="竹下憲二">takeshitakenji</a> There is a reason that was deprecated and we don't use tables to design websites anymore. HTML needs to be semantic, i.e. tags need to describe the *kind* of content, not how it should *look*, which is a responsibility delegated to CSS. There are so many upsides to this separation of concerns, should I start listing?
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-17T17:00:26+00:00
- 2016-03-17T17:00:26+00:00
-
-
-
- tag:gs.kawa-kun.com,2016-03-17:objectType=thread:nonce=a83963573a0520f1
-
-
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:24:13+01:00
- DIGITAL CAT (robcolbert)'s status on Wednesday, 16-Mar-2016 21:24:13 CET
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:24:13+00:00
- 2016-03-16T20:24:13+00:00
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/robcolbert
- Eugen
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
-
-
-
- robcolbert
- Eugen
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=073bda8223dfcaa7
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:22:38+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:22:38+00:00
- 2016-03-16T20:22:38+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:22:38+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=b157f676181e0ecd
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:16:14+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:16:15+00:00
- 2016-03-16T20:16:15+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:16:14+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=6a6ebd1ed6504a11
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:13:06+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:13:06+00:00
- 2016-03-16T20:13:06+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:13:06+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=8f5f92443584e8f0
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:05:02+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:05:03+00:00
- 2016-03-16T20:05:03+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:05:02+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=b630d235232fcff5
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T19:04:16+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T18:04:16+00:00
- 2016-03-16T18:04:16+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T19:04:16+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=40eb98e5f85c9908
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-15:noticeId=1251422:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> LGB, not LGBT?
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-15T20:28:13+00:00
- 2016-03-15T20:28:13+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-15:objectType=thread:nonce=70ff6886d69e5225
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-15:noticeId=1250742:objectType=comment
- New comment by robcolbert
- @<a href="https://social.umeahackerspace.se/user/2" class="h-card mention" title="<Mikael & Nordfeldth>">mmn</a> I'm like reeeeally close to actually deploying the first production instance of Gab Social.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-15T18:44:54+00:00
- 2016-03-15T18:44:54+00:00
-
-
-
- tag:quitter.no,2016-03-15:objectType=thread:nonce=2fbd771270b5da80
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-15:noticeId=1250653:objectType=note
- New note by robcolbert
- @<a href="https://social.umeahackerspace.se/user/2" class="h-card mention" title="<Mikael & Nordfeldth>">mmn</a> Any progress on the issues I created?
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-15T18:27:00+00:00
- 2016-03-15T18:27:00+00:00
-
- tag:quitter.no,2016-03-15:objectType=thread:nonce=2fbd771270b5da80
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-14:noticeId=1243566:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> I heard Piwik is also good.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-14T15:35:23+00:00
- 2016-03-14T15:35:23+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-14:objectType=thread:nonce=8fbf00e7f76866d3
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-14:noticeId=1243331:objectType=comment
- New comment by robcolbert
- I do wish I had somebody else partake in the development process if only to give me feedback on my decisions
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-14T14:52:03+00:00
- 2016-03-14T14:52:03+00:00
-
-
-
- tag:quitter.no,2016-03-14:objectType=thread:nonce=46e8a2abc1839d01
-
-
-
-
-
-
-
diff --git a/spec/fixtures/push/reblog.atom b/spec/fixtures/push/reblog.atom
deleted file mode 100644
index dcf3430a..00000000
--- a/spec/fixtures/push/reblog.atom
+++ /dev/null
@@ -1,92 +0,0 @@
-
- tag:gs.smuglo.li,2016-09-03:noticeId=661684:objectType=note
- dtluna repeated a notice by robcolbert
- RT @<a href="https://gab.com/users/robcolbert" class="h-card mention" title="Eugen">robcolbert</a> Stormbending from Devin Townsend's upcoming album Transcendence is now on YouTube <a href="https://www.youtube.com/watch?v=8s9qh77gj6Y" title="https://www.youtube.com/watch?v=8s9qh77gj6Y" class="attachment thumbnail" id="attachment-122081" rel="nofollow external">https://www.youtube.com/watch?v=8s9qh77gj6Y</a>
-
- http://activitystrea.ms/schema/1.0/share
- 2016-09-03T13:48:19+00:00
- 2016-09-03T13:48:19+00:00
-
- http://activitystrea.ms/schema/1.0/person
- https://gs.smuglo.li/user/537
- dtluna
- Sex Goddess of Fediverse. Parabola GNU/Linux-libre user. PGP: 0xA490DBE4 XMPP and email: dtluna@memeware.net
-
-
-
-
-
- dtluna
- dtluna
- Sex Goddess of Fediverse. Parabola GNU/Linux-libre user. PGP: 0xA490DBE4 XMPP and email: dtluna@memeware.net
-
- Minsk, Belarus
-
-
- homepage
- https://liberapay.com/dtluna/
- true
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/activity
- tag:gab.com,2016-09-03:objectId=5984:objectType=Status
-
- Stormbending from Devin Townsend's upcoming album Transcendence is now on YouTube <a rel="nofollow" href="https://www.youtube.com/watch?v=8s9qh77gj6Y">https://www.youtube.com/watch?v=8s9qh77gj6Y</a>
-
- http://activitystrea.ms/schema/1.0/post
- 2016-09-03T13:47:59+00:00
- 2016-09-03T13:47:59+00:00
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/robcolbert
- robcolbert
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
-
-
-
- robcolbert
- Eugen
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:gab.com,2016-09-03:objectId=5984:objectType=Status
- New note by robcolbert
- Stormbending from Devin Townsend's upcoming album Transcendence is now on YouTube <a rel="nofollow" href="https://www.youtube.com/watch?v=8s9qh77gj6Y">https://www.youtube.com/watch?v=8s9qh77gj6Y</a>
-
-
-
-
- tag:gs.smuglo.li,2016-09-03:objectType=thread:nonce=aec0feafff16e2cf
-
-
- https://gab.com/users/robcolbert.atom
- Eugen
-
-
- https://gs.smuglo.li/avatar/1292-original-20160903122640.gif
- 2016-09-04T12:10:44+00:00
-
-
-
- tag:gs.smuglo.li,2016-09-03:objectType=thread:nonce=aec0feafff16e2cf
-
-
- https://gs.smuglo.li/api/statuses/user_timeline/537.atom
- dtluna
-
-
-
- https://gs.smuglo.li/avatar/537-96-20160807184048.jpeg
- 2016-09-04T01:48:58+00:00
-
-
-
-
-
diff --git a/spec/fixtures/requests/.host-meta.txt b/spec/fixtures/requests/.host-meta.txt
deleted file mode 100644
index b312b11f..00000000
--- a/spec/fixtures/requests/.host-meta.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:11:00 GMT
-Content-Type: application/xrd+xml
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-
-
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/activitypub-actor-individual.txt b/spec/fixtures/requests/activitypub-actor-individual.txt
deleted file mode 100644
index 74411e54..00000000
--- a/spec/fixtures/requests/activitypub-actor-individual.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-HTTP/1.1 200 OK
-Cache-Control: max-age=0, private, must-revalidate
-Content-Type: application/activity+json; charset=utf-8
-Link: ; rel="lrdd"; type="application/xrd+xml", ; rel="alternate"; type="application/atom+xml", ; rel="alternate"; type="application/activity+json"
-Vary: Accept-Encoding
-X-Content-Type-Options: nosniff
-X-Xss-Protection: 1; mode=block
-
-{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"vcard": "http://www.w3.org/2006/vcard/ns#"},{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","Hashtag":"as:Hashtag","ostatus":"http://ostatus.org#","atomUri":"ostatus:atomUri","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation"}],"id":"https://ap.example.com/users/foo","type":["Person","vcard:individual"],"following":"https://ap.example.com/users/foo/following","followers":"https://ap.example.com/users/foo/followers","inbox":"https://ap.example.com/users/foo/inbox","outbox":"https://ap.example.com/users/foo/outbox","preferredUsername":"foo","vcard:fn":"foo","name":"","summary":"\u003cp\u003etest\u003c/p\u003e","url":"https://ap.example.com/@foo","manuallyApprovesFollowers":false,"publicKey":{"id":"https://ap.example.com/users/foo#main-key","owner":"https://ap.example.com/users/foo","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3L4vnpNLzVH31MeWI39\n4F0wKeJFsLDAsNXGeOu0QF2x+h1zLWZw/agqD2R3JPU9/kaDJGPIV2Sn5zLyUA9S\n6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh\n8lDET6X4Pyw+ZJU0/OLo/41q9w+OrGtlsTm/PuPIeXnxa6BLqnDaxC+4IcjG/FiP\nahNCTINl/1F/TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq+t8nhQYkgAkt64euW\npva3qL5KD1mTIZQEP+LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3Qvu\nHQIDAQAB\n-----END PUBLIC KEY-----\n"},"endpoints":{"sharedInbox":"https://ap.example.com/inbox"},"icon":{"type":"Image","url":"https://quitter.no/avatar/7477-300-20160211190340.png"}}
\ No newline at end of file
diff --git a/spec/fixtures/requests/activitypub-actor-noinbox.txt b/spec/fixtures/requests/activitypub-actor-noinbox.txt
deleted file mode 100644
index 95b4650e..00000000
--- a/spec/fixtures/requests/activitypub-actor-noinbox.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-HTTP/1.1 200 OK
-Date: Sun, 17 Sep 2017 06:51:23 GMT
-Content-Type: application/json; charset=utf-8
-X-XSS-Protection: 1; mode=block
-Link: ; rel="lrdd"; type="application/xrd+xml", ; rel="alternate"; type="application/atom+xml"
-Vary: Accept-Encoding
-Cache-Control: max-age=0, private, must-revalidate
-
-{"@context":"https://www.w3.org/ns/activitystreams","id":"https://ap.example.com/users/foo","type":"Person","following":"https://ap.example.com/users/foo/following","followers":"https://ap.example.com/users/foo/followers","inbox":null,"outbox":"https://ap.example.com/users/foo/outbox","preferredUsername":"foo","name":"","summary":"\u003cp\u003etest\u003c/p\u003e","icon":"https://quitter.no/avatar/7477-300-20160211190340.png","image":"/headers/original/missing.png","publicKey":{"id":"https://ap.example.com/users/foo#main-key","owner":"https://ap.example.com/users/foo","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3L4vnpNLzVH31MeWI39\n4F0wKeJFsLDAsNXGeOu0QF2x+h1zLWZw/agqD2R3JPU9/kaDJGPIV2Sn5zLyUA9S\n6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh\n8lDET6X4Pyw+ZJU0/OLo/41q9w+OrGtlsTm/PuPIeXnxa6BLqnDaxC+4IcjG/FiP\nahNCTINl/1F/TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq+t8nhQYkgAkt64euW\npva3qL5KD1mTIZQEP+LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3Qvu\nHQIDAQAB\n-----END PUBLIC KEY-----\n"}}
\ No newline at end of file
diff --git a/spec/fixtures/requests/activitypub-actor.txt b/spec/fixtures/requests/activitypub-actor.txt
deleted file mode 100644
index 6514241c..00000000
--- a/spec/fixtures/requests/activitypub-actor.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-HTTP/1.1 200 OK
-Cache-Control: max-age=0, private, must-revalidate
-Content-Type: application/activity+json; charset=utf-8
-Link: ; rel="lrdd"; type="application/xrd+xml", ; rel="alternate"; type="application/atom+xml", ; rel="alternate"; type="application/activity+json"
-Vary: Accept-Encoding
-X-Content-Type-Options: nosniff
-X-Xss-Protection: 1; mode=block
-
-{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","Hashtag":"as:Hashtag","ostatus":"http://ostatus.org#","atomUri":"ostatus:atomUri","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation"}],"id":"https://ap.example.com/users/foo","type":"Person","following":"https://ap.example.com/users/foo/following","followers":"https://ap.example.com/users/foo/followers","inbox":"https://ap.example.com/users/foo/inbox","outbox":"https://ap.example.com/users/foo/outbox","preferredUsername":"foo","name":"","summary":"\u003cp\u003etest\u003c/p\u003e","url":"https://ap.example.com/@foo","manuallyApprovesFollowers":false,"publicKey":{"id":"https://ap.example.com/users/foo#main-key","owner":"https://ap.example.com/users/foo","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3L4vnpNLzVH31MeWI39\n4F0wKeJFsLDAsNXGeOu0QF2x+h1zLWZw/agqD2R3JPU9/kaDJGPIV2Sn5zLyUA9S\n6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh\n8lDET6X4Pyw+ZJU0/OLo/41q9w+OrGtlsTm/PuPIeXnxa6BLqnDaxC+4IcjG/FiP\nahNCTINl/1F/TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq+t8nhQYkgAkt64euW\npva3qL5KD1mTIZQEP+LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3Qvu\nHQIDAQAB\n-----END PUBLIC KEY-----\n"},"endpoints":{"sharedInbox":"https://ap.example.com/inbox"},"icon":{"type":"Image","url":"https://quitter.no/avatar/7477-300-20160211190340.png"}}
\ No newline at end of file
diff --git a/spec/fixtures/requests/activitypub-feed.txt b/spec/fixtures/requests/activitypub-feed.txt
deleted file mode 100644
index 9d6ca22a..00000000
--- a/spec/fixtures/requests/activitypub-feed.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-HTTP/1.1 200 OK
-Cache-Control: max-age=0, private, must-revalidate
-Content-Type: application/atom+xml; charset=utf-8
-Link: ; rel="lrdd"; type="application/xrd+xml", ; rel="alternate"; type="application/atom+xml", ; rel="alternate"; type="application/activity+json"
-Vary: Accept-Encoding
-Date: Sun, 17 Sep 2017 06:33:53 GMT
-
-
-
- https://ap.example.com/users/foo.atom
- foo
- test
- 2017-09-16T18:50:09Z
- https://ap.example.com/system/accounts/avatars/000/000/001/original/141ee5846d159cba.png?1505587809
-
- https://ap.example.com/users/foo
- http://activitystrea.ms/schema/1.0/person
- https://ap.example.com/users/foo
- foo
- foo@ap.example.com
- <p>test</p>
-
-
- foo
- test
- public
-
-
-
-
-
-
- https://ap.example.com/users/foo/statuses/11076
- 2017-09-13T01:23:19Z
- 2017-09-13T01:23:19Z
- New status by foo
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- <p>test</p>
-
- public
-
-
-
-
-
diff --git a/spec/fixtures/requests/activitypub-webfinger.txt b/spec/fixtures/requests/activitypub-webfinger.txt
deleted file mode 100644
index 465066d8..00000000
--- a/spec/fixtures/requests/activitypub-webfinger.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-HTTP/1.1 200 OK
-Cache-Control: max-age=0, private, must-revalidate
-Content-Type: application/jrd+json; charset=utf-8
-X-Content-Type-Options: nosniff
-Date: Sun, 17 Sep 2017 06:22:50 GMT
-
-{"subject":"acct:foo@ap.example.com","aliases":["https://ap.example.com/@foo","https://ap.example.com/users/foo"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://ap.example.com/@foo"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://ap.example.com/users/foo.atom"},{"rel":"self","type":"application/activity+json","href":"https://ap.example.com/users/foo"},{"rel":"salmon","href":"https://ap.example.com/api/salmon/1"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA.u3L4vnpNLzVH31MeWI394F0wKeJFsLDAsNXGeOu0QF2x-h1zLWZw_agqD2R3JPU9_kaDJGPIV2Sn5zLyUA9S6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh8lDET6X4Pyw-ZJU0_OLo_41q9w-OrGtlsTm_PuPIeXnxa6BLqnDaxC-4IcjG_FiPahNCTINl_1F_TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq-t8nhQYkgAkt64euWpva3qL5KD1mTIZQEP-LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3QvuHQ==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://ap.example.com/authorize_follow?acct={uri}"}]}
\ No newline at end of file
diff --git a/spec/fixtures/requests/attachment1.txt b/spec/fixtures/requests/attachment1.txt
deleted file mode 100644
index 30bd456b..00000000
Binary files a/spec/fixtures/requests/attachment1.txt and /dev/null differ
diff --git a/spec/fixtures/requests/attachment2.txt b/spec/fixtures/requests/attachment2.txt
deleted file mode 100644
index 2a252d2d..00000000
Binary files a/spec/fixtures/requests/attachment2.txt and /dev/null differ
diff --git a/spec/fixtures/requests/avatar.txt b/spec/fixtures/requests/avatar.txt
deleted file mode 100644
index d771f5dd..00000000
Binary files a/spec/fixtures/requests/avatar.txt and /dev/null differ
diff --git a/spec/fixtures/requests/feed.txt b/spec/fixtures/requests/feed.txt
deleted file mode 100644
index fc20db56..00000000
--- a/spec/fixtures/requests/feed.txt
+++ /dev/null
@@ -1,440 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:15:03 GMT
-Content-Type: application/atom+xml; charset=utf-8
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-ETag: "ApiTimelineUser:0:en:7477:1458471931:1457967123"
-Last-Modified: Sun, 20 Mar 2016 11:05:31 +0000
-Expires: Thu, 01 Jan 1970 00:00:00 GMT
-Cache-Control: private, must-revalidate, max-age=0
-Pragma:
-X-SUP-ID: https://quitter.no/main/sup
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-
-
- GNU social
- https://quitter.no/api/statuses/user_timeline/7477.atom
- robcolbert timeline
- Updates from robcolbert on Quitter.no!
- https://quitter.no/avatar/7477-96-20160211190340.png
- 2016-03-20T12:15:03+01:00
-
- http://activitystrea.ms/schema/1.0/person
- https://quitter.no/user/7477
- robcolbert
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
-
-
-
- robcolbert
- DIGITAL CAT
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
- Germany
-
-
- homepage
- https://zeonfederated.com
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-20:noticeId=1276923:objectType=note
- New note by robcolbert
- @<a href="https://cb6e6126.ngrok.io/users/catsrgr8" class="h-card mention">catsrgr8</a> this is a mention
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-20T11:05:31+00:00
- 2016-03-20T11:05:31+00:00
-
- tag:quitter.no,2016-03-20:objectType=thread:nonce=7c998112e39a6685
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-19:noticeId=1273635:objectType=note
- New note by robcolbert
- Just testing a thing.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-19T20:35:53+00:00
- 2016-03-19T20:35:53+00:00
-
- tag:quitter.no,2016-03-19:objectType=thread:nonce=c4a61886d5cad4c2
-
-
-
-
-
-
-
- tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note
- Delete
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> deleted notice <a href="https://quitter.no/notice/1272988">{{tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note}}</a>.
-
- delete
- 2016-03-19T18:16:58+00:00
- 2016-03-19T18:16:58+00:00
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note
-
-
- tag:quitter.no,2016-03-19:objectType=thread:nonce=7913e6b6256b6d0b
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-19:noticeId=1272988:objectType=note
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-19:noticeId=1269381:objectType=comment
- New comment by robcolbert
- @<a href="https://gab.com/users/robcolbert" class="h-card mention" title="Eugen">robcolbert</a> I have to wonder if this will appear as a reply to the right status, and not just a mention.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-19T00:10:14+00:00
- 2016-03-19T00:10:14+00:00
-
-
-
- tag:quitter.no,2016-03-18:objectType=thread:nonce=d05c6330fbe23fb9
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-18:noticeId=1265337:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> Plus, Android can hardly be considered free software given how many proprietary blobs are used. I'm speaking as a disappointed Android user.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-18T10:01:50+00:00
- 2016-03-18T10:01:50+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-18:objectType=thread:nonce=d61438407b882959
-
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-18:noticeId=1265331:objectType=comment
- New comment by robcolbertrobcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> Well as it turns out, Apple software is better than Android in terms of security, and Apple is fighting FBI while Google promised to build a messaging app that facilitates wire tapping. The whole free software thing should imo be considered a bonus and not overshadow other factors.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-18T10:01:01+00:00
- 2016-03-18T10:01:01+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-18:objectType=thread:nonce=d61438407b882959
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-17:noticeId=1261358:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> @<a href="https://gs.kawa-kun.com/user/2" class="h-card mention" title="竹下憲二">takeshitakenji</a> There is a reason that was deprecated and we don't use tables to design websites anymore. HTML needs to be semantic, i.e. tags need to describe the *kind* of content, not how it should *look*, which is a responsibility delegated to CSS. There are so many upsides to this separation of concerns, should I start listing?
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-17T17:00:26+00:00
- 2016-03-17T17:00:26+00:00
-
-
-
- tag:gs.kawa-kun.com,2016-03-17:objectType=thread:nonce=a83963573a0520f1
-
-
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:24:13+01:00
- DIGITAL CAT (robcolbert)'s status on Wednesday, 16-Mar-2016 21:24:13 CET
- <a href="https://quitter.no/robcolbertrobcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:24:13+00:00
- 2016-03-16T20:24:13+00:00
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/robcolbert
- Eugen
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
-
-
-
- robcolbertrobcolbert
- Eugen
- Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=073bda8223dfcaa7
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:22:38+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:22:38+00:00
- 2016-03-16T20:22:38+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:22:38+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=b157f676181e0ecd
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:16:14+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:16:15+00:00
- 2016-03-16T20:16:15+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T21:16:14+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=6a6ebd1ed6504a11
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:13:06+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:13:06+00:00
- 2016-03-16T20:13:06+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:13:06+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbertrobcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=8f5f92443584e8f0
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:05:02+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T20:05:03+00:00
- 2016-03-16T20:05:03+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15750:2016-03-16T21:05:02+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://acda7931.ngrok.io/users/catsrgr8">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=b630d235232fcff5
-
-
-
-
-
-
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T19:04:16+01:00
-
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
- http://activitystrea.ms/schema/1.0/follow
- 2016-03-16T18:04:16+00:00
- 2016-03-16T18:04:16+00:00
-
- http://activitystrea.ms/schema/1.0/person
- tag:quitter.no,2016-03-16:subscription:7477:person:15743:2016-03-16T19:04:16+01:00
- New person by robcolbert
- <a href="https://quitter.no/robcolbert">DIGITAL CAT</a> started following <a href="https://gab.com/users/robcolbert">Eugen</a>.
-
-
-
-
- tag:quitter.no,2016-03-16:objectType=thread:nonce=40eb98e5f85c9908
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-15:noticeId=1251422:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> LGB, not LGBT?
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-15T20:28:13+00:00
- 2016-03-15T20:28:13+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-15:objectType=thread:nonce=70ff6886d69e5225
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-15:noticeId=1250742:objectType=comment
- New comment by robcolbert
- @<a href="https://social.umeahackerspace.se/user/2" class="h-card mention" title="<Mikael & Nordfeldth>">mmn</a> I'm like reeeeally close to actually deploying the first production instance of Gab Social.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-15T18:44:54+00:00
- 2016-03-15T18:44:54+00:00
-
-
-
- tag:quitter.no,2016-03-15:objectType=thread:nonce=2fbd771270b5da80
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:quitter.no,2016-03-15:noticeId=1250653:objectType=note
- New note by robcolbertrobcolbert
- @<a href="https://social.umeahackerspace.se/user/2" class="h-card mention" title="<Mikael & Nordfeldth>">mmn</a> Any progress on the issues I created?
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-15T18:27:00+00:00
- 2016-03-15T18:27:00+00:00
-
- tag:quitter.no,2016-03-15:objectType=thread:nonce=2fbd771270b5da80
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-14:noticeId=1243566:objectType=comment
- New comment by robcolbert
- @<a href="https://community.highlandarrow.com/user/1" class="h-card mention" title="Maiyannah Bishop">maiyannah</a> I heard Piwik is also good.
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-14T15:35:23+00:00
- 2016-03-14T15:35:23+00:00
-
-
-
- tag:community.highlandarrow.com,2016-03-14:objectType=thread:nonce=8fbf00e7f76866d3
-
-
-
-
-
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:quitter.no,2016-03-14:noticeId=1243331:objectType=comment
- New comment by robcolbert
- I do wish I had somebody else partake in the development process if only to give me feedback on my decisions
-
-
- http://activitystrea.ms/schema/1.0/post
- 2016-03-14T14:52:03+00:00
- 2016-03-14T14:52:03+00:00
-
-
-
- tag:quitter.no,2016-03-14:objectType=thread:nonce=46e8a2abc1839d01
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/idn.txt b/spec/fixtures/requests/idn.txt
deleted file mode 100644
index 5d07f2b7..00000000
--- a/spec/fixtures/requests/idn.txt
+++ /dev/null
@@ -1,483 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx
-Date: Sun, 23 Apr 2017 19:37:13 GMT
-Content-Type: text/html
-Content-Length: 38111
-Last-Modified: Wed, 20 Jul 2016 02:50:52 GMT
-Connection: keep-alive
-Accept-Ranges: bytes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ä¸å›½åŸŸå网站
-
-
-
-
-
-
-
-
-
-
-
-
-
å站导航
-
-
-
-
-
-
-
-
-
-
-
-
-
-
ä¸æ–‡åŸŸå简介
-
- “ä¸å›½åŸŸåâ€æ˜¯ä¸æ–‡åŸŸå的一ç§ï¼Œç‰¹æŒ‡ä»¥â€œä¸å›½â€ä¸ºåŽç¼€çš„ä¸æ–‡åŸŸå,是我国域å体系和全çƒäº’è”网域å体系的é‡è¦ç»„æˆéƒ¨åˆ†ã€‚“ä¸å›½â€æ˜¯åœ¨å…¨çƒäº’è”网上代表ä¸å›½çš„ä¸æ–‡é¡¶çº§åŸŸå,于2010å¹´7月æ£å¼çº³å…¥å…¨çƒäº’è”网域å体系,全çƒäº’è”网域å体系,全çƒç½‘æ°‘å¯é€šè¿‡è”ç½‘è®¡ç®—æœºåœ¨ä¸–ç•Œä»»ä½•å›½å®¶å’Œåœ°åŒºå®žçŽ°æ— éšœç¢è®¿é—®ã€‚“ä¸å›½â€åŸŸå在使用上和 .CN,相似属于互è”网上的基础æœåŠ¡ï¼ŒåŸºäºŽåŸŸåå¯ä»¥æä¾›WWW.EMAIL FTPç‰åº”用æœåŠ¡ã€‚
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/json-ld.activitystreams.txt b/spec/fixtures/requests/json-ld.activitystreams.txt
deleted file mode 100644
index 395797b2..00000000
--- a/spec/fixtures/requests/json-ld.activitystreams.txt
+++ /dev/null
@@ -1,391 +0,0 @@
-HTTP/1.1 200 OK
-Date: Tue, 01 May 2018 23:25:57 GMT
-Content-Location: activitystreams.jsonld
-Vary: negotiate,accept
-TCN: choice
-Last-Modified: Mon, 16 Apr 2018 00:28:23 GMT
-ETag: "1eb0-569ec4caa97c0;d3-540ee27e0eec0"
-Accept-Ranges: bytes
-Content-Length: 7856
-Cache-Control: max-age=21600
-Expires: Wed, 02 May 2018 05:25:57 GMT
-P3P: policyref="http://www.w3.org/2014/08/p3p.xml"
-Access-Control-Allow-Origin: *
-Content-Type: application/ld+json
-Strict-Transport-Security: max-age=15552000; includeSubdomains; preload
-Content-Security-Policy: upgrade-insecure-requests
-
-{
- "@context": {
- "@vocab": "_:",
- "xsd": "http://www.w3.org/2001/XMLSchema#",
- "as": "https://www.w3.org/ns/activitystreams#",
- "ldp": "http://www.w3.org/ns/ldp#",
- "id": "@id",
- "type": "@type",
- "Accept": "as:Accept",
- "Activity": "as:Activity",
- "IntransitiveActivity": "as:IntransitiveActivity",
- "Add": "as:Add",
- "Announce": "as:Announce",
- "Application": "as:Application",
- "Arrive": "as:Arrive",
- "Article": "as:Article",
- "Audio": "as:Audio",
- "Block": "as:Block",
- "Collection": "as:Collection",
- "CollectionPage": "as:CollectionPage",
- "Relationship": "as:Relationship",
- "Create": "as:Create",
- "Delete": "as:Delete",
- "Dislike": "as:Dislike",
- "Document": "as:Document",
- "Event": "as:Event",
- "Follow": "as:Follow",
- "Flag": "as:Flag",
- "Group": "as:Group",
- "Ignore": "as:Ignore",
- "Image": "as:Image",
- "Invite": "as:Invite",
- "Join": "as:Join",
- "Leave": "as:Leave",
- "Like": "as:Like",
- "Link": "as:Link",
- "Mention": "as:Mention",
- "Note": "as:Note",
- "Object": "as:Object",
- "Offer": "as:Offer",
- "OrderedCollection": "as:OrderedCollection",
- "OrderedCollectionPage": "as:OrderedCollectionPage",
- "Organization": "as:Organization",
- "Page": "as:Page",
- "Person": "as:Person",
- "Place": "as:Place",
- "Profile": "as:Profile",
- "Question": "as:Question",
- "Reject": "as:Reject",
- "Remove": "as:Remove",
- "Service": "as:Service",
- "TentativeAccept": "as:TentativeAccept",
- "TentativeReject": "as:TentativeReject",
- "Tombstone": "as:Tombstone",
- "Undo": "as:Undo",
- "Update": "as:Update",
- "Video": "as:Video",
- "View": "as:View",
- "Listen": "as:Listen",
- "Read": "as:Read",
- "Move": "as:Move",
- "Travel": "as:Travel",
- "IsFollowing": "as:IsFollowing",
- "IsFollowedBy": "as:IsFollowedBy",
- "IsContact": "as:IsContact",
- "IsMember": "as:IsMember",
- "subject": {
- "@id": "as:subject",
- "@type": "@id"
- },
- "relationship": {
- "@id": "as:relationship",
- "@type": "@id"
- },
- "actor": {
- "@id": "as:actor",
- "@type": "@id"
- },
- "attributedTo": {
- "@id": "as:attributedTo",
- "@type": "@id"
- },
- "attachment": {
- "@id": "as:attachment",
- "@type": "@id"
- },
- "bcc": {
- "@id": "as:bcc",
- "@type": "@id"
- },
- "bto": {
- "@id": "as:bto",
- "@type": "@id"
- },
- "cc": {
- "@id": "as:cc",
- "@type": "@id"
- },
- "context": {
- "@id": "as:context",
- "@type": "@id"
- },
- "current": {
- "@id": "as:current",
- "@type": "@id"
- },
- "first": {
- "@id": "as:first",
- "@type": "@id"
- },
- "generator": {
- "@id": "as:generator",
- "@type": "@id"
- },
- "icon": {
- "@id": "as:icon",
- "@type": "@id"
- },
- "image": {
- "@id": "as:image",
- "@type": "@id"
- },
- "inReplyTo": {
- "@id": "as:inReplyTo",
- "@type": "@id"
- },
- "items": {
- "@id": "as:items",
- "@type": "@id"
- },
- "instrument": {
- "@id": "as:instrument",
- "@type": "@id"
- },
- "orderedItems": {
- "@id": "as:items",
- "@type": "@id",
- "@container": "@list"
- },
- "last": {
- "@id": "as:last",
- "@type": "@id"
- },
- "location": {
- "@id": "as:location",
- "@type": "@id"
- },
- "next": {
- "@id": "as:next",
- "@type": "@id"
- },
- "object": {
- "@id": "as:object",
- "@type": "@id"
- },
- "oneOf": {
- "@id": "as:oneOf",
- "@type": "@id"
- },
- "anyOf": {
- "@id": "as:anyOf",
- "@type": "@id"
- },
- "closed": {
- "@id": "as:closed",
- "@type": "xsd:dateTime"
- },
- "origin": {
- "@id": "as:origin",
- "@type": "@id"
- },
- "accuracy": {
- "@id": "as:accuracy",
- "@type": "xsd:float"
- },
- "prev": {
- "@id": "as:prev",
- "@type": "@id"
- },
- "preview": {
- "@id": "as:preview",
- "@type": "@id"
- },
- "replies": {
- "@id": "as:replies",
- "@type": "@id"
- },
- "result": {
- "@id": "as:result",
- "@type": "@id"
- },
- "audience": {
- "@id": "as:audience",
- "@type": "@id"
- },
- "partOf": {
- "@id": "as:partOf",
- "@type": "@id"
- },
- "tag": {
- "@id": "as:tag",
- "@type": "@id"
- },
- "target": {
- "@id": "as:target",
- "@type": "@id"
- },
- "to": {
- "@id": "as:to",
- "@type": "@id"
- },
- "url": {
- "@id": "as:url",
- "@type": "@id"
- },
- "altitude": {
- "@id": "as:altitude",
- "@type": "xsd:float"
- },
- "content": "as:content",
- "contentMap": {
- "@id": "as:content",
- "@container": "@language"
- },
- "name": "as:name",
- "nameMap": {
- "@id": "as:name",
- "@container": "@language"
- },
- "duration": {
- "@id": "as:duration",
- "@type": "xsd:duration"
- },
- "endTime": {
- "@id": "as:endTime",
- "@type": "xsd:dateTime"
- },
- "height": {
- "@id": "as:height",
- "@type": "xsd:nonNegativeInteger"
- },
- "href": {
- "@id": "as:href",
- "@type": "@id"
- },
- "hreflang": "as:hreflang",
- "latitude": {
- "@id": "as:latitude",
- "@type": "xsd:float"
- },
- "longitude": {
- "@id": "as:longitude",
- "@type": "xsd:float"
- },
- "mediaType": "as:mediaType",
- "published": {
- "@id": "as:published",
- "@type": "xsd:dateTime"
- },
- "radius": {
- "@id": "as:radius",
- "@type": "xsd:float"
- },
- "rel": "as:rel",
- "startIndex": {
- "@id": "as:startIndex",
- "@type": "xsd:nonNegativeInteger"
- },
- "startTime": {
- "@id": "as:startTime",
- "@type": "xsd:dateTime"
- },
- "summary": "as:summary",
- "summaryMap": {
- "@id": "as:summary",
- "@container": "@language"
- },
- "totalItems": {
- "@id": "as:totalItems",
- "@type": "xsd:nonNegativeInteger"
- },
- "units": "as:units",
- "updated": {
- "@id": "as:updated",
- "@type": "xsd:dateTime"
- },
- "width": {
- "@id": "as:width",
- "@type": "xsd:nonNegativeInteger"
- },
- "describes": {
- "@id": "as:describes",
- "@type": "@id"
- },
- "formerType": {
- "@id": "as:formerType",
- "@type": "@id"
- },
- "deleted": {
- "@id": "as:deleted",
- "@type": "xsd:dateTime"
- },
- "inbox": {
- "@id": "ldp:inbox",
- "@type": "@id"
- },
- "outbox": {
- "@id": "as:outbox",
- "@type": "@id"
- },
- "following": {
- "@id": "as:following",
- "@type": "@id"
- },
- "followers": {
- "@id": "as:followers",
- "@type": "@id"
- },
- "streams": {
- "@id": "as:streams",
- "@type": "@id"
- },
- "preferredUsername": "as:preferredUsername",
- "endpoints": {
- "@id": "as:endpoints",
- "@type": "@id"
- },
- "uploadMedia": {
- "@id": "as:uploadMedia",
- "@type": "@id"
- },
- "proxyUrl": {
- "@id": "as:proxyUrl",
- "@type": "@id"
- },
- "liked": {
- "@id": "as:liked",
- "@type": "@id"
- },
- "oauthAuthorizationEndpoint": {
- "@id": "as:oauthAuthorizationEndpoint",
- "@type": "@id"
- },
- "oauthTokenEndpoint": {
- "@id": "as:oauthTokenEndpoint",
- "@type": "@id"
- },
- "provideClientKey": {
- "@id": "as:provideClientKey",
- "@type": "@id"
- },
- "signClientKey": {
- "@id": "as:signClientKey",
- "@type": "@id"
- },
- "sharedInbox": {
- "@id": "as:sharedInbox",
- "@type": "@id"
- },
- "Public": {
- "@id": "as:Public",
- "@type": "@id"
- },
- "source": "as:source",
- "likes": {
- "@id": "as:likes",
- "@type": "@id"
- },
- "shares": {
- "@id": "as:shares",
- "@type": "@id"
- }
- }
-}
diff --git a/spec/fixtures/requests/json-ld.identity.txt b/spec/fixtures/requests/json-ld.identity.txt
deleted file mode 100644
index 8810526c..00000000
--- a/spec/fixtures/requests/json-ld.identity.txt
+++ /dev/null
@@ -1,100 +0,0 @@
-HTTP/1.1 200 OK
-Accept-Ranges: bytes
-Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept-Encoding
-Access-Control-Allow-Origin: *
-Content-Type: application/ld+json
-Date: Tue, 01 May 2018 23:28:21 GMT
-Etag: "e26-547a6fc75b04a-gzip"
-Last-Modified: Fri, 03 Feb 2017 21:30:09 GMT
-Server: Apache/2.4.7 (Ubuntu)
-Vary: Accept-Encoding
-Transfer-Encoding: chunked
-
-{
- "@context": {
- "id": "@id",
- "type": "@type",
-
- "cred": "https://w3id.org/credentials#",
- "dc": "http://purl.org/dc/terms/",
- "identity": "https://w3id.org/identity#",
- "perm": "https://w3id.org/permissions#",
- "ps": "https://w3id.org/payswarm#",
- "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
- "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
- "sec": "https://w3id.org/security#",
- "schema": "http://schema.org/",
- "xsd": "http://www.w3.org/2001/XMLSchema#",
-
- "Group": "https://www.w3.org/ns/activitystreams#Group",
-
- "claim": {"@id": "cred:claim", "@type": "@id"},
- "credential": {"@id": "cred:credential", "@type": "@id"},
- "issued": {"@id": "cred:issued", "@type": "xsd:dateTime"},
- "issuer": {"@id": "cred:issuer", "@type": "@id"},
- "recipient": {"@id": "cred:recipient", "@type": "@id"},
- "Credential": "cred:Credential",
- "CryptographicKeyCredential": "cred:CryptographicKeyCredential",
-
- "about": {"@id": "schema:about", "@type": "@id"},
- "address": {"@id": "schema:address", "@type": "@id"},
- "addressCountry": "schema:addressCountry",
- "addressLocality": "schema:addressLocality",
- "addressRegion": "schema:addressRegion",
- "comment": "rdfs:comment",
- "created": {"@id": "dc:created", "@type": "xsd:dateTime"},
- "creator": {"@id": "dc:creator", "@type": "@id"},
- "description": "schema:description",
- "email": "schema:email",
- "familyName": "schema:familyName",
- "givenName": "schema:givenName",
- "image": {"@id": "schema:image", "@type": "@id"},
- "label": "rdfs:label",
- "name": "schema:name",
- "postalCode": "schema:postalCode",
- "streetAddress": "schema:streetAddress",
- "title": "dc:title",
- "url": {"@id": "schema:url", "@type": "@id"},
- "Person": "schema:Person",
- "PostalAddress": "schema:PostalAddress",
- "Organization": "schema:Organization",
-
- "identityService": {"@id": "identity:identityService", "@type": "@id"},
- "idp": {"@id": "identity:idp", "@type": "@id"},
- "Identity": "identity:Identity",
-
- "paymentProcessor": "ps:processor",
- "preferences": {"@id": "ps:preferences", "@type": "@vocab"},
-
- "cipherAlgorithm": "sec:cipherAlgorithm",
- "cipherData": "sec:cipherData",
- "cipherKey": "sec:cipherKey",
- "digestAlgorithm": "sec:digestAlgorithm",
- "digestValue": "sec:digestValue",
- "domain": "sec:domain",
- "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"},
- "initializationVector": "sec:initializationVector",
- "member": {"@id": "schema:member", "@type": "@id"},
- "memberOf": {"@id": "schema:memberOf", "@type": "@id"},
- "nonce": "sec:nonce",
- "normalizationAlgorithm": "sec:normalizationAlgorithm",
- "owner": {"@id": "sec:owner", "@type": "@id"},
- "password": "sec:password",
- "privateKey": {"@id": "sec:privateKey", "@type": "@id"},
- "privateKeyPem": "sec:privateKeyPem",
- "publicKey": {"@id": "sec:publicKey", "@type": "@id"},
- "publicKeyPem": "sec:publicKeyPem",
- "publicKeyService": {"@id": "sec:publicKeyService", "@type": "@id"},
- "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"},
- "signature": "sec:signature",
- "signatureAlgorithm": "sec:signatureAlgorithm",
- "signatureValue": "sec:signatureValue",
- "CryptographicKey": "sec:Key",
- "EncryptedMessage": "sec:EncryptedMessage",
- "GraphSignature2012": "sec:GraphSignature2012",
- "LinkedDataSignature2015": "sec:LinkedDataSignature2015",
-
- "accessControl": {"@id": "perm:accessControl", "@type": "@id"},
- "writePermission": {"@id": "perm:writePermission", "@type": "@id"}
- }
-}
diff --git a/spec/fixtures/requests/json-ld.security.txt b/spec/fixtures/requests/json-ld.security.txt
deleted file mode 100644
index 0d29903e..00000000
--- a/spec/fixtures/requests/json-ld.security.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-HTTP/1.1 200 OK
-Accept-Ranges: bytes
-Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept-Encoding
-Access-Control-Allow-Origin: *
-Content-Type: application/ld+json
-Date: Wed, 02 May 2018 16:25:32 GMT
-Etag: "7e3-5651ec0f7c5ed-gzip"
-Last-Modified: Tue, 13 Feb 2018 21:34:04 GMT
-Server: Apache/2.4.7 (Ubuntu)
-Vary: Accept-Encoding
-Content-Length: 2019
-
-{
- "@context": {
- "id": "@id",
- "type": "@type",
-
- "dc": "http://purl.org/dc/terms/",
- "sec": "https://w3id.org/security#",
- "xsd": "http://www.w3.org/2001/XMLSchema#",
-
- "EcdsaKoblitzSignature2016": "sec:EcdsaKoblitzSignature2016",
- "Ed25519Signature2018": "sec:Ed25519Signature2018",
- "EncryptedMessage": "sec:EncryptedMessage",
- "GraphSignature2012": "sec:GraphSignature2012",
- "LinkedDataSignature2015": "sec:LinkedDataSignature2015",
- "LinkedDataSignature2016": "sec:LinkedDataSignature2016",
- "CryptographicKey": "sec:Key",
-
- "authenticationTag": "sec:authenticationTag",
- "canonicalizationAlgorithm": "sec:canonicalizationAlgorithm",
- "cipherAlgorithm": "sec:cipherAlgorithm",
- "cipherData": "sec:cipherData",
- "cipherKey": "sec:cipherKey",
- "created": {"@id": "dc:created", "@type": "xsd:dateTime"},
- "creator": {"@id": "dc:creator", "@type": "@id"},
- "digestAlgorithm": "sec:digestAlgorithm",
- "digestValue": "sec:digestValue",
- "domain": "sec:domain",
- "encryptionKey": "sec:encryptionKey",
- "expiration": {"@id": "sec:expiration", "@type": "xsd:dateTime"},
- "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"},
- "initializationVector": "sec:initializationVector",
- "iterationCount": "sec:iterationCount",
- "nonce": "sec:nonce",
- "normalizationAlgorithm": "sec:normalizationAlgorithm",
- "owner": {"@id": "sec:owner", "@type": "@id"},
- "password": "sec:password",
- "privateKey": {"@id": "sec:privateKey", "@type": "@id"},
- "privateKeyPem": "sec:privateKeyPem",
- "publicKey": {"@id": "sec:publicKey", "@type": "@id"},
- "publicKeyBase58": "sec:publicKeyBase58",
- "publicKeyPem": "sec:publicKeyPem",
- "publicKeyService": {"@id": "sec:publicKeyService", "@type": "@id"},
- "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"},
- "salt": "sec:salt",
- "signature": "sec:signature",
- "signatureAlgorithm": "sec:signingAlgorithm",
- "signatureValue": "sec:signatureValue"
- }
-}
diff --git a/spec/fixtures/requests/koi8-r.txt b/spec/fixtures/requests/koi8-r.txt
deleted file mode 100644
index d4242af0..00000000
--- a/spec/fixtures/requests/koi8-r.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.11.10
-Date: Tue, 04 Jul 2017 16:43:39 GMT
-Content-Type: text/html
-Content-Length: 273
-Connection: keep-alive
-Last-Modified: Tue, 04 Jul 2017 16:41:34 GMT
-Accept-Ranges: bytes
-
-
-
-
-
- íÏÓËÏ×Ñ ÎÁÞÉÎÁÅÔß ÔÏÌØËÏ ×ß XVI ÓÔ. ÐÒÉ×ÌÅËÁÔØ ×ÎÉÍÁÎÅ ÉÎÏÓÔÒÁÎÃÅ×ß.
-
-
-
íÏÓËÏ×Ñ ÎÁÞÉÎÁÅÔß ÔÏÌØËÏ ×ß XVI ÓÔ. ÐÒÉ×ÌÅËÁÔØ ×ÎÉÍÁÎÅ ÉÎÏÓÔÒÁÎÃÅ×ß.
-
-
-
diff --git a/spec/fixtures/requests/localdomain-feed.txt b/spec/fixtures/requests/localdomain-feed.txt
deleted file mode 100644
index 03aa492f..00000000
--- a/spec/fixtures/requests/localdomain-feed.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-HTTP/1.1 200 OK
-Date: Thu, 20 Apr 2017 07:36:08 GMT
-Content-Type: application/atom+xml; charset=utf-8
-Transfer-Encoding: chunked
-Connection: keep-alive
-Server: GabSocial
-X-Frame-Options: DENY
-X-Content-Type-Options: nosniff
-X-XSS-Protection: 1; mode=block
-Link: ; rel="lrdd"; type="application/xrd+xml", ; rel="alternate"; type="application/atom+xml"
-Vary: Accept-Encoding
-ETag: W/"1fa54baac599205a1e54c136dea2b671"
-Cache-Control: max-age=0, private, must-revalidate
-Set-Cookie: _gabsocial_session=Vk5XbERyQ0NscjJhdEw1eVEyY3JwQTlBVThObUJ1N3NFcVlJaCtpNU5FSmZlTzFIZ2FqSzhVY1lneFlLQ1haNkh1SDM5L0FSdnFLTGwwTnhJMy9qWWI5aWRnM1NOU1NLTmtuamR5cG5Ebm8vekFNL20ydGkxYXFXU2FwVTF1NnctLXdxdFhNVFA2VmlFVm5BY25QU2N1clE9PQ%3D%3D--47e86fed56f94d3998bfc3837af8de93ec8c104e; path=/; secure; HttpOnly
-X-Request-Id: 071ec889-04fb-4efa-b55e-81eb90772b50
-X-Runtime: 1.173933
-Strict-Transport-Security: max-age=31536000; includeSubDomains
-
-
-
- https://webdomain.com/users/foo.atom
- foo
- foo
- 2017-04-08T15:38:58Z
- https://quitter.no/avatar/7477-300-20160211190340.png
-
- https://webdomain.com/users/foo
- http://activitystrea.ms/schema/1.0/person
- https://webdomain.com/users/foo
- foo
- foo@localdomain.com
- foo
-
-
- foo
- foo
- foo
- public
-
-
-
-
-
-
- tag:localdomain.com,2017-04-19:objectId=12774:objectType=Status
- 2017-04-19T22:28:01Z
- 2017-04-19T22:28:01Z
- New status by foo
- http://activitystrea.ms/schema/1.0/comment
- http://activitystrea.ms/schema/1.0/post
- <p>Meh, ça foire l'attribution des boosts.<br />Faudra que je corrige ça…</p>
- unlisted
-
-
-
-
-
diff --git a/spec/fixtures/requests/localdomain-hostmeta.txt b/spec/fixtures/requests/localdomain-hostmeta.txt
deleted file mode 100644
index 0639d6f9..00000000
--- a/spec/fixtures/requests/localdomain-hostmeta.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:11:00 GMT
-Content-Type: application/xrd+xml
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-
-
-
-
diff --git a/spec/fixtures/requests/localdomain-webfinger.txt b/spec/fixtures/requests/localdomain-webfinger.txt
deleted file mode 100644
index 6c2a366a..00000000
--- a/spec/fixtures/requests/localdomain-webfinger.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:11:00 GMT
-Content-Type: application/xrd+xml
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-
-
- acct:foo@localdomain.com
- https://webdomain.com/@foo
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/oembed_invalid_xml.html b/spec/fixtures/requests/oembed_invalid_xml.html
deleted file mode 100644
index 405834f1..00000000
--- a/spec/fixtures/requests/oembed_invalid_xml.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/oembed_json.html b/spec/fixtures/requests/oembed_json.html
deleted file mode 100644
index 16708587..00000000
--- a/spec/fixtures/requests/oembed_json.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/oembed_json_empty.html b/spec/fixtures/requests/oembed_json_empty.html
deleted file mode 100644
index 4b02413a..00000000
--- a/spec/fixtures/requests/oembed_json_empty.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/oembed_json_xml.html b/spec/fixtures/requests/oembed_json_xml.html
deleted file mode 100644
index 9f5b9e8b..00000000
--- a/spec/fixtures/requests/oembed_json_xml.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/oembed_undiscoverable.html b/spec/fixtures/requests/oembed_undiscoverable.html
deleted file mode 100644
index a4acdc47..00000000
--- a/spec/fixtures/requests/oembed_undiscoverable.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/spec/fixtures/requests/oembed_xml.html b/spec/fixtures/requests/oembed_xml.html
deleted file mode 100644
index 788dfaab..00000000
--- a/spec/fixtures/requests/oembed_xml.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/redirected.host-meta.txt b/spec/fixtures/requests/redirected.host-meta.txt
deleted file mode 100644
index a4f731b0..00000000
--- a/spec/fixtures/requests/redirected.host-meta.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:11:00 GMT
-Content-Type: application/xrd+xml
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-
-
-
-
-
diff --git a/spec/fixtures/requests/sjis.txt b/spec/fixtures/requests/sjis.txt
deleted file mode 100644
index faf18d35..00000000
--- a/spec/fixtures/requests/sjis.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.11.10
-Date: Tue, 04 Jul 2017 16:43:39 GMT
-Content-Type: text/html
-Content-Length: 273
-Connection: keep-alive
-Last-Modified: Tue, 04 Jul 2017 16:41:34 GMT
-Accept-Ranges: bytes
-
-
-
-
-
- SJIS‚̃y[ƒW
-
-
-
Ž„‚à“¯”N‚Ü‚µ‚Ä‚¢‚í‚ä‚é‹L”Ol‚Á‚Ä‚à‚Ì‚ÌŽž‚Å‚µ‚ ‚è‚Å‚·B‚à‚µŽžŠÔ‚ɈӖ¡ŽÒ‚ͳ‚µ‚‚Ç‚ñ‚È”‰ï‚Ü‚¹‚¾‚Ü‚Å‚ª\‚µã‚°‚ª‚¢‚ç‚Á‚µ‚á‚邽‚É‚ÍŽQl‹A‚邽‚¢‚¾‚©‚çA‚µ‚É‚à‚â‚Á‚ ‚Á‚Ü‚µ‚È‚½B‹à‚©‚ç‚¢‚¤‚È‚¢‚Ì‚Í‚Ç‚¤‚à‹ãŒŽ‚ð‚Å‚«‚邾‚¯‚½‚½‚‚½B‚¯‚Á‚µ‚ĉª“c‚³‚ñ‚É”½RK‚µ’¥‚ɉ]‚¨‚Å‚µ‚å‹à—Í‚±‚¤‚µ‚½Œ —Í‚ ‚È‚½‚©Žw}‚ª‚Æ‚¢‚¤‚¨o“ü‚è‚È‚‚¾‚ë‚È‚ ‚è‚ÄA‚»‚ÌÌ‚ÍŽ„‚©‹à—͉A‚ð“{‚ç‚©‚çA‹vŒ´‚³‚ñ‚Ì‚à‚Ì‚ð‚ª‚½‚Ì‚¢‚‚ª‚µ‚©‚é‚É‚²Šó–]‚ÆŒü‚¢‚΂»‚êman‚É‚²–µ‚‚ÖŽQ‚è‚悤‚É“¯Žž‚É‚²‰‰à‚ª‚µ‚Å‚È‚ç‚Ì‚ÅA‘½•ª‚à‚µ•\— ‚É•Ï‚Á‚½‚Ä‚‚ê‚Å‚·Ž–‚Ål‚¦‚½‚½B‚µ‚©‚à—Ⴆ‚΂²‚ª‚½‚ª‚Æ‚Ç‚Ü‚ç‚à‚Ì‚àŽÀÛ‚Þ‚â‚Ý‚Æ‚ ‚è‚Å‚·‚ÄA‚±‚ÌŽ©•ª‚Å‚Í\‚µ‚ñ‚Ä‚Æ‚µ‚Ä¢ŠÔ‚É•À‚ׂ̂És‚©‚È‚©‚Á‚ÈB
-
-
-
diff --git a/spec/fixtures/requests/sjis_with_wrong_charset.txt b/spec/fixtures/requests/sjis_with_wrong_charset.txt
deleted file mode 100644
index 456750c6..00000000
--- a/spec/fixtures/requests/sjis_with_wrong_charset.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.11.10
-Date: Tue, 04 Jul 2017 16:43:39 GMT
-Content-Type: text/html; charset=utf-8
-Content-Length: 273
-Connection: keep-alive
-Last-Modified: Tue, 04 Jul 2017 16:41:34 GMT
-Accept-Ranges: bytes
-
-
-
-
-
- SJIS‚̃y[ƒW
-
-
-
Ž„‚à“¯”N‚Ü‚µ‚Ä‚¢‚í‚ä‚é‹L”Ol‚Á‚Ä‚à‚Ì‚ÌŽž‚Å‚µ‚ ‚è‚Å‚·B‚à‚µŽžŠÔ‚ɈӖ¡ŽÒ‚ͳ‚µ‚‚Ç‚ñ‚È”‰ï‚Ü‚¹‚¾‚Ü‚Å‚ª\‚µã‚°‚ª‚¢‚ç‚Á‚µ‚á‚邽‚É‚ÍŽQl‹A‚邽‚¢‚¾‚©‚çA‚µ‚É‚à‚â‚Á‚ ‚Á‚Ü‚µ‚È‚½B‹à‚©‚ç‚¢‚¤‚È‚¢‚Ì‚Í‚Ç‚¤‚à‹ãŒŽ‚ð‚Å‚«‚邾‚¯‚½‚½‚‚½B‚¯‚Á‚µ‚ĉª“c‚³‚ñ‚É”½RK‚µ’¥‚ɉ]‚¨‚Å‚µ‚å‹à—Í‚±‚¤‚µ‚½Œ —Í‚ ‚È‚½‚©Žw}‚ª‚Æ‚¢‚¤‚¨o“ü‚è‚È‚‚¾‚ë‚È‚ ‚è‚ÄA‚»‚ÌÌ‚ÍŽ„‚©‹à—͉A‚ð“{‚ç‚©‚çA‹vŒ´‚³‚ñ‚Ì‚à‚Ì‚ð‚ª‚½‚Ì‚¢‚‚ª‚µ‚©‚é‚É‚²Šó–]‚ÆŒü‚¢‚΂»‚êman‚É‚²–µ‚‚ÖŽQ‚è‚悤‚É“¯Žž‚É‚²‰‰à‚ª‚µ‚Å‚È‚ç‚Ì‚ÅA‘½•ª‚à‚µ•\— ‚É•Ï‚Á‚½‚Ä‚‚ê‚Å‚·Ž–‚Ål‚¦‚½‚½B‚µ‚©‚à—Ⴆ‚΂²‚ª‚½‚ª‚Æ‚Ç‚Ü‚ç‚à‚Ì‚àŽÀÛ‚Þ‚â‚Ý‚Æ‚ ‚è‚Å‚·‚ÄA‚±‚ÌŽ©•ª‚Å‚Í\‚µ‚ñ‚Ä‚Æ‚µ‚Ä¢ŠÔ‚É•À‚ׂ̂És‚©‚È‚©‚Á‚ÈB
-
-
-
diff --git a/spec/fixtures/requests/webfinger-hacker1.txt b/spec/fixtures/requests/webfinger-hacker1.txt
deleted file mode 100644
index 3752b0a7..00000000
--- a/spec/fixtures/requests/webfinger-hacker1.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:13:16 GMT
-Content-Type: application/jrd+json
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-{"subject":"acct:robcolbert@quitter.no","aliases":["https:\/\/quitter.no\/user\/7477","https:\/\/quitter.no\/robcolbert","https:\/\/quitter.no\/index.php\/user\/7477","https:\/\/quitter.no\/index.php\/robcolbert"],"links":[{"rel":"http:\/\/webfinger.net\/rel\/profile-page","type":"text\/html","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"http:\/\/gmpg.org\/xfn\/11","type":"text\/html","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"describedby","type":"application\/rdf+xml","href":"https:\/\/quitter.no\/robcolbert\/foaf"},{"rel":"http:\/\/apinamespace.org\/atom","type":"application\/atomsvc+xml","href":"https:\/\/quitter.no\/api\/statusnet\/app\/service\/robcolbert.xml"},{"rel":"http:\/\/apinamespace.org\/twitter","href":"https:\/\/quitter.no\/api\/"},{"rel":"http:\/\/specs.openid.net\/auth\/2.0\/provider","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"http:\/\/schemas.google.com\/g\/2010#updates-from","type":"application\/atom+xml","href":"https:\/\/quitter.no\/api\/statuses\/user_timeline\/7477.atom"},{"rel":"magic-public-key","href":"data:application\/magic-public-key,RSA.1ZBkHTavLvxH3FzlKv4O6WtlILKRFfNami3_Rcu8EuogtXSYiS-bB6hElZfUCSHbC4uLemOA34PEhz__CDMozax1iI_t8dzjDnh1x0iFSup7pSfW9iXk_WU3Dm74yWWW2jildY41vWgrEstuQ1dJ8vVFfSJ9T_tO4c-T9y8vDI8=.AQAB"},{"rel":"salmon","href":"https:\/\/hacker.com\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-replies","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-mention","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/ostatus.org\/schema\/1.0\/subscribe","template":"https:\/\/quitter.no\/main\/ostatussub?profile={uri}"}]}
diff --git a/spec/fixtures/requests/webfinger-hacker2.txt b/spec/fixtures/requests/webfinger-hacker2.txt
deleted file mode 100644
index 09d1a206..00000000
--- a/spec/fixtures/requests/webfinger-hacker2.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:13:16 GMT
-Content-Type: application/jrd+json
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-{"subject":"acct:catsrgr8@quitter.no","aliases":["https:\/\/quitter.no\/user\/7477","https:\/\/quitter.no\/robcolbert","https:\/\/quitter.no\/index.php\/user\/7477","https:\/\/quitter.no\/index.php\/robcolbert"],"links":[{"rel":"http:\/\/webfinger.net\/rel\/profile-page","type":"text\/html","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"http:\/\/gmpg.org\/xfn\/11","type":"text\/html","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"describedby","type":"application\/rdf+xml","href":"https:\/\/quitter.no\/robcolbert\/foaf"},{"rel":"http:\/\/apinamespace.org\/atom","type":"application\/atomsvc+xml","href":"https:\/\/quitter.no\/api\/statusnet\/app\/service\/robcolbert.xml"},{"rel":"http:\/\/apinamespace.org\/twitter","href":"https:\/\/quitter.no\/api\/"},{"rel":"http:\/\/specs.openid.net\/auth\/2.0\/provider","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"http:\/\/schemas.google.com\/g\/2010#updates-from","type":"application\/atom+xml","href":"https:\/\/quitter.no\/api\/statuses\/user_timeline\/7477.atom"},{"rel":"magic-public-key","href":"data:application\/magic-public-key,RSA.1ZBkHTavLvxH3FzlKv4O6WtlILKRFfNami3_Rcu8EuogtXSYiS-bB6hElZfUCSHbC4uLemOA34PEhz__CDMozax1iI_t8dzjDnh1x0iFSup7pSfW9iXk_WU3Dm74yWWW2jildY41vWgrEstuQ1dJ8vVFfSJ9T_tO4c-T9y8vDI8=.AQAB"},{"rel":"salmon","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-replies","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-mention","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/ostatus.org\/schema\/1.0\/subscribe","template":"https:\/\/quitter.no\/main\/ostatussub?profile={uri}"}]}
diff --git a/spec/fixtures/requests/webfinger-hacker3.txt b/spec/fixtures/requests/webfinger-hacker3.txt
deleted file mode 100644
index 7e508d3b..00000000
--- a/spec/fixtures/requests/webfinger-hacker3.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:13:16 GMT
-Content-Type: application/jrd+json
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-{"subject":"acct:localhost@kickass.zone","aliases":["https:\/\/kickass.zone\/user\/7477","https:\/\/kickass.zone\/robcolbert","https:\/\/kickass.zone\/index.php\/user\/7477","https:\/\/kickass.zone\/index.php\/robcolbert"],"links":[{"rel":"http:\/\/webfinger.net\/rel\/profile-page","type":"text\/html","href":"https:\/\/kickass.zone\/robcolbert"},{"rel":"http:\/\/gmpg.org\/xfn\/11","type":"text\/html","href":"https:\/\/kickass.zone\/robcolbert"},{"rel":"describedby","type":"application\/rdf+xml","href":"https:\/\/kickass.zone\/robcolbert\/foaf"},{"rel":"http:\/\/apinamespace.org\/atom","type":"application\/atomsvc+xml","href":"https:\/\/kickass.zone\/api\/statusnet\/app\/service\/robcolbert.xml"},{"rel":"http:\/\/apinamespace.org\/twitter","href":"https:\/\/kickass.zone\/api\/"},{"rel":"http:\/\/specs.openid.net\/auth\/2.0\/provider","href":"https:\/\/kickass.zone\/robcolbert"},{"rel":"http:\/\/schemas.google.com\/g\/2010#updates-from","type":"application\/atom+xml","href":"https:\/\/kickass.zone\/api\/statuses\/user_timeline\/7477.atom"},{"rel":"magic-public-key","href":"data:application\/magic-public-key,RSA.1ZBkHTavLvxH3FzlKv4O6WtlILKRFfNami3_Rcu8EuogtXSYiS-bB6hElZfUCSHbC4uLemOA34PEhz__CDMozax1iI_t8dzjDnh1x0iFSup7pSfW9iXk_WU3Dm74yWWW2jildY41vWgrEstuQ1dJ8vVFfSJ9T_tO4c-T9y8vDI8=.AQAB"},{"rel":"salmon","href":"https:\/\/kickass.zone\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-replies","href":"https:\/\/kickass.zone\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-mention","href":"https:\/\/kickass.zone\/main\/salmon\/user\/7477"},{"rel":"http:\/\/ostatus.org\/schema\/1.0\/subscribe","template":"https:\/\/kickass.zone\/main\/ostatussub?profile={uri}"}]}
diff --git a/spec/fixtures/requests/webfinger.txt b/spec/fixtures/requests/webfinger.txt
deleted file mode 100644
index d988c000..00000000
--- a/spec/fixtures/requests/webfinger.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-HTTP/1.1 200 OK
-Server: nginx/1.6.2
-Date: Sun, 20 Mar 2016 11:13:16 GMT
-Content-Type: application/jrd+json
-Transfer-Encoding: chunked
-Connection: keep-alive
-Access-Control-Allow-Origin: *
-Vary: Accept-Encoding,Cookie
-Strict-Transport-Security: max-age=31536000; includeSubdomains;
-
-{"subject":"acct:robcolbert@quitter.no","aliases":["https:\/\/quitter.no\/user\/7477","https:\/\/quitter.no\/robcolbert","https:\/\/quitter.no\/index.php\/user\/7477","https:\/\/quitter.no\/index.php\/robcolbert"],"links":[{"rel":"http:\/\/webfinger.net\/rel\/profile-page","type":"text\/html","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"http:\/\/gmpg.org\/xfn\/11","type":"text\/html","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"describedby","type":"application\/rdf+xml","href":"https:\/\/quitter.no\/robcolbert\/foaf"},{"rel":"http:\/\/apinamespace.org\/atom","type":"application\/atomsvc+xml","href":"https:\/\/quitter.no\/api\/statusnet\/app\/service\/robcolbert.xml"},{"rel":"http:\/\/apinamespace.org\/twitter","href":"https:\/\/quitter.no\/api\/"},{"rel":"http:\/\/specs.openid.net\/auth\/2.0\/provider","href":"https:\/\/quitter.no\/robcolbert"},{"rel":"http:\/\/schemas.google.com\/g\/2010#updates-from","type":"application\/atom+xml","href":"https:\/\/quitter.no\/api\/statuses\/user_timeline\/7477.atom"},{"rel":"magic-public-key","href":"data:application\/magic-public-key,RSA.1ZBkHTavLvxH3FzlKv4O6WtlILKRFfNami3_Rcu8EuogtXSYiS-bB6hElZfUCSHbC4uLemOA34PEhz__CDMozax1iI_t8dzjDnh1x0iFSup7pSfW9iXk_WU3Dm74yWWW2jildY41vWgrEstuQ1dJ8vVFfSJ9T_tO4c-T9y8vDI8=.AQAB"},{"rel":"salmon","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-replies","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/salmon-protocol.org\/ns\/salmon-mention","href":"https:\/\/quitter.no\/main\/salmon\/user\/7477"},{"rel":"http:\/\/ostatus.org\/schema\/1.0\/subscribe","template":"https:\/\/quitter.no\/main\/ostatussub?profile={uri}"}]}
\ No newline at end of file
diff --git a/spec/fixtures/requests/windows-1251.txt b/spec/fixtures/requests/windows-1251.txt
deleted file mode 100644
index f573e28b..00000000
--- a/spec/fixtures/requests/windows-1251.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-HTTP/1.1 200 OK
-server: nginx
-date: Wed, 12 Dec 2018 13:14:03 GMT
-content-type: text/html
-content-length: 190
-accept-ranges: bytes
-
-
-
-
-
- ñýìïë òåêñò
-
-
- ñýìïë òåêñò
-
-
diff --git a/spec/fixtures/salmon/mention.xml b/spec/fixtures/salmon/mention.xml
deleted file mode 100644
index 4d387ad8..00000000
--- a/spec/fixtures/salmon/mention.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiID8-PGVudHJ5IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDA1L0F0b20iIHhtbG5zOnRocj0iaHR0cDovL3B1cmwub3JnL3N5bmRpY2F0aW9uL3RocmVhZC8xLjAiIHhtbG5zOmFjdGl2aXR5PSJodHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zcGVjLzEuMC8iIHhtbG5zOmdlb3Jzcz0iaHR0cDovL3d3dy5nZW9yc3Mub3JnL2dlb3JzcyIgeG1sbnM6b3N0YXR1cz0iaHR0cDovL29zdGF0dXMub3JnL3NjaGVtYS8xLjAiIHhtbG5zOnBvY289Imh0dHA6Ly9wb3J0YWJsZWNvbnRhY3RzLm5ldC9zcGVjLzEuMCIgeG1sbnM6bWVkaWE9Imh0dHA6Ly9wdXJsLm9yZy9zeW5kaWNhdGlvbi9hdG9tbWVkaWEiIHhtbG5zOnN0YXR1c25ldD0iaHR0cDovL3N0YXR1cy5uZXQvc2NoZW1hL2FwaS8xLyI-CiA8YWN0aXZpdHk6b2JqZWN0LXR5cGU-aHR0cDovL2FjdGl2aXR5c3RyZWEubXMvc2NoZW1hLzEuMC9ub3RlPC9hY3Rpdml0eTpvYmplY3QtdHlwZT4KIDxpZD50YWc6cXVpdHRlci5ubywyMDE2LTAzLTIwOm5vdGljZUlkPTEyNzY5MjM6b2JqZWN0VHlwZT1ub3RlPC9pZD4KIDx0aXRsZT5OZXcgbm90ZSBieSBnYXJncm9uPC90aXRsZT4KIDxjb250ZW50IHR5cGU9Imh0bWwiPkAmbHQ7YSBocmVmPSZxdW90O2h0dHBzOi8vY2I2ZTYxMjYubmdyb2suaW8vdXNlcnMvY2F0c3JncjgmcXVvdDsgY2xhc3M9JnF1b3Q7aC1jYXJkIG1lbnRpb24mcXVvdDsmZ3Q7Y2F0c3JncjgmbHQ7L2EmZ3Q7IHRoaXMgaXMgYSBtZW50aW9uPC9jb250ZW50PgogPGxpbmsgcmVsPSJhbHRlcm5hdGUiIHR5cGU9InRleHQvaHRtbCIgaHJlZj0iaHR0cHM6Ly9xdWl0dGVyLm5vL25vdGljZS8xMjc2OTIzIi8-CiA8c3RhdHVzX25ldCBub3RpY2VfaWQ9IjEyNzY5MjMiPjwvc3RhdHVzX25ldD4KIDxhY3Rpdml0eTp2ZXJiPmh0dHA6Ly9hY3Rpdml0eXN0cmVhLm1zL3NjaGVtYS8xLjAvcG9zdDwvYWN0aXZpdHk6dmVyYj4KIDxwdWJsaXNoZWQ-MjAxNi0wMy0yMFQxMTowNTozMSswMDowMDwvcHVibGlzaGVkPgogPHVwZGF0ZWQ-MjAxNi0wMy0yMFQxMTowNTozMSswMDowMDwvdXBkYXRlZD4KIDxhdXRob3I-CiAgPGFjdGl2aXR5Om9iamVjdC10eXBlPmh0dHA6Ly9hY3Rpdml0eXN0cmVhLm1zL3NjaGVtYS8xLjAvcGVyc29uPC9hY3Rpdml0eTpvYmplY3QtdHlwZT4KICA8dXJpPmh0dHBzOi8vcXVpdHRlci5uby91c2VyLzc0Nzc8L3VyaT4KICA8bmFtZT5nYXJncm9uPC9uYW1lPgogIDxzdW1tYXJ5PlNvZnR3YXJlIGVuZ2luZWVyLCBmcmVlIHRpbWUgbXVzaWNpYW4gYW5kIO-8pO-8qe-8p--8qe-8tO-8oe-8rCDvvLPvvLDvvK_vvLLvvLTvvLMgZW50aHVzaWFzdC4gTGlrZXMgY2F0cy4gV2FybmluZzogTWF5IGNvbnRhaW4gbWVtZXM8L3N1bW1hcnk-CiAgPGxpbmsgcmVsPSJhbHRlcm5hdGUiIHR5cGU9InRleHQvaHRtbCIgaHJlZj0iaHR0cHM6Ly9xdWl0dGVyLm5vL2dhcmdyb24iLz4KICA8bGluayByZWw9ImF2YXRhciIgdHlwZT0iaW1hZ2UvcG5nIiBtZWRpYTp3aWR0aD0iMzAwIiBtZWRpYTpoZWlnaHQ9IjMwMCIgaHJlZj0iaHR0cHM6Ly9xdWl0dGVyLm5vL2F2YXRhci83NDc3LTMwMC0yMDE2MDIxMTE5MDM0MC5wbmciLz4KICA8bGluayByZWw9ImF2YXRhciIgdHlwZT0iaW1hZ2UvcG5nIiBtZWRpYTp3aWR0aD0iOTYiIG1lZGlhOmhlaWdodD0iOTYiIGhyZWY9Imh0dHBzOi8vcXVpdHRlci5uby9hdmF0YXIvNzQ3Ny05Ni0yMDE2MDIxMTE5MDM0MC5wbmciLz4KICA8bGluayByZWw9ImF2YXRhciIgdHlwZT0iaW1hZ2UvcG5nIiBtZWRpYTp3aWR0aD0iNDgiIG1lZGlhOmhlaWdodD0iNDgiIGhyZWY9Imh0dHBzOi8vcXVpdHRlci5uby9hdmF0YXIvNzQ3Ny00OC0yMDE2MDIxMTE5MDQ0OS5wbmciLz4KICA8bGluayByZWw9ImF2YXRhciIgdHlwZT0iaW1hZ2UvcG5nIiBtZWRpYTp3aWR0aD0iMjQiIG1lZGlhOmhlaWdodD0iMjQiIGhyZWY9Imh0dHBzOi8vcXVpdHRlci5uby9hdmF0YXIvNzQ3Ny0yNC0yMDE2MDIxMTE5MDUxNy5wbmciLz4KICA8cG9jbzpwcmVmZXJyZWRVc2VybmFtZT5nYXJncm9uPC9wb2NvOnByZWZlcnJlZFVzZXJuYW1lPgogIDxwb2NvOmRpc3BsYXlOYW1lPu-8pO-8qe-8p--8qe-8tO-8oe-8rCDvvKPvvKHvvLQ8L3BvY286ZGlzcGxheU5hbWU-CiAgPHBvY286bm90ZT5Tb2Z0d2FyZSBlbmdpbmVlciwgZnJlZSB0aW1lIG11c2ljaWFuIGFuZCDvvKTvvKnvvKfvvKnvvLTvvKHvvKwg77yz77yw77yv77yy77y077yzIGVudGh1c2lhc3QuIExpa2VzIGNhdHMuIFdhcm5pbmc6IE1heSBjb250YWluIG1lbWVzPC9wb2NvOm5vdGU-CiAgPHBvY286YWRkcmVzcz4KICAgPHBvY286Zm9ybWF0dGVkPkdlcm1hbnk8L3BvY286Zm9ybWF0dGVkPgogIDwvcG9jbzphZGRyZXNzPgogIDxwb2NvOnVybHM-CiAgIDxwb2NvOnR5cGU-aG9tZXBhZ2U8L3BvY286dHlwZT4KICAgPHBvY286dmFsdWU-aHR0cHM6Ly96ZW9uZmVkZXJhdGVkLmNvbTwvcG9jbzp2YWx1ZT4KICAgPHBvY286cHJpbWFyeT50cnVlPC9wb2NvOnByaW1hcnk-CiAgPC9wb2NvOnVybHM-CiAgPGZvbGxvd2VycyB1cmw9Imh0dHBzOi8vcXVpdHRlci5uby9nYXJncm9uL3N1YnNjcmliZXJzIj48L2ZvbGxvd2Vycz4KICA8c3RhdHVzbmV0OnByb2ZpbGVfaW5mbyBsb2NhbF9pZD0iNzQ3NyI-PC9zdGF0dXNuZXQ6cHJvZmlsZV9pbmZvPgogPC9hdXRob3I-CiA8bGluayByZWw9Im9zdGF0dXM6Y29udmVyc2F0aW9uIiBocmVmPSJ0YWc6cXVpdHRlci5ubywyMDE2LTAzLTIwOm9iamVjdFR5cGU9dGhyZWFkOm5vbmNlPTdjOTk4MTEyZTM5YTY2ODUiLz4KIDxvc3RhdHVzOmNvbnZlcnNhdGlvbj50YWc6cXVpdHRlci5ubywyMDE2LTAzLTIwOm9iamVjdFR5cGU9dGhyZWFkOm5vbmNlPTdjOTk4MTEyZTM5YTY2ODU8L29zdGF0dXM6Y29udmVyc2F0aW9uPgogPGxpbmsgcmVsPSJtZW50aW9uZWQiIG9zdGF0dXM6b2JqZWN0LXR5cGU9Imh0dHA6Ly9hY3Rpdml0eXN0cmVhLm1zL3NjaGVtYS8xLjAvcGVyc29uIiBocmVmPSJodHRwczovL2NiNmU2MTI2Lm5ncm9rLmlvL3VzZXJzL2NhdHNyZ3I4Ii8-CiA8bGluayByZWw9Im1lbnRpb25lZCIgb3N0YXR1czpvYmplY3QtdHlwZT0iaHR0cDovL2FjdGl2aXR5c3RyZWEubXMvc2NoZW1hLzEuMC9jb2xsZWN0aW9uIiBocmVmPSJodHRwOi8vYWN0aXZpdHlzY2hlbWEub3JnL2NvbGxlY3Rpb24vcHVibGljIi8-CiA8c291cmNlPgogIDxpZD5odHRwczovL3F1aXR0ZXIubm8vYXBpL3N0YXR1c2VzL3VzZXJfdGltZWxpbmUvNzQ3Ny5hdG9tPC9pZD4KICA8dGl0bGU-77yk77yp77yn77yp77y077yh77ysIO-8o--8oe-8tDwvdGl0bGU-CiAgPGxpbmsgcmVsPSJhbHRlcm5hdGUiIHR5cGU9InRleHQvaHRtbCIgaHJlZj0iaHR0cHM6Ly9xdWl0dGVyLm5vL2dhcmdyb24iLz4KICA8bGluayByZWw9InNlbGYiIHR5cGU9ImFwcGxpY2F0aW9uL2F0b20reG1sIiBocmVmPSJodHRwczovL3F1aXR0ZXIubm8vYXBpL3N0YXR1c2VzL3VzZXJfdGltZWxpbmUvNzQ3Ny5hdG9tIi8-CiAgPGxpbmsgcmVsPSJsaWNlbnNlIiBocmVmPSJodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnkvMy4wLyIvPgogIDxpY29uPmh0dHBzOi8vcXVpdHRlci5uby9hdmF0YXIvNzQ3Ny05Ni0yMDE2MDIxMTE5MDM0MC5wbmc8L2ljb24-CiAgPHVwZGF0ZWQ-MjAxNi0wMy0yMFQxMTowNTozMSswMDowMDwvdXBkYXRlZD4KIDwvc291cmNlPgogPGxpbmsgcmVsPSJzZWxmIiB0eXBlPSJhcHBsaWNhdGlvbi9hdG9tK3htbCIgaHJlZj0iaHR0cHM6Ly9xdWl0dGVyLm5vL2FwaS9zdGF0dXNlcy9zaG93LzEyNzY5MjMuYXRvbSIvPgogPGxpbmsgcmVsPSJlZGl0IiB0eXBlPSJhcHBsaWNhdGlvbi9hdG9tK3htbCIgaHJlZj0iaHR0cHM6Ly9xdWl0dGVyLm5vL2FwaS9zdGF0dXNlcy9zaG93LzEyNzY5MjMuYXRvbSIvPgogPHN0YXR1c25ldDpub3RpY2VfaW5mbyBsb2NhbF9pZD0iMTI3NjkyMyIgc291cmNlPSJRdml0dGVyIj48L3N0YXR1c25ldDpub3RpY2VfaW5mbz4KPC9lbnRyeT4K base64url RSA-SHA256 XOSdsku4Tq6zLxmOv0KtTpyG-UKOnlYzEoDXyPl_lkZzcZYm8Jc7ao50swJE1NFIw4uW8PfTTlqnz0pC62MVOVRxOUtiPTTJicux5W__HWf0j_ymUre87VF0Wdt1BoZYR9HeLnx2SGALDc6_ib-eabHA0O3AtSdm0JLq2pprtpA=
diff --git a/spec/fixtures/xml/gabsocial.atom b/spec/fixtures/xml/gabsocial.atom
deleted file mode 100644
index 1158832c..00000000
--- a/spec/fixtures/xml/gabsocial.atom
+++ /dev/null
@@ -1,261 +0,0 @@
-
-
- http://kickass.zone/users/localhost.atom
- ::1
- 2016-10-10T13:29:56Z
- http://kickass.zone/system/accounts/avatars/000/000/001/medium/eris.png
-
- http://activitystrea.ms/schema/1.0/person
- http://kickass.zone/users/localhost
- localhost
- localhost@kickass.zone
-
-
-
-
- localhost
- ::1
-
-
-
-
-
-
- tag:kickass.zone,2016-10-10:objectId=7:objectType=Follow
- 2016-10-10T13:29:56Z
- 2016-10-10T13:29:56Z
- localhost started following kat@gab.com
- localhost started following kat@gab.com
- http://activitystrea.ms/schema/1.0/follow
-
-
- http://activitystrea.ms/schema/1.0/activity
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/kat
- kat
- kat@gab.com
- #trans #queer
-
-
-
-
- kat
- Kat
- #trans #queer
-
-
-
- tag:kickass.zone,2016-10-10:objectId=3:objectType=Favourite
- 2016-10-10T13:29:26Z
- 2016-10-10T13:29:26Z
- localhost favourited a status by kat@gab.com
- localhost favourited a status by kat@gab.com
- http://activitystrea.ms/schema/1.0/favorite
-
-
- http://activitystrea.ms/schema/1.0/activity
-
-
- http://activitystrea.ms/schema/1.0/comment
- tag:gab.com,2016-10-10:objectId=22833:objectType=Status
- @localhost oooh more stuffs ❤
-
- <p><a href="http://kickass.zone/users/localhost">@localhost</a> oooh more stuffs ❤</p>
- http://activitystrea.ms/schema/1.0/post
- 2016-10-10T13:23:35Z
- 2016-10-10T13:23:35Z
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/kat
- kat
- kat@gab.com
- #trans #queer
-
-
-
-
- kat
- Kat
- #trans #queer
-
-
-
-
-
- tag:kickass.zone,2016-10-10:objectId=2:objectType=Favourite
- 2016-10-10T13:13:15Z
- 2016-10-10T13:13:15Z
- localhost favourited a status by robcolbert@gab.com
- localhost favourited a status by robcolbert@gab.com
- http://activitystrea.ms/schema/1.0/favorite
-
-
- http://activitystrea.ms/schema/1.0/activity
-
-
- http://activitystrea.ms/schema/1.0/note
- tag:gab.com,2016-10-10:objectId=22825:objectType=Status
- Deployed some fixes
-
- <p>Deployed some fixes</p>
- http://activitystrea.ms/schema/1.0/post
- 2016-10-10T13:10:37Z
- 2016-10-10T13:10:37Z
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/robcolbert
- Rob Colbert
- robcolbert@gab.com
- Developer of Gab Social, a GNU social alternative: https://code.gab.com/gab/social/gab-social
-
-
-
-
- robcolbert
- Eugen
- Developer of Gab Social, a GNU social alternative: https://code.gab.com/gab/social/gab-social
-
-
-
-
- tag:kickass.zone,2016-10-10:objectId=17:objectType=Status
- 2016-10-10T00:41:31Z
- 2016-10-10T00:41:31Z
- Social media needs MOAR cats! http://kickass.zone/media/3
- <p>Social media needs MOAR cats! <a rel="nofollow noopener noreferrer" href="http://kickass.zone/media/3">http://kickass.zone/media/3</a></p>
- http://activitystrea.ms/schema/1.0/post
-
-
- http://activitystrea.ms/schema/1.0/note
-
-
-
- tag:kickass.zone,2016-10-10:objectId=14:objectType=Status
- 2016-10-10T00:38:39Z
- 2016-10-10T00:38:39Z
- http://kickass.zone/media/2
- <p><a rel="nofollow noopener noreferrer" href="http://kickass.zone/media/2">http://kickass.zone/media/2</a></p>
- http://activitystrea.ms/schema/1.0/post
-
-
- http://activitystrea.ms/schema/1.0/note
-
-
-
- tag:kickass.zone,2016-10-10:objectId=12:objectType=Status
- 2016-10-10T00:37:49Z
- 2016-10-10T00:37:49Z
-
- http://activitystrea.ms/schema/1.0/delete
-
-
- http://activitystrea.ms/schema/1.0/activity
-
-
- tag:kickass.zone,2016-10-10:objectId=4:objectType=Follow
- 2016-10-10T00:23:07Z
- 2016-10-10T00:23:07Z
- localhost started following bignimbus@gab.com
- localhost started following bignimbus@gab.com
- http://activitystrea.ms/schema/1.0/follow
-
-
- http://activitystrea.ms/schema/1.0/activity
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/bignimbus
- bignimbus
- bignimbus@gab.com
- jdauriemma.com
-
-
-
-
- bignimbus
- Jeff Auriemma
- jdauriemma.com
-
-
-
- tag:kickass.zone,2016-10-10:objectId=2:objectType=Follow
- 2016-10-10T00:14:18Z
- 2016-10-10T00:14:18Z
- localhost started following robcolbert@gab.com
- localhost started following robcolbert@gab.com
- http://activitystrea.ms/schema/1.0/follow
-
-
- http://activitystrea.ms/schema/1.0/activity
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/robcolbert
- Rob Colbert
- robcolbert@gab.com
- Developer of Gab Social, a GNU social alternative: https://code.gab.com/gab/social/gab-social
-
-
-
-
- robcolbert
- Eugen
- Developer of Gab Social, a GNU social alternative: https://code.gab.com/gab/social/gab-social
-
-
-
- tag:kickass.zone,2016-10-10:objectId=1:objectType=Follow
- 2016-10-10T00:09:09Z
- 2016-10-10T00:09:09Z
- localhost started following abc@gab.com
- localhost started following abc@gab.com
- http://activitystrea.ms/schema/1.0/follow
-
-
- http://activitystrea.ms/schema/1.0/activity
-
- http://activitystrea.ms/schema/1.0/person
- https://gab.com/users/abc
- abc
- abc@gab.com
-
-
-
-
- abc
- abc
-
-
-
- tag:kickass.zone,2016-10-10:objectId=3:objectType=Status
- 2016-10-10T00:02:47Z
- 2016-10-10T00:02:47Z
-
- http://activitystrea.ms/schema/1.0/delete
-
-
- http://activitystrea.ms/schema/1.0/activity
-
-
- tag:kickass.zone,2016-10-10:objectId=2:objectType=Status
- 2016-10-10T00:02:18Z
- 2016-10-10T00:02:18Z
- Yes, that was the obligatory first post. :)
- <p>Yes, that was the obligatory first post. :)</p>
- http://activitystrea.ms/schema/1.0/post
-
-
- http://activitystrea.ms/schema/1.0/comment
-
-
-
- tag:kickass.zone,2016-10-10:objectId=1:objectType=Status
- 2016-10-10T00:01:56Z
- 2016-10-10T00:01:56Z
- Hello, world!
- <p>Hello, world!</p>
- http://activitystrea.ms/schema/1.0/post
-
-
- http://activitystrea.ms/schema/1.0/note
-
-
diff --git a/spec/helpers/admin/account_moderation_notes_helper_spec.rb b/spec/helpers/admin/account_moderation_notes_helper_spec.rb
deleted file mode 100644
index c07f6c4b..00000000
--- a/spec/helpers/admin/account_moderation_notes_helper_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::AccountModerationNotesHelper, type: :helper do
- include StreamEntriesHelper
-
- describe '#admin_account_link_to' do
- context 'account is nil' do
- let(:account) { nil }
-
- it 'returns nil' do
- expect(helper.admin_account_link_to(account)).to be_nil
- end
- end
-
- context 'with account' do
- let(:account) { Fabricate(:account) }
-
- it 'calls #link_to' do
- expect(helper).to receive(:link_to).with(
- admin_account_path(account.id),
- class: name_tag_classes(account),
- title: account.acct
- )
-
- helper.admin_account_link_to(account)
- end
- end
- end
-
- describe '#admin_account_inline_link_to' do
- context 'account is nil' do
- let(:account) { nil }
-
- it 'returns nil' do
- expect(helper.admin_account_inline_link_to(account)).to be_nil
- end
- end
-
- context 'with account' do
- let(:account) { Fabricate(:account) }
-
- it 'calls #link_to' do
- expect(helper).to receive(:link_to).with(
- admin_account_path(account.id),
- class: name_tag_classes(account, true),
- title: account.acct
- )
-
- helper.admin_account_inline_link_to(account)
- end
- end
- end
-end
diff --git a/spec/helpers/admin/action_log_helper_spec.rb b/spec/helpers/admin/action_log_helper_spec.rb
deleted file mode 100644
index d7af6b93..00000000
--- a/spec/helpers/admin/action_log_helper_spec.rb
+++ /dev/null
@@ -1,272 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::ActionLogsHelper, type: :helper do
- klass = Class.new do
- include ActionView::Helpers
- include Admin::ActionLogsHelper
- end
-
- let(:hoge) { klass.new }
-
- describe '#log_target' do
- after do
- hoge.log_target(log)
- end
-
- context 'log.target' do
- let(:log) { double(target: true) }
-
- it 'calls linkable_log_target' do
- expect(hoge).to receive(:linkable_log_target).with(log.target)
- end
- end
-
- context '!log.target' do
- let(:log) { double(target: false, target_type: :type, recorded_changes: :change) }
-
- it 'calls log_target_from_history' do
- expect(hoge).to receive(:log_target_from_history).with(log.target_type, log.recorded_changes)
- end
- end
- end
-
- describe '#relevant_log_changes' do
- let(:log) { double(target_type: target_type, action: log_action, recorded_changes: recorded_changes) }
- let(:recorded_changes) { double }
-
- after do
- hoge.relevant_log_changes(log)
- end
-
- context "log.target_type == 'CustomEmoji' && [:enable, :disable, :destroy].include?(log.action)" do
- let(:target_type) { 'CustomEmoji' }
- let(:log_action) { :enable }
-
- it "calls log.recorded_changes.slice('domain')" do
- expect(recorded_changes).to receive(:slice).with('domain')
- end
- end
-
- context "log.target_type == 'CustomEmoji' && log.action == :update" do
- let(:target_type) { 'CustomEmoji' }
- let(:log_action) { :update }
-
- it "calls log.recorded_changes.slice('domain', 'visible_in_picker')" do
- expect(recorded_changes).to receive(:slice).with('domain', 'visible_in_picker')
- end
- end
-
- context "log.target_type == 'User' && [:promote, :demote].include?(log.action)" do
- let(:target_type) { 'User' }
- let(:log_action) { :promote }
-
- it "calls log.recorded_changes.slice('moderator', 'admin')" do
- expect(recorded_changes).to receive(:slice).with('moderator', 'admin')
- end
- end
-
- context "log.target_type == 'User' && [:change_email].include?(log.action)" do
- let(:target_type) { 'User' }
- let(:log_action) { :change_email }
-
- it "calls log.recorded_changes.slice('email', 'unconfirmed_email')" do
- expect(recorded_changes).to receive(:slice).with('email', 'unconfirmed_email')
- end
- end
-
- context "log.target_type == 'DomainBlock'" do
- let(:target_type) { 'DomainBlock' }
- let(:log_action) { nil }
-
- it "calls log.recorded_changes.slice('severity', 'reject_media')" do
- expect(recorded_changes).to receive(:slice).with('severity', 'reject_media')
- end
- end
-
- context "log.target_type == 'Status' && log.action == :update" do
- let(:target_type) { 'Status' }
- let(:log_action) { :update }
-
- it "log.recorded_changes.slice('sensitive')" do
- expect(recorded_changes).to receive(:slice).with('sensitive')
- end
- end
- end
-
- describe '#log_extra_attributes' do
- after do
- hoge.log_extra_attributes(hoge: 'hoge')
- end
-
- it "calls content_tag(:span, key, class: 'diff-key')" do
- allow(hoge).to receive(:log_change).with(anything)
- expect(hoge).to receive(:content_tag).with(:span, :hoge, class: 'diff-key')
- end
-
- it 'calls safe_join twice' do
- expect(hoge).to receive(:safe_join).with(
- ['hoge ',
- '=',
- 'hoge ']
- )
-
- expect(hoge).to receive(:safe_join).with([nil], ' ')
- end
- end
-
- describe '#log_change' do
- after do
- hoge.log_change(val)
- end
-
- context '!val.is_a?(Array)' do
- let(:val) { 'hoge' }
-
- it "calls content_tag(:span, val, class: 'diff-neutral')" do
- expect(hoge).to receive(:content_tag).with(:span, val, class: 'diff-neutral')
- end
- end
-
- context 'val.is_a?(Array)' do
- let(:val) { %w(foo bar) }
-
- it 'calls #content_tag twice and #safe_join' do
- expect(hoge).to receive(:content_tag).with(:span, 'foo', class: 'diff-old')
- expect(hoge).to receive(:content_tag).with(:span, 'bar', class: 'diff-new')
- expect(hoge).to receive(:safe_join).with([nil, nil], '→')
- end
- end
- end
-
- describe '#icon_for_log' do
- subject { hoge.icon_for_log(log) }
-
- context "log.target_type == 'Account'" do
- let(:log) { double(target_type: 'Account') }
-
- it 'returns "user"' do
- expect(subject).to be 'user'
- end
- end
-
- context "log.target_type == 'User'" do
- let(:log) { double(target_type: 'User') }
-
- it 'returns "user"' do
- expect(subject).to be 'user'
- end
- end
-
- context "log.target_type == 'CustomEmoji'" do
- let(:log) { double(target_type: 'CustomEmoji') }
-
- it 'returns "file"' do
- expect(subject).to be 'file'
- end
- end
-
- context "log.target_type == 'Report'" do
- let(:log) { double(target_type: 'Report') }
-
- it 'returns "flag"' do
- expect(subject).to be 'flag'
- end
- end
-
- context "log.target_type == 'DomainBlock'" do
- let(:log) { double(target_type: 'DomainBlock') }
-
- it 'returns "lock"' do
- expect(subject).to be 'lock'
- end
- end
-
- context "log.target_type == 'EmailDomainBlock'" do
- let(:log) { double(target_type: 'EmailDomainBlock') }
-
- it 'returns "envelope"' do
- expect(subject).to be 'envelope'
- end
- end
-
- context "log.target_type == 'Status'" do
- let(:log) { double(target_type: 'Status') }
-
- it 'returns "pencil"' do
- expect(subject).to be 'pencil'
- end
- end
- end
-
- describe '#class_for_log_icon' do
- subject { hoge.class_for_log_icon(log) }
-
- %i(enable unsuspend unsilence confirm promote resolve).each do |action|
- context "log.action == #{action}" do
- let(:log) { double(action: action) }
-
- it 'returns "positive"' do
- expect(subject).to be 'positive'
- end
- end
- end
-
- context 'log.action == :create' do
- context 'opposite_verbs?(log)' do
- let(:log) { double(action: :create, target_type: 'DomainBlock') }
-
- it 'returns "negative"' do
- expect(subject).to be 'negative'
- end
- end
-
- context '!opposite_verbs?(log)' do
- let(:log) { double(action: :create, target_type: '') }
-
- it 'returns "positive"' do
- expect(subject).to be 'positive'
- end
- end
- end
-
- %i(update reset_password disable_2fa memorialize change_email).each do |action|
- context "log.action == #{action}" do
- let(:log) { double(action: action) }
-
- it 'returns "neutral"' do
- expect(subject).to be 'neutral'
- end
- end
- end
-
- %i(demote silence disable suspend remove_avatar remove_header reopen).each do |action|
- context "log.action == #{action}" do
- let(:log) { double(action: action) }
-
- it 'returns "negative"' do
- expect(subject).to be 'negative'
- end
- end
- end
-
- context 'log.action == :destroy' do
- context 'opposite_verbs?(log)' do
- let(:log) { double(action: :destroy, target_type: 'DomainBlock') }
-
- it 'returns "positive"' do
- expect(subject).to be 'positive'
- end
- end
-
- context '!opposite_verbs?(log)' do
- let(:log) { double(action: :destroy, target_type: '') }
-
- it 'returns "negative"' do
- expect(subject).to be 'negative'
- end
- end
- end
- end
-end
diff --git a/spec/helpers/admin/filter_helper_spec.rb b/spec/helpers/admin/filter_helper_spec.rb
deleted file mode 100644
index 9d4ea282..00000000
--- a/spec/helpers/admin/filter_helper_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'rails_helper'
-
-describe Admin::FilterHelper do
- it 'Uses filter_link_to to create filter links' do
- params = ActionController::Parameters.new(
- { test: 'test' }
- )
- allow(helper).to receive(:params).and_return(params)
- allow(helper).to receive(:url_for).and_return('/test')
- result = helper.filter_link_to('text', { resolved: true })
-
- expect(result).to match(/text/)
- end
-
- it 'Uses table_link_to to create icon links' do
- result = helper.table_link_to 'icon', 'text', 'path'
-
- expect(result).to match(/text/)
- end
-end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
deleted file mode 100644
index f09e32ec..00000000
--- a/spec/helpers/application_helper_spec.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-require 'rails_helper'
-
-describe ApplicationHelper do
- describe 'active_nav_class' do
- it 'returns active when on the current page' do
- allow(helper).to receive(:current_page?).and_return(true)
-
- result = helper.active_nav_class("/test")
- expect(result).to eq "active"
- end
-
- it 'returns active when on a current page' do
- allow(helper).to receive(:current_page?).with('/foo').and_return(false)
- allow(helper).to receive(:current_page?).with('/test').and_return(true)
-
- result = helper.active_nav_class('/foo', '/test')
- expect(result).to eq "active"
- end
-
- it 'returns empty string when not on current page' do
- allow(helper).to receive(:current_page?).and_return(false)
-
- result = helper.active_nav_class("/test")
- expect(result).to eq ""
- end
- end
-
- describe 'locale_direction' do
- around do |example|
- current_locale = I18n.locale
- example.run
- I18n.locale = current_locale
- end
-
- it 'adds rtl body class if locale is Arabic' do
- I18n.locale = :ar
- expect(helper.locale_direction).to eq 'rtl'
- end
-
- it 'adds rtl body class if locale is Farsi' do
- I18n.locale = :fa
- expect(helper.locale_direction).to eq 'rtl'
- end
-
- it 'adds rtl if locale is Hebrew' do
- I18n.locale = :he
- expect(helper.locale_direction).to eq 'rtl'
- end
-
- it 'does not add rtl if locale is Thai' do
- I18n.locale = :th
- expect(helper.locale_direction).to_not eq 'rtl'
- end
- end
-
- describe 'fa_icon' do
- it 'returns a tag of fixed-width cog' do
- expect(helper.fa_icon('cog fw')).to eq ' '
- end
- end
-
- describe 'favicon_path' do
- it 'returns /favicon.ico on production enviromnent' do
- expect(Rails.env).to receive(:production?).and_return(true)
- expect(helper.favicon_path).to eq '/favicon.ico'
- end
- end
-
- describe 'open_registrations?' do
- it 'returns true when open for registrations' do
- without_partial_double_verification do
- expect(Setting).to receive(:registrations_mode).and_return('open')
- end
-
- expect(helper.open_registrations?).to eq true
- end
-
- it 'returns false when closed for registrations' do
- without_partial_double_verification do
- expect(Setting).to receive(:registrations_mode).and_return('none')
- end
-
- expect(helper.open_registrations?).to eq false
- end
- end
-
- describe 'show_landing_strip?', without_verify_partial_doubles: true do
- describe 'when signed in' do
- before do
- allow(helper).to receive(:user_signed_in?).and_return(true)
- end
- it 'does not show landing strip' do
- expect(helper.show_landing_strip?).to eq false
- end
- end
-
- describe 'when signed out' do
- before do
- allow(helper).to receive(:user_signed_in?).and_return(false)
- end
-
- it 'does not show landing strip on single user instance' do
- allow(helper).to receive(:single_user_mode?).and_return(true)
-
- expect(helper.show_landing_strip?).to eq false
- end
-
- it 'shows landing strip on multi user instance' do
- allow(helper).to receive(:single_user_mode?).and_return(false)
-
- expect(helper.show_landing_strip?).to eq true
- end
- end
- end
-
- describe 'title' do
- around do |example|
- site_title = Setting.site_title
- example.run
- Setting.site_title = site_title
- end
-
- it 'returns site title on production enviroment' do
- Setting.site_title = 'site title'
- expect(Rails.env).to receive(:production?).and_return(true)
- expect(helper.title).to eq 'site title'
- end
- end
-end
diff --git a/spec/helpers/flashes_helper_spec.rb b/spec/helpers/flashes_helper_spec.rb
deleted file mode 100644
index ea143eed..00000000
--- a/spec/helpers/flashes_helper_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe FlashesHelper, type: :helper do
- describe 'user_facing_flashes' do
- it 'returns user facing flashes' do
- flash[:alert] = 'an alert'
- flash[:error] = 'an error'
- flash[:notice] = 'a notice'
- flash[:success] = 'a success'
- flash[:not_user_facing] = 'a not user facing flash'
- expect(helper.user_facing_flashes).to eq 'alert' => 'an alert',
- 'error' => 'an error',
- 'notice' => 'a notice',
- 'success' => 'a success'
- end
- end
-end
diff --git a/spec/helpers/home_helper_spec.rb b/spec/helpers/home_helper_spec.rb
deleted file mode 100644
index a3dc6f83..00000000
--- a/spec/helpers/home_helper_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe HomeHelper, type: :helper do
- describe 'default_props' do
- it 'returns default properties according to the context' do
- expect(helper.default_props).to eq locale: I18n.locale
- end
- end
-end
diff --git a/spec/helpers/instance_helper_spec.rb b/spec/helpers/instance_helper_spec.rb
deleted file mode 100644
index c2e26dbe..00000000
--- a/spec/helpers/instance_helper_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe InstanceHelper do
- describe 'site_title' do
- around do |example|
- site_title = Setting.site_title
- example.run
- Setting.site_title = site_title
- end
-
- it 'Uses the Setting.site_title value when it exists' do
- Setting.site_title = 'New site title'
-
- expect(helper.site_title).to eq 'New site title'
- end
- end
-
- describe 'site_hostname' do
- around(:each) do |example|
- before = Rails.configuration.x.local_domain
- example.run
- Rails.configuration.x.local_domain = before
- end
-
- it 'returns the local domain value' do
- Rails.configuration.x.local_domain = 'example.com'
-
- expect(helper.site_hostname).to eq 'example.com'
- end
- end
-end
diff --git a/spec/helpers/jsonld_helper_spec.rb b/spec/helpers/jsonld_helper_spec.rb
deleted file mode 100644
index 883a88b1..00000000
--- a/spec/helpers/jsonld_helper_spec.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe JsonLdHelper do
- describe '#equals_or_includes?' do
- it 'returns true when value equals' do
- expect(helper.equals_or_includes?('foo', 'foo')).to be true
- end
-
- it 'returns false when value does not equal' do
- expect(helper.equals_or_includes?('foo', 'bar')).to be false
- end
-
- it 'returns true when value is included' do
- expect(helper.equals_or_includes?(%w(foo baz), 'foo')).to be true
- end
-
- it 'returns false when value is not included' do
- expect(helper.equals_or_includes?(%w(foo baz), 'bar')).to be false
- end
- end
-
- describe '#first_of_value' do
- context 'value.is_a?(Array)' do
- it 'returns value.first' do
- value = ['a']
- expect(helper.first_of_value(value)).to be 'a'
- end
- end
-
- context '!value.is_a?(Array)' do
- it 'returns value' do
- value = 'a'
- expect(helper.first_of_value(value)).to be 'a'
- end
- end
- end
-
- describe '#supported_context?' do
- context "!json.nil? && equals_or_includes?(json['@context'], ActivityPub::TagManager::CONTEXT)" do
- it 'returns true' do
- json = { '@context' => ActivityPub::TagManager::CONTEXT }.as_json
- expect(helper.supported_context?(json)).to be true
- end
- end
-
- context 'else' do
- it 'returns false' do
- json = nil
- expect(helper.supported_context?(json)).to be false
- end
- end
- end
-
- describe '#fetch_resource' do
- context 'when the second argument is false' do
- it 'returns resource even if the retrieved ID and the given URI does not match' do
- stub_request(:get, 'https://bob.test/').to_return body: '{"id": "https://alice.test/"}'
- stub_request(:get, 'https://alice.test/').to_return body: '{"id": "https://alice.test/"}'
-
- expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' })
- end
-
- it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do
- stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://marvin.test/"}'
- stub_request(:get, 'https://marvin.test/').to_return body: '{"id": "https://alice.test/"}'
-
- expect(fetch_resource('https://mallory.test/', false)).to eq nil
- end
- end
-
- context 'when the second argument is true' do
- it 'returns nil if the retrieved ID and the given URI does not match' do
- stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://alice.test/"}'
- expect(fetch_resource('https://mallory.test/', true)).to eq nil
- end
- end
- end
-
- describe '#fetch_resource_without_id_validation' do
- it 'returns nil if the status code is not 200' do
- stub_request(:get, 'https://host.test/').to_return status: 400, body: '{}'
- expect(fetch_resource_without_id_validation('https://host.test/')).to eq nil
- end
-
- it 'returns hash' do
- stub_request(:get, 'https://host.test/').to_return status: 200, body: '{}'
- expect(fetch_resource_without_id_validation('https://host.test/')).to eq({})
- end
- end
-end
diff --git a/spec/helpers/routing_helper_spec.rb b/spec/helpers/routing_helper_spec.rb
deleted file mode 100644
index 940392c9..00000000
--- a/spec/helpers/routing_helper_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe RoutingHelper, type: :helper do
- describe '.full_asset_url' do
- around do |example|
- use_s3 = Rails.configuration.x.use_s3
- example.run
- Rails.configuration.x.use_s3 = use_s3
- end
-
- shared_examples 'returns full path URL' do
- it 'with host' do
- url = helper.full_asset_url('https://example.com/avatars/000/000/002/original/icon.png')
-
- expect(url).to eq 'https://example.com/avatars/000/000/002/original/icon.png'
- end
-
- it 'without host' do
- url = helper.full_asset_url('/avatars/original/missing.png', skip_pipeline: true)
-
- expect(url).to eq 'http://test.host/avatars/original/missing.png'
- end
- end
-
- context 'Do not use S3' do
- before do
- Rails.configuration.x.use_s3 = false
- end
-
- it_behaves_like 'returns full path URL'
- end
-
- context 'Use S3' do
- before do
- Rails.configuration.x.use_s3 = true
- end
-
- it_behaves_like 'returns full path URL'
- end
- end
-end
diff --git a/spec/helpers/settings_helper_spec.rb b/spec/helpers/settings_helper_spec.rb
deleted file mode 100644
index 092c3758..00000000
--- a/spec/helpers/settings_helper_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe SettingsHelper do
- describe 'the HUMAN_LOCALES constant' do
- it 'includes all I18n locales' do
- options = I18n.available_locales
-
- expect(described_class::HUMAN_LOCALES.keys).to include(*options)
- end
- end
-
- describe 'human_locale' do
- it 'finds the human readable local description from a key' do
- # Ensure the value is as we expect
- expect(described_class::HUMAN_LOCALES[:en]).to eq('English')
-
- expect(helper.human_locale(:en)).to eq('English')
- end
- end
-end
diff --git a/spec/helpers/stream_entries_helper_spec.rb b/spec/helpers/stream_entries_helper_spec.rb
deleted file mode 100644
index 845b9974..00000000
--- a/spec/helpers/stream_entries_helper_spec.rb
+++ /dev/null
@@ -1,224 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe StreamEntriesHelper, type: :helper do
- describe '#display_name' do
- it 'uses the display name when it exists' do
- account = Account.new(display_name: "Display", username: "Username")
-
- expect(helper.display_name(account)).to eq "Display"
- end
-
- it 'uses the username when display name is nil' do
- account = Account.new(display_name: nil, username: "Username")
-
- expect(helper.display_name(account)).to eq "Username"
- end
- end
-
- describe '#stream_link_target' do
- it 'returns nil if it is not an embedded view' do
- set_not_embedded_view
-
- expect(helper.stream_link_target).to be_nil
- end
-
- it 'returns _blank if it is an embedded view' do
- set_embedded_view
-
- expect(helper.stream_link_target).to eq '_blank'
- end
- end
-
- describe '#acct' do
- it 'is fully qualified for embedded local accounts' do
- allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain')
- set_embedded_view
- account = Account.new(domain: nil, username: 'user')
-
- acct = helper.acct(account)
-
- expect(acct).to eq '@user@local_domain'
- end
-
- it 'is fully qualified for embedded foreign accounts' do
- set_embedded_view
- account = Account.new(domain: 'foreign_server.com', username: 'user')
-
- acct = helper.acct(account)
-
- expect(acct).to eq '@user@foreign_server.com'
- end
-
- it 'is fully qualified for non embedded foreign accounts' do
- set_not_embedded_view
- account = Account.new(domain: 'foreign_server.com', username: 'user')
-
- acct = helper.acct(account)
-
- expect(acct).to eq '@user@foreign_server.com'
- end
-
- it 'is fully qualified for non embedded local accounts' do
- allow(Rails.configuration.x).to receive(:local_domain).and_return('local_domain')
- set_not_embedded_view
- account = Account.new(domain: nil, username: 'user')
-
- acct = helper.acct(account)
-
- expect(acct).to eq '@user@local_domain'
- end
- end
-
- def set_not_embedded_view
- params[:controller] = "not_#{StreamEntriesHelper::EMBEDDED_CONTROLLER}"
- params[:action] = "not_#{StreamEntriesHelper::EMBEDDED_ACTION}"
- end
-
- def set_embedded_view
- params[:controller] = StreamEntriesHelper::EMBEDDED_CONTROLLER
- params[:action] = StreamEntriesHelper::EMBEDDED_ACTION
- end
-
- describe '#style_classes' do
- it do
- status = double(reblog?: false)
- classes = helper.style_classes(status, false, false, false)
-
- expect(classes).to eq 'entry'
- end
-
- it do
- status = double(reblog?: true)
- classes = helper.style_classes(status, false, false, false)
-
- expect(classes).to eq 'entry entry-reblog'
- end
-
- it do
- status = double(reblog?: false)
- classes = helper.style_classes(status, true, false, false)
-
- expect(classes).to eq 'entry entry-predecessor'
- end
-
- it do
- status = double(reblog?: false)
- classes = helper.style_classes(status, false, true, false)
-
- expect(classes).to eq 'entry entry-successor'
- end
-
- it do
- status = double(reblog?: false)
- classes = helper.style_classes(status, false, false, true)
-
- expect(classes).to eq 'entry entry-center'
- end
-
- it do
- status = double(reblog?: true)
- classes = helper.style_classes(status, true, true, true)
-
- expect(classes).to eq 'entry entry-predecessor entry-reblog entry-successor entry-center'
- end
- end
-
- describe '#microformats_classes' do
- it do
- status = double(reblog?: false)
- classes = helper.microformats_classes(status, false, false)
-
- expect(classes).to eq ''
- end
-
- it do
- status = double(reblog?: false)
- classes = helper.microformats_classes(status, true, false)
-
- expect(classes).to eq 'p-in-reply-to'
- end
-
- it do
- status = double(reblog?: false)
- classes = helper.microformats_classes(status, false, true)
-
- expect(classes).to eq 'p-comment'
- end
-
- it do
- status = double(reblog?: true)
- classes = helper.microformats_classes(status, true, false)
-
- expect(classes).to eq 'p-in-reply-to p-repost-of'
- end
-
- it do
- status = double(reblog?: true)
- classes = helper.microformats_classes(status, true, true)
-
- expect(classes).to eq 'p-in-reply-to p-repost-of p-comment'
- end
- end
-
- describe '#microformats_h_class' do
- it do
- status = double(reblog?: false)
- css_class = helper.microformats_h_class(status, false, false, false)
-
- expect(css_class).to eq 'h-entry'
- end
-
- it do
- status = double(reblog?: true)
- css_class = helper.microformats_h_class(status, false, false, false)
-
- expect(css_class).to eq 'h-cite'
- end
-
- it do
- status = double(reblog?: false)
- css_class = helper.microformats_h_class(status, true, false, false)
-
- expect(css_class).to eq 'h-cite'
- end
-
- it do
- status = double(reblog?: false)
- css_class = helper.microformats_h_class(status, false, true, false)
-
- expect(css_class).to eq 'h-cite'
- end
-
- it do
- status = double(reblog?: false)
- css_class = helper.microformats_h_class(status, false, false, true)
-
- expect(css_class).to eq ''
- end
-
- it do
- status = double(reblog?: true)
- css_class = helper.microformats_h_class(status, true, true, true)
-
- expect(css_class).to eq 'h-cite'
- end
- end
-
- describe '#rtl?' do
- it 'is false if text is empty' do
- expect(helper).not_to be_rtl ''
- end
-
- it 'is false if there are no right to left characters' do
- expect(helper).not_to be_rtl 'hello world'
- end
-
- it 'is false if right to left characters are fewer than 1/3 of total text' do
- expect(helper).not_to be_rtl 'hello ÝŸ world'
- end
-
- it 'is true if right to left characters are greater than 1/3 of total text' do
- expect(helper).to be_rtl 'aaÝŸaaÝŸ'
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/accept_spec.rb b/spec/lib/activitypub/activity/accept_spec.rb
deleted file mode 100644
index 883bab6a..00000000
--- a/spec/lib/activitypub/activity/accept_spec.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Accept do
- let(:sender) { Fabricate(:account) }
- let(:recipient) { Fabricate(:account) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Accept',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: {
- id: 'bar',
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(recipient),
- object: ActivityPub::TagManager.instance.uri_for(sender),
- },
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- Fabricate(:follow_request, account: recipient, target_account: sender)
- subject.perform
- end
-
- it 'creates a follow relationship' do
- expect(recipient.following?(sender)).to be true
- end
-
- it 'removes the follow request' do
- expect(recipient.requested?(sender)).to be false
- end
- end
-
- context 'given a relay' do
- let!(:relay) { Fabricate(:relay, state: :pending, follow_activity_id: 'https://abc-123/456') }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Accept',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: {
- id: 'https://abc-123/456',
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(recipient),
- object: ActivityPub::TagManager.instance.uri_for(sender),
- },
- }.with_indifferent_access
- end
-
- subject { described_class.new(json, sender) }
-
- it 'marks the relay as accepted' do
- subject.perform
- expect(relay.reload.accepted?).to be true
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/add_spec.rb b/spec/lib/activitypub/activity/add_spec.rb
deleted file mode 100644
index 16db71c8..00000000
--- a/spec/lib/activitypub/activity/add_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Add do
- let(:sender) { Fabricate(:account, featured_collection_url: 'https://example.com/featured') }
- let(:status) { Fabricate(:status, account: sender) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Add',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(status),
- target: sender.featured_collection_url,
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- it 'creates a pin' do
- subject.perform
- expect(sender.pinned?(status)).to be true
- end
-
- context 'when status was not known before' do
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Add',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: 'https://example.com/unknown',
- target: sender.featured_collection_url,
- }.with_indifferent_access
- end
-
- before do
- stub_request(:get, 'https://example.com/unknown').to_return(status: 410)
- end
-
- it 'fetches the status' do
- subject.perform
- expect(a_request(:get, 'https://example.com/unknown')).to have_been_made.at_least_once
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/announce_spec.rb b/spec/lib/activitypub/activity/announce_spec.rb
deleted file mode 100644
index ebafc137..00000000
--- a/spec/lib/activitypub/activity/announce_spec.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Announce do
- let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers', uri: 'https://example.com/actor') }
- let(:recipient) { Fabricate(:account) }
- let(:status) { Fabricate(:status, account: recipient) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Announce',
- actor: 'https://example.com/actor',
- object: object_json,
- to: 'http://example.com/followers',
- }.with_indifferent_access
- end
-
- let(:unknown_object_json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'https://example.com/actor/hello-world',
- type: 'Note',
- attributedTo: 'https://example.com/actor',
- content: 'Hello world',
- to: 'http://example.com/followers',
- }
- end
-
- subject { described_class.new(json, sender) }
-
- describe '#perform' do
- context 'when sender is followed by a local account' do
- before do
- Fabricate(:account).follow!(sender)
- stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json))
- subject.perform
- end
-
- context 'a known status' do
- let(:object_json) do
- ActivityPub::TagManager.instance.uri_for(status)
- end
-
- it 'creates a reblog by sender of status' do
- expect(sender.reblogged?(status)).to be true
- end
- end
-
- context 'an unknown status' do
- let(:object_json) { 'https://example.com/actor/hello-world' }
-
- it 'creates a reblog by sender of status' do
- reblog = sender.statuses.first
-
- expect(reblog).to_not be_nil
- expect(reblog.reblog.text).to eq 'Hello world'
- end
- end
-
- context 'self-repost of a previously unknown status with missing attributedTo' do
- let(:object_json) do
- {
- id: 'https://example.com/actor#bar',
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'http://example.com/followers',
- }
- end
-
- it 'creates a reblog by sender of status' do
- expect(sender.reblogged?(sender.statuses.first)).to be true
- end
- end
-
- context 'self-repost of a previously unknown status with correct attributedTo' do
- let(:object_json) do
- {
- id: 'https://example.com/actor#bar',
- type: 'Note',
- content: 'Lorem ipsum',
- attributedTo: 'https://example.com/actor',
- to: 'http://example.com/followers',
- }
- end
-
- it 'creates a reblog by sender of status' do
- expect(sender.reblogged?(sender.statuses.first)).to be true
- end
- end
- end
-
- context 'when the status belongs to a local user' do
- before do
- subject.perform
- end
-
- let(:object_json) do
- ActivityPub::TagManager.instance.uri_for(status)
- end
-
- it 'creates a reblog by sender of status' do
- expect(sender.reblogged?(status)).to be true
- end
- end
-
- context 'when the sender is relayed' do
- let!(:relay_account) { Fabricate(:account, inbox_url: 'https://relay.example.com/inbox') }
- let!(:relay) { Fabricate(:relay, inbox_url: 'https://relay.example.com/inbox') }
-
- subject { described_class.new(json, sender, relayed_through_account: relay_account) }
-
- context 'and the relay is enabled' do
- before do
- relay.update(state: :accepted)
- subject.perform
- end
-
- let(:object_json) do
- {
- id: 'https://example.com/actor#bar',
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'http://example.com/followers',
- }
- end
-
- it 'creates a reblog by sender of status' do
- expect(sender.statuses.count).to eq 2
- end
- end
-
- context 'and the relay is disabled' do
- before do
- subject.perform
- end
-
- let(:object_json) do
- {
- id: 'https://example.com/actor#bar',
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'http://example.com/followers',
- }
- end
-
- it 'does not create anything' do
- expect(sender.statuses.count).to eq 0
- end
- end
- end
-
- context 'when the sender has no relevance to local activity' do
- before do
- subject.perform
- end
-
- let(:object_json) do
- {
- id: 'https://example.com/actor#bar',
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'http://example.com/followers',
- }
- end
-
- it 'does not create anything' do
- expect(sender.statuses.count).to eq 0
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb
deleted file mode 100644
index 94d37356..00000000
--- a/spec/lib/activitypub/activity/block_spec.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Block do
- let(:sender) { Fabricate(:account) }
- let(:recipient) { Fabricate(:account) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Block',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(recipient),
- }.with_indifferent_access
- end
-
- context 'when the recipient does not follow the sender' do
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'creates a block from sender to recipient' do
- expect(sender.blocking?(recipient)).to be true
- end
- end
- end
-
- context 'when the recipient follows the sender' do
- before do
- recipient.follow!(sender)
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'creates a block from sender to recipient' do
- expect(sender.blocking?(recipient)).to be true
- end
-
- it 'ensures recipient is not following sender' do
- expect(recipient.following?(sender)).to be false
- end
- end
- end
-
- context 'when a matching undo has been received first' do
- let(:undo_json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'bar',
- type: 'Undo',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: json,
- }.with_indifferent_access
- end
-
- before do
- recipient.follow!(sender)
- ActivityPub::Activity::Undo.new(undo_json, sender).perform
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'does not create a block from sender to recipient' do
- expect(sender.blocking?(recipient)).to be false
- end
-
- it 'ensures recipient is not following sender' do
- expect(recipient.following?(sender)).to be false
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
deleted file mode 100644
index 412609de..00000000
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ /dev/null
@@ -1,631 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Create do
- let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor') }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#foo'].join,
- type: 'Create',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: object_json,
- }.with_indifferent_access
- end
-
- before do
- sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender))
-
- stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
- stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png'))
- end
-
- describe '#perform' do
- context 'when fetching' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- context 'unknown object type' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Banana',
- content: 'Lorem ipsum',
- }
- end
-
- it 'does not create a status' do
- expect(sender.statuses.count).to be_zero
- end
- end
-
- context 'standalone' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
-
- it 'missing to/cc defaults to direct privacy' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.visibility).to eq 'direct'
- end
- end
-
- context 'public' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'https://www.w3.org/ns/activitystreams#Public',
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.visibility).to eq 'public'
- end
- end
-
- context 'unlisted' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- cc: 'https://www.w3.org/ns/activitystreams#Public',
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.visibility).to eq 'unlisted'
- end
- end
-
- context 'private' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: 'http://example.com/followers',
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.visibility).to eq 'private'
- end
- end
-
- context 'limited' do
- let(:recipient) { Fabricate(:account) }
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: ActivityPub::TagManager.instance.uri_for(recipient),
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.visibility).to eq 'limited'
- end
-
- it 'creates silent mention' do
- status = sender.statuses.first
- expect(status.mentions.first).to be_silent
- end
- end
-
- context 'direct' do
- let(:recipient) { Fabricate(:account) }
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: ActivityPub::TagManager.instance.uri_for(recipient),
- tag: {
- type: 'Mention',
- href: ActivityPub::TagManager.instance.uri_for(recipient),
- },
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.visibility).to eq 'direct'
- end
- end
-
- context 'as a reply' do
- let(:original_status) { Fabricate(:status) }
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.thread).to eq original_status
- expect(status.reply?).to be true
- expect(status.in_reply_to_account).to eq original_status.account
- expect(status.conversation).to eq original_status.conversation
- end
- end
-
- context 'with mentions' do
- let(:recipient) { Fabricate(:account) }
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- tag: [
- {
- type: 'Mention',
- href: ActivityPub::TagManager.instance.uri_for(recipient),
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.mentions.map(&:account)).to include(recipient)
- end
- end
-
- context 'with mentions missing href' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- tag: [
- {
- type: 'Mention',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
- expect(status).to_not be_nil
- end
- end
-
- context 'with media attachments' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- attachment: [
- {
- type: 'Document',
- mediaType: 'image/png',
- url: 'http://example.com/attachment.png',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.media_attachments.map(&:remote_url)).to include('http://example.com/attachment.png')
- end
- end
-
- context 'with media attachments with focal points' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- attachment: [
- {
- type: 'Document',
- mediaType: 'image/png',
- url: 'http://example.com/attachment.png',
- focalPoint: [0.5, -0.7],
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.media_attachments.map(&:focus)).to include('0.5,-0.7')
- end
- end
-
- context 'with media attachments missing url' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- attachment: [
- {
- type: 'Document',
- mediaType: 'image/png',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
- expect(status).to_not be_nil
- end
- end
-
- context 'with hashtags' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- tag: [
- {
- type: 'Hashtag',
- href: 'http://example.com/blah',
- name: '#test',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.tags.map(&:name)).to include('test')
- end
- end
-
- context 'with hashtags missing name' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- tag: [
- {
- type: 'Hashtag',
- href: 'http://example.com/blah',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
- expect(status).to_not be_nil
- end
- end
-
- context 'with emojis' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum :tinking:',
- tag: [
- {
- type: 'Emoji',
- icon: {
- url: 'http://example.com/emoji.png',
- },
- name: 'tinking',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.emojis.map(&:shortcode)).to include('tinking')
- end
- end
-
- context 'with emojis missing name' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum :tinking:',
- tag: [
- {
- type: 'Emoji',
- icon: {
- url: 'http://example.com/emoji.png',
- },
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
- expect(status).to_not be_nil
- end
- end
-
- context 'with emojis missing icon' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum :tinking:',
- tag: [
- {
- type: 'Emoji',
- name: 'tinking',
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
- expect(status).to_not be_nil
- end
- end
-
- context 'with poll' do
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Question',
- content: 'Which color was the submarine?',
- oneOf: [
- {
- name: 'Yellow',
- replies: {
- type: 'Collection',
- totalItems: 10,
- },
- },
- {
- name: 'Blue',
- replies: {
- type: 'Collection',
- totalItems: 3,
- }
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
- expect(status).to_not be_nil
- expect(status.poll).to_not be_nil
- end
-
- it 'creates a poll' do
- poll = sender.polls.first
- expect(poll).to_not be_nil
- expect(poll.status).to_not be_nil
- expect(poll.options).to eq %w(Yellow Blue)
- expect(poll.cached_tallies).to eq [10, 3]
- end
- end
-
- context 'when a vote to a local poll' do
- let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) }
- let!(:local_status) { Fabricate(:status, poll: poll) }
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- name: 'Yellow',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status)
- }
- end
-
- it 'adds a vote to the poll with correct uri' do
- vote = poll.votes.first
- expect(vote).to_not be_nil
- expect(vote.uri).to eq object_json[:id]
- expect(poll.reload.cached_tallies).to eq [1, 0]
- end
- end
-
- context 'when a vote to an expired local poll' do
- let(:poll) do
- poll = Fabricate.build(:poll, options: %w(Yellow Blue), expires_at: 1.day.ago)
- poll.save(validate: false)
- poll
- end
- let!(:local_status) { Fabricate(:status, poll: poll) }
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- name: 'Yellow',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status)
- }
- end
-
- it 'does not add a vote to the poll' do
- expect(poll.votes.first).to be_nil
- end
- end
- end
-
- context 'when sender is followed by local users' do
- subject { described_class.new(json, sender, delivery: true) }
-
- before do
- Fabricate(:account).follow!(sender)
- subject.perform
- end
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
- end
-
- context 'when sender replies to local status' do
- let!(:local_status) { Fabricate(:status) }
-
- subject { described_class.new(json, sender, delivery: true) }
-
- before do
- subject.perform
- end
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status),
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
- end
-
- context 'when sender targets a local user' do
- let!(:local_account) { Fabricate(:account) }
-
- subject { described_class.new(json, sender, delivery: true) }
-
- before do
- subject.perform
- end
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- to: ActivityPub::TagManager.instance.uri_for(local_account),
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
- end
-
- context 'when sender cc\'s a local user' do
- let!(:local_account) { Fabricate(:account) }
-
- subject { described_class.new(json, sender, delivery: true) }
-
- before do
- subject.perform
- end
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- cc: ActivityPub::TagManager.instance.uri_for(local_account),
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
- end
-
- context 'when the sender has no relevance to local activity' do
- subject { described_class.new(json, sender, delivery: true) }
-
- before do
- subject.perform
- end
-
- let(:object_json) do
- {
- id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
- type: 'Note',
- content: 'Lorem ipsum',
- }
- end
-
- it 'does not create anything' do
- expect(sender.statuses.count).to eq 0
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/delete_spec.rb b/spec/lib/activitypub/activity/delete_spec.rb
deleted file mode 100644
index 37b93ecf..00000000
--- a/spec/lib/activitypub/activity/delete_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Delete do
- let(:sender) { Fabricate(:account, domain: 'example.com') }
- let(:status) { Fabricate(:status, account: sender, uri: 'foobar') }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Delete',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(status),
- signature: 'foo',
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'deletes sender\'s status' do
- expect(Status.find_by(id: status.id)).to be_nil
- end
- end
-
- context 'when the status has been reblogged' do
- describe '#perform' do
- subject { described_class.new(json, sender) }
- let!(:reblogger) { Fabricate(:account) }
- let!(:follower) { Fabricate(:account, username: 'follower', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
- let!(:reblog) { Fabricate(:status, account: reblogger, reblog: status) }
-
- before do
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- follower.follow!(reblogger)
- subject.perform
- end
-
- it 'deletes sender\'s status' do
- expect(Status.find_by(id: status.id)).to be_nil
- end
-
- it 'sends delete activity to followers of rebloggers' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/flag_spec.rb b/spec/lib/activitypub/activity/flag_spec.rb
deleted file mode 100644
index ec7359f2..00000000
--- a/spec/lib/activitypub/activity/flag_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Flag do
- let(:sender) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }
- let(:flagged) { Fabricate(:account) }
- let(:status) { Fabricate(:status, account: flagged, uri: 'foobar') }
- let(:flag_id) { nil }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: flag_id,
- type: 'Flag',
- content: 'Boo!!',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: [
- ActivityPub::TagManager.instance.uri_for(flagged),
- ActivityPub::TagManager.instance.uri_for(status),
- ],
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'creates a report' do
- report = Report.find_by(account: sender, target_account: flagged)
-
- expect(report).to_not be_nil
- expect(report.comment).to eq 'Boo!!'
- expect(report.status_ids).to eq [status.id]
- end
- end
-
- describe '#perform with a defined uri' do
- subject { described_class.new(json, sender) }
- let (:flag_id) { 'http://example.com/reports/1' }
-
- before do
- subject.perform
- end
-
- it 'creates a report' do
- report = Report.find_by(account: sender, target_account: flagged)
-
- expect(report).to_not be_nil
- expect(report.comment).to eq 'Boo!!'
- expect(report.status_ids).to eq [status.id]
- expect(report.uri).to eq flag_id
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/follow_spec.rb b/spec/lib/activitypub/activity/follow_spec.rb
deleted file mode 100644
index 6bbacdbe..00000000
--- a/spec/lib/activitypub/activity/follow_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Follow do
- let(:sender) { Fabricate(:account) }
- let(:recipient) { Fabricate(:account) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(recipient),
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- context 'unlocked account' do
- before do
- subject.perform
- end
-
- it 'creates a follow from sender to recipient' do
- expect(sender.following?(recipient)).to be true
- end
-
- it 'does not create a follow request' do
- expect(sender.requested?(recipient)).to be false
- end
- end
-
- context 'locked account' do
- before do
- recipient.update(locked: true)
- subject.perform
- end
-
- it 'does not create a follow from sender to recipient' do
- expect(sender.following?(recipient)).to be false
- end
-
- it 'creates a follow request' do
- expect(sender.requested?(recipient)).to be true
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/like_spec.rb b/spec/lib/activitypub/activity/like_spec.rb
deleted file mode 100644
index b69615a9..00000000
--- a/spec/lib/activitypub/activity/like_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Like do
- let(:sender) { Fabricate(:account) }
- let(:recipient) { Fabricate(:account) }
- let(:status) { Fabricate(:status, account: recipient) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Like',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(status),
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'creates a favourite from sender to status' do
- expect(sender.favourited?(status)).to be true
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/move_spec.rb b/spec/lib/activitypub/activity/move_spec.rb
deleted file mode 100644
index 3574f273..00000000
--- a/spec/lib/activitypub/activity/move_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Move do
- let(:follower) { Fabricate(:account) }
- let(:old_account) { Fabricate(:account) }
- let(:new_account) { Fabricate(:account) }
-
- before do
- follower.follow!(old_account)
-
- old_account.update!(uri: 'https://example.org/alice', domain: 'example.org', protocol: :activitypub, inbox_url: 'https://example.org/inbox')
- new_account.update!(uri: 'https://example.com/alice', domain: 'example.com', protocol: :activitypub, inbox_url: 'https://example.com/inbox', also_known_as: [old_account.uri])
-
- stub_request(:post, 'https://example.org/inbox').to_return(status: 200)
- stub_request(:post, 'https://example.com/inbox').to_return(status: 200)
-
- service_stub = double
- allow(ActivityPub::FetchRemoteAccountService).to receive(:new).and_return(service_stub)
- allow(service_stub).to receive(:call).and_return(new_account)
- end
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Move',
- actor: old_account.uri,
- object: old_account.uri,
- target: new_account.uri,
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, old_account) }
-
- before do
- subject.perform
- end
-
- it 'sets moved account on old account' do
- expect(old_account.reload.moved_to_account_id).to eq new_account.id
- end
-
- it 'makes followers unfollow old account' do
- expect(follower.following?(old_account)).to be false
- end
-
- it 'makes followers follow-request the new account' do
- expect(follower.requested?(new_account)).to be true
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/reject_spec.rb b/spec/lib/activitypub/activity/reject_spec.rb
deleted file mode 100644
index e7205df8..00000000
--- a/spec/lib/activitypub/activity/reject_spec.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Reject do
- let(:sender) { Fabricate(:account) }
- let(:recipient) { Fabricate(:account) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Reject',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: {
- id: 'bar',
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(recipient),
- object: ActivityPub::TagManager.instance.uri_for(sender),
- },
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- Fabricate(:follow_request, account: recipient, target_account: sender)
- subject.perform
- end
-
- it 'does not create a follow relationship' do
- expect(recipient.following?(sender)).to be false
- end
-
- it 'removes the follow request' do
- expect(recipient.requested?(sender)).to be false
- end
- end
-
- context 'given a relay' do
- let!(:relay) { Fabricate(:relay, state: :pending, follow_activity_id: 'https://abc-123/456') }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Reject',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: {
- id: 'https://abc-123/456',
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(recipient),
- object: ActivityPub::TagManager.instance.uri_for(sender),
- },
- }.with_indifferent_access
- end
-
- subject { described_class.new(json, sender) }
-
- it 'marks the relay as rejected' do
- subject.perform
- expect(relay.reload.rejected?).to be true
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/remove_spec.rb b/spec/lib/activitypub/activity/remove_spec.rb
deleted file mode 100644
index 4209dfde..00000000
--- a/spec/lib/activitypub/activity/remove_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Remove do
- let(:sender) { Fabricate(:account, featured_collection_url: 'https://example.com/featured') }
- let(:status) { Fabricate(:status, account: sender) }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Add',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(status),
- target: sender.featured_collection_url,
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- StatusPin.create!(account: sender, status: status)
- subject.perform
- end
-
- it 'removes a pin' do
- expect(sender.pinned?(status)).to be false
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/undo_spec.rb b/spec/lib/activitypub/activity/undo_spec.rb
deleted file mode 100644
index 9545e1f4..00000000
--- a/spec/lib/activitypub/activity/undo_spec.rb
+++ /dev/null
@@ -1,147 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Undo do
- let(:sender) { Fabricate(:account, domain: 'example.com') }
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Undo',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: object_json,
- }.with_indifferent_access
- end
-
- subject { described_class.new(json, sender) }
-
- describe '#perform' do
- context 'with Announce' do
- let(:status) { Fabricate(:status) }
-
- let(:object_json) do
- {
- id: 'bar',
- type: 'Announce',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(status),
- atomUri: 'barbar',
- }
- end
-
- context do
- before do
- Fabricate(:status, reblog: status, account: sender, uri: 'bar')
- end
-
- it 'deletes the reblog' do
- subject.perform
- expect(sender.reblogged?(status)).to be false
- end
- end
-
- context 'with atomUri' do
- before do
- Fabricate(:status, reblog: status, account: sender, uri: 'barbar')
- end
-
- it 'deletes the reblog by atomUri' do
- subject.perform
- expect(sender.reblogged?(status)).to be false
- end
- end
- end
-
- context 'with Accept' do
- let(:recipient) { Fabricate(:account) }
- let(:object_json) do
- {
- id: 'bar',
- type: 'Accept',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: 'follow-to-revoke',
- }
- end
-
- before do
- recipient.follow!(sender, uri: 'follow-to-revoke')
- end
-
- it 'deletes follow from recipient to sender' do
- subject.perform
- expect(recipient.following?(sender)).to be false
- end
-
- it 'creates a follow request from recipient to sender' do
- subject.perform
- expect(recipient.requested?(sender)).to be true
- end
- end
-
- context 'with Block' do
- let(:recipient) { Fabricate(:account) }
-
- let(:object_json) do
- {
- id: 'bar',
- type: 'Block',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(recipient),
- }
- end
-
- before do
- sender.block!(recipient)
- end
-
- it 'deletes block from sender to recipient' do
- subject.perform
- expect(sender.blocking?(recipient)).to be false
- end
- end
-
- context 'with Follow' do
- let(:recipient) { Fabricate(:account) }
-
- let(:object_json) do
- {
- id: 'bar',
- type: 'Follow',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(recipient),
- }
- end
-
- before do
- sender.follow!(recipient)
- end
-
- it 'deletes follow from sender to recipient' do
- subject.perform
- expect(sender.following?(recipient)).to be false
- end
- end
-
- context 'with Like' do
- let(:status) { Fabricate(:status) }
-
- let(:object_json) do
- {
- id: 'bar',
- type: 'Like',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: ActivityPub::TagManager.instance.uri_for(status),
- }
- end
-
- before do
- Fabricate(:favourite, account: sender, status: status)
- end
-
- it 'deletes favourite from sender to status' do
- subject.perform
- expect(sender.favourited?(status)).to be false
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/activity/update_spec.rb b/spec/lib/activitypub/activity/update_spec.rb
deleted file mode 100644
index fbfc585c..00000000
--- a/spec/lib/activitypub/activity/update_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Activity::Update do
- let!(:sender) { Fabricate(:account) }
-
- before do
- stub_request(:get, actor_json[:outbox]).to_return(status: 404)
- stub_request(:get, actor_json[:followers]).to_return(status: 404)
- stub_request(:get, actor_json[:following]).to_return(status: 404)
- stub_request(:get, actor_json[:featured]).to_return(status: 404)
-
- sender.update!(uri: ActivityPub::TagManager.instance.uri_for(sender))
- end
-
- let(:modified_sender) do
- sender.dup.tap do |modified_sender|
- modified_sender.display_name = 'Totally modified now'
- end
- end
-
- let(:actor_json) do
- ActiveModelSerializers::SerializableResource.new(modified_sender, serializer: ActivityPub::ActorSerializer, key_transform: :camel_lower).as_json
- end
-
- let(:json) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Update',
- actor: ActivityPub::TagManager.instance.uri_for(sender),
- object: actor_json,
- }.with_indifferent_access
- end
-
- describe '#perform' do
- subject { described_class.new(json, sender) }
-
- before do
- subject.perform
- end
-
- it 'updates profile' do
- expect(sender.reload.display_name).to eq 'Totally modified now'
- end
- end
-end
diff --git a/spec/lib/activitypub/adapter_spec.rb b/spec/lib/activitypub/adapter_spec.rb
deleted file mode 100644
index ea03797a..00000000
--- a/spec/lib/activitypub/adapter_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::Adapter do
- class TestObject < ActiveModelSerializers::Model
- attributes :foo
- end
-
- class TestWithBasicContextSerializer < ActivityPub::Serializer
- attributes :foo
- end
-
- class TestWithNamedContextSerializer < ActivityPub::Serializer
- context :security
- attributes :foo
- end
-
- class TestWithNestedNamedContextSerializer < ActivityPub::Serializer
- attributes :foo
-
- has_one :virtual_object, key: :baz, serializer: TestWithNamedContextSerializer
-
- def virtual_object
- object
- end
- end
-
- class TestWithContextExtensionSerializer < ActivityPub::Serializer
- context_extensions :sensitive
- attributes :foo
- end
-
- class TestWithNestedContextExtensionSerializer < ActivityPub::Serializer
- context_extensions :manually_approves_followers
- attributes :foo
-
- has_one :virtual_object, key: :baz, serializer: TestWithContextExtensionSerializer
-
- def virtual_object
- object
- end
- end
-
- describe '#serializable_hash' do
- let(:serializer_class) {}
-
- subject { ActiveModelSerializers::SerializableResource.new(TestObject.new(foo: 'bar'), serializer: serializer_class, adapter: described_class).as_json }
-
- context 'when serializer defines no context' do
- let(:serializer_class) { TestWithBasicContextSerializer }
-
- it 'renders a basic @context' do
- expect(subject).to include({ '@context' => 'https://www.w3.org/ns/activitystreams' })
- end
- end
-
- context 'when serializer defines a named context' do
- let(:serializer_class) { TestWithNamedContextSerializer }
-
- it 'renders a @context with both items' do
- expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })
- end
- end
-
- context 'when serializer has children that define a named context' do
- let(:serializer_class) { TestWithNestedNamedContextSerializer }
-
- it 'renders a @context with both items' do
- expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })
- end
- end
-
- context 'when serializer defines context extensions' do
- let(:serializer_class) { TestWithContextExtensionSerializer }
-
- it 'renders a @context with the extension' do
- expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', { 'sensitive' => 'as:sensitive' }] })
- end
- end
-
- context 'when serializer has children that define context extensions' do
- let(:serializer_class) { TestWithNestedContextExtensionSerializer }
-
- it 'renders a @context with both extensions' do
- expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive' }] })
- end
- end
- end
-end
diff --git a/spec/lib/activitypub/linked_data_signature_spec.rb b/spec/lib/activitypub/linked_data_signature_spec.rb
deleted file mode 100644
index 1f413eec..00000000
--- a/spec/lib/activitypub/linked_data_signature_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::LinkedDataSignature do
- include JsonLdHelper
-
- let!(:sender) { Fabricate(:account, uri: 'http://example.com/alice') }
-
- let(:raw_json) do
- {
- '@context' => 'https://www.w3.org/ns/activitystreams',
- 'id' => 'http://example.com/hello-world',
- }
- end
-
- let(:json) { raw_json.merge('signature' => signature) }
-
- subject { described_class.new(json) }
-
- before do
- stub_jsonld_contexts!
- end
-
- describe '#verify_account!' do
- context 'when signature matches' do
- let(:raw_signature) do
- {
- 'creator' => 'http://example.com/alice',
- 'created' => '2017-09-23T20:21:34Z',
- }
- end
-
- let(:signature) { raw_signature.merge('type' => 'RsaSignature2017', 'signatureValue' => sign(sender, raw_signature, raw_json)) }
-
- it 'returns creator' do
- expect(subject.verify_account!).to eq sender
- end
- end
-
- context 'when signature is missing' do
- let(:signature) { nil }
-
- it 'returns nil' do
- expect(subject.verify_account!).to be_nil
- end
- end
-
- context 'when signature is tampered' do
- let(:raw_signature) do
- {
- 'creator' => 'http://example.com/alice',
- 'created' => '2017-09-23T20:21:34Z',
- }
- end
-
- let(:signature) { raw_signature.merge('type' => 'RsaSignature2017', 'signatureValue' => 's69F3mfddd99dGjmvjdjjs81e12jn121Gkm1') }
-
- it 'returns nil' do
- expect(subject.verify_account!).to be_nil
- end
- end
- end
-
- describe '#sign!' do
- subject { described_class.new(raw_json).sign!(sender) }
-
- it 'returns a hash' do
- expect(subject).to be_a Hash
- end
-
- it 'contains signature' do
- expect(subject['signature']).to be_a Hash
- expect(subject['signature']['signatureValue']).to be_present
- end
-
- it 'can be verified again' do
- expect(described_class.new(subject).verify_account!).to eq sender
- end
- end
-
- def sign(from_account, options, document)
- options_hash = Digest::SHA256.hexdigest(canonicalize(options.merge('@context' => ActivityPub::LinkedDataSignature::CONTEXT)))
- document_hash = Digest::SHA256.hexdigest(canonicalize(document))
- to_be_verified = options_hash + document_hash
- Base64.strict_encode64(from_account.keypair.sign(OpenSSL::Digest::SHA256.new, to_be_verified))
- end
-end
diff --git a/spec/lib/activitypub/tag_manager_spec.rb b/spec/lib/activitypub/tag_manager_spec.rb
deleted file mode 100644
index 6d246629..00000000
--- a/spec/lib/activitypub/tag_manager_spec.rb
+++ /dev/null
@@ -1,157 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::TagManager do
- include RoutingHelper
-
- subject { described_class.instance }
-
- describe '#url_for' do
- it 'returns a string' do
- account = Fabricate(:account)
- expect(subject.url_for(account)).to be_a String
- end
- end
-
- describe '#uri_for' do
- it 'returns a string' do
- account = Fabricate(:account)
- expect(subject.uri_for(account)).to be_a String
- end
- end
-
- describe '#to' do
- it 'returns public collection for public status' do
- status = Fabricate(:status, visibility: :public)
- expect(subject.to(status)).to eq ['https://www.w3.org/ns/activitystreams#Public']
- end
-
- it 'returns followers collection for unlisted status' do
- status = Fabricate(:status, visibility: :unlisted)
- expect(subject.to(status)).to eq [account_followers_url(status.account)]
- end
-
- it 'returns followers collection for private status' do
- status = Fabricate(:status, visibility: :private)
- expect(subject.to(status)).to eq [account_followers_url(status.account)]
- end
-
- it 'returns URIs of mentions for direct status' do
- status = Fabricate(:status, visibility: :direct)
- mentioned = Fabricate(:account)
- status.mentions.create(account: mentioned)
- expect(subject.to(status)).to eq [subject.uri_for(mentioned)]
- end
-
- it "returns URIs of mentions for direct silenced author's status only if they are followers or requesting to be" do
- bob = Fabricate(:account, username: 'bob')
- alice = Fabricate(:account, username: 'alice')
- foo = Fabricate(:account)
- author = Fabricate(:account, username: 'author', silenced: true)
- status = Fabricate(:status, visibility: :direct, account: author)
- bob.follow!(author)
- FollowRequest.create!(account: foo, target_account: author)
- status.mentions.create(account: alice)
- status.mentions.create(account: bob)
- status.mentions.create(account: foo)
- expect(subject.to(status)).to include(subject.uri_for(bob))
- expect(subject.to(status)).to include(subject.uri_for(foo))
- expect(subject.to(status)).to_not include(subject.uri_for(alice))
- end
- end
-
- describe '#cc' do
- it 'returns followers collection for public status' do
- status = Fabricate(:status, visibility: :public)
- expect(subject.cc(status)).to eq [account_followers_url(status.account)]
- end
-
- it 'returns public collection for unlisted status' do
- status = Fabricate(:status, visibility: :unlisted)
- expect(subject.cc(status)).to eq ['https://www.w3.org/ns/activitystreams#Public']
- end
-
- it 'returns empty array for private status' do
- status = Fabricate(:status, visibility: :private)
- expect(subject.cc(status)).to eq []
- end
-
- it 'returns empty array for direct status' do
- status = Fabricate(:status, visibility: :direct)
- expect(subject.cc(status)).to eq []
- end
-
- it 'returns URIs of mentions for non-direct status' do
- status = Fabricate(:status, visibility: :public)
- mentioned = Fabricate(:account)
- status.mentions.create(account: mentioned)
- expect(subject.cc(status)).to include(subject.uri_for(mentioned))
- end
-
- it "returns URIs of mentions for silenced author's non-direct status only if they are followers or requesting to be" do
- bob = Fabricate(:account, username: 'bob')
- alice = Fabricate(:account, username: 'alice')
- foo = Fabricate(:account)
- author = Fabricate(:account, username: 'author', silenced: true)
- status = Fabricate(:status, visibility: :public, account: author)
- bob.follow!(author)
- FollowRequest.create!(account: foo, target_account: author)
- status.mentions.create(account: alice)
- status.mentions.create(account: bob)
- status.mentions.create(account: foo)
- expect(subject.cc(status)).to include(subject.uri_for(bob))
- expect(subject.cc(status)).to include(subject.uri_for(foo))
- expect(subject.cc(status)).to_not include(subject.uri_for(alice))
- end
- end
-
- describe '#local_uri?' do
- it 'returns false for non-local URI' do
- expect(subject.local_uri?('http://example.com/123')).to be false
- end
-
- it 'returns true for local URIs' do
- account = Fabricate(:account)
- expect(subject.local_uri?(subject.uri_for(account))).to be true
- end
- end
-
- describe '#uri_to_local_id' do
- it 'returns the local ID' do
- account = Fabricate(:account)
- expect(subject.uri_to_local_id(subject.uri_for(account), :username)).to eq account.username
- end
- end
-
- describe '#uri_to_resource' do
- it 'returns the local account' do
- account = Fabricate(:account)
- expect(subject.uri_to_resource(subject.uri_for(account), Account)).to eq account
- end
-
- it 'returns the remote account by matching URI without fragment part' do
- account = Fabricate(:account, uri: 'https://example.com/123')
- expect(subject.uri_to_resource('https://example.com/123#456', Account)).to eq account
- end
-
- it 'returns the local status for ActivityPub URI' do
- status = Fabricate(:status)
- expect(subject.uri_to_resource(subject.uri_for(status), Status)).to eq status
- end
-
- it 'returns the local status for OStatus tag: URI' do
- status = Fabricate(:status)
- expect(subject.uri_to_resource(OStatus::TagManager.instance.uri_for(status), Status)).to eq status
- end
-
- it 'returns the local status for OStatus StreamEntry URL' do
- status = Fabricate(:status)
- stream_entry_url = account_stream_entry_url(status.account, status.stream_entry)
- expect(subject.uri_to_resource(stream_entry_url, Status)).to eq status
- end
-
- it 'returns the remote status by matching URI without fragment part' do
- status = Fabricate(:status, uri: 'https://example.com/123')
- expect(subject.uri_to_resource('https://example.com/123#456', Status)).to eq status
- end
- end
-end
diff --git a/spec/lib/delivery_failure_tracker_spec.rb b/spec/lib/delivery_failure_tracker_spec.rb
deleted file mode 100644
index 39c8c7aa..00000000
--- a/spec/lib/delivery_failure_tracker_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe DeliveryFailureTracker do
- subject { described_class.new('http://example.com/inbox') }
-
- describe '#track_success!' do
- before do
- subject.track_failure!
- subject.track_success!
- end
-
- it 'marks URL as available again' do
- expect(described_class.available?('http://example.com/inbox')).to be true
- end
-
- it 'resets days to 0' do
- expect(subject.days).to be_zero
- end
- end
-
- describe '#track_failure!' do
- it 'marks URL as unavailable after 7 days of being called' do
- 6.times { |i| Redis.current.sadd('exhausted_deliveries:http://example.com/inbox', i) }
- subject.track_failure!
-
- expect(subject.days).to eq 7
- expect(described_class.unavailable?('http://example.com/inbox')).to be true
- end
-
- it 'repeated calls on the same day do not count' do
- subject.track_failure!
- subject.track_failure!
-
- expect(subject.days).to eq 1
- end
- end
-
- describe '.filter' do
- before do
- Redis.current.sadd('unavailable_inboxes', 'http://example.com/unavailable/inbox')
- end
-
- it 'removes URLs that are unavailable' do
- result = described_class.filter(['http://example.com/good/inbox', 'http://example.com/unavailable/inbox'])
-
- expect(result).to include('http://example.com/good/inbox')
- expect(result).to_not include('http://example.com/unavailable/inbox')
- end
- end
-
- describe '.track_inverse_success!' do
- let(:from_account) { Fabricate(:account, inbox_url: 'http://example.com/inbox', shared_inbox_url: 'http://example.com/shared/inbox') }
-
- before do
- Redis.current.sadd('unavailable_inboxes', 'http://example.com/inbox')
- Redis.current.sadd('unavailable_inboxes', 'http://example.com/shared/inbox')
-
- described_class.track_inverse_success!(from_account)
- end
-
- it 'marks inbox URL as available again' do
- expect(described_class.available?('http://example.com/inbox')).to be true
- end
-
- it 'marks shared inbox URL as available again' do
- expect(described_class.available?('http://example.com/shared/inbox')).to be true
- end
- end
-end
diff --git a/spec/lib/extractor_spec.rb b/spec/lib/extractor_spec.rb
deleted file mode 100644
index dba4bd0b..00000000
--- a/spec/lib/extractor_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Extractor do
- describe 'extract_mentions_or_lists_with_indices' do
- it 'returns an empty array if the given string does not have at signs' do
- text = 'a string without at signs'
- extracted = Extractor.extract_mentions_or_lists_with_indices(text)
- expect(extracted).to eq []
- end
-
- it 'does not extract mentions which ends with particular characters' do
- text = '@screen_name@'
- extracted = Extractor.extract_mentions_or_lists_with_indices(text)
- expect(extracted).to eq []
- end
-
- it 'returns mentions as an array' do
- text = '@screen_name'
- extracted = Extractor.extract_mentions_or_lists_with_indices(text)
- expect(extracted).to eq [
- { screen_name: 'screen_name', indices: [ 0, 12 ] }
- ]
- end
-
- it 'yields mentions if a block is given' do
- text = '@screen_name'
- Extractor.extract_mentions_or_lists_with_indices(text) do |screen_name, start_position, end_position|
- expect(screen_name).to eq 'screen_name'
- expect(start_position).to eq 0
- expect(end_position).to eq 12
- end
- end
- end
-
- describe 'extract_hashtags_with_indices' do
- it 'returns an empty array if it does not have #' do
- text = 'a string without hash sign'
- extracted = Extractor.extract_hashtags_with_indices(text)
- expect(extracted).to eq []
- end
-
- it 'does not exclude normal hash text before ://' do
- text = '#hashtag://'
- extracted = Extractor.extract_hashtags_with_indices(text)
- expect(extracted).to eq [ { hashtag: 'hashtag', indices: [ 0, 8 ] } ]
- end
-
- it 'excludes http://' do
- text = '#hashtaghttp://'
- extracted = Extractor.extract_hashtags_with_indices(text)
- expect(extracted).to eq [ { hashtag: 'hashtag', indices: [ 0, 8 ] } ]
- end
-
- it 'excludes https://' do
- text = '#hashtaghttps://'
- extracted = Extractor.extract_hashtags_with_indices(text)
- expect(extracted).to eq [ { hashtag: 'hashtag', indices: [ 0, 8 ] } ]
- end
-
- it 'yields hashtags if a block is given' do
- text = '#hashtag'
- Extractor.extract_hashtags_with_indices(text) do |hashtag, start_position, end_position|
- expect(hashtag).to eq 'hashtag'
- expect(start_position).to eq 0
- expect(end_position).to eq 8
- end
- end
- end
-
- describe 'extract_cashtags_with_indices' do
- it 'returns []' do
- text = '$cashtag'
- extracted = Extractor.extract_cashtags_with_indices(text)
- expect(extracted).to eq []
- end
- end
-end
diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb
deleted file mode 100644
index 5f8eb86a..00000000
--- a/spec/lib/feed_manager_spec.rb
+++ /dev/null
@@ -1,407 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FeedManager do
- before do |example|
- unless example.metadata[:skip_stub]
- stub_const 'FeedManager::MAX_ITEMS', 10
- stub_const 'FeedManager::REBLOG_FALLOFF', 4
- end
- end
-
- it 'tracks at least as many statuses as reblogs', skip_stub: true do
- expect(FeedManager::REBLOG_FALLOFF).to be <= FeedManager::MAX_ITEMS
- end
-
- describe '#key' do
- subject { FeedManager.instance.key(:home, 1) }
-
- it 'returns a string' do
- expect(subject).to be_a String
- end
- end
-
- describe '#filter?' do
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
- let(:jeff) { Fabricate(:account, username: 'jeff') }
-
- context 'for home feed' do
- it 'returns false for followee\'s status' do
- status = Fabricate(:status, text: 'Hello world', account: alice)
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:home, status, bob.id)).to be false
- end
-
- it 'returns false for reblog by followee' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reblog = Fabricate(:status, reblog: status, account: alice)
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be false
- end
-
- it 'returns true for reblog by followee of blocked account' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reblog = Fabricate(:status, reblog: status, account: alice)
- bob.follow!(alice)
- bob.block!(jeff)
- expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true
- end
-
- it 'returns true for reblog by followee of muted account' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reblog = Fabricate(:status, reblog: status, account: alice)
- bob.follow!(alice)
- bob.mute!(jeff)
- expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true
- end
-
- it 'returns true for reblog by followee of someone who is blocking recipient' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reblog = Fabricate(:status, reblog: status, account: alice)
- bob.follow!(alice)
- jeff.block!(bob)
- expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true
- end
-
- it 'returns true for reblog from account with reblogs disabled' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reblog = Fabricate(:status, reblog: status, account: alice)
- bob.follow!(alice, reblogs: false)
- expect(FeedManager.instance.filter?(:home, reblog, bob.id)).to be true
- end
-
- it 'returns false for reply by followee to another followee' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reply = Fabricate(:status, text: 'Nay', thread: status, account: alice)
- bob.follow!(alice)
- bob.follow!(jeff)
- expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be false
- end
-
- it 'returns false for reply by followee to recipient' do
- status = Fabricate(:status, text: 'Hello world', account: bob)
- reply = Fabricate(:status, text: 'Nay', thread: status, account: alice)
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be false
- end
-
- it 'returns false for reply by followee to self' do
- status = Fabricate(:status, text: 'Hello world', account: alice)
- reply = Fabricate(:status, text: 'Nay', thread: status, account: alice)
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be false
- end
-
- it 'returns true for reply by followee to non-followed account' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reply = Fabricate(:status, text: 'Nay', thread: status, account: alice)
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:home, reply, bob.id)).to be true
- end
-
- it 'returns true for the second reply by followee to a non-federated status' do
- reply = Fabricate(:status, text: 'Reply 1', reply: true, account: alice)
- second_reply = Fabricate(:status, text: 'Reply 2', thread: reply, account: alice)
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:home, second_reply, bob.id)).to be true
- end
-
- it 'returns false for status by followee mentioning another account' do
- bob.follow!(alice)
- status = PostStatusService.new.call(alice, text: 'Hey @jeff')
- expect(FeedManager.instance.filter?(:home, status, bob.id)).to be false
- end
-
- it 'returns true for status by followee mentioning blocked account' do
- bob.block!(jeff)
- bob.follow!(alice)
- status = PostStatusService.new.call(alice, text: 'Hey @jeff')
- expect(FeedManager.instance.filter?(:home, status, bob.id)).to be true
- end
-
- it 'returns true for reblog of a personally blocked domain' do
- alice.block_domain!('example.com')
- alice.follow!(jeff)
- status = Fabricate(:status, text: 'Hello world', account: bob)
- reblog = Fabricate(:status, reblog: status, account: jeff)
- expect(FeedManager.instance.filter?(:home, reblog, alice.id)).to be true
- end
-
- context 'for irreversibly muted phrases' do
- it 'considers word boundaries when matching' do
- alice.custom_filters.create!(phrase: 'bob', context: %w(home), irreversible: true)
- alice.follow!(jeff)
- status = Fabricate(:status, text: 'bobcats', account: jeff)
- expect(FeedManager.instance.filter?(:home, status, alice.id)).to be_falsy
- end
-
- it 'returns true if phrase is contained' do
- alice.custom_filters.create!(phrase: 'farts', context: %w(home public), irreversible: true)
- alice.custom_filters.create!(phrase: 'pop tarts', context: %w(home), irreversible: true)
- alice.follow!(jeff)
- status = Fabricate(:status, text: 'i sure like POP TARts', account: jeff)
- expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true
- end
-
- it 'matches substrings if whole_word is false' do
- alice.custom_filters.create!(phrase: 'take', context: %w(home), whole_word: false, irreversible: true)
- alice.follow!(jeff)
- status = Fabricate(:status, text: 'shiitake', account: jeff)
- expect(FeedManager.instance.filter?(:home, status, alice.id)).to be true
- end
- end
- end
-
- context 'for mentions feed' do
- it 'returns true for status that mentions blocked account' do
- bob.block!(jeff)
- status = PostStatusService.new.call(alice, text: 'Hey @jeff')
- expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be true
- end
-
- it 'returns true for status that replies to a blocked account' do
- status = Fabricate(:status, text: 'Hello world', account: jeff)
- reply = Fabricate(:status, text: 'Nay', thread: status, account: alice)
- bob.block!(jeff)
- expect(FeedManager.instance.filter?(:mentions, reply, bob.id)).to be true
- end
-
- it 'returns true for status by silenced account who recipient is not following' do
- status = Fabricate(:status, text: 'Hello world', account: alice)
- alice.silence!
- expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be true
- end
-
- it 'returns false for status by followed silenced account' do
- status = Fabricate(:status, text: 'Hello world', account: alice)
- alice.silence!
- bob.follow!(alice)
- expect(FeedManager.instance.filter?(:mentions, status, bob.id)).to be false
- end
- end
- end
-
- describe '#push_to_home' do
- it 'trims timelines if they will have more than FeedManager::MAX_ITEMS' do
- account = Fabricate(:account)
- status = Fabricate(:status)
- members = FeedManager::MAX_ITEMS.times.map { |count| [count, count] }
- Redis.current.zadd("feed:home:#{account.id}", members)
-
- FeedManager.instance.push_to_home(account, status)
-
- expect(Redis.current.zcard("feed:home:#{account.id}")).to eq FeedManager::MAX_ITEMS
- end
-
- context 'reblogs' do
- it 'saves reblogs of unseen statuses' do
- account = Fabricate(:account)
- reblogged = Fabricate(:status)
- reblog = Fabricate(:status, reblog: reblogged)
-
- expect(FeedManager.instance.push_to_home(account, reblog)).to be true
- end
-
- it 'does not save a new reblog of a recent status' do
- account = Fabricate(:account)
- reblogged = Fabricate(:status)
- reblog = Fabricate(:status, reblog: reblogged)
-
- FeedManager.instance.push_to_home(account, reblogged)
-
- expect(FeedManager.instance.push_to_home(account, reblog)).to be false
- end
-
- it 'saves a new reblog of an old status' do
- account = Fabricate(:account)
- reblogged = Fabricate(:status)
- reblog = Fabricate(:status, reblog: reblogged)
-
- FeedManager.instance.push_to_home(account, reblogged)
-
- # Fill the feed with intervening statuses
- FeedManager::REBLOG_FALLOFF.times do
- FeedManager.instance.push_to_home(account, Fabricate(:status))
- end
-
- expect(FeedManager.instance.push_to_home(account, reblog)).to be true
- end
-
- it 'does not save a new reblog of a recently-reblogged status' do
- account = Fabricate(:account)
- reblogged = Fabricate(:status)
- reblogs = 2.times.map { Fabricate(:status, reblog: reblogged) }
-
- # The first reblog will be accepted
- FeedManager.instance.push_to_home(account, reblogs.first)
-
- # The second reblog should be ignored
- expect(FeedManager.instance.push_to_home(account, reblogs.last)).to be false
- end
-
- it 'does not save a new reblog of a multiply-reblogged-then-unreblogged status' do
- account = Fabricate(:account)
- reblogged = Fabricate(:status)
- reblogs = 3.times.map { Fabricate(:status, reblog: reblogged) }
-
- # Accept the reblogs
- FeedManager.instance.push_to_home(account, reblogs[0])
- FeedManager.instance.push_to_home(account, reblogs[1])
-
- # Unreblog the first one
- FeedManager.instance.unpush_from_home(account, reblogs[0])
-
- # The last reblog should still be ignored
- expect(FeedManager.instance.push_to_home(account, reblogs.last)).to be false
- end
-
- it 'saves a new reblog of a long-ago-reblogged status' do
- account = Fabricate(:account)
- reblogged = Fabricate(:status)
- reblogs = 2.times.map { Fabricate(:status, reblog: reblogged) }
-
- # The first reblog will be accepted
- FeedManager.instance.push_to_home(account, reblogs.first)
-
- # Fill the feed with intervening statuses
- FeedManager::REBLOG_FALLOFF.times do
- FeedManager.instance.push_to_home(account, Fabricate(:status))
- end
-
- # The second reblog should also be accepted
- expect(FeedManager.instance.push_to_home(account, reblogs.last)).to be true
- end
- end
-
- it "does not push when the given status's reblog is already inserted" do
- account = Fabricate(:account)
- reblog = Fabricate(:status)
- status = Fabricate(:status, reblog: reblog)
- FeedManager.instance.push_to_home(account, status)
-
- expect(FeedManager.instance.push_to_home(account, reblog)).to eq false
- end
- end
-
- describe '#push_to_list' do
- it "does not push when the given status's reblog is already inserted" do
- list = Fabricate(:list)
- reblog = Fabricate(:status)
- status = Fabricate(:status, reblog: reblog)
- FeedManager.instance.push_to_list(list, status)
-
- expect(FeedManager.instance.push_to_list(list, reblog)).to eq false
- end
- end
-
- describe '#merge_into_timeline' do
- it "does not push source account's statuses whose reblogs are already inserted" do
- account = Fabricate(:account, id: 0)
- reblog = Fabricate(:status)
- status = Fabricate(:status, reblog: reblog)
- FeedManager.instance.push_to_home(account, status)
-
- FeedManager.instance.merge_into_timeline(account, reblog.account)
-
- expect(Redis.current.zscore("feed:home:0", reblog.id)).to eq nil
- end
- end
-
- describe '#trim' do
- let(:receiver) { Fabricate(:account) }
-
- it 'cleans up reblog tracking keys' do
- reblogged = Fabricate(:status)
- status = Fabricate(:status, reblog: reblogged)
- another_status = Fabricate(:status, reblog: reblogged)
- reblogs_key = FeedManager.instance.key('home', receiver.id, 'reblogs')
- reblog_set_key = FeedManager.instance.key('home', receiver.id, "reblogs:#{reblogged.id}")
-
- FeedManager.instance.push_to_home(receiver, status)
- FeedManager.instance.push_to_home(receiver, another_status)
-
- # We should have a tracking set and an entry in reblogs.
- expect(Redis.current.exists(reblog_set_key)).to be true
- expect(Redis.current.zrange(reblogs_key, 0, -1)).to eq [reblogged.id.to_s]
-
- # Push everything off the end of the feed.
- FeedManager::MAX_ITEMS.times do
- FeedManager.instance.push_to_home(receiver, Fabricate(:status))
- end
-
- # `trim` should be called automatically, but do it anyway, as
- # we're testing `trim`, not side effects of `push`.
- FeedManager.instance.trim('home', receiver.id)
-
- # We should not have any reblog tracking data.
- expect(Redis.current.exists(reblog_set_key)).to be false
- expect(Redis.current.zrange(reblogs_key, 0, -1)).to be_empty
- end
- end
-
- describe '#unpush' do
- let(:receiver) { Fabricate(:account) }
-
- it 'leaves a reblogged status if original was on feed' do
- reblogged = Fabricate(:status)
- status = Fabricate(:status, reblog: reblogged)
-
- FeedManager.instance.push_to_home(receiver, reblogged)
- FeedManager::REBLOG_FALLOFF.times { FeedManager.instance.push_to_home(receiver, Fabricate(:status)) }
- FeedManager.instance.push_to_home(receiver, status)
-
- # The reblogging status should show up under normal conditions.
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to include(status.id.to_s)
-
- FeedManager.instance.unpush_from_home(receiver, status)
-
- # Restore original status
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to_not include(status.id.to_s)
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to include(reblogged.id.to_s)
- end
-
- it 'removes a reblogged status if it was only reblogged once' do
- reblogged = Fabricate(:status)
- status = Fabricate(:status, reblog: reblogged)
-
- FeedManager.instance.push_to_home(receiver, status)
-
- # The reblogging status should show up under normal conditions.
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to eq [status.id.to_s]
-
- FeedManager.instance.unpush_from_home(receiver, status)
-
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to be_empty
- end
-
- it 'leaves a multiply-reblogged status if another reblog was in feed' do
- reblogged = Fabricate(:status)
- reblogs = 3.times.map { Fabricate(:status, reblog: reblogged) }
-
- reblogs.each do |reblog|
- FeedManager.instance.push_to_home(receiver, reblog)
- end
-
- # The reblogging status should show up under normal conditions.
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to eq [reblogs.first.id.to_s]
-
- reblogs[0...-1].each do |reblog|
- FeedManager.instance.unpush_from_home(receiver, reblog)
- end
-
- expect(Redis.current.zrange("feed:home:#{receiver.id}", 0, -1)).to eq [reblogs.last.id.to_s]
- end
-
- it 'sends push updates' do
- status = Fabricate(:status)
-
- FeedManager.instance.push_to_home(receiver, status)
-
- allow(Redis.current).to receive_messages(publish: nil)
- FeedManager.instance.unpush_from_home(receiver, status)
-
- deletion = Oj.dump(event: :delete, payload: status.id.to_s)
- expect(Redis.current).to have_received(:publish).with("timeline:#{receiver.id}", deletion)
- end
- end
-end
diff --git a/spec/lib/formatter_spec.rb b/spec/lib/formatter_spec.rb
deleted file mode 100644
index d167a243..00000000
--- a/spec/lib/formatter_spec.rb
+++ /dev/null
@@ -1,594 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Formatter do
- let(:local_account) { Fabricate(:account, domain: nil, username: 'alice') }
- let(:remote_account) { Fabricate(:account, domain: 'remote.test', username: 'bob', url: 'https://remote.test/') }
-
- shared_examples 'encode and link URLs' do
- context 'given a stand-alone medium URL' do
- let(:text) { 'https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4"'
- end
- end
-
- context 'given a stand-alone google URL' do
- let(:text) { 'http://google.com' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="http://google.com"'
- end
- end
-
- context 'given a stand-alone IDN URL' do
- let(:text) { 'https://nic.ã¿ã‚“ãª/' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://nic.ã¿ã‚“ãª/"'
- end
-
- it 'has display URL' do
- is_expected.to include 'nic.ã¿ã‚“ãª/ '
- end
- end
-
- context 'given a URL with a trailing period' do
- let(:text) { 'http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona. ' }
-
- it 'matches the full URL but not the period' do
- is_expected.to include 'href="http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona"'
- end
- end
-
- context 'given a URL enclosed with parentheses' do
- let(:text) { '(http://google.com/)' }
-
- it 'matches the full URL but not the parentheses' do
- is_expected.to include 'href="http://google.com/"'
- end
- end
-
- context 'given a URL with a trailing exclamation point' do
- let(:text) { 'http://www.google.com!' }
-
- it 'matches the full URL but not the exclamation point' do
- is_expected.to include 'href="http://www.google.com"'
- end
- end
-
- context 'given a URL with a trailing single quote' do
- let(:text) { "http://www.google.com'" }
-
- it 'matches the full URL but not the single quote' do
- is_expected.to include 'href="http://www.google.com"'
- end
- end
-
- context 'given a URL with a trailing angle bracket' do
- let(:text) { 'http://www.google.com>' }
-
- it 'matches the full URL but not the angle bracket' do
- is_expected.to include 'href="http://www.google.com"'
- end
- end
-
- context 'given a URL with a query string' do
- context 'with escaped unicode character' do
- let(:text) { 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink"'
- end
- end
-
- context 'with unicode character' do
- let(:text) { 'https://www.ruby-toolbox.com/search?utf8=✓&q=autolink' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=✓&q=autolink"'
- end
- end
-
- context 'with unicode character at the end' do
- let(:text) { 'https://www.ruby-toolbox.com/search?utf8=✓' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=✓"'
- end
- end
-
- context 'with escaped and not escaped unicode characters' do
- let(:text) { 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&utf81=✓&q=autolink' }
-
- it 'preserves escaped unicode characters' do
- is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&utf81=✓&q=autolink"'
- end
- end
- end
-
- context 'given a URL with parentheses in it' do
- let(:text) { 'https://en.wikipedia.org/wiki/Diaspora_(software)' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://en.wikipedia.org/wiki/Diaspora_(software)"'
- end
- end
-
- context 'given a URL in quotation marks' do
- let(:text) { '"https://example.com/"' }
-
- it 'does not match the quotation marks' do
- is_expected.to include 'href="https://example.com/"'
- end
- end
-
- context 'given a URL in angle brackets' do
- let(:text) { ' ' }
-
- it 'does not match the angle brackets' do
- is_expected.to include 'href="https://example.com/"'
- end
- end
-
- context 'given a URL with Japanese path string' do
- let(:text) { 'https://ja.wikipedia.org/wiki/日本' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://ja.wikipedia.org/wiki/日本"'
- end
- end
-
- context 'given a URL with Korean path string' do
- let(:text) { 'https://ko.wikipedia.org/wiki/대한민êµ' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://ko.wikipedia.org/wiki/대한민êµ"'
- end
- end
-
- context 'given a URL with a full-width space' do
- let(:text) { 'https://example.com/ abc123' }
-
- it 'does not match the full-width space' do
- is_expected.to include 'href="https://example.com/"'
- end
- end
-
- context 'given a URL in Japanese quotation marks' do
- let(:text) { '「[https://example.org/ã€' }
-
- it 'does not match the quotation marks' do
- is_expected.to include 'href="https://example.org/"'
- end
- end
-
- context 'given a URL with Simplified Chinese path string' do
- let(:text) { 'https://baike.baidu.com/item/ä¸åŽäººæ°‘共和国' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://baike.baidu.com/item/ä¸åŽäººæ°‘共和国"'
- end
- end
-
- context 'given a URL with Traditional Chinese path string' do
- let(:text) { 'https://zh.wikipedia.org/wiki/臺ç£' }
-
- it 'matches the full URL' do
- is_expected.to include 'href="https://zh.wikipedia.org/wiki/臺ç£"'
- end
- end
-
- context 'given a URL containing unsafe code (XSS attack, visible part)' do
- let(:text) { %q{http://example.com/bb} }
-
- it 'does not include the HTML in the URL' do
- is_expected.to include '"http://example.com/b"'
- end
-
- it 'escapes the HTML' do
- is_expected.to include '<del>b</del>'
- end
- end
-
- context 'given a URL containing unsafe code (XSS attack, invisible part)' do
- let(:text) { %q{http://example.com/blahblahblahblah/a} }
-
- it 'does not include the HTML in the URL' do
- is_expected.to include '"http://example.com/blahblahblahblah/a"'
- end
-
- it 'escapes the HTML' do
- is_expected.to include '<script>alert("Hello")</script>'
- end
- end
-
- context 'given text containing HTML code (script tag)' do
- let(:text) { '' }
-
- it 'escapes the HTML' do
- is_expected.to include '<script>alert("Hello")</script>
'
- end
- end
-
- context 'given text containing HTML (XSS attack)' do
- let(:text) { %q{ } }
-
- it 'escapes the HTML' do
- is_expected.to include '<img src="javascript:alert('XSS');">
'
- end
- end
-
- context 'given an invalid URL' do
- let(:text) { 'http://www\.google\.com' }
-
- it 'outputs the raw URL' do
- is_expected.to eq 'http://www\.google\.com
'
- end
- end
-
- context 'given text containing a hashtag' do
- let(:text) { '#hashtag' }
-
- it 'creates a hashtag link' do
- is_expected.to include '/tags/hashtag" class="mention hashtag" rel="tag">#hashtag '
- end
- end
-
- context 'given text containing a hashtag with Unicode chars' do
- let(:text) { '#hashtagã‚¿ã‚°' }
-
- it 'creates a hashtag link' do
- is_expected.to include '/tags/hashtag%E3%82%BF%E3%82%B0" class="mention hashtag" rel="tag">#hashtagã‚¿ã‚° '
- end
- end
- end
-
- describe '#format_spoiler' do
- subject { Formatter.instance.format_spoiler(status) }
-
- context 'given a post containing plain text' do
- let(:status) { Fabricate(:status, text: 'text', spoiler_text: 'Secret!', uri: nil) }
-
- it 'Returns the spoiler text' do
- is_expected.to eq 'Secret!'
- end
- end
-
- context 'given a post with an emoji shortcode at the start' do
- let!(:emoji) { Fabricate(:custom_emoji) }
- let(:status) { Fabricate(:status, text: 'text', spoiler_text: ':coolcat: Secret!', uri: nil) }
- let(:text) { ':coolcat: Beep boop' }
-
- it 'converts the shortcode to an image tag' do
- is_expected.to match(/@alice Hello world'
- end
- end
-
- context 'given a post containing plain text' do
- let(:status) { Fabricate(:status, text: 'text', uri: nil) }
-
- it 'paragraphizes the text' do
- is_expected.to eq 'text
'
- end
- end
-
- context 'given a post containing line feeds' do
- let(:status) { Fabricate(:status, text: "line\nfeed", uri: nil) }
-
- it 'removes line feeds' do
- is_expected.not_to include "\n"
- end
- end
-
- context 'given a post containing linkable mentions' do
- let(:status) { Fabricate(:status, mentions: [ Fabricate(:mention, account: local_account) ], text: '@alice') }
-
- it 'creates a mention link' do
- is_expected.to include '@alice '
- end
- end
-
- context 'given a post containing unlinkable mentions' do
- let(:status) { Fabricate(:status, text: '@alice', uri: nil) }
-
- it 'does not create a mention link' do
- is_expected.to include '@alice'
- end
- end
-
- context do
- subject do
- status = Fabricate(:status, text: text, uri: nil)
- Formatter.instance.format(status)
- end
-
- include_examples 'encode and link URLs'
- end
-
- context 'given a post with custom_emojify option' do
- let!(:emoji) { Fabricate(:custom_emoji) }
- let(:status) { Fabricate(:status, account: local_account, text: text) }
-
- subject { Formatter.instance.format(status, custom_emojify: true) }
-
- context 'given a post with an emoji shortcode at the start' do
- let(:text) { ':coolcat: Beep boop' }
-
- it 'converts the shortcode to an image tag' do
- is_expected.to match(/ :coolcat: Beep boop ' }
-
- it 'converts the shortcode to an image tag' do
- is_expected.to match(/
Beep :coolcat: boop
' }
-
- it 'converts the shortcode to an image tag' do
- is_expected.to match(/Beep :coolcat::coolcat:' }
-
- it 'does not touch the shortcodes' do
- is_expected.to match(/:coolcat::coolcat:<\/p>/)
- end
- end
-
- context 'given a post with an emoji shortcode at the end' do
- let(:text) { '
Beep boop :coolcat:
' }
-
- it 'converts the shortcode to an image tag' do
- is_expected.to match(/ alert("Hello")' }
-
- it 'strips the scripts' do
- is_expected.to_not include ''
- end
- end
-
- context 'given a post containing malicious classes' do
- let(:text) { 'Show more ' }
-
- it 'strips the malicious classes' do
- is_expected.to_not include 'status__content__spoiler-link'
- end
- end
- end
-
- describe '#plaintext' do
- subject { Formatter.instance.plaintext(status) }
-
- context 'given a post with local status' do
- let(:status) { Fabricate(:status, text: 'a text by a nerd who uses an HTML tag in text
', uri: nil) }
-
- it 'returns the raw text' do
- is_expected.to eq 'a text by a nerd who uses an HTML tag in text
'
- end
- end
-
- context 'given a post with remote status' do
- let(:status) { Fabricate(:status, account: remote_account, text: '') }
-
- it 'returns tag-stripped text' do
- is_expected.to eq ''
- end
- end
- end
-
- describe '#simplified_format' do
- subject { Formatter.instance.simplified_format(account) }
-
- context 'given a post with local status' do
- let(:account) { Fabricate(:account, domain: nil, note: text) }
-
- context 'given a post containing linkable mentions for local accounts' do
- let(:text) { '@alice' }
-
- before { local_account }
-
- it 'creates a mention link' do
- is_expected.to eq '@alice
'
- end
- end
-
- context 'given a post containing linkable mentions for remote accounts' do
- let(:text) { '@bob@remote.test' }
-
- before { remote_account }
-
- it 'creates a mention link' do
- is_expected.to eq '@bob
'
- end
- end
-
- context 'given a post containing unlinkable mentions' do
- let(:text) { '@alice' }
-
- it 'does not create a mention link' do
- is_expected.to eq '@alice
'
- end
- end
-
- context 'given a post with custom_emojify option' do
- let!(:emoji) { Fabricate(:custom_emoji) }
-
- before { account.note = text }
- subject { Formatter.instance.simplified_format(account, custom_emojify: true) }
-
- context 'given a post with an emoji shortcode at the start' do
- let(:text) { ':coolcat: Beep boop' }
-
- it 'converts the shortcode to an image tag' do
- is_expected.to match(/ alert("Hello")' }
- let(:account) { Fabricate(:account, domain: 'remote', note: text) }
-
- it 'reformats' do
- is_expected.to_not include ''
- end
-
- context 'with custom_emojify option' do
- let!(:emoji) { Fabricate(:custom_emoji, domain: remote_account.domain) }
-
- before { remote_account.note = text }
-
- subject { Formatter.instance.simplified_format(remote_account, custom_emojify: true) }
-
- context 'given a post with an emoji shortcode at the start' do
- let(:text) { '
:coolcat: Beep boop ' }
-
- it 'converts shortcode to image tag' do
- is_expected.to match(/
Beep :coolcat: boop
' }
-
- it 'converts shortcode to image tag' do
- is_expected.to match(/Beep :coolcat::coolcat:' }
-
- it 'does not touch the shortcodes' do
- is_expected.to match(/:coolcat::coolcat:<\/p>/)
- end
- end
-
- context 'given a post with an emoji shortcode at the end' do
- let(:text) { '
Beep boop :coolcat:
' }
-
- it 'converts shortcode to image tag' do
- is_expected.to match(/ alert("Hello")' }
-
- subject { Formatter.instance.sanitize(html, Sanitize::Config::GABSOCIAL_STRICT) }
-
- it 'sanitizes' do
- is_expected.to eq ''
- end
- end
-end
diff --git a/spec/lib/hash_object_spec.rb b/spec/lib/hash_object_spec.rb
deleted file mode 100644
index ce180652..00000000
--- a/spec/lib/hash_object_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe HashObject do
- it 'has methods corresponding to hash properties' do
- expect(HashObject.new(key: 'value').key).to eq 'value'
- end
-end
diff --git a/spec/lib/language_detector_spec.rb b/spec/lib/language_detector_spec.rb
deleted file mode 100644
index d2b443ed..00000000
--- a/spec/lib/language_detector_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe LanguageDetector do
- describe 'prepare_text' do
- it 'returns unmodified string without special cases' do
- string = 'just a regular string'
- result = described_class.instance.send(:prepare_text, string)
-
- expect(result).to eq string
- end
-
- it 'collapses spacing in strings' do
- string = 'The formatting in this is very odd'
-
- result = described_class.instance.send(:prepare_text, string)
- expect(result).to eq 'The formatting in this is very odd'
- end
-
- it 'strips usernames from strings before detection' do
- string = '@username Yeah, very surreal...! also @friend'
-
- result = described_class.instance.send(:prepare_text, string)
- expect(result).to eq 'Yeah, very surreal...! also'
- end
-
- it 'strips URLs from strings before detection' do
- string = 'Our website is https://example.com and also http://localhost.dev'
-
- result = described_class.instance.send(:prepare_text, string)
- expect(result).to eq 'Our website is and also'
- end
-
- it 'strips #hashtags from strings before detection' do
- string = 'Hey look at all the #animals and #fish'
-
- result = described_class.instance.send(:prepare_text, string)
- expect(result).to eq 'Hey look at all the and'
- end
- end
-
- describe 'detect' do
- let(:account_without_user_locale) { Fabricate(:user, locale: nil).account }
- let(:account_remote) { Fabricate(:account, domain: 'gab.com') }
-
- it 'detects english language for basic strings' do
- strings = [
- "Hello and welcome to Gab Social how are you today?",
- "I'd rather not!",
- "a lot of people just want to feel righteous all the time and that's all that matters",
- ]
- strings.each do |string|
- result = described_class.instance.detect(string, account_without_user_locale)
-
- expect(result).to eq(:en), string
- end
- end
-
- it 'detects spanish language' do
- string = 'Obtener un Hola y bienvenidos a Gab Social. Obtener un Hola y bienvenidos a Gab Social. Obtener un Hola y bienvenidos a Gab Social. Obtener un Hola y bienvenidos a Gab Social'
- result = described_class.instance.detect(string, account_without_user_locale)
-
- expect(result).to eq :es
- end
-
- describe 'when language can\'t be detected' do
- it 'uses nil when sent an empty document' do
- result = described_class.instance.detect('', account_without_user_locale)
- expect(result).to eq nil
- end
-
- describe 'because of a URL' do
- it 'uses nil when sent just a URL' do
- string = 'http://example.com/media/2kFTgOJLXhQf0g2nKB4'
- cld_result = CLD3::NNetLanguageIdentifier.new(0, 2048).find_language(string)
- expect(cld_result).not_to eq :en
-
- result = described_class.instance.detect(string, account_without_user_locale)
-
- expect(result).to eq nil
- end
- end
-
- describe 'with an account' do
- it 'uses the account locale when present' do
- account = double(user_locale: 'fr')
- result = described_class.instance.detect('', account)
-
- expect(result).to eq nil
- end
-
- it 'uses nil when account is present but has no locale' do
- result = described_class.instance.detect('', account_without_user_locale)
-
- expect(result).to eq nil
- end
- end
-
- describe 'with an `en` default locale' do
- it 'uses nil for undetectable string' do
- result = described_class.instance.detect('', account_without_user_locale)
-
- expect(result).to eq nil
- end
- end
-
- describe 'remote user' do
- it 'detects Korean language' do
- string = '안녕하세요'
- result = described_class.instance.detect(string, account_remote)
-
- expect(result).to eq :ko
- end
- end
-
- describe 'with a non-`en` default locale' do
- around(:each) do |example|
- before = I18n.default_locale
- I18n.default_locale = :ja
- example.run
- I18n.default_locale = before
- end
-
- it 'uses nil for undetectable string' do
- string = ''
- result = described_class.instance.detect(string, account_without_user_locale)
-
- expect(result).to eq nil
- end
- end
- end
- end
-end
diff --git a/spec/lib/ostatus/atom_serializer_spec.rb b/spec/lib/ostatus/atom_serializer_spec.rb
deleted file mode 100644
index bfb957a8..00000000
--- a/spec/lib/ostatus/atom_serializer_spec.rb
+++ /dev/null
@@ -1,1560 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe OStatus::AtomSerializer do
- shared_examples 'follow request salmon' do
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'username')
- follow_request = Fabricate(:follow_request, account: account)
-
- follow_request_salmon = serialize(follow_request)
-
- expect(follow_request_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends activity:object-type element with activity type' do
- follow_request = Fabricate(:follow_request)
-
- follow_request_salmon = serialize(follow_request)
-
- object_type = follow_request_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with request_friend type' do
- follow_request = Fabricate(:follow_request)
-
- follow_request_salmon = serialize(follow_request)
-
- verb = follow_request_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:request_friend]
- end
-
- it 'appends activity:object with target account' do
- target_account = Fabricate(:account, domain: 'domain.test', uri: 'https://domain.test/id')
- follow_request = Fabricate(:follow_request, target_account: target_account)
-
- follow_request_salmon = serialize(follow_request)
-
- object = follow_request_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq 'https://domain.test/id'
- end
- end
-
- shared_examples 'namespaces' do
- it 'adds namespaces' do
- element = serialize
-
- expect(element['xmlns']).to eq OStatus::TagManager::XMLNS
- expect(element['xmlns:thr']).to eq OStatus::TagManager::THR_XMLNS
- expect(element['xmlns:activity']).to eq OStatus::TagManager::AS_XMLNS
- expect(element['xmlns:poco']).to eq OStatus::TagManager::POCO_XMLNS
- expect(element['xmlns:media']).to eq OStatus::TagManager::MEDIA_XMLNS
- expect(element['xmlns:ostatus']).to eq OStatus::TagManager::OS_XMLNS
- expect(element['xmlns:gabsocial']).to eq OStatus::TagManager::MTDN_XMLNS
- end
- end
-
- shared_examples 'no namespaces' do
- it 'does not add namespaces' do
- expect(serialize['xmlns']).to eq nil
- end
- end
-
- shared_examples 'status attributes' do
- it 'appends summary element with spoiler text if present' do
- status = Fabricate(:status, language: :ca, spoiler_text: 'spoiler text')
-
- element = serialize(status)
-
- summary = element.summary
- expect(summary['xml:lang']).to eq 'ca'
- expect(summary.text).to eq 'spoiler text'
- end
-
- it 'does not append summary element with spoiler text if not present' do
- status = Fabricate(:status, spoiler_text: '')
- element = serialize(status)
- element.nodes.each { |node| expect(node.name).not_to eq 'summary' }
- end
-
- it 'appends content element with formatted status' do
- status = Fabricate(:status, language: :ca, text: 'text')
-
- element = serialize(status)
-
- content = element.content
- expect(content[:type]).to eq 'html'
- expect(content['xml:lang']).to eq 'ca'
- expect(content.text).to eq 'text
'
- end
-
- it 'appends link elements for mentioned accounts' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status)
- Fabricate(:mention, account: account, status: status)
-
- element = serialize(status)
-
- mentioned = element.nodes.find do |node|
- node.name == 'link' &&
- node[:rel] == 'mentioned' &&
- node['ostatus:object-type'] == OStatus::TagManager::TYPES[:person]
- end
-
- expect(mentioned[:href]).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends link elements for emojis' do
- Fabricate(:custom_emoji)
-
- status = Fabricate(:status, text: ':coolcat:')
- element = serialize(status)
- emoji = element.nodes.find { |node| node.name == 'link' && node[:rel] == 'emoji' }
-
- expect(emoji[:name]).to eq 'coolcat'
- expect(emoji[:href]).to_not be_blank
- end
- end
-
- describe 'render' do
- it 'returns XML with emojis' do
- element = Ox::Element.new('tag')
- element << '💩'
- xml = OStatus::AtomSerializer.render(element)
-
- expect(xml).to eq "\n💩 \n"
- end
-
- it 'returns XML, stripping invalid characters like \b and \v' do
- element = Ox::Element.new('tag')
- element << "im l33t\b haxo\b\vr"
- xml = OStatus::AtomSerializer.render(element)
-
- expect(xml).to eq "\nim l33t haxor \n"
- end
- end
-
- describe '#author' do
- context 'when note is present' do
- it 'appends poco:note element with note for local account' do
- account = Fabricate(:account, domain: nil, note: 'note
')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- note = author.nodes.find { |node| node.name == 'poco:note' }
- expect(note.text).to eq 'note
'
- end
-
- it 'appends poco:note element with tags-stripped note for remote account' do
- account = Fabricate(:account, domain: 'remote', note: 'note
')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- note = author.nodes.find { |node| node.name == 'poco:note' }
- expect(note.text).to eq 'note'
- end
-
- it 'appends summary element with type attribute and simplified note if present' do
- account = Fabricate(:account, note: 'note')
- author = OStatus::AtomSerializer.new.author(account)
- expect(author.summary.text).to eq 'note
'
- expect(author.summary[:type]).to eq 'html'
- end
- end
-
- context 'when note is not present' do
- it 'does not append poco:note element' do
- account = Fabricate(:account, note: '')
- author = OStatus::AtomSerializer.new.author(account)
- author.nodes.each { |node| expect(node.name).not_to eq 'poco:note' }
- end
-
- it 'does not append summary element' do
- account = Fabricate(:account, note: '')
- author = OStatus::AtomSerializer.new.author(account)
- author.nodes.each { |node| expect(node.name).not_to eq 'summary' }
- end
- end
-
- it 'returns author element' do
- account = Fabricate(:account)
- author = OStatus::AtomSerializer.new.author(account)
- expect(author.name).to eq 'author'
- end
-
- it 'appends activity:object-type element with person type' do
- account = Fabricate(:account, domain: nil, username: 'username')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- object_type = author.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:person]
- end
-
- it 'appends email element with username and domain for local account' do
- account = Fabricate(:account, username: 'username')
- author = OStatus::AtomSerializer.new.author(account)
- expect(author.email.text).to eq 'username@cb6e6126.ngrok.io'
- end
-
- it 'appends email element with username and domain for remote user' do
- account = Fabricate(:account, domain: 'domain', username: 'username')
- author = OStatus::AtomSerializer.new.author(account)
- expect(author.email.text).to eq 'username@domain'
- end
-
- it 'appends link element for an alternative' do
- account = Fabricate(:account, domain: nil, username: 'username')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- link = author.nodes.find { |node| node.name == 'link' && node[:rel] == 'alternate' && node[:type] == 'text/html' }
- expect(link[:type]).to eq 'text/html'
- expect(link[:rel]).to eq 'alternate'
- expect(link[:href]).to eq 'https://cb6e6126.ngrok.io/@username'
- end
-
- it 'has link element for avatar if present' do
- account = Fabricate(:account, avatar: attachment_fixture('avatar.gif'))
-
- author = OStatus::AtomSerializer.new.author(account)
-
- link = author.nodes.find { |node| node.name == 'link' && node[:rel] == 'avatar' }
- expect(link[:type]).to eq 'image/gif'
- expect(link['media:width']).to eq '120'
- expect(link['media:height']).to eq '120'
- expect(link[:href]).to match /^https:\/\/cb6e6126.ngrok.io\/system\/accounts\/avatars\/.+\/original\/avatar.gif/
- end
-
- it 'does not have link element for avatar if not present' do
- account = Fabricate(:account, avatar: nil)
-
- author = OStatus::AtomSerializer.new.author(account)
-
- author.nodes.each do |node|
- expect(node[:rel]).not_to eq 'avatar' if node.name == 'link'
- end
- end
-
- it 'appends link element for header if present' do
- account = Fabricate(:account, header: attachment_fixture('avatar.gif'))
-
- author = OStatus::AtomSerializer.new.author(account)
-
- link = author.nodes.find { |node| node.name == 'link' && node[:rel] == 'header' }
- expect(link[:type]).to eq 'image/gif'
- expect(link['media:width']).to eq '700'
- expect(link['media:height']).to eq '335'
- expect(link[:href]).to match /^https:\/\/cb6e6126.ngrok.io\/system\/accounts\/headers\/.+\/original\/avatar.gif/
- end
-
- it 'does not append link element for header if not present' do
- account = Fabricate(:account, header: nil)
-
- author = OStatus::AtomSerializer.new.author(account)
-
- author.nodes.each do |node|
- expect(node[:rel]).not_to eq 'header' if node.name == 'link'
- end
- end
-
- it 'appends poco:displayName element with display name if present' do
- account = Fabricate(:account, display_name: 'display name')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- display_name = author.nodes.find { |node| node.name == 'poco:displayName' }
- expect(display_name.text).to eq 'display name'
- end
-
- it 'does not append poco:displayName element with display name if not present' do
- account = Fabricate(:account, display_name: '')
- author = OStatus::AtomSerializer.new.author(account)
- author.nodes.each { |node| expect(node.name).not_to eq 'poco:displayName' }
- end
-
- it "appends gabsocial:scope element with 'private' if locked" do
- account = Fabricate(:account, locked: true)
-
- author = OStatus::AtomSerializer.new.author(account)
-
- scope = author.nodes.find { |node| node.name == 'gabsocial:scope' }
- expect(scope.text).to eq 'private'
- end
-
- it "appends gabsocial:scope element with 'public' if unlocked" do
- account = Fabricate(:account, locked: false)
-
- author = OStatus::AtomSerializer.new.author(account)
-
- scope = author.nodes.find { |node| node.name == 'gabsocial:scope' }
- expect(scope.text).to eq 'public'
- end
-
- it 'includes URI' do
- account = Fabricate(:account, domain: nil, username: 'username')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- expect(author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- expect(author.uri.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'includes username' do
- account = Fabricate(:account, username: 'username')
-
- author = OStatus::AtomSerializer.new.author(account)
-
- name = author.nodes.find { |node| node.name == 'name' }
- username = author.nodes.find { |node| node.name == 'poco:preferredUsername' }
- expect(name.text).to eq 'username'
- expect(username.text).to eq 'username'
- end
- end
-
- describe '#entry' do
- shared_examples 'not root' do
- include_examples 'no namespaces' do
- def serialize
- subject
- end
- end
-
- it 'does not append author element' do
- subject.nodes.each { |node| expect(node.name).not_to eq 'author' }
- end
- end
-
- context 'it is root' do
- include_examples 'namespaces' do
- def serialize
- stream_entry = Fabricate(:stream_entry)
- OStatus::AtomSerializer.new.entry(stream_entry, true)
- end
- end
-
- it 'appends author element' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry, true)
-
- expect(entry.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
- end
-
- context 'if status is present' do
- include_examples 'status attributes' do
- def serialize(status)
- OStatus::AtomSerializer.new.entry(status.stream_entry, true)
- end
- end
-
- it 'appends link element for the public collection if status is publicly visible' do
- status = Fabricate(:status, visibility: :public)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- mentioned_person = entry.nodes.find do |node|
- node.name == 'link' &&
- node[:rel] == 'mentioned' &&
- node['ostatus:object-type'] == OStatus::TagManager::TYPES[:collection]
- end
- expect(mentioned_person[:href]).to eq OStatus::TagManager::COLLECTIONS[:public]
- end
-
- it 'does not append link element for the public collection if status is not publicly visible' do
- status = Fabricate(:status, visibility: :private)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- entry.nodes.each do |node|
- if node.name == 'link' &&
- node[:rel] == 'mentioned' &&
- node['ostatus:object-type'] == OStatus::TagManager::TYPES[:collection]
- expect(mentioned_collection[:href]).not_to eq OStatus::TagManager::COLLECTIONS[:public]
- end
- end
- end
-
- it 'appends category elements for tags' do
- tag = Fabricate(:tag, name: 'tag')
- status = Fabricate(:status, tags: [ tag ])
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- expect(entry.category[:term]).to eq 'tag'
- end
-
- it 'appends link elements for media attachments' do
- file = attachment_fixture('attachment.jpg')
- media_attachment = Fabricate(:media_attachment, file: file)
- status = Fabricate(:status, media_attachments: [ media_attachment ])
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- enclosure = entry.nodes.find { |node| node.name == 'link' && node[:rel] == 'enclosure' }
- expect(enclosure[:type]).to eq 'image/jpeg'
- expect(enclosure[:href]).to match /^https:\/\/cb6e6126.ngrok.io\/system\/media_attachments\/files\/.+\/original\/attachment.jpg$/
- end
-
- it 'appends gabsocial:scope element with visibility' do
- status = Fabricate(:status, visibility: :public)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- scope = entry.nodes.find { |node| node.name == 'gabsocial:scope' }
- expect(scope.text).to eq 'public'
- end
-
- it 'returns element whose rendered view triggers creation when processed' do
- remote_account = Account.create!(username: 'username')
- remote_status = Fabricate(:status, account: remote_account, created_at: '2000-01-01T00:00:00Z')
-
- entry = OStatus::AtomSerializer.new.entry(remote_status.stream_entry, true)
- entry.nodes.delete_if { |node| node[:type] == 'application/activity+json' } # Remove ActivityPub link to simplify test
- xml = OStatus::AtomSerializer.render(entry).gsub('cb6e6126.ngrok.io', 'remote.test')
-
- remote_status.destroy!
- remote_account.destroy!
-
- account = Account.create!(
- domain: 'remote.test',
- username: 'username',
- last_webfingered_at: Time.now.utc
- )
-
- ProcessFeedService.new.call(xml, account)
-
- expect(Status.find_by(uri: "https://remote.test/users/#{remote_status.account.to_param}/statuses/#{remote_status.id}")).to be_instance_of Status
- end
- end
-
- context 'if status is not present' do
- it 'appends content element saying status is deleted' do
- status = Fabricate(:status)
- status.destroy!
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- expect(entry.content.text).to eq 'Deleted status'
- end
-
- it 'appends title element saying the status is deleted' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
- status.destroy!
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- expect(entry.title.text).to eq 'username deleted status'
- end
- end
-
- context 'it is not root' do
- let(:stream_entry) { Fabricate(:stream_entry) }
- subject { OStatus::AtomSerializer.new.entry(stream_entry, false) }
- include_examples 'not root'
- end
-
- context 'without root parameter' do
- let(:stream_entry) { Fabricate(:stream_entry) }
- subject { OStatus::AtomSerializer.new.entry(stream_entry) }
- include_examples 'not root'
- end
-
- it 'returns entry element' do
- stream_entry = Fabricate(:stream_entry)
- entry = OStatus::AtomSerializer.new.entry(stream_entry)
- expect(entry.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- status = Fabricate(:status, reblog_of_id: nil, created_at: '2000-01-01T00:00:00Z')
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- expect(entry.id.text).to eq "https://cb6e6126.ngrok.io/users/#{status.account.to_param}/statuses/#{status.id}"
- end
-
- it 'appends published element with created date' do
- stream_entry = Fabricate(:stream_entry, created_at: '2000-01-01T00:00:00Z')
- entry = OStatus::AtomSerializer.new.entry(stream_entry)
- expect(entry.published.text).to eq '2000-01-01T00:00:00Z'
- end
-
- it 'appends updated element with updated date' do
- stream_entry = Fabricate(:stream_entry, updated_at: '2000-01-01T00:00:00Z')
- entry = OStatus::AtomSerializer.new.entry(stream_entry)
- expect(entry.updated.text).to eq '2000-01-01T00:00:00Z'
- end
-
- it 'appends title element with status title' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account, reblog_of_id: nil)
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
- expect(entry.title.text).to eq 'New status by username'
- end
-
- it 'appends activity:object-type element with object type' do
- status = Fabricate(:status)
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
- object_type = entry.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:note]
- end
-
- it 'appends activity:verb element with object type' do
- status = Fabricate(:status)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- object_type = entry.nodes.find { |node| node.name == 'activity:verb' }
- expect(object_type.text).to eq OStatus::TagManager::VERBS[:post]
- end
-
- it 'appends activity:object element with target if present' do
- reblogged = Fabricate(:status, created_at: '2000-01-01T00:00:00Z')
- reblog = Fabricate(:status, reblog: reblogged)
-
- entry = OStatus::AtomSerializer.new.entry(reblog.stream_entry)
-
- object = entry.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq "https://cb6e6126.ngrok.io/users/#{reblogged.account.to_param}/statuses/#{reblogged.id}"
- end
-
- it 'does not append activity:object element if target is not present' do
- status = Fabricate(:status, reblog_of_id: nil)
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
- entry.nodes.each { |node| expect(node.name).not_to eq 'activity:object' }
- end
-
- it 'appends link element for an alternative' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- link = entry.nodes.find { |node| node.name == 'link' && node[:rel] == 'alternate' && node[:type] == 'text/html' }
- expect(link[:type]).to eq 'text/html'
- expect(link[:href]).to eq "https://cb6e6126.ngrok.io/@username/#{status.id}"
- end
-
- it 'appends link element for itself' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- link = entry.nodes.find { |node| node.name == 'link' && node[:rel] == 'self' }
- expect(link[:type]).to eq 'application/atom+xml'
- expect(link[:href]).to eq "https://cb6e6126.ngrok.io/users/username/updates/#{status.stream_entry.id}.atom"
- end
-
- it 'appends thr:in-reply-to element if threaded' do
- in_reply_to_status = Fabricate(:status, created_at: '2000-01-01T00:00:00Z', reblog_of_id: nil)
- reply_status = Fabricate(:status, in_reply_to_id: in_reply_to_status.id)
-
- entry = OStatus::AtomSerializer.new.entry(reply_status.stream_entry)
-
- in_reply_to = entry.nodes.find { |node| node.name == 'thr:in-reply-to' }
- expect(in_reply_to[:ref]).to eq "https://cb6e6126.ngrok.io/users/#{in_reply_to_status.account.to_param}/statuses/#{in_reply_to_status.id}"
- end
-
- it 'does not append thr:in-reply-to element if not threaded' do
- status = Fabricate(:status)
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
- entry.nodes.each { |node| expect(node.name).not_to eq 'thr:in-reply-to' }
- end
-
- it 'appends ostatus:conversation if conversation id is present' do
- status = Fabricate(:status)
- status.conversation.update!(created_at: '2000-01-01T00:00:00Z')
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- conversation = entry.nodes.find { |node| node.name == 'ostatus:conversation' }
- expect(conversation[:ref]).to eq "tag:cb6e6126.ngrok.io,2000-01-01:objectId=#{status.conversation_id}:objectType=Conversation"
- end
-
- it 'does not append ostatus:conversation if conversation id is not present' do
- status = Fabricate.build(:status, conversation_id: nil)
- status.save!(validate: false)
-
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
-
- entry.nodes.each { |node| expect(node.name).not_to eq 'ostatus:conversation' }
- end
- end
-
- describe '#feed' do
- include_examples 'namespaces' do
- def serialize
- account = Fabricate(:account)
- OStatus::AtomSerializer.new.feed(account, [])
- end
- end
-
- it 'returns feed element' do
- account = Fabricate(:account)
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.name).to eq 'feed'
- end
-
- it 'appends id element with account Atom URL' do
- account = Fabricate(:account, username: 'username')
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.id.text).to eq 'https://cb6e6126.ngrok.io/users/username.atom'
- end
-
- it 'appends title element with account display name if present' do
- account = Fabricate(:account, display_name: 'display name')
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.title.text).to eq 'display name'
- end
-
- it 'does not append title element with account username if account display name is not present' do
- account = Fabricate(:account, display_name: '', username: 'username')
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.title.text).to eq 'username'
- end
-
- it 'appends subtitle element with account note' do
- account = Fabricate(:account, note: 'note')
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.subtitle.text).to eq 'note'
- end
-
- it 'appends updated element with date account got updated' do
- account = Fabricate(:account, updated_at: '2000-01-01T00:00:00Z')
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.updated.text).to eq '2000-01-01T00:00:00Z'
- end
-
- it 'appends logo element with full asset URL for original account avatar' do
- account = Fabricate(:account, avatar: attachment_fixture('avatar.gif'))
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.logo.text).to match /^https:\/\/cb6e6126.ngrok.io\/system\/accounts\/avatars\/.+\/original\/avatar.gif/
- end
-
- it 'appends author element' do
- account = Fabricate(:account, username: 'username')
- feed = OStatus::AtomSerializer.new.feed(account, [])
- expect(feed.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends link element for an alternative' do
- account = Fabricate(:account, username: 'username')
-
- feed = OStatus::AtomSerializer.new.feed(account, [])
-
- link = feed.nodes.find { |node| node.name == 'link' && node[:rel] == 'alternate' && node[:type] == 'text/html' }
- expect(link[:type]).to eq 'text/html'
- expect(link[:href]).to eq 'https://cb6e6126.ngrok.io/@username'
- end
-
- it 'appends link element for itself' do
- account = Fabricate(:account, username: 'username')
-
- feed = OStatus::AtomSerializer.new.feed(account, [])
-
- link = feed.nodes.find { |node| node.name == 'link' && node[:rel] == 'self' }
- expect(link[:type]).to eq 'application/atom+xml'
- expect(link[:href]).to eq 'https://cb6e6126.ngrok.io/users/username.atom'
- end
-
- it 'appends link element for the next if it has 20 stream entries' do
- account = Fabricate(:account, username: 'username')
- stream_entry = Fabricate(:stream_entry)
-
- feed = OStatus::AtomSerializer.new.feed(account, Array.new(20, stream_entry))
-
- link = feed.nodes.find { |node| node.name == 'link' && node[:rel] == 'next' }
- expect(link[:type]).to eq 'application/atom+xml'
- expect(link[:href]).to eq "https://cb6e6126.ngrok.io/users/username.atom?max_id=#{stream_entry.id}"
- end
-
- it 'does not append link element for the next if it does not have 20 stream entries' do
- account = Fabricate(:account, username: 'username')
-
- feed = OStatus::AtomSerializer.new.feed(account, [])
-
- feed.nodes.each do |node|
- expect(node[:rel]).not_to eq 'next' if node.name == 'link'
- end
- end
-
- it 'appends link element for hub' do
- account = Fabricate(:account, username: 'username')
-
- feed = OStatus::AtomSerializer.new.feed(account, [])
-
- link = feed.nodes.find { |node| node.name == 'link' && node[:rel] == 'hub' }
- expect(link[:href]).to eq 'https://cb6e6126.ngrok.io/api/push'
- end
-
- it 'appends link element for Salmon' do
- account = Fabricate(:account, username: 'username')
-
- feed = OStatus::AtomSerializer.new.feed(account, [])
-
- link = feed.nodes.find { |node| node.name == 'link' && node[:rel] == 'salmon' }
- expect(link[:href]).to start_with 'https://cb6e6126.ngrok.io/api/salmon/'
- end
-
- it 'appends stream entries' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- feed = OStatus::AtomSerializer.new.feed(account, [status.stream_entry])
-
- expect(feed.entry.title.text).to eq 'New status by username'
- end
- end
-
- describe '#block_salmon' do
- include_examples 'namespaces' do
- def serialize
- block = Fabricate(:block)
- OStatus::AtomSerializer.new.block_salmon(block)
- end
- end
-
- it 'returns entry element' do
- block = Fabricate(:block)
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
- expect(block_salmon.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- block = Fabricate(:block)
-
- time_before = Time.zone.now
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
- time_after = Time.zone.now
-
- expect(block_salmon.id.text).to(
- eq(OStatus::TagManager.instance.unique_tag(time_before.utc, block.id, 'Block'))
- .or(eq(OStatus::TagManager.instance.unique_tag(time_after.utc, block.id, 'Block')))
- )
- end
-
- it 'appends title element with description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- target_account = Fabricate(:account, domain: 'remote', username: 'target_account')
- block = Fabricate(:block, account: account, target_account: target_account)
-
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
-
- expect(block_salmon.title.text).to eq 'account no longer wishes to interact with target_account@remote'
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'account')
- block = Fabricate(:block, account: account)
-
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
-
- expect(block_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/account'
- end
-
- it 'appends activity:object-type element with activity type' do
- block = Fabricate(:block)
-
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
-
- object_type = block_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with block' do
- block = Fabricate(:block)
-
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
-
- verb = block_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:block]
- end
-
- it 'appends activity:object element with target account' do
- target_account = Fabricate(:account, domain: 'domain.test', uri: 'https://domain.test/id')
- block = Fabricate(:block, target_account: target_account)
-
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
-
- object = block_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq 'https://domain.test/id'
- end
-
- it 'returns element whose rendered view triggers block when processed' do
- block = Fabricate(:block)
- block_salmon = OStatus::AtomSerializer.new.block_salmon(block)
- xml = OStatus::AtomSerializer.render(block_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, block.account.keypair)
- block.destroy!
-
- ProcessInteractionService.new.call(envelope, block.target_account)
-
- expect(block.account.blocking?(block.target_account)).to be true
- end
- end
-
- describe '#unblock_salmon' do
- include_examples 'namespaces' do
- def serialize
- block = Fabricate(:block)
- OStatus::AtomSerializer.new.unblock_salmon(block)
- end
- end
-
- it 'returns entry element' do
- block = Fabricate(:block)
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
- expect(unblock_salmon.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- block = Fabricate(:block)
-
- time_before = Time.zone.now
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
- time_after = Time.zone.now
-
- expect(unblock_salmon.id.text).to(
- eq(OStatus::TagManager.instance.unique_tag(time_before.utc, block.id, 'Block'))
- .or(eq(OStatus::TagManager.instance.unique_tag(time_after.utc, block.id, 'Block')))
- )
- end
-
- it 'appends title element with description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- target_account = Fabricate(:account, domain: 'remote', username: 'target_account')
- block = Fabricate(:block, account: account, target_account: target_account)
-
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
-
- expect(unblock_salmon.title.text).to eq 'account no longer blocks target_account@remote'
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'account')
- block = Fabricate(:block, account: account)
-
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
-
- expect(unblock_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/account'
- end
-
- it 'appends activity:object-type element with activity type' do
- block = Fabricate(:block)
-
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
-
- object_type = unblock_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with block' do
- block = Fabricate(:block)
-
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
-
- verb = unblock_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:unblock]
- end
-
- it 'appends activity:object element with target account' do
- target_account = Fabricate(:account, domain: 'domain.test', uri: 'https://domain.test/id')
- block = Fabricate(:block, target_account: target_account)
-
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
-
- object = unblock_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq 'https://domain.test/id'
- end
-
- it 'returns element whose rendered view triggers block when processed' do
- block = Fabricate(:block)
- unblock_salmon = OStatus::AtomSerializer.new.unblock_salmon(block)
- xml = OStatus::AtomSerializer.render(unblock_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, block.account.keypair)
-
- ProcessInteractionService.new.call(envelope, block.target_account)
-
- expect { block.reload }.to raise_error ActiveRecord::RecordNotFound
- end
- end
-
- describe '#favourite_salmon' do
- include_examples 'namespaces' do
- def serialize
- favourite = Fabricate(:favourite)
- OStatus::AtomSerializer.new.favourite_salmon(favourite)
- end
- end
-
- it 'returns entry element' do
- favourite = Fabricate(:favourite)
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
- expect(favourite_salmon.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- favourite = Fabricate(:favourite, created_at: '2000-01-01T00:00:00Z')
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
- expect(favourite_salmon.id.text).to eq "tag:cb6e6126.ngrok.io,2000-01-01:objectId=#{favourite.id}:objectType=Favourite"
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'username')
- favourite = Fabricate(:favourite, account: account)
-
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
-
- expect(favourite_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends activity:object-type element with activity type' do
- favourite = Fabricate(:favourite)
-
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
-
- object_type = favourite_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq 'http://activitystrea.ms/schema/1.0/activity'
- end
-
- it 'appends activity:verb element with favorite' do
- favourite = Fabricate(:favourite)
-
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
-
- verb = favourite_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:favorite]
- end
-
- it 'appends activity:object element with status' do
- status = Fabricate(:status, created_at: '2000-01-01T00:00:00Z')
- favourite = Fabricate(:favourite, status: status)
-
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
-
- object = favourite_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq "https://cb6e6126.ngrok.io/users/#{status.account.to_param}/statuses/#{status.id}"
- end
-
- it 'appends thr:in-reply-to element for status' do
- status_account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: status_account, created_at: '2000-01-01T00:00:00Z')
- favourite = Fabricate(:favourite, status: status)
-
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
-
- in_reply_to = favourite_salmon.nodes.find { |node| node.name == 'thr:in-reply-to' }
- expect(in_reply_to.ref).to eq "https://cb6e6126.ngrok.io/users/#{status.account.to_param}/statuses/#{status.id}"
- expect(in_reply_to.href).to eq "https://cb6e6126.ngrok.io/@username/#{status.id}"
- end
-
- it 'includes description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- status_account = Fabricate(:account, domain: 'remote', username: 'status_account')
- status = Fabricate(:status, account: status_account)
- favourite = Fabricate(:favourite, account: account, status: status)
-
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
-
- expect(favourite_salmon.title.text).to eq 'account favourited a status by status_account@remote'
- expect(favourite_salmon.content.text).to eq 'account favourited a status by status_account@remote'
- end
-
- it 'returns element whose rendered view triggers favourite when processed' do
- favourite = Fabricate(:favourite)
- favourite_salmon = OStatus::AtomSerializer.new.favourite_salmon(favourite)
- xml = OStatus::AtomSerializer.render(favourite_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, favourite.account.keypair)
- favourite.destroy!
-
- ProcessInteractionService.new.call(envelope, favourite.status.account)
- expect(favourite.account.favourited?(favourite.status)).to be true
- end
- end
-
- describe '#unfavourite_salmon' do
- include_examples 'namespaces' do
- def serialize
- favourite = Fabricate(:favourite)
- OStatus::AtomSerializer.new.favourite_salmon(favourite)
- end
- end
-
- it 'returns entry element' do
- favourite = Fabricate(:favourite)
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
- expect(unfavourite_salmon.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- favourite = Fabricate(:favourite)
-
- time_before = Time.zone.now
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
- time_after = Time.zone.now
-
- expect(unfavourite_salmon.id.text).to(
- eq(OStatus::TagManager.instance.unique_tag(time_before.utc, favourite.id, 'Favourite'))
- .or(eq(OStatus::TagManager.instance.unique_tag(time_after.utc, favourite.id, 'Favourite')))
- )
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'username')
- favourite = Fabricate(:favourite, account: account)
-
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
-
- expect(unfavourite_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends activity:object-type element with activity type' do
- favourite = Fabricate(:favourite)
-
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
-
- object_type = unfavourite_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq 'http://activitystrea.ms/schema/1.0/activity'
- end
-
- it 'appends activity:verb element with favorite' do
- favourite = Fabricate(:favourite)
-
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
-
- verb = unfavourite_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:unfavorite]
- end
-
- it 'appends activity:object element with status' do
- status = Fabricate(:status, created_at: '2000-01-01T00:00:00Z')
- favourite = Fabricate(:favourite, status: status)
-
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
-
- object = unfavourite_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq "https://cb6e6126.ngrok.io/users/#{status.account.to_param}/statuses/#{status.id}"
- end
-
- it 'appends thr:in-reply-to element for status' do
- status_account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: status_account, created_at: '2000-01-01T00:00:00Z')
- favourite = Fabricate(:favourite, status: status)
-
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
-
- in_reply_to = unfavourite_salmon.nodes.find { |node| node.name == 'thr:in-reply-to' }
- expect(in_reply_to.ref).to eq "https://cb6e6126.ngrok.io/users/#{status.account.to_param}/statuses/#{status.id}"
- expect(in_reply_to.href).to eq "https://cb6e6126.ngrok.io/@username/#{status.id}"
- end
-
- it 'includes description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- status_account = Fabricate(:account, domain: 'remote', username: 'status_account')
- status = Fabricate(:status, account: status_account)
- favourite = Fabricate(:favourite, account: account, status: status)
-
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
-
- expect(unfavourite_salmon.title.text).to eq 'account no longer favourites a status by status_account@remote'
- expect(unfavourite_salmon.content.text).to eq 'account no longer favourites a status by status_account@remote'
- end
-
- it 'returns element whose rendered view triggers unfavourite when processed' do
- favourite = Fabricate(:favourite)
- unfavourite_salmon = OStatus::AtomSerializer.new.unfavourite_salmon(favourite)
- xml = OStatus::AtomSerializer.render(unfavourite_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, favourite.account.keypair)
-
- ProcessInteractionService.new.call(envelope, favourite.status.account)
- expect { favourite.reload }.to raise_error ActiveRecord::RecordNotFound
- end
- end
-
- describe '#follow_salmon' do
- include_examples 'namespaces' do
- def serialize
- follow = Fabricate(:follow)
- OStatus::AtomSerializer.new.follow_salmon(follow)
- end
- end
-
- it 'returns entry element' do
- follow = Fabricate(:follow)
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
- expect(follow_salmon.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- follow = Fabricate(:follow, created_at: '2000-01-01T00:00:00Z')
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
- expect(follow_salmon.id.text).to eq "tag:cb6e6126.ngrok.io,2000-01-01:objectId=#{follow.id}:objectType=Follow"
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'username')
- follow = Fabricate(:follow, account: account)
-
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
-
- expect(follow_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends activity:object-type element with activity type' do
- follow = Fabricate(:follow)
-
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
-
- object_type = follow_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with follow' do
- follow = Fabricate(:follow)
-
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
-
- verb = follow_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:follow]
- end
-
- it 'appends activity:object element with target account' do
- target_account = Fabricate(:account, domain: 'domain.test', uri: 'https://domain.test/id')
- follow = Fabricate(:follow, target_account: target_account)
-
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
-
- object = follow_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq 'https://domain.test/id'
- end
-
- it 'includes description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- target_account = Fabricate(:account, domain: 'remote', username: 'target_account')
- follow = Fabricate(:follow, account: account, target_account: target_account)
-
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
-
- expect(follow_salmon.title.text).to eq 'account started following target_account@remote'
- expect(follow_salmon.content.text).to eq 'account started following target_account@remote'
- end
-
- it 'returns element whose rendered view triggers follow when processed' do
- follow = Fabricate(:follow)
- follow_salmon = OStatus::AtomSerializer.new.follow_salmon(follow)
- xml = OStatus::AtomSerializer.render(follow_salmon)
- follow.destroy!
- envelope = OStatus2::Salmon.new.pack(xml, follow.account.keypair)
-
- ProcessInteractionService.new.call(envelope, follow.target_account)
-
- expect(follow.account.following?(follow.target_account)).to be true
- end
- end
-
- describe '#unfollow_salmon' do
- include_examples 'namespaces' do
- def serialize
- follow = Fabricate(:follow)
- follow.destroy!
- OStatus::AtomSerializer.new.unfollow_salmon(follow)
- end
- end
-
- it 'returns entry element' do
- follow = Fabricate(:follow)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- expect(unfollow_salmon.name).to eq 'entry'
- end
-
- it 'appends id element with unique tag' do
- follow = Fabricate(:follow)
- follow.destroy!
-
- time_before = Time.zone.now
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
- time_after = Time.zone.now
-
- expect(unfollow_salmon.id.text).to(
- eq(OStatus::TagManager.instance.unique_tag(time_before.utc, follow.id, 'Follow'))
- .or(eq(OStatus::TagManager.instance.unique_tag(time_after.utc, follow.id, 'Follow')))
- )
- end
-
- it 'appends title element with description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- target_account = Fabricate(:account, domain: 'remote', username: 'target_account')
- follow = Fabricate(:follow, account: account, target_account: target_account)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- expect(unfollow_salmon.title.text).to eq 'account is no longer following target_account@remote'
- end
-
- it 'appends content element with description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- target_account = Fabricate(:account, domain: 'remote', username: 'target_account')
- follow = Fabricate(:follow, account: account, target_account: target_account)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- expect(unfollow_salmon.content.text).to eq 'account is no longer following target_account@remote'
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, domain: nil, username: 'username')
- follow = Fabricate(:follow, account: account)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- expect(unfollow_salmon.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends activity:object-type element with activity type' do
- follow = Fabricate(:follow)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- object_type = unfollow_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with follow' do
- follow = Fabricate(:follow)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- verb = unfollow_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:unfollow]
- end
-
- it 'appends activity:object element with target account' do
- target_account = Fabricate(:account, domain: 'domain.test', uri: 'https://domain.test/id')
- follow = Fabricate(:follow, target_account: target_account)
- follow.destroy!
-
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
-
- object = unfollow_salmon.nodes.find { |node| node.name == 'activity:object' }
- expect(object.id.text).to eq 'https://domain.test/id'
- end
-
- it 'returns element whose rendered view triggers unfollow when processed' do
- follow = Fabricate(:follow)
- follow.destroy!
- unfollow_salmon = OStatus::AtomSerializer.new.unfollow_salmon(follow)
- xml = OStatus::AtomSerializer.render(unfollow_salmon)
- follow.account.follow!(follow.target_account)
- envelope = OStatus2::Salmon.new.pack(xml, follow.account.keypair)
-
- ProcessInteractionService.new.call(envelope, follow.target_account)
-
- expect(follow.account.following?(follow.target_account)).to be false
- end
- end
-
- describe '#follow_request_salmon' do
- include_examples 'namespaces' do
- def serialize
- follow_request = Fabricate(:follow_request)
- OStatus::AtomSerializer.new.follow_request_salmon(follow_request)
- end
- end
-
- context do
- def serialize(follow_request)
- OStatus::AtomSerializer.new.follow_request_salmon(follow_request)
- end
-
- it_behaves_like 'follow request salmon'
-
- it 'appends id element with unique tag' do
- follow_request = Fabricate(:follow_request, created_at: '2000-01-01T00:00:00Z')
- follow_request_salmon = serialize(follow_request)
- expect(follow_request_salmon.id.text).to eq "tag:cb6e6126.ngrok.io,2000-01-01:objectId=#{follow_request.id}:objectType=FollowRequest"
- end
-
- it 'appends title element with description' do
- account = Fabricate(:account, domain: nil, username: 'account')
- target_account = Fabricate(:account, domain: 'remote', username: 'target_account')
- follow_request = Fabricate(:follow_request, account: account, target_account: target_account)
- follow_request_salmon = serialize(follow_request)
- expect(follow_request_salmon.title.text).to eq 'account requested to follow target_account@remote'
- end
-
- it 'returns element whose rendered view triggers follow request when processed' do
- follow_request = Fabricate(:follow_request)
- follow_request_salmon = serialize(follow_request)
- xml = OStatus::AtomSerializer.render(follow_request_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, follow_request.account.keypair)
- follow_request.destroy!
-
- ProcessInteractionService.new.call(envelope, follow_request.target_account)
-
- expect(follow_request.account.requested?(follow_request.target_account)).to eq true
- end
- end
- end
-
- describe '#authorize_follow_request_salmon' do
- include_examples 'namespaces' do
- def serialize
- follow_request = Fabricate(:follow_request)
- OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
- end
- end
-
- it_behaves_like 'follow request salmon' do
- def serialize(follow_request)
- authorize_follow_request_salmon = OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
- authorize_follow_request_salmon.nodes.find { |node| node.name == 'activity:object' }
- end
- end
-
- it 'appends id element with unique tag' do
- follow_request = Fabricate(:follow_request)
-
- time_before = Time.zone.now
- authorize_follow_request_salmon = OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
- time_after = Time.zone.now
-
- expect(authorize_follow_request_salmon.id.text).to(
- eq(OStatus::TagManager.instance.unique_tag(time_before.utc, follow_request.id, 'FollowRequest'))
- .or(eq(OStatus::TagManager.instance.unique_tag(time_after.utc, follow_request.id, 'FollowRequest')))
- )
- end
-
- it 'appends title element with description' do
- account = Fabricate(:account, domain: 'remote', username: 'account')
- target_account = Fabricate(:account, domain: nil, username: 'target_account')
- follow_request = Fabricate(:follow_request, account: account, target_account: target_account)
-
- authorize_follow_request_salmon = OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
-
- expect(authorize_follow_request_salmon.title.text).to eq 'target_account authorizes follow request by account@remote'
- end
-
- it 'appends activity:object-type element with activity type' do
- follow_request = Fabricate(:follow_request)
-
- authorize_follow_request_salmon = OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
-
- object_type = authorize_follow_request_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with authorize' do
- follow_request = Fabricate(:follow_request)
-
- authorize_follow_request_salmon = OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
-
- verb = authorize_follow_request_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:authorize]
- end
-
- it 'returns element whose rendered view creates follow from follow request when processed' do
- follow_request = Fabricate(:follow_request)
- authorize_follow_request_salmon = OStatus::AtomSerializer.new.authorize_follow_request_salmon(follow_request)
- xml = OStatus::AtomSerializer.render(authorize_follow_request_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, follow_request.target_account.keypair)
-
- ProcessInteractionService.new.call(envelope, follow_request.account)
-
- expect(follow_request.account.following?(follow_request.target_account)).to eq true
- expect { follow_request.reload }.to raise_error ActiveRecord::RecordNotFound
- end
- end
-
- describe '#reject_follow_request_salmon' do
- include_examples 'namespaces' do
- def serialize
- follow_request = Fabricate(:follow_request)
- OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- end
- end
-
- it_behaves_like 'follow request salmon' do
- def serialize(follow_request)
- reject_follow_request_salmon = OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- reject_follow_request_salmon.nodes.find { |node| node.name == 'activity:object' }
- end
- end
-
- it 'appends id element with unique tag' do
- follow_request = Fabricate(:follow_request)
-
- time_before = Time.zone.now
- reject_follow_request_salmon = OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- time_after = Time.zone.now
-
- expect(reject_follow_request_salmon.id.text).to(
- eq(OStatus::TagManager.instance.unique_tag(time_before.utc, follow_request.id, 'FollowRequest'))
- .or(OStatus::TagManager.instance.unique_tag(time_after.utc, follow_request.id, 'FollowRequest'))
- )
- end
-
- it 'appends title element with description' do
- account = Fabricate(:account, domain: 'remote', username: 'account')
- target_account = Fabricate(:account, domain: nil, username: 'target_account')
- follow_request = Fabricate(:follow_request, account: account, target_account: target_account)
- reject_follow_request_salmon = OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- expect(reject_follow_request_salmon.title.text).to eq 'target_account rejects follow request by account@remote'
- end
-
- it 'appends activity:object-type element with activity type' do
- follow_request = Fabricate(:follow_request)
- reject_follow_request_salmon = OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- object_type = reject_follow_request_salmon.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:activity]
- end
-
- it 'appends activity:verb element with authorize' do
- follow_request = Fabricate(:follow_request)
- reject_follow_request_salmon = OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- verb = reject_follow_request_salmon.nodes.find { |node| node.name == 'activity:verb' }
- expect(verb.text).to eq OStatus::TagManager::VERBS[:reject]
- end
-
- it 'returns element whose rendered view deletes follow request when processed' do
- follow_request = Fabricate(:follow_request)
- reject_follow_request_salmon = OStatus::AtomSerializer.new.reject_follow_request_salmon(follow_request)
- xml = OStatus::AtomSerializer.render(reject_follow_request_salmon)
- envelope = OStatus2::Salmon.new.pack(xml, follow_request.target_account.keypair)
-
- ProcessInteractionService.new.call(envelope, follow_request.account)
-
- expect(follow_request.account.following?(follow_request.target_account)).to eq false
- expect { follow_request.reload }.to raise_error ActiveRecord::RecordNotFound
- end
- end
-
- describe '#object' do
- include_examples 'status attributes' do
- def serialize(status)
- OStatus::AtomSerializer.new.object(status)
- end
- end
-
- it 'returns activity:object element' do
- status = Fabricate(:status)
- object = OStatus::AtomSerializer.new.object(status)
- expect(object.name).to eq 'activity:object'
- end
-
- it 'appends id element with URL for status' do
- status = Fabricate(:status, created_at: '2000-01-01T00:00:00Z')
- object = OStatus::AtomSerializer.new.object(status)
- expect(object.id.text).to eq "https://cb6e6126.ngrok.io/users/#{status.account.to_param}/statuses/#{status.id}"
- end
-
- it 'appends published element with created date' do
- status = Fabricate(:status, created_at: '2000-01-01T00:00:00Z')
- object = OStatus::AtomSerializer.new.object(status)
- expect(object.published.text).to eq '2000-01-01T00:00:00Z'
- end
-
- it 'appends updated element with updated date' do
- status = Fabricate(:status)
- status.updated_at = '2000-01-01T00:00:00Z'
- object = OStatus::AtomSerializer.new.object(status)
- expect(object.updated.text).to eq '2000-01-01T00:00:00Z'
- end
-
- it 'appends title element with title' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- object = OStatus::AtomSerializer.new.object(status)
-
- expect(object.title.text).to eq 'New status by username'
- end
-
- it 'appends author element with account' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- entry = OStatus::AtomSerializer.new.object(status)
-
- expect(entry.author.id.text).to eq 'https://cb6e6126.ngrok.io/users/username'
- end
-
- it 'appends activity:object-type element with object type' do
- status = Fabricate(:status)
-
- entry = OStatus::AtomSerializer.new.object(status)
-
- object_type = entry.nodes.find { |node| node.name == 'activity:object-type' }
- expect(object_type.text).to eq OStatus::TagManager::TYPES[:note]
- end
-
- it 'appends activity:verb element with verb' do
- status = Fabricate(:status)
-
- entry = OStatus::AtomSerializer.new.object(status)
-
- object_type = entry.nodes.find { |node| node.name == 'activity:verb' }
- expect(object_type.text).to eq OStatus::TagManager::VERBS[:post]
- end
-
- it 'appends link element for an alternative' do
- account = Fabricate(:account, username: 'username')
- status = Fabricate(:status, account: account)
-
- entry = OStatus::AtomSerializer.new.object(status)
-
- link = entry.nodes.find { |node| node.name == 'link' && node[:rel] == 'alternate' && node[:type] == 'text/html' }
- expect(link[:type]).to eq 'text/html'
- expect(link[:href]).to eq "https://cb6e6126.ngrok.io/@username/#{status.id}"
- end
-
- it 'appends thr:in-reply-to element if it is a reply and thread is not nil' do
- account = Fabricate(:account, username: 'username')
- thread = Fabricate(:status, account: account, created_at: '2000-01-01T00:00:00Z')
- reply = Fabricate(:status, thread: thread)
-
- entry = OStatus::AtomSerializer.new.object(reply)
-
- in_reply_to = entry.nodes.find { |node| node.name == 'thr:in-reply-to' }
- expect(in_reply_to.ref).to eq "https://cb6e6126.ngrok.io/users/#{thread.account.to_param}/statuses/#{thread.id}"
- expect(in_reply_to.href).to eq "https://cb6e6126.ngrok.io/@username/#{thread.id}"
- end
-
- it 'does not append thr:in-reply-to element if thread is nil' do
- status = Fabricate(:status, thread: nil)
- entry = OStatus::AtomSerializer.new.object(status)
- entry.nodes.each { |node| expect(node.name).not_to eq 'thr:in-reply-to' }
- end
-
- it 'does not append ostatus:conversation element if conversation_id is nil' do
- status = Fabricate.build(:status, conversation_id: nil)
- status.save!(validate: false)
-
- entry = OStatus::AtomSerializer.new.object(status)
-
- entry.nodes.each { |node| expect(node.name).not_to eq 'ostatus:conversation' }
- end
-
- it 'appends ostatus:conversation element if conversation_id is not nil' do
- status = Fabricate(:status)
- status.conversation.update!(created_at: '2000-01-01T00:00:00Z')
-
- entry = OStatus::AtomSerializer.new.object(status)
-
- conversation = entry.nodes.find { |node| node.name == 'ostatus:conversation' }
- expect(conversation[:ref]).to eq "tag:cb6e6126.ngrok.io,2000-01-01:objectId=#{status.conversation.id}:objectType=Conversation"
- end
- end
-end
diff --git a/spec/lib/ostatus/tag_manager_spec.rb b/spec/lib/ostatus/tag_manager_spec.rb
deleted file mode 100644
index 31195bae..00000000
--- a/spec/lib/ostatus/tag_manager_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe OStatus::TagManager do
- describe '#unique_tag' do
- it 'returns a unique tag' do
- expect(OStatus::TagManager.instance.unique_tag(Time.utc(2000), 12, 'Status')).to eq 'tag:cb6e6126.ngrok.io,2000-01-01:objectId=12:objectType=Status'
- end
- end
-
- describe '#unique_tag_to_local_id' do
- it 'returns the ID part' do
- expect(OStatus::TagManager.instance.unique_tag_to_local_id('tag:cb6e6126.ngrok.io,2000-01-01:objectId=12:objectType=Status', 'Status')).to eql '12'
- end
-
- it 'returns nil if it is not local id' do
- expect(OStatus::TagManager.instance.unique_tag_to_local_id('tag:remote,2000-01-01:objectId=12:objectType=Status', 'Status')).to eq nil
- end
-
- it 'returns nil if it is not expected type' do
- expect(OStatus::TagManager.instance.unique_tag_to_local_id('tag:cb6e6126.ngrok.io,2000-01-01:objectId=12:objectType=Block', 'Status')).to eq nil
- end
-
- it 'returns nil if it does not have object ID' do
- expect(OStatus::TagManager.instance.unique_tag_to_local_id('tag:cb6e6126.ngrok.io,2000-01-01:objectType=Status', 'Status')).to eq nil
- end
- end
-
- describe '#local_id?' do
- it 'returns true for a local ID' do
- expect(OStatus::TagManager.instance.local_id?('tag:cb6e6126.ngrok.io;objectId=12:objectType=Status')).to be true
- end
-
- it 'returns false for a foreign ID' do
- expect(OStatus::TagManager.instance.local_id?('tag:foreign.tld;objectId=12:objectType=Status')).to be false
- end
- end
-
- describe '#uri_for' do
- subject { OStatus::TagManager.instance.uri_for(target) }
-
- context 'comment object' do
- let(:target) { Fabricate(:status, created_at: '2000-01-01T00:00:00Z', reply: true) }
-
- it 'returns the unique tag for status' do
- expect(target.object_type).to eq :comment
- is_expected.to eq target.uri
- end
- end
-
- context 'note object' do
- let(:target) { Fabricate(:status, created_at: '2000-01-01T00:00:00Z', reply: false, thread: nil) }
-
- it 'returns the unique tag for status' do
- expect(target.object_type).to eq :note
- is_expected.to eq target.uri
- end
- end
-
- context 'person object' do
- let(:target) { Fabricate(:account, username: 'alice') }
-
- it 'returns the URL for account' do
- expect(target.object_type).to eq :person
- is_expected.to eq 'https://cb6e6126.ngrok.io/users/alice'
- end
- end
- end
-end
diff --git a/spec/lib/proof_provider/keybase/verifier_spec.rb b/spec/lib/proof_provider/keybase/verifier_spec.rb
deleted file mode 100644
index 0081a735..00000000
--- a/spec/lib/proof_provider/keybase/verifier_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-require 'rails_helper'
-
-describe ProofProvider::Keybase::Verifier do
- let(:my_domain) { Rails.configuration.x.local_domain }
-
- let(:keybase_proof) do
- local_proof = AccountIdentityProof.new(
- provider: 'Keybase',
- provider_username: 'cryptoalice',
- token: '11111111111111111111111111'
- )
-
- described_class.new('alice', 'cryptoalice', '11111111111111111111111111', my_domain)
- end
-
- let(:query_params) do
- "domain=#{my_domain}&kb_username=cryptoalice&sig_hash=11111111111111111111111111&username=alice"
- end
-
- describe '#valid?' do
- let(:base_url) { 'https://keybase.io/_/api/1.0/sig/proof_valid.json' }
-
- context 'when valid' do
- before do
- json_response_body = '{"status":{"code":0,"name":"OK"},"proof_valid":true}'
- stub_request(:get, "#{base_url}?#{query_params}").to_return(status: 200, body: json_response_body)
- end
-
- it 'calls out to keybase and returns true' do
- expect(keybase_proof.valid?).to eq true
- end
- end
-
- context 'when invalid' do
- before do
- json_response_body = '{"status":{"code":0,"name":"OK"},"proof_valid":false}'
- stub_request(:get, "#{base_url}?#{query_params}").to_return(status: 200, body: json_response_body)
- end
-
- it 'calls out to keybase and returns false' do
- expect(keybase_proof.valid?).to eq false
- end
- end
-
- context 'with an unexpected api response' do
- before do
- json_response_body = '{"status":{"code":100,"desc":"wrong size hex_id","fields":{"sig_hash":"wrong size hex_id"},"name":"INPUT_ERROR"}}'
- stub_request(:get, "#{base_url}?#{query_params}").to_return(status: 200, body: json_response_body)
- end
-
- it 'swallows the error and returns false' do
- expect(keybase_proof.valid?).to eq false
- end
- end
- end
-
- describe '#status' do
- let(:base_url) { 'https://keybase.io/_/api/1.0/sig/proof_live.json' }
-
- context 'with a normal response' do
- before do
- json_response_body = '{"status":{"code":0,"name":"OK"},"proof_live":false,"proof_valid":true}'
- stub_request(:get, "#{base_url}?#{query_params}").to_return(status: 200, body: json_response_body)
- end
-
- it 'calls out to keybase and returns the status fields as proof_valid and proof_live' do
- expect(keybase_proof.status).to include({ 'proof_valid' => true, 'proof_live' => false })
- end
- end
-
- context 'with an unexpected keybase response' do
- before do
- json_response_body = '{"status":{"code":100,"desc":"missing non-optional field sig_hash","fields":{"sig_hash":"missing non-optional field sig_hash"},"name":"INPUT_ERROR"}}'
- stub_request(:get, "#{base_url}?#{query_params}").to_return(status: 200, body: json_response_body)
- end
-
- it 'raises a ProofProvider::Keybase::UnexpectedResponseError' do
- expect { keybase_proof.status }.to raise_error ProofProvider::Keybase::UnexpectedResponseError
- end
- end
- end
-end
diff --git a/spec/lib/request_spec.rb b/spec/lib/request_spec.rb
deleted file mode 100644
index 7142edf9..00000000
--- a/spec/lib/request_spec.rb
+++ /dev/null
@@ -1,138 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'securerandom'
-
-describe Request do
- subject { Request.new(:get, 'http://example.com') }
-
- describe '#headers' do
- it 'returns user agent' do
- expect(subject.headers['User-Agent']).to be_present
- end
-
- it 'returns the date header' do
- expect(subject.headers['Date']).to be_present
- end
-
- it 'returns the host header' do
- expect(subject.headers['Host']).to be_present
- end
-
- it 'does not return virtual request-target header' do
- expect(subject.headers['(request-target)']).to be_nil
- end
- end
-
- describe '#on_behalf_of' do
- it 'when used, adds signature header' do
- subject.on_behalf_of(Fabricate(:account))
- expect(subject.headers['Signature']).to be_present
- end
- end
-
- describe '#add_headers' do
- it 'adds headers to the request' do
- subject.add_headers('Test' => 'Foo')
- expect(subject.headers['Test']).to eq 'Foo'
- end
- end
-
- describe '#perform' do
- context 'with valid host' do
- before { stub_request(:get, 'http://example.com') }
-
- it 'executes a HTTP request' do
- expect { |block| subject.perform &block }.to yield_control
- expect(a_request(:get, 'http://example.com')).to have_been_made.once
- end
-
- it 'executes a HTTP request when the first address is private' do
- resolver = double
-
- allow(resolver).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:4860:4860::8844))
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- expect { |block| subject.perform &block }.to yield_control
- expect(a_request(:get, 'http://example.com')).to have_been_made.once
- end
-
- it 'sets headers' do
- expect { |block| subject.perform &block }.to yield_control
- expect(a_request(:get, 'http://example.com').with(headers: subject.headers)).to have_been_made
- end
-
- it 'closes underlaying connection' do
- expect_any_instance_of(HTTP::Client).to receive(:close)
- expect { |block| subject.perform &block }.to yield_control
- end
-
- it 'returns response which implements body_with_limit' do
- subject.perform do |response|
- expect(response).to respond_to :body_with_limit
- end
- end
- end
-
- context 'with private host' do
- around do |example|
- WebMock.disable!
- example.run
- WebMock.enable!
- end
-
- it 'raises GabSocial::ValidationError' do
- resolver = double
-
- allow(resolver).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:db8::face))
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- expect { subject.perform }.to raise_error GabSocial::ValidationError
- end
- end
- end
-
- describe "response's body_with_limit method" do
- it 'rejects body more than 1 megabyte by default' do
- stub_request(:any, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.megabytes))
- expect { subject.perform { |response| response.body_with_limit } }.to raise_error GabSocial::LengthValidationError
- end
-
- it 'accepts body less than 1 megabyte by default' do
- stub_request(:any, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.kilobytes))
- expect { subject.perform { |response| response.body_with_limit } }.not_to raise_error
- end
-
- it 'rejects body by given size' do
- stub_request(:any, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.kilobytes))
- expect { subject.perform { |response| response.body_with_limit(1.kilobyte) } }.to raise_error GabSocial::LengthValidationError
- end
-
- it 'rejects too large chunked body' do
- stub_request(:any, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.megabytes), headers: { 'Transfer-Encoding' => 'chunked' })
- expect { subject.perform { |response| response.body_with_limit } }.to raise_error GabSocial::LengthValidationError
- end
-
- it 'rejects too large monolithic body' do
- stub_request(:any, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.megabytes), headers: { 'Content-Length' => 2.megabytes })
- expect { subject.perform { |response| response.body_with_limit } }.to raise_error GabSocial::LengthValidationError
- end
-
- it 'uses binary encoding if Content-Type does not tell encoding' do
- stub_request(:any, 'http://example.com').to_return(body: '', headers: { 'Content-Type' => 'text/html' })
- expect(subject.perform { |response| response.body_with_limit.encoding }).to eq Encoding::BINARY
- end
-
- it 'uses binary encoding if Content-Type tells unknown encoding' do
- stub_request(:any, 'http://example.com').to_return(body: '', headers: { 'Content-Type' => 'text/html; charset=unknown' })
- expect(subject.perform { |response| response.body_with_limit.encoding }).to eq Encoding::BINARY
- end
-
- it 'uses encoding specified by Content-Type' do
- stub_request(:any, 'http://example.com').to_return(body: '', headers: { 'Content-Type' => 'text/html; charset=UTF-8' })
- expect(subject.perform { |response| response.body_with_limit.encoding }).to eq Encoding::UTF_8
- end
- end
-end
diff --git a/spec/lib/settings/extend_spec.rb b/spec/lib/settings/extend_spec.rb
deleted file mode 100644
index 83ced423..00000000
--- a/spec/lib/settings/extend_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Settings::Extend do
- class User
- include Settings::Extend
- end
-
- describe '#settings' do
- it 'sets @settings as an instance of Settings::ScopedSettings' do
- user = Fabricate(:user)
- expect(user.settings).to be_kind_of Settings::ScopedSettings
- end
- end
-end
diff --git a/spec/lib/settings/scoped_settings_spec.rb b/spec/lib/settings/scoped_settings_spec.rb
deleted file mode 100644
index 7566685b..00000000
--- a/spec/lib/settings/scoped_settings_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Settings::ScopedSettings do
- let(:object) { Fabricate(:user) }
- let(:scoped_setting) { described_class.new(object) }
- let(:val) { 'whatever' }
- let(:methods) { %i(auto_play_gif default_sensitive unfollow_modal boost_modal delete_modal reduce_motion system_font_ui noindex theme) }
-
- describe '.initialize' do
- it 'sets @object' do
- scoped_setting = described_class.new(object)
- expect(scoped_setting.instance_variable_get(:@object)).to be object
- end
- end
-
- describe '#method_missing' do
- it 'sets scoped_setting.method_name = val' do
- methods.each do |key|
- scoped_setting.send("#{key}=", val)
- expect(scoped_setting.send(key)).to eq val
- end
- end
- end
-
- describe '#[]= and #[]' do
- it 'sets [key] = val' do
- methods.each do |key|
- scoped_setting[key] = val
- expect(scoped_setting[key]).to eq val
- end
- end
- end
-end
diff --git a/spec/lib/status_filter_spec.rb b/spec/lib/status_filter_spec.rb
deleted file mode 100644
index a851014d..00000000
--- a/spec/lib/status_filter_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe StatusFilter do
- describe '#filtered?' do
- let(:status) { Fabricate(:status) }
-
- context 'without an account' do
- subject { described_class.new(status, nil) }
-
- context 'when there are no connections' do
- it { is_expected.not_to be_filtered }
- end
-
- context 'when status account is silenced' do
- before do
- status.account.silence!
- end
-
- it { is_expected.to be_filtered }
- end
-
- context 'when status policy does not allow show' do
- before do
- expect_any_instance_of(StatusPolicy).to receive(:show?).and_return(false)
- end
-
- it { is_expected.to be_filtered }
- end
- end
-
- context 'with real account' do
- let(:account) { Fabricate(:account) }
- subject { described_class.new(status, account) }
-
- context 'when there are no connections' do
- it { is_expected.not_to be_filtered }
- end
-
- context 'when status account is blocked' do
- before do
- Fabricate(:block, account: account, target_account: status.account)
- end
-
- it { is_expected.to be_filtered }
- end
-
- context 'when status account domain is blocked' do
- before do
- status.account.update(domain: 'example.com')
- Fabricate(:account_domain_block, account: account, domain: status.account_domain)
- end
-
- it { is_expected.to be_filtered }
- end
-
- context 'when status account is muted' do
- before do
- Fabricate(:mute, account: account, target_account: status.account)
- end
-
- it { is_expected.to be_filtered }
- end
-
- context 'when status account is silenced' do
- before do
- status.account.silence!
- end
-
- it { is_expected.to be_filtered }
- end
-
- context 'when status policy does not allow show' do
- before do
- expect_any_instance_of(StatusPolicy).to receive(:show?).and_return(false)
- end
-
- it { is_expected.to be_filtered }
- end
- end
- end
-end
diff --git a/spec/lib/status_finder_spec.rb b/spec/lib/status_finder_spec.rb
deleted file mode 100644
index 6b4ee434..00000000
--- a/spec/lib/status_finder_spec.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe StatusFinder do
- include RoutingHelper
-
- describe '#status' do
- subject { described_class.new(url) }
-
- context 'with a status url' do
- let(:status) { Fabricate(:status) }
- let(:url) { short_account_status_url(account_username: status.account.username, id: status.id) }
-
- it 'finds the stream entry' do
- expect(subject.status).to eq(status)
- end
-
- it 'raises an error if action is not :show' do
- recognized = Rails.application.routes.recognize_path(url)
- expect(recognized).to receive(:[]).with(:action).and_return(:create)
- expect(Rails.application.routes).to receive(:recognize_path).with(url).and_return(recognized)
-
- expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'with a stream entry url' do
- let(:stream_entry) { Fabricate(:stream_entry) }
- let(:url) { account_stream_entry_url(stream_entry.account, stream_entry) }
-
- it 'finds the stream entry' do
- expect(subject.status).to eq(stream_entry.status)
- end
- end
-
- context 'with a remote url even if id exists on local' do
- let(:status) { Fabricate(:status) }
- let(:url) { "https://example.com/users/test/statuses/#{status.id}" }
-
- it 'raises an error' do
- expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'with a plausible url' do
- let(:url) { 'https://example.com/users/test/updates/123/embed' }
-
- it 'raises an error' do
- expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'with an unrecognized url' do
- let(:url) { 'https://example.com/about' }
-
- it 'raises an error' do
- expect { subject.status }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
- end
-end
diff --git a/spec/lib/tag_manager_spec.rb b/spec/lib/tag_manager_spec.rb
deleted file mode 100644
index 3a804ac0..00000000
--- a/spec/lib/tag_manager_spec.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe TagManager do
- describe '#local_domain?' do
- # The following comparisons MUST be case-insensitive.
-
- around do |example|
- original_local_domain = Rails.configuration.x.local_domain
- Rails.configuration.x.local_domain = 'domain.test'
-
- example.run
-
- Rails.configuration.x.local_domain = original_local_domain
- end
-
- it 'returns true for nil' do
- expect(TagManager.instance.local_domain?(nil)).to eq true
- end
-
- it 'returns true if the slash-stripped string equals to local domain' do
- expect(TagManager.instance.local_domain?('DoMaIn.Test/')).to eq true
- end
-
- it 'returns false for irrelevant string' do
- expect(TagManager.instance.local_domain?('DoMaIn.Test!')).to eq false
- end
- end
-
- describe '#web_domain?' do
- # The following comparisons MUST be case-insensitive.
-
- around do |example|
- original_web_domain = Rails.configuration.x.web_domain
- Rails.configuration.x.web_domain = 'domain.test'
-
- example.run
-
- Rails.configuration.x.web_domain = original_web_domain
- end
-
- it 'returns true for nil' do
- expect(TagManager.instance.web_domain?(nil)).to eq true
- end
-
- it 'returns true if the slash-stripped string equals to web domain' do
- expect(TagManager.instance.web_domain?('DoMaIn.Test/')).to eq true
- end
-
- it 'returns false for string with irrelevant characters' do
- expect(TagManager.instance.web_domain?('DoMaIn.Test!')).to eq false
- end
- end
-
- describe '#normalize_domain' do
- it 'returns nil if the given parameter is nil' do
- expect(TagManager.instance.normalize_domain(nil)).to eq nil
- end
-
- it 'returns normalized domain' do
- expect(TagManager.instance.normalize_domain('DoMaIn.Test/')).to eq 'domain.test'
- end
- end
-
- describe '#local_url?' do
- around do |example|
- original_web_domain = Rails.configuration.x.web_domain
- example.run
- Rails.configuration.x.web_domain = original_web_domain
- end
-
- it 'returns true if the normalized string with port is local URL' do
- Rails.configuration.x.web_domain = 'domain.test:42'
- expect(TagManager.instance.local_url?('https://DoMaIn.Test:42/')).to eq true
- end
-
- it 'returns true if the normalized string without port is local URL' do
- Rails.configuration.x.web_domain = 'domain.test'
- expect(TagManager.instance.local_url?('https://DoMaIn.Test/')).to eq true
- end
-
- it 'returns false for string with irrelevant characters' do
- Rails.configuration.x.web_domain = 'domain.test'
- expect(TagManager.instance.local_url?('https://domainn.test/')).to eq false
- end
- end
-
- describe '#same_acct?' do
- # The following comparisons MUST be case-insensitive.
-
- it 'returns true if the needle has a correct username and domain for remote user' do
- expect(TagManager.instance.same_acct?('username@domain.test', 'UsErNaMe@DoMaIn.Test')).to eq true
- end
-
- it 'returns false if the needle is missing a domain for remote user' do
- expect(TagManager.instance.same_acct?('username@domain.test', 'UsErNaMe')).to eq false
- end
-
- it 'returns false if the needle has an incorrect domain for remote user' do
- expect(TagManager.instance.same_acct?('username@domain.test', 'UsErNaMe@incorrect.test')).to eq false
- end
-
- it 'returns false if the needle has an incorrect username for remote user' do
- expect(TagManager.instance.same_acct?('username@domain.test', 'incorrect@DoMaIn.test')).to eq false
- end
-
- it 'returns true if the needle has a correct username and domain for local user' do
- expect(TagManager.instance.same_acct?('username', 'UsErNaMe@Cb6E6126.nGrOk.Io')).to eq true
- end
-
- it 'returns true if the needle is missing a domain for local user' do
- expect(TagManager.instance.same_acct?('username', 'UsErNaMe')).to eq true
- end
-
- it 'returns false if the needle has an incorrect username for local user' do
- expect(TagManager.instance.same_acct?('username', 'UsErNaM@Cb6E6126.nGrOk.Io')).to eq false
- end
-
- it 'returns false if the needle has an incorrect domain for local user' do
- expect(TagManager.instance.same_acct?('username', 'incorrect@Cb6E6126.nGrOk.Io')).to eq false
- end
- end
-
- describe '#url_for' do
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- subject { TagManager.instance.url_for(target) }
-
- context 'activity object' do
- let(:target) { Fabricate(:status, account: alice, reblog: Fabricate(:status)).stream_entry }
-
- it 'returns the unique tag for status' do
- expect(target.object_type).to eq :activity
- is_expected.to eq "https://cb6e6126.ngrok.io/@alice/#{target.id}"
- end
- end
-
- context 'comment object' do
- let(:target) { Fabricate(:status, account: alice, reply: true) }
-
- it 'returns the unique tag for status' do
- expect(target.object_type).to eq :comment
- is_expected.to eq "https://cb6e6126.ngrok.io/@alice/#{target.id}"
- end
- end
-
- context 'note object' do
- let(:target) { Fabricate(:status, account: alice, reply: false, thread: nil) }
-
- it 'returns the unique tag for status' do
- expect(target.object_type).to eq :note
- is_expected.to eq "https://cb6e6126.ngrok.io/@alice/#{target.id}"
- end
- end
-
- context 'person object' do
- let(:target) { alice }
-
- it 'returns the URL for account' do
- expect(target.object_type).to eq :person
- is_expected.to eq 'https://cb6e6126.ngrok.io/@alice'
- end
- end
- end
-end
diff --git a/spec/lib/user_settings_decorator_spec.rb b/spec/lib/user_settings_decorator_spec.rb
deleted file mode 100644
index 2ad1fa32..00000000
--- a/spec/lib/user_settings_decorator_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe UserSettingsDecorator do
- describe 'update' do
- let(:user) { Fabricate(:user) }
- let(:settings) { described_class.new(user) }
-
- it 'updates the user settings value for email notifications' do
- values = { 'notification_emails' => { 'follow' => '1' } }
-
- settings.update(values)
- expect(user.settings['notification_emails']['follow']).to eq true
- end
-
- it 'updates the user settings value for interactions' do
- values = { 'interactions' => { 'must_be_follower' => '0' } }
-
- settings.update(values)
- expect(user.settings['interactions']['must_be_follower']).to eq false
- end
-
- it 'updates the user settings value for privacy' do
- values = { 'setting_default_privacy' => 'public' }
-
- settings.update(values)
- expect(user.settings['default_privacy']).to eq 'public'
- end
-
- it 'updates the user settings value for sensitive' do
- values = { 'setting_default_sensitive' => '1' }
-
- settings.update(values)
- expect(user.settings['default_sensitive']).to eq true
- end
-
- it 'updates the user settings value for unfollow modal' do
- values = { 'setting_unfollow_modal' => '0' }
-
- settings.update(values)
- expect(user.settings['unfollow_modal']).to eq false
- end
-
- it 'updates the user settings value for repost modal' do
- values = { 'setting_boost_modal' => '1' }
-
- settings.update(values)
- expect(user.settings['boost_modal']).to eq true
- end
-
- it 'updates the user settings value for delete toot modal' do
- values = { 'setting_delete_modal' => '0' }
-
- settings.update(values)
- expect(user.settings['delete_modal']).to eq false
- end
-
- it 'updates the user settings value for gif auto play' do
- values = { 'setting_auto_play_gif' => '0' }
-
- settings.update(values)
- expect(user.settings['auto_play_gif']).to eq false
- end
-
- it 'updates the user settings value for system font in UI' do
- values = { 'setting_system_font_ui' => '0' }
-
- settings.update(values)
- expect(user.settings['system_font_ui']).to eq false
- end
-
- it 'decoerces setting values before applying' do
- values = {
- 'setting_delete_modal' => 'false',
- 'setting_boost_modal' => 'true',
- }
-
- settings.update(values)
- expect(user.settings['delete_modal']).to eq false
- expect(user.settings['boost_modal']).to eq true
- end
- end
-end
diff --git a/spec/lib/webfinger_resource_spec.rb b/spec/lib/webfinger_resource_spec.rb
deleted file mode 100644
index 287537a2..00000000
--- a/spec/lib/webfinger_resource_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-require 'rails_helper'
-
-describe WebfingerResource do
- around do |example|
- before_local = Rails.configuration.x.local_domain
- before_web = Rails.configuration.x.web_domain
- example.run
- Rails.configuration.x.local_domain = before_local
- Rails.configuration.x.web_domain = before_web
- end
-
- describe '#username' do
- describe 'with a URL value' do
- it 'raises with a route whose controller is not AccountsController' do
- resource = 'https://example.com/users/alice/other'
-
- expect {
- WebfingerResource.new(resource).username
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises with a route whose action is not show' do
- resource = 'https://example.com/users/alice'
-
- recognized = Rails.application.routes.recognize_path(resource)
- allow(recognized).to receive(:[]).with(:controller).and_return('accounts')
- allow(recognized).to receive(:[]).with(:username).and_return('alice')
- expect(recognized).to receive(:[]).with(:action).and_return('create')
-
- expect(Rails.application.routes).to receive(:recognize_path).with(resource).and_return(recognized).at_least(:once)
-
- expect {
- WebfingerResource.new(resource).username
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises with a string that doesnt start with URL' do
- resource = 'website for http://example.com/users/alice/other'
-
- expect {
- WebfingerResource.new(resource).username
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'finds the username in a valid https route' do
- resource = 'https://example.com/users/alice'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
-
- it 'finds the username in a mixed case http route' do
- resource = 'HTTp://exAMPLEe.com/users/alice'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
-
- it 'finds the username in a valid http route' do
- resource = 'http://example.com/users/alice'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
- end
-
- describe 'with a username and hostname value' do
- it 'raises on a non-local domain' do
- resource = 'user@remote-host.com'
-
- expect {
- WebfingerResource.new(resource).username
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'finds username for a local domain' do
- Rails.configuration.x.local_domain = 'example.com'
- resource = 'alice@example.com'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
-
- it 'finds username for a web domain' do
- Rails.configuration.x.web_domain = 'example.com'
- resource = 'alice@example.com'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
- end
-
- describe 'with an acct value' do
- it 'raises on a non-local domain' do
- resource = 'acct:user@remote-host.com'
-
- expect {
- WebfingerResource.new(resource).username
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises on a nonsense domain' do
- resource = 'acct:user@remote-host@remote-hostess.remote.local@remote'
-
- expect {
- WebfingerResource.new(resource).username
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'finds the username for a local account if the domain is the local one' do
- Rails.configuration.x.local_domain = 'example.com'
- resource = 'acct:alice@example.com'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
-
- it 'finds the username for a local account if the domain is the Web one' do
- Rails.configuration.x.web_domain = 'example.com'
- resource = 'acct:alice@example.com'
-
- result = WebfingerResource.new(resource).username
- expect(result).to eq 'alice'
- end
- end
- end
-end
diff --git a/spec/mailers/admin_mailer_spec.rb b/spec/mailers/admin_mailer_spec.rb
deleted file mode 100644
index 4a8ef7b5..00000000
--- a/spec/mailers/admin_mailer_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe AdminMailer, type: :mailer do
- describe '.new_report' do
- let(:sender) { Fabricate(:account, username: 'John', user: Fabricate(:user)) }
- let(:recipient) { Fabricate(:account, username: 'Mike', user: Fabricate(:user, locale: :en)) }
- let(:report) { Fabricate(:report, account: sender, target_account: recipient) }
- let(:mail) { described_class.new_report(recipient, report) }
-
- it 'renders the headers' do
- expect(mail.subject).to eq("New report for cb6e6126.ngrok.io (##{report.id})")
- expect(mail.to).to eq [recipient.user_email]
- expect(mail.from).to eq ['notifications@localhost']
- end
-
- it 'renders the body' do
- expect(mail.body.encoded).to eq("Mike,\r\n\r\nJohn has reported Mike\r\n\r\nView: https://cb6e6126.ngrok.io/admin/reports/#{report.id}\r\n")
- end
- end
-end
diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb
deleted file mode 100644
index 03652ab7..00000000
--- a/spec/mailers/notification_mailer_spec.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-require "rails_helper"
-
-RSpec.describe NotificationMailer, type: :mailer do
- let(:receiver) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) }
- let(:sender) { Fabricate(:account, username: 'bob') }
- let(:foreign_status) { Fabricate(:status, account: sender, text: 'The body of the foreign status') }
- let(:own_status) { Fabricate(:status, account: receiver.account, text: 'The body of the own status') }
-
- shared_examples 'localized subject' do |*args, **kwrest|
- it 'renders subject localized for the locale of the receiver' do
- locale = %i(de en).sample
- receiver.update!(locale: locale)
- expect(mail.subject).to eq I18n.t(*args, kwrest.merge(locale: locale))
- end
-
- it 'renders subject localized for the default locale if the locale of the receiver is unavailable' do
- receiver.update!(locale: nil)
- expect(mail.subject).to eq I18n.t(*args, kwrest.merge(locale: I18n.default_locale))
- end
- end
-
- describe "mention" do
- let(:mention) { Mention.create!(account: receiver.account, status: foreign_status) }
- let(:mail) { NotificationMailer.mention(receiver.account, Notification.create!(account: receiver.account, activity: mention)) }
-
- include_examples 'localized subject', 'notification_mailer.mention.subject', name: 'bob'
-
- it "renders the headers" do
- expect(mail.subject).to eq("You were mentioned by bob")
- expect(mail.to).to eq([receiver.email])
- end
-
- it "renders the body" do
- expect(mail.body.encoded).to match("You were mentioned by bob")
- expect(mail.body.encoded).to include 'The body of the foreign status'
- end
- end
-
- describe "follow" do
- let(:follow) { sender.follow!(receiver.account) }
- let(:mail) { NotificationMailer.follow(receiver.account, Notification.create!(account: receiver.account, activity: follow)) }
-
- include_examples 'localized subject', 'notification_mailer.follow.subject', name: 'bob'
-
- it "renders the headers" do
- expect(mail.subject).to eq("bob is now following you")
- expect(mail.to).to eq([receiver.email])
- end
-
- it "renders the body" do
- expect(mail.body.encoded).to match("bob is now following you")
- end
- end
-
- describe "favourite" do
- let(:favourite) { Favourite.create!(account: sender, status: own_status) }
- let(:mail) { NotificationMailer.favourite(own_status.account, Notification.create!(account: receiver.account, activity: favourite)) }
-
- include_examples 'localized subject', 'notification_mailer.favourite.subject', name: 'bob'
-
- it "renders the headers" do
- expect(mail.subject).to eq("bob favourited your status")
- expect(mail.to).to eq([receiver.email])
- end
-
- it "renders the body" do
- expect(mail.body.encoded).to match("Your status was favourited by bob")
- expect(mail.body.encoded).to include 'The body of the own status'
- end
- end
-
- describe "reblog" do
- let(:reblog) { Status.create!(account: sender, reblog: own_status) }
- let(:mail) { NotificationMailer.reblog(own_status.account, Notification.create!(account: receiver.account, activity: reblog)) }
-
- include_examples 'localized subject', 'notification_mailer.reblog.subject', name: 'bob'
-
- it "renders the headers" do
- expect(mail.subject).to eq("bob reposted your status")
- expect(mail.to).to eq([receiver.email])
- end
-
- it "renders the body" do
- expect(mail.body.encoded).to match("Your status was reposted by bob")
- expect(mail.body.encoded).to include 'The body of the own status'
- end
- end
-
- describe 'follow_request' do
- let(:follow_request) { Fabricate(:follow_request, account: sender, target_account: receiver.account) }
- let(:mail) { NotificationMailer.follow_request(receiver.account, Notification.create!(account: receiver.account, activity: follow_request)) }
-
- include_examples 'localized subject', 'notification_mailer.follow_request.subject', name: 'bob'
-
- it 'renders the headers' do
- expect(mail.subject).to eq('Pending follower: bob')
- expect(mail.to).to eq([receiver.email])
- end
-
- it 'renders the body' do
- expect(mail.body.encoded).to match("bob has requested to follow you")
- end
- end
-
- describe 'digest' do
- before do
- mention = Fabricate(:mention, account: receiver.account, status: foreign_status)
- Fabricate(:notification, account: receiver.account, activity: mention)
- sender.follow!(receiver.account)
- end
-
- context do
- let!(:mail) { NotificationMailer.digest(receiver.account, since: 5.days.ago) }
-
- include_examples 'localized subject', 'notification_mailer.digest.subject', count: 1, name: 'bob'
-
- it 'renders the headers' do
- expect(mail.subject).to match('notification since your last')
- expect(mail.to).to eq([receiver.email])
- end
-
- it 'renders the body' do
- expect(mail.body.encoded).to match('brief summary')
- expect(mail.body.encoded).to include 'The body of the foreign status'
- expect(mail.body.encoded).to include sender.username
- end
- end
-
- it 'includes activities since the receiver last signed in' do
- receiver.update!(last_emailed_at: nil, current_sign_in_at: '2000-03-01T00:00:00Z')
- mail = NotificationMailer.digest(receiver.account)
- expect(mail.body.encoded).to include 'Mar 01, 2000, 00:00'
- end
- end
-end
diff --git a/spec/mailers/previews/admin_mailer_preview.rb b/spec/mailers/previews/admin_mailer_preview.rb
deleted file mode 100644
index 561a56b7..00000000
--- a/spec/mailers/previews/admin_mailer_preview.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Preview all emails at http://localhost:3000/rails/mailers/admin_mailer
-
-class AdminMailerPreview < ActionMailer::Preview
- # Preview this email at http://localhost:3000/rails/mailers/admin_mailer/new_pending_account
- def new_pending_account
- AdminMailer.new_pending_account(Account.first, User.pending.first)
- end
-end
diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb
deleted file mode 100644
index e31445c3..00000000
--- a/spec/mailers/previews/notification_mailer_preview.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# Preview all emails at http://localhost:3000/rails/mailers/notification_mailer
-
-class NotificationMailerPreview < ActionMailer::Preview
- # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/mention
- def mention
- m = Mention.last
- NotificationMailer.mention(m.account, Notification.find_by(activity: m))
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/follow
- def follow
- f = Follow.last
- NotificationMailer.follow(f.target_account, Notification.find_by(activity: f))
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/follow_request
- def follow_request
- f = Follow.last
- NotificationMailer.follow_request(f.target_account, Notification.find_by(activity: f))
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/favourite
- def favourite
- f = Favourite.last
- NotificationMailer.favourite(f.status.account, Notification.find_by(activity: f))
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/reblog
- def reblog
- r = Status.where.not(reblog_of_id: nil).first
- NotificationMailer.reblog(r.reblog.account, Notification.find_by(activity: r))
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/notification_mailer/digest
- def digest
- NotificationMailer.digest(Account.first, since: 90.days.ago)
- end
-end
diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb
deleted file mode 100644
index 53c83649..00000000
--- a/spec/mailers/previews/user_mailer_preview.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
-
-class UserMailerPreview < ActionMailer::Preview
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/confirmation_instructions
- def confirmation_instructions
- UserMailer.confirmation_instructions(User.first, 'spec')
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/email_changed
- def email_changed
- user = User.first
- user.unconfirmed_email = 'foo@bar.com'
- UserMailer.email_changed(user)
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/password_change
- def password_change
- UserMailer.password_change(User.first)
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/reconfirmation_instructions
- def reconfirmation_instructions
- user = User.first
- user.unconfirmed_email = 'foo@bar.com'
- UserMailer.confirmation_instructions(user, 'spec')
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/reset_password_instructions
- def reset_password_instructions
- UserMailer.reset_password_instructions(User.first, 'spec')
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/welcome
- def welcome
- UserMailer.welcome(User.first)
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/backup_ready
- def backup_ready
- UserMailer.backup_ready(User.first, Backup.first)
- end
-
- # Preview this email at http://localhost:3000/rails/mailers/user_mailer/warning
- def warning
- UserMailer.warning(User.first, AccountWarning.new(text: '', action: :silence))
- end
-end
diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb
deleted file mode 100644
index 6b430b50..00000000
--- a/spec/mailers/user_mailer_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe UserMailer, type: :mailer do
- let(:receiver) { Fabricate(:user) }
-
- shared_examples 'localized subject' do |*args, **kwrest|
- it 'renders subject localized for the locale of the receiver' do
- locale = I18n.available_locales.sample
- receiver.update!(locale: locale)
- expect(mail.subject).to eq I18n.t(*args, kwrest.merge(locale: locale))
- end
-
- it 'renders subject localized for the default locale if the locale of the receiver is unavailable' do
- receiver.update!(locale: nil)
- expect(mail.subject).to eq I18n.t(*args, kwrest.merge(locale: I18n.default_locale))
- end
- end
-
- describe 'confirmation_instructions' do
- let(:mail) { UserMailer.confirmation_instructions(receiver, 'spec') }
-
- it 'renders confirmation instructions' do
- receiver.update!(locale: nil)
- expect(mail.body.encoded).to include I18n.t('devise.mailer.confirmation_instructions.title')
- expect(mail.body.encoded).to include 'spec'
- expect(mail.body.encoded).to include Rails.configuration.x.local_domain
- end
-
- include_examples 'localized subject',
- 'devise.mailer.confirmation_instructions.subject',
- instance: Rails.configuration.x.local_domain
- end
-
- describe 'reconfirmation_instructions' do
- let(:mail) { UserMailer.confirmation_instructions(receiver, 'spec') }
-
- it 'renders reconfirmation instructions' do
- receiver.update!(email: 'new-email@example.com', locale: nil)
- expect(mail.body.encoded).to include I18n.t('devise.mailer.reconfirmation_instructions.title')
- expect(mail.body.encoded).to include 'spec'
- expect(mail.body.encoded).to include Rails.configuration.x.local_domain
- expect(mail.subject).to eq I18n.t('devise.mailer.reconfirmation_instructions.subject',
- instance: Rails.configuration.x.local_domain,
- locale: I18n.default_locale)
- end
- end
-
- describe 'reset_password_instructions' do
- let(:mail) { UserMailer.reset_password_instructions(receiver, 'spec') }
-
- it 'renders reset password instructions' do
- receiver.update!(locale: nil)
- expect(mail.body.encoded).to include I18n.t('devise.mailer.reset_password_instructions.title')
- expect(mail.body.encoded).to include 'spec'
- end
-
- include_examples 'localized subject',
- 'devise.mailer.reset_password_instructions.subject'
- end
-
- describe 'password_change' do
- let(:mail) { UserMailer.password_change(receiver) }
-
- it 'renders password change notification' do
- receiver.update!(locale: nil)
- expect(mail.body.encoded).to include I18n.t('devise.mailer.password_change.title')
- end
-
- include_examples 'localized subject',
- 'devise.mailer.password_change.subject'
- end
-
- describe 'email_changed' do
- let(:mail) { UserMailer.email_changed(receiver) }
-
- it 'renders email change notification' do
- receiver.update!(locale: nil)
- expect(mail.body.encoded).to include I18n.t('devise.mailer.email_changed.title')
- end
-
- include_examples 'localized subject',
- 'devise.mailer.email_changed.subject'
- end
-end
diff --git a/spec/models/account_conversation_spec.rb b/spec/models/account_conversation_spec.rb
deleted file mode 100644
index 70a76281..00000000
--- a/spec/models/account_conversation_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AccountConversation, type: :model do
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:bob) { Fabricate(:account, username: 'bob') }
- let!(:mark) { Fabricate(:account, username: 'mark') }
-
- describe '.add_status' do
- it 'creates new record when no others exist' do
- status = Fabricate(:status, account: alice, visibility: :direct)
- status.mentions.create(account: bob)
-
- conversation = AccountConversation.add_status(alice, status)
-
- expect(conversation.participant_accounts).to include(bob)
- expect(conversation.last_status).to eq status
- expect(conversation.status_ids).to eq [status.id]
- end
-
- it 'appends to old record when there is a match' do
- last_status = Fabricate(:status, account: alice, visibility: :direct)
- conversation = AccountConversation.create!(account: alice, conversation: last_status.conversation, participant_account_ids: [bob.id], status_ids: [last_status.id])
-
- status = Fabricate(:status, account: bob, visibility: :direct, thread: last_status)
- status.mentions.create(account: alice)
-
- new_conversation = AccountConversation.add_status(alice, status)
-
- expect(new_conversation.id).to eq conversation.id
- expect(new_conversation.participant_accounts).to include(bob)
- expect(new_conversation.last_status).to eq status
- expect(new_conversation.status_ids).to eq [last_status.id, status.id]
- end
-
- it 'creates new record when new participants are added' do
- last_status = Fabricate(:status, account: alice, visibility: :direct)
- conversation = AccountConversation.create!(account: alice, conversation: last_status.conversation, participant_account_ids: [bob.id], status_ids: [last_status.id])
-
- status = Fabricate(:status, account: bob, visibility: :direct, thread: last_status)
- status.mentions.create(account: alice)
- status.mentions.create(account: mark)
-
- new_conversation = AccountConversation.add_status(alice, status)
-
- expect(new_conversation.id).to_not eq conversation.id
- expect(new_conversation.participant_accounts).to include(bob, mark)
- expect(new_conversation.last_status).to eq status
- expect(new_conversation.status_ids).to eq [status.id]
- end
- end
-
- describe '.remove_status' do
- it 'updates last status to a previous value' do
- last_status = Fabricate(:status, account: alice, visibility: :direct)
- status = Fabricate(:status, account: alice, visibility: :direct)
- conversation = AccountConversation.create!(account: alice, conversation: last_status.conversation, participant_account_ids: [bob.id], status_ids: [status.id, last_status.id])
- last_status.mentions.create(account: bob)
- last_status.destroy!
- conversation.reload
- expect(conversation.last_status).to eq status
- expect(conversation.status_ids).to eq [status.id]
- end
-
- it 'removes the record if no other statuses are referenced' do
- last_status = Fabricate(:status, account: alice, visibility: :direct)
- conversation = AccountConversation.create!(account: alice, conversation: last_status.conversation, participant_account_ids: [bob.id], status_ids: [last_status.id])
- last_status.mentions.create(account: bob)
- last_status.destroy!
- expect(AccountConversation.where(id: conversation.id).count).to eq 0
- end
- end
-end
diff --git a/spec/models/account_domain_block_spec.rb b/spec/models/account_domain_block_spec.rb
deleted file mode 100644
index 469bc05c..00000000
--- a/spec/models/account_domain_block_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AccountDomainBlock, type: :model do
- it 'removes blocking cache after creation' do
- account = Fabricate(:account)
- Rails.cache.write("exclude_domains_for:#{account.id}", 'a.domain.already.blocked')
-
- AccountDomainBlock.create!(account: account, domain: 'a.domain.blocked.later')
-
- expect(Rails.cache.exist?("exclude_domains_for:#{account.id}")).to eq false
- end
-
- it 'removes blocking cache after destruction' do
- account = Fabricate(:account)
- block = AccountDomainBlock.create!(account: account, domain: 'domain')
- Rails.cache.write("exclude_domains_for:#{account.id}", 'domain')
-
- block.destroy!
-
- expect(Rails.cache.exist?("exclude_domains_for:#{account.id}")).to eq false
- end
-end
diff --git a/spec/models/account_filter_spec.rb b/spec/models/account_filter_spec.rb
deleted file mode 100644
index 176a0eea..00000000
--- a/spec/models/account_filter_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-require 'rails_helper'
-
-describe AccountFilter do
- describe 'with empty params' do
- it 'defaults to recent local not-suspended account list' do
- filter = described_class.new({})
-
- expect(filter.results).to eq Account.local.recent.without_suspended
- end
- end
-
- describe 'with invalid params' do
- it 'raises with key error' do
- filter = described_class.new(wrong: true)
-
- expect { filter.results }.to raise_error(/wrong/)
- end
- end
-
- describe 'with valid params' do
- it 'combines filters on Account' do
- filter = described_class.new(
- by_domain: 'test.com',
- silenced: true,
- username: 'test',
- display_name: 'name',
- email: 'user@example.com',
- )
-
- allow(Account).to receive(:where).and_return(Account.none)
- allow(Account).to receive(:silenced).and_return(Account.none)
- allow(Account).to receive(:matches_display_name).and_return(Account.none)
- allow(Account).to receive(:matches_username).and_return(Account.none)
- allow(User).to receive(:matches_email).and_return(User.none)
-
- filter.results
-
- expect(Account).to have_received(:where).with(domain: 'test.com')
- expect(Account).to have_received(:silenced)
- expect(Account).to have_received(:matches_username).with('test')
- expect(Account).to have_received(:matches_display_name).with('name')
- expect(User).to have_received(:matches_email).with('user@example.com')
- end
-
- describe 'that call account methods' do
- %i(local remote silenced suspended).each do |option|
- it "delegates the #{option} option" do
- allow(Account).to receive(option).and_return(Account.none)
- filter = described_class.new({ option => true })
- filter.results
-
- expect(Account).to have_received(option).at_least(1)
- end
- end
- end
- end
-end
diff --git a/spec/models/account_moderation_note_spec.rb b/spec/models/account_moderation_note_spec.rb
deleted file mode 100644
index 69bd5500..00000000
--- a/spec/models/account_moderation_note_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AccountModerationNote, type: :model do
-end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
deleted file mode 100644
index 37987231..00000000
--- a/spec/models/account_spec.rb
+++ /dev/null
@@ -1,792 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Account, type: :model do
- context do
- let(:bob) { Fabricate(:account, username: 'bob') }
- subject { Fabricate(:account) }
-
- describe '#follow!' do
- it 'creates a follow' do
- follow = subject.follow!(bob)
-
- expect(follow).to be_instance_of Follow
- expect(follow.account).to eq subject
- expect(follow.target_account).to eq bob
- end
- end
-
- describe '#unfollow!' do
- before do
- subject.follow!(bob)
- end
-
- it 'destroys a follow' do
- unfollow = subject.unfollow!(bob)
-
- expect(unfollow).to be_instance_of Follow
- expect(unfollow.account).to eq subject
- expect(unfollow.target_account).to eq bob
- expect(unfollow.destroyed?).to be true
- end
- end
-
- describe '#following?' do
- it 'returns true when the target is followed' do
- subject.follow!(bob)
- expect(subject.following?(bob)).to be true
- end
-
- it 'returns false if the target is not followed' do
- expect(subject.following?(bob)).to be false
- end
- end
- end
-
- describe '#local?' do
- it 'returns true when the account is local' do
- account = Fabricate(:account, domain: nil)
- expect(account.local?).to be true
- end
-
- it 'returns false when the account is on a different domain' do
- account = Fabricate(:account, domain: 'foreign.tld')
- expect(account.local?).to be false
- end
- end
-
- describe 'Local domain user methods' do
- around do |example|
- before = Rails.configuration.x.local_domain
- example.run
- Rails.configuration.x.local_domain = before
- end
-
- subject { Fabricate(:account, domain: nil, username: 'alice') }
-
- describe '#to_webfinger_s' do
- it 'returns a webfinger string for the account' do
- Rails.configuration.x.local_domain = 'example.com'
-
- expect(subject.to_webfinger_s).to eq 'acct:alice@example.com'
- end
- end
-
- describe '#local_username_and_domain' do
- it 'returns the username and local domain for the account' do
- Rails.configuration.x.local_domain = 'example.com'
-
- expect(subject.local_username_and_domain).to eq 'alice@example.com'
- end
- end
- end
-
- describe '#acct' do
- it 'returns username for local users' do
- account = Fabricate(:account, domain: nil, username: 'alice')
- expect(account.acct).to eql 'alice'
- end
-
- it 'returns username@domain for foreign users' do
- account = Fabricate(:account, domain: 'foreign.tld', username: 'alice')
- expect(account.acct).to eql 'alice@foreign.tld'
- end
- end
-
- describe '#save_with_optional_media!' do
- before do
- stub_request(:get, 'https://remote.test/valid_avatar').to_return(request_fixture('avatar.txt'))
- stub_request(:get, 'https://remote.test/invalid_avatar').to_return(request_fixture('feed.txt'))
- end
-
- let(:account) do
- Fabricate(:account,
- avatar_remote_url: 'https://remote.test/valid_avatar',
- header_remote_url: 'https://remote.test/valid_avatar')
- end
-
- let!(:expectation) { account.dup }
-
- context 'with valid properties' do
- before do
- account.save_with_optional_media!
- end
-
- it 'unchanges avatar, header, avatar_remote_url, and header_remote_url' do
- expect(account.avatar_remote_url).to eq expectation.avatar_remote_url
- expect(account.header_remote_url).to eq expectation.header_remote_url
- expect(account.avatar_file_name).to eq expectation.avatar_file_name
- expect(account.header_file_name).to eq expectation.header_file_name
- end
- end
-
- context 'with invalid properties' do
- before do
- account.avatar_remote_url = 'https://remote.test/invalid_avatar'
- account.save_with_optional_media!
- end
-
- it 'sets default avatar, header, avatar_remote_url, and header_remote_url' do
- expect(account.avatar_remote_url).to eq ''
- expect(account.header_remote_url).to eq ''
- expect(account.avatar_file_name).to eq nil
- expect(account.header_file_name).to eq nil
- end
- end
- end
-
- describe '#subscribed?' do
- it 'returns false when no subscription expiration information is present' do
- account = Fabricate(:account, subscription_expires_at: nil)
- expect(account.subscribed?).to be false
- end
-
- it 'returns true when subscription expiration has been set' do
- account = Fabricate(:account, subscription_expires_at: 30.days.from_now)
- expect(account.subscribed?).to be true
- end
- end
-
- describe '#possibly_stale?' do
- let(:account) { Fabricate(:account, last_webfingered_at: last_webfingered_at) }
-
- context 'last_webfingered_at is nil' do
- let(:last_webfingered_at) { nil }
-
- it 'returns true' do
- expect(account.possibly_stale?).to be true
- end
- end
-
- context 'last_webfingered_at is more than 24 hours before' do
- let(:last_webfingered_at) { 25.hours.ago }
-
- it 'returns true' do
- expect(account.possibly_stale?).to be true
- end
- end
-
- context 'last_webfingered_at is less than 24 hours before' do
- let(:last_webfingered_at) { 23.hours.ago }
-
- it 'returns false' do
- expect(account.possibly_stale?).to be false
- end
- end
- end
-
- describe '#refresh!' do
- let(:account) { Fabricate(:account, domain: domain) }
- let(:acct) { account.acct }
-
- context 'domain is nil' do
- let(:domain) { nil }
-
- it 'returns nil' do
- expect(account.refresh!).to be_nil
- end
-
- it 'calls not ResolveAccountService#call' do
- expect_any_instance_of(ResolveAccountService).not_to receive(:call).with(acct)
- account.refresh!
- end
- end
-
- context 'domain is present' do
- let(:domain) { 'example.com' }
-
- it 'calls ResolveAccountService#call' do
- expect_any_instance_of(ResolveAccountService).to receive(:call).with(acct).once
- account.refresh!
- end
- end
- end
-
- describe '#to_param' do
- it 'returns username' do
- account = Fabricate(:account, username: 'alice')
- expect(account.to_param).to eq 'alice'
- end
- end
-
- describe '#keypair' do
- it 'returns an RSA key pair' do
- account = Fabricate(:account)
- expect(account.keypair).to be_instance_of OpenSSL::PKey::RSA
- end
- end
-
- describe '#subscription' do
- it 'returns an OStatus subscription' do
- account = Fabricate(:account)
- expect(account.subscription('')).to be_instance_of OStatus2::Subscription
- end
- end
-
- describe '#object_type' do
- it 'is always a person' do
- account = Fabricate(:account)
- expect(account.object_type).to be :person
- end
- end
-
- describe '#favourited?' do
- let(:original_status) do
- author = Fabricate(:account, username: 'original')
- Fabricate(:status, account: author)
- end
-
- subject { Fabricate(:account) }
-
- context 'when the status is a reblog of another status' do
- let(:original_reblog) do
- author = Fabricate(:account, username: 'original_reblogger')
- Fabricate(:status, reblog: original_status, account: author)
- end
-
- it 'is is true when this account has favourited it' do
- Fabricate(:favourite, status: original_reblog, account: subject)
-
- expect(subject.favourited?(original_status)).to eq true
- end
-
- it 'is false when this account has not favourited it' do
- expect(subject.favourited?(original_status)).to eq false
- end
- end
-
- context 'when the status is an original status' do
- it 'is is true when this account has favourited it' do
- Fabricate(:favourite, status: original_status, account: subject)
-
- expect(subject.favourited?(original_status)).to eq true
- end
-
- it 'is false when this account has not favourited it' do
- expect(subject.favourited?(original_status)).to eq false
- end
- end
- end
-
- describe '#reblogged?' do
- let(:original_status) do
- author = Fabricate(:account, username: 'original')
- Fabricate(:status, account: author)
- end
-
- subject { Fabricate(:account) }
-
- context 'when the status is a reblog of another status' do
- let(:original_reblog) do
- author = Fabricate(:account, username: 'original_reblogger')
- Fabricate(:status, reblog: original_status, account: author)
- end
-
- it 'is true when this account has reblogged it' do
- Fabricate(:status, reblog: original_reblog, account: subject)
-
- expect(subject.reblogged?(original_reblog)).to eq true
- end
-
- it 'is false when this account has not reblogged it' do
- expect(subject.reblogged?(original_reblog)).to eq false
- end
- end
-
- context 'when the status is an original status' do
- it 'is true when this account has reblogged it' do
- Fabricate(:status, reblog: original_status, account: subject)
-
- expect(subject.reblogged?(original_status)).to eq true
- end
-
- it 'is false when this account has not reblogged it' do
- expect(subject.reblogged?(original_status)).to eq false
- end
- end
- end
-
- describe '#excluded_from_timeline_account_ids' do
- it 'includes account ids of blockings, blocked_bys and mutes' do
- account = Fabricate(:account)
- block = Fabricate(:block, account: account)
- mute = Fabricate(:mute, account: account)
- block_by = Fabricate(:block, target_account: account)
-
- results = account.excluded_from_timeline_account_ids
- expect(results.size).to eq 3
- expect(results).to include(block.target_account.id)
- expect(results).to include(mute.target_account.id)
- expect(results).to include(block_by.account.id)
- end
- end
-
- describe '#excluded_from_timeline_domains' do
- it 'returns the domains blocked by the account' do
- account = Fabricate(:account)
- account.block_domain!('domain')
- expect(account.excluded_from_timeline_domains).to match_array ['domain']
- end
- end
-
- describe '.search_for' do
- before do
- _missing = Fabricate(
- :account,
- display_name: "Missing",
- username: "missing",
- domain: "missing.com"
- )
- end
-
- it 'accepts ?, \, : and space as delimiter' do
- match = Fabricate(
- :account,
- display_name: 'A & l & i & c & e',
- username: 'username',
- domain: 'example.com'
- )
-
- results = Account.search_for('A?l\i:c e')
- expect(results).to eq [match]
- end
-
- it 'finds accounts with matching display_name' do
- match = Fabricate(
- :account,
- display_name: "Display Name",
- username: "username",
- domain: "example.com"
- )
-
- results = Account.search_for("display")
- expect(results).to eq [match]
- end
-
- it 'finds accounts with matching username' do
- match = Fabricate(
- :account,
- display_name: "Display Name",
- username: "username",
- domain: "example.com"
- )
-
- results = Account.search_for("username")
- expect(results).to eq [match]
- end
-
- it 'finds accounts with matching domain' do
- match = Fabricate(
- :account,
- display_name: "Display Name",
- username: "username",
- domain: "example.com"
- )
-
- results = Account.search_for("example")
- expect(results).to eq [match]
- end
-
- it 'limits by 10 by default' do
- 11.times.each { Fabricate(:account, display_name: "Display Name") }
- results = Account.search_for("display")
- expect(results.size).to eq 10
- end
-
- it 'accepts arbitrary limits' do
- 2.times.each { Fabricate(:account, display_name: "Display Name") }
- results = Account.search_for("display", 1)
- expect(results.size).to eq 1
- end
-
- it 'ranks multiple matches higher' do
- matches = [
- { username: "username", display_name: "username" },
- { display_name: "Display Name", username: "username", domain: "example.com" },
- ].map(&method(:Fabricate).curry(2).call(:account))
-
- results = Account.search_for("username")
- expect(results).to eq matches
- end
- end
-
- describe '.advanced_search_for' do
- it 'accepts ?, \, : and space as delimiter' do
- account = Fabricate(:account)
- match = Fabricate(
- :account,
- display_name: 'A & l & i & c & e',
- username: 'username',
- domain: 'example.com'
- )
-
- results = Account.advanced_search_for('A?l\i:c e', account)
- expect(results).to eq [match]
- end
-
- it 'limits by 10 by default' do
- 11.times { Fabricate(:account, display_name: "Display Name") }
- results = Account.search_for("display")
- expect(results.size).to eq 10
- end
-
- it 'accepts arbitrary limits' do
- 2.times { Fabricate(:account, display_name: "Display Name") }
- results = Account.search_for("display", 1)
- expect(results.size).to eq 1
- end
-
- it 'ranks followed accounts higher' do
- account = Fabricate(:account)
- match = Fabricate(:account, username: "Matching")
- followed_match = Fabricate(:account, username: "Matcher")
- Fabricate(:follow, account: account, target_account: followed_match)
-
- results = Account.advanced_search_for("match", account)
- expect(results).to eq [followed_match, match]
- expect(results.first.rank).to be > results.last.rank
- end
- end
-
- describe '.domains' do
- it 'returns domains' do
- Fabricate(:account, domain: 'domain')
- expect(Account.domains).to match_array(['domain'])
- end
- end
-
- describe '#statuses_count' do
- subject { Fabricate(:account) }
-
- it 'counts statuses' do
- Fabricate(:status, account: subject)
- Fabricate(:status, account: subject)
- expect(subject.statuses_count).to eq 2
- end
-
- it 'does not count direct statuses' do
- Fabricate(:status, account: subject, visibility: :direct)
- expect(subject.statuses_count).to eq 0
- end
-
- it 'is decremented when status is removed' do
- status = Fabricate(:status, account: subject)
- expect(subject.statuses_count).to eq 1
- status.destroy
- expect(subject.statuses_count).to eq 0
- end
-
- it 'is decremented when status is removed when account is not preloaded' do
- status = Fabricate(:status, account: subject)
- expect(subject.reload.statuses_count).to eq 1
- clean_status = Status.find(status.id)
- expect(clean_status.association(:account).loaded?).to be false
- clean_status.destroy
- expect(subject.reload.statuses_count).to eq 0
- end
- end
-
- describe '.following_map' do
- it 'returns an hash' do
- expect(Account.following_map([], 1)).to be_a Hash
- end
- end
-
- describe '.followed_by_map' do
- it 'returns an hash' do
- expect(Account.followed_by_map([], 1)).to be_a Hash
- end
- end
-
- describe '.blocking_map' do
- it 'returns an hash' do
- expect(Account.blocking_map([], 1)).to be_a Hash
- end
- end
-
- describe '.requested_map' do
- it 'returns an hash' do
- expect(Account.requested_map([], 1)).to be_a Hash
- end
- end
-
- describe 'MENTION_RE' do
- subject { Account::MENTION_RE }
-
- it 'matches usernames in the middle of a sentence' do
- expect(subject.match('Hello to @alice from me')[1]).to eq 'alice'
- end
-
- it 'matches usernames in the beginning of status' do
- expect(subject.match('@alice Hey how are you?')[1]).to eq 'alice'
- end
-
- it 'matches full usernames' do
- expect(subject.match('@alice@example.com')[1]).to eq 'alice@example.com'
- end
-
- it 'matches full usernames with a dot at the end' do
- expect(subject.match('Hello @alice@example.com.')[1]).to eq 'alice@example.com'
- end
-
- it 'matches dot-prepended usernames' do
- expect(subject.match('.@alice I want everybody to see this')[1]).to eq 'alice'
- end
-
- it 'does not match e-mails' do
- expect(subject.match('Drop me an e-mail at alice@example.com')).to be_nil
- end
-
- it 'does not match URLs' do
- expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
- end
-
- xit 'does not match URL querystring' do
- expect(subject.match('https://example.com/?x=@alice')).to be_nil
- end
- end
-
- describe 'validations' do
- it 'has a valid fabricator' do
- account = Fabricate.build(:account)
- account.valid?
- expect(account).to be_valid
- end
-
- it 'is invalid without a username' do
- account = Fabricate.build(:account, username: nil)
- account.valid?
- expect(account).to model_have_error_on_field(:username)
- end
-
- it 'squishes the username before validation' do
- account = Fabricate(:account, domain: nil, username: " \u3000bob \t \u00a0 \n ")
- expect(account.username).to eq 'bob'
- end
-
- context 'when is local' do
- it 'is invalid if the username is not unique in case-insensitive comparison among local accounts' do
- account_1 = Fabricate(:account, username: 'the_doctor')
- account_2 = Fabricate.build(:account, username: 'the_Doctor')
- account_2.valid?
- expect(account_2).to model_have_error_on_field(:username)
- end
-
- it 'is invalid if the username is reserved' do
- account = Fabricate.build(:account, username: 'support')
- account.valid?
- expect(account).to model_have_error_on_field(:username)
- end
-
- it 'is valid when username is reserved but record has already been created' do
- account = Fabricate.build(:account, username: 'support')
- account.save(validate: false)
- expect(account.valid?).to be true
- end
-
- it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do
- account = Fabricate.build(:account, username: 'the-doctor')
- account.valid?
- expect(account).to model_have_error_on_field(:username)
- end
-
- it 'is invalid if the username is longer then 30 characters' do
- account = Fabricate.build(:account, username: Faker::Lorem.characters(31))
- account.valid?
- expect(account).to model_have_error_on_field(:username)
- end
-
- it 'is invalid if the display name is longer than 30 characters' do
- account = Fabricate.build(:account, display_name: Faker::Lorem.characters(31))
- account.valid?
- expect(account).to model_have_error_on_field(:display_name)
- end
-
- it 'is invalid if the note is longer than 500 characters' do
- account = Fabricate.build(:account, note: Faker::Lorem.characters(501))
- account.valid?
- expect(account).to model_have_error_on_field(:note)
- end
- end
-
- context 'when is remote' do
- it 'is invalid if the username is not unique in case-sensitive comparison among accounts in the same normalized domain' do
- Fabricate(:account, domain: 'ã«ã‚ƒã‚“', username: 'username')
- account = Fabricate.build(:account, domain: 'xn--r9j5b5b', username: 'username')
- account.valid?
- expect(account).to model_have_error_on_field(:username)
- end
-
- it 'is valid even if the username is unique only in case-sensitive comparison among accounts in the same normalized domain' do
- Fabricate(:account, domain: 'ã«ã‚ƒã‚“', username: 'username')
- account = Fabricate.build(:account, domain: 'xn--r9j5b5b', username: 'Username')
- account.valid?
- expect(account).not_to model_have_error_on_field(:username)
- end
-
- it 'is valid even if the username contains hyphens' do
- account = Fabricate.build(:account, domain: 'domain', username: 'the-doctor')
- account.valid?
- expect(account).to_not model_have_error_on_field(:username)
- end
-
- it 'is invalid if the username doesn\'t only contains letters, numbers, underscores and hyphens' do
- account = Fabricate.build(:account, domain: 'domain', username: 'the doctor')
- account.valid?
- expect(account).to model_have_error_on_field(:username)
- end
-
- it 'is valid even if the username is longer then 30 characters' do
- account = Fabricate.build(:account, domain: 'domain', username: Faker::Lorem.characters(31))
- account.valid?
- expect(account).not_to model_have_error_on_field(:username)
- end
-
- it 'is valid even if the display name is longer than 30 characters' do
- account = Fabricate.build(:account, domain: 'domain', display_name: Faker::Lorem.characters(31))
- account.valid?
- expect(account).not_to model_have_error_on_field(:display_name)
- end
-
- it 'is valid even if the note is longer than 500 characters' do
- account = Fabricate.build(:account, domain: 'domain', note: Faker::Lorem.characters(501))
- account.valid?
- expect(account).not_to model_have_error_on_field(:note)
- end
- end
- end
-
- describe 'scopes' do
- describe 'alphabetic' do
- it 'sorts by alphabetic order of domain and username' do
- matches = [
- { username: 'a', domain: 'a' },
- { username: 'b', domain: 'a' },
- { username: 'a', domain: 'b' },
- { username: 'b', domain: 'b' },
- ].map(&method(:Fabricate).curry(2).call(:account))
-
- expect(Account.alphabetic).to eq matches
- end
- end
-
- describe 'matches_display_name' do
- it 'matches display name which starts with the given string' do
- match = Fabricate(:account, display_name: 'pattern and suffix')
- Fabricate(:account, display_name: 'prefix and pattern')
-
- expect(Account.matches_display_name('pattern')).to eq [match]
- end
- end
-
- describe 'matches_username' do
- it 'matches display name which starts with the given string' do
- match = Fabricate(:account, username: 'pattern_and_suffix')
- Fabricate(:account, username: 'prefix_and_pattern')
-
- expect(Account.matches_username('pattern')).to eq [match]
- end
- end
-
- describe 'expiring' do
- it 'returns remote accounts with followers whose subscription expiration date is past or not given' do
- local = Fabricate(:account, domain: nil)
- matches = [
- { domain: 'remote', subscription_expires_at: '2000-01-01T00:00:00Z' },
- ].map(&method(:Fabricate).curry(2).call(:account))
- matches.each(&local.method(:follow!))
- Fabricate(:account, domain: 'remote', subscription_expires_at: nil)
- local.follow!(Fabricate(:account, domain: 'remote', subscription_expires_at: '2000-01-03T00:00:00Z'))
- local.follow!(Fabricate(:account, domain: nil, subscription_expires_at: nil))
-
- expect(Account.expiring('2000-01-02T00:00:00Z').recent).to eq matches.reverse
- end
- end
-
- describe 'remote' do
- it 'returns an array of accounts who have a domain' do
- account_1 = Fabricate(:account, domain: nil)
- account_2 = Fabricate(:account, domain: 'example.com')
- expect(Account.remote).to match_array([account_2])
- end
- end
-
- describe 'by_domain_accounts' do
- it 'returns accounts grouped by domain sorted by accounts' do
- 2.times { Fabricate(:account, domain: 'example.com') }
- Fabricate(:account, domain: 'example2.com')
-
- results = Account.by_domain_accounts
- expect(results.length).to eq 2
- expect(results.first.domain).to eq 'example.com'
- expect(results.first.accounts_count).to eq 2
- expect(results.last.domain).to eq 'example2.com'
- expect(results.last.accounts_count).to eq 1
- end
- end
-
- describe 'local' do
- it 'returns an array of accounts who do not have a domain' do
- account_1 = Fabricate(:account, domain: nil)
- account_2 = Fabricate(:account, domain: 'example.com')
- expect(Account.local).to match_array([account_1])
- end
- end
-
- describe 'partitioned' do
- it 'returns a relation of accounts partitioned by domain' do
- matches = ['a', 'b', 'a', 'b']
- matches.size.times.to_a.shuffle.each do |index|
- matches[index] = Fabricate(:account, domain: matches[index])
- end
-
- expect(Account.partitioned).to match_array(matches)
- end
- end
-
- describe 'recent' do
- it 'returns a relation of accounts sorted by recent creation' do
- matches = 2.times.map { Fabricate(:account) }
- expect(Account.recent).to match_array(matches)
- end
- end
-
- describe 'silenced' do
- it 'returns an array of accounts who are silenced' do
- account_1 = Fabricate(:account, silenced: true)
- account_2 = Fabricate(:account, silenced: false)
- expect(Account.silenced).to match_array([account_1])
- end
- end
-
- describe 'suspended' do
- it 'returns an array of accounts who are suspended' do
- account_1 = Fabricate(:account, suspended: true)
- account_2 = Fabricate(:account, suspended: false)
- expect(Account.suspended).to match_array([account_1])
- end
- end
- end
-
- context 'when is local' do
- # Test disabled because test environment omits autogenerating keys for performance
- xit 'generates keys' do
- account = Account.create!(domain: nil, username: Faker::Internet.user_name(nil, ['_']))
- expect(account.keypair.private?).to eq true
- end
- end
-
- context 'when is remote' do
- it 'does not generate keys' do
- key = OpenSSL::PKey::RSA.new(1024).public_key
- account = Account.create!(domain: 'remote', username: Faker::Internet.user_name(nil, ['_']), public_key: key.to_pem)
- expect(account.keypair.params).to eq key.params
- end
-
- it 'normalizes domain' do
- account = Account.create!(domain: 'ã«ã‚ƒã‚“', username: Faker::Internet.user_name(nil, ['_']))
- expect(account.domain).to eq 'xn--r9j5b5b'
- end
- end
-
- include_examples 'AccountAvatar', :account
-end
diff --git a/spec/models/account_stat_spec.rb b/spec/models/account_stat_spec.rb
deleted file mode 100644
index a9418510..00000000
--- a/spec/models/account_stat_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AccountStat, type: :model do
-end
diff --git a/spec/models/account_tag_stat_spec.rb b/spec/models/account_tag_stat_spec.rb
deleted file mode 100644
index 6d3057f3..00000000
--- a/spec/models/account_tag_stat_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe AccountTagStat, type: :model do
- key = 'accounts_count'
- let(:account_tag_stat) { Fabricate(:tag).account_tag_stat }
-
- describe '#increment_count!' do
- it 'calls #update' do
- args = { key => account_tag_stat.public_send(key) + 1 }
- expect(account_tag_stat).to receive(:update).with(args)
- account_tag_stat.increment_count!(key)
- end
-
- it 'increments value by 1' do
- expect do
- account_tag_stat.increment_count!(key)
- end.to change { account_tag_stat.accounts_count }.by(1)
- end
- end
-
- describe '#decrement_count!' do
- it 'calls #update' do
- args = { key => [account_tag_stat.public_send(key) - 1, 0].max }
- expect(account_tag_stat).to receive(:update).with(args)
- account_tag_stat.decrement_count!(key)
- end
-
- it 'decrements value by 1' do
- account_tag_stat.update(key => 1)
-
- expect do
- account_tag_stat.decrement_count!(key)
- end.to change { account_tag_stat.accounts_count }.by(-1)
- end
- end
-end
diff --git a/spec/models/admin/account_action_spec.rb b/spec/models/admin/account_action_spec.rb
deleted file mode 100644
index a3db60cf..00000000
--- a/spec/models/admin/account_action_spec.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Admin::AccountAction, type: :model do
- let(:account_action) { described_class.new }
-
- describe '#save!' do
- subject { account_action.save! }
- let(:account) { Fabricate(:account, user: Fabricate(:user, admin: true)) }
- let(:target_account) { Fabricate(:account, user: Fabricate(:user)) }
- let(:type) { 'disable' }
-
- before do
- account_action.assign_attributes(
- type: type,
- current_account: account,
- target_account: target_account
- )
- end
-
- context 'type is "disable"' do
- let(:type) { 'disable' }
-
- it 'disable user' do
- subject
- expect(target_account.user).to be_disabled
- end
- end
-
- context 'type is "silence"' do
- let(:type) { 'silence' }
-
- it 'silences account' do
- subject
- expect(target_account).to be_silenced
- end
- end
-
- context 'type is "suspend"' do
- let(:type) { 'suspend' }
-
- it 'suspends account' do
- subject
- expect(target_account).to be_suspended
- end
-
- it 'queues Admin::SuspensionWorker by 1' do
- Sidekiq::Testing.fake! do
- expect do
- subject
- end.to change { Admin::SuspensionWorker.jobs.size }.by 1
- end
- end
- end
-
- it 'creates Admin::ActionLog' do
- expect do
- subject
- end.to change { Admin::ActionLog.count }.by 1
- end
-
- it 'calls queue_email!' do
- expect(account_action).to receive(:queue_email!)
- subject
- end
-
- it 'calls process_reports!' do
- expect(account_action).to receive(:process_reports!)
- subject
- end
- end
-
- describe '#report' do
- subject { account_action.report }
-
- context 'report_id.present?' do
- before do
- account_action.report_id = Fabricate(:report).id
- end
-
- it 'returns Report' do
- expect(subject).to be_instance_of Report
- end
- end
-
- context '!report_id.present?' do
- it 'returns nil' do
- expect(subject).to be_nil
- end
- end
- end
-
- describe '#with_report?' do
- subject { account_action.with_report? }
-
- context '!report.nil?' do
- before do
- account_action.report_id = Fabricate(:report).id
- end
-
- it 'returns true' do
- expect(subject).to be true
- end
- end
-
- context '!(!report.nil?)' do
- it 'returns false' do
- expect(subject).to be false
- end
- end
- end
-
- describe '.types_for_account' do
- subject { described_class.types_for_account(account) }
-
- context 'account.local?' do
- let(:account) { Fabricate(:account, domain: nil) }
-
- it 'returns ["none", "disable", "silence", "suspend"]' do
- expect(subject).to eq %w(none disable silence suspend)
- end
- end
-
- context '!account.local?' do
- let(:account) { Fabricate(:account, domain: 'hoge.com') }
-
- it 'returns ["silence", "suspend"]' do
- expect(subject).to eq %w(silence suspend)
- end
- end
- end
-end
diff --git a/spec/models/admin/action_log_spec.rb b/spec/models/admin/action_log_spec.rb
deleted file mode 100644
index 3495cc51..00000000
--- a/spec/models/admin/action_log_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Admin::ActionLog, type: :model do
- describe '#action' do
- it 'returns action' do
- action_log = described_class.new(action: 'hoge')
- expect(action_log.action).to be :hoge
- end
- end
-end
diff --git a/spec/models/backup_spec.rb b/spec/models/backup_spec.rb
deleted file mode 100644
index 45230986..00000000
--- a/spec/models/backup_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Backup, type: :model do
-end
diff --git a/spec/models/block_spec.rb b/spec/models/block_spec.rb
deleted file mode 100644
index acbdc77f..00000000
--- a/spec/models/block_spec.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Block, type: :model do
- describe 'validations' do
- it 'has a valid fabricator' do
- block = Fabricate.build(:block)
- expect(block).to be_valid
- end
-
- it 'is invalid without an account' do
- block = Fabricate.build(:block, account: nil)
- block.valid?
- expect(block).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a target_account' do
- block = Fabricate.build(:block, target_account: nil)
- block.valid?
- expect(block).to model_have_error_on_field(:target_account)
- end
- end
-
- it 'removes blocking cache after creation' do
- account = Fabricate(:account)
- target_account = Fabricate(:account)
- Rails.cache.write("exclude_account_ids_for:#{account.id}", [])
- Rails.cache.write("exclude_account_ids_for:#{target_account.id}", [])
-
- Block.create!(account: account, target_account: target_account)
-
- expect(Rails.cache.exist?("exclude_account_ids_for:#{account.id}")).to eq false
- expect(Rails.cache.exist?("exclude_account_ids_for:#{target_account.id}")).to eq false
- end
-
- it 'removes blocking cache after destruction' do
- account = Fabricate(:account)
- target_account = Fabricate(:account)
- block = Block.create!(account: account, target_account: target_account)
- Rails.cache.write("exclude_account_ids_for:#{account.id}", [target_account.id])
- Rails.cache.write("exclude_account_ids_for:#{target_account.id}", [account.id])
-
- block.destroy!
-
- expect(Rails.cache.exist?("exclude_account_ids_for:#{account.id}")).to eq false
- expect(Rails.cache.exist?("exclude_account_ids_for:#{target_account.id}")).to eq false
- end
-end
diff --git a/spec/models/concerns/account_finder_concern_spec.rb b/spec/models/concerns/account_finder_concern_spec.rb
deleted file mode 100644
index 7b1c1155..00000000
--- a/spec/models/concerns/account_finder_concern_spec.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe AccountFinderConcern do
- describe 'local finders' do
- before do
- @account = Fabricate(:account, username: 'Alice')
- end
-
- describe '.find_local' do
- it 'returns case-insensitive result' do
- expect(Account.find_local('alice')).to eq(@account)
- end
-
- it 'returns correctly cased result' do
- expect(Account.find_local('Alice')).to eq(@account)
- end
-
- it 'returns nil without a match' do
- expect(Account.find_local('a_ice')).to be_nil
- end
-
- it 'returns nil for regex style username value' do
- expect(Account.find_local('al%')).to be_nil
- end
-
- it 'returns nil for nil username value' do
- expect(Account.find_local(nil)).to be_nil
- end
-
- it 'returns nil for blank username value' do
- expect(Account.find_local('')).to be_nil
- end
- end
-
- describe '.find_local!' do
- it 'returns matching result' do
- expect(Account.find_local!('alice')).to eq(@account)
- end
-
- it 'raises on non-matching result' do
- expect { Account.find_local!('missing') }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises with blank username' do
- expect { Account.find_local!('') }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises with nil username' do
- expect { Account.find_local!(nil) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
- end
-
- describe 'remote finders' do
- before do
- @account = Fabricate(:account, username: 'Alice', domain: 'gab.com')
- end
-
- describe '.find_remote' do
- it 'returns exact match result' do
- expect(Account.find_remote('alice', 'gab.com')).to eq(@account)
- end
-
- it 'returns case-insensitive result' do
- expect(Account.find_remote('ALICE', 'GAB.COM')).to eq(@account)
- end
-
- it 'returns nil when username does not match' do
- expect(Account.find_remote('a_ice', 'gab.com')).to be_nil
- end
-
- it 'returns nil when domain does not match' do
- expect(Account.find_remote('alice', 'g_b.com')).to be_nil
- end
-
- it 'returns nil for regex style domain value' do
- expect(Account.find_remote('alice', 'm%')).to be_nil
- end
-
- it 'returns nil for nil username value' do
- expect(Account.find_remote(nil, 'domain')).to be_nil
- end
-
- it 'returns nil for blank username value' do
- expect(Account.find_remote('', 'domain')).to be_nil
- end
- end
-
- describe '.find_remote!' do
- it 'returns matching result' do
- expect(Account.find_remote!('alice', 'gab.com')).to eq(@account)
- end
-
- it 'raises on non-matching result' do
- expect { Account.find_remote!('missing', 'gab.host') }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises with blank username' do
- expect { Account.find_remote!('', '') }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'raises with nil username' do
- expect { Account.find_remote!(nil, nil) }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
- end
-end
diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb
deleted file mode 100644
index e8ef61f6..00000000
--- a/spec/models/concerns/account_interactions_spec.rb
+++ /dev/null
@@ -1,613 +0,0 @@
-require 'rails_helper'
-
-describe AccountInteractions do
- let(:account) { Fabricate(:account, username: 'account') }
- let(:account_id) { account.id }
- let(:account_ids) { [account_id] }
- let(:target_account) { Fabricate(:account, username: 'target') }
- let(:target_account_id) { target_account.id }
- let(:target_account_ids) { [target_account_id] }
-
- describe '.following_map' do
- subject { Account.following_map(target_account_ids, account_id) }
-
- context 'account with Follow' do
- it 'returns { target_account_id => true }' do
- Fabricate(:follow, account: account, target_account: target_account)
- is_expected.to eq(target_account_id => { reblogs: true })
- end
- end
-
- context 'account without Follow' do
- it 'returns {}' do
- is_expected.to eq({})
- end
- end
- end
-
- describe '.followed_by_map' do
- subject { Account.followed_by_map(target_account_ids, account_id) }
-
- context 'account with Follow' do
- it 'returns { target_account_id => true }' do
- Fabricate(:follow, account: target_account, target_account: account)
- is_expected.to eq(target_account_id => true)
- end
- end
-
- context 'account without Follow' do
- it 'returns {}' do
- is_expected.to eq({})
- end
- end
- end
-
- describe '.blocking_map' do
- subject { Account.blocking_map(target_account_ids, account_id) }
-
- context 'account with Block' do
- it 'returns { target_account_id => true }' do
- Fabricate(:block, account: account, target_account: target_account)
- is_expected.to eq(target_account_id => true)
- end
- end
-
- context 'account without Block' do
- it 'returns {}' do
- is_expected.to eq({})
- end
- end
- end
-
- describe '.muting_map' do
- subject { Account.muting_map(target_account_ids, account_id) }
-
- context 'account with Mute' do
- before do
- Fabricate(:mute, target_account: target_account, account: account, hide_notifications: hide)
- end
-
- context 'if Mute#hide_notifications?' do
- let(:hide) { true }
-
- it 'returns { target_account_id => { notifications: true } }' do
- is_expected.to eq(target_account_id => { notifications: true })
- end
- end
-
- context 'unless Mute#hide_notifications?' do
- let(:hide) { false }
-
- it 'returns { target_account_id => { notifications: false } }' do
- is_expected.to eq(target_account_id => { notifications: false })
- end
- end
- end
-
- context 'account without Mute' do
- it 'returns {}' do
- is_expected.to eq({})
- end
- end
- end
-
- describe '#follow!' do
- it 'creates and returns Follow' do
- expect do
- expect(account.follow!(target_account)).to be_kind_of Follow
- end.to change { account.following.count }.by 1
- end
- end
-
- describe '#block' do
- it 'creates and returns Block' do
- expect do
- expect(account.block!(target_account)).to be_kind_of Block
- end.to change { account.block_relationships.count }.by 1
- end
- end
-
- describe '#mute!' do
- subject { account.mute!(target_account, notifications: arg_notifications) }
-
- context 'Mute does not exist yet' do
- context 'arg :notifications is nil' do
- let(:arg_notifications) { nil }
-
- it 'creates Mute, and returns Mute' do
- expect do
- expect(subject).to be_kind_of Mute
- end.to change { account.mute_relationships.count }.by 1
- end
- end
-
- context 'arg :notifications is false' do
- let(:arg_notifications) { false }
-
- it 'creates Mute, and returns Mute' do
- expect do
- expect(subject).to be_kind_of Mute
- end.to change { account.mute_relationships.count }.by 1
- end
- end
-
- context 'arg :notifications is true' do
- let(:arg_notifications) { true }
-
- it 'creates Mute, and returns Mute' do
- expect do
- expect(subject).to be_kind_of Mute
- end.to change { account.mute_relationships.count }.by 1
- end
- end
- end
-
- context 'Mute already exists' do
- before do
- account.mute_relationships << mute
- end
-
- let(:mute) do
- Fabricate(:mute,
- account: account,
- target_account: target_account,
- hide_notifications: hide_notifications)
- end
-
- context 'mute.hide_notifications is true' do
- let(:hide_notifications) { true }
-
- context 'arg :notifications is nil' do
- let(:arg_notifications) { nil }
-
- it 'returns Mute without updating mute.hide_notifications' do
- expect do
- expect(subject).to be_kind_of Mute
- end.not_to change { mute.reload.hide_notifications? }.from(true)
- end
- end
-
- context 'arg :notifications is false' do
- let(:arg_notifications) { false }
-
- it 'returns Mute, and updates mute.hide_notifications false' do
- expect do
- expect(subject).to be_kind_of Mute
- end.to change { mute.reload.hide_notifications? }.from(true).to(false)
- end
- end
-
- context 'arg :notifications is true' do
- let(:arg_notifications) { true }
-
- it 'returns Mute without updating mute.hide_notifications' do
- expect do
- expect(subject).to be_kind_of Mute
- end.not_to change { mute.reload.hide_notifications? }.from(true)
- end
- end
- end
-
- context 'mute.hide_notifications is false' do
- let(:hide_notifications) { false }
-
- context 'arg :notifications is nil' do
- let(:arg_notifications) { nil }
-
- it 'returns Mute, and updates mute.hide_notifications true' do
- expect do
- expect(subject).to be_kind_of Mute
- end.to change { mute.reload.hide_notifications? }.from(false).to(true)
- end
- end
-
- context 'arg :notifications is false' do
- let(:arg_notifications) { false }
-
- it 'returns Mute without updating mute.hide_notifications' do
- expect do
- expect(subject).to be_kind_of Mute
- end.not_to change { mute.reload.hide_notifications? }.from(false)
- end
- end
-
- context 'arg :notifications is true' do
- let(:arg_notifications) { true }
-
- it 'returns Mute, and updates mute.hide_notifications true' do
- expect do
- expect(subject).to be_kind_of Mute
- end.to change { mute.reload.hide_notifications? }.from(false).to(true)
- end
- end
- end
- end
- end
-
- describe '#mute_conversation!' do
- let(:conversation) { Fabricate(:conversation) }
-
- subject { account.mute_conversation!(conversation) }
-
- it 'creates and returns ConversationMute' do
- expect do
- is_expected.to be_kind_of ConversationMute
- end.to change { account.conversation_mutes.count }.by 1
- end
- end
-
- describe '#block_domain!' do
- let(:domain) { 'example.com' }
-
- subject { account.block_domain!(domain) }
-
- it 'creates and returns AccountDomainBlock' do
- expect do
- is_expected.to be_kind_of AccountDomainBlock
- end.to change { account.domain_blocks.count }.by 1
- end
- end
-
- describe '#unfollow!' do
- subject { account.unfollow!(target_account) }
-
- context 'following target_account' do
- it 'returns destroyed Follow' do
- account.active_relationships.create(target_account: target_account)
- is_expected.to be_kind_of Follow
- expect(subject).to be_destroyed
- end
- end
-
- context 'not following target_account' do
- it 'returns nil' do
- is_expected.to be_nil
- end
- end
- end
-
- describe '#unblock!' do
- subject { account.unblock!(target_account) }
-
- context 'blocking target_account' do
- it 'returns destroyed Block' do
- account.block_relationships.create(target_account: target_account)
- is_expected.to be_kind_of Block
- expect(subject).to be_destroyed
- end
- end
-
- context 'not blocking target_account' do
- it 'returns nil' do
- is_expected.to be_nil
- end
- end
- end
-
- describe '#unmute!' do
- subject { account.unmute!(target_account) }
-
- context 'muting target_account' do
- it 'returns destroyed Mute' do
- account.mute_relationships.create(target_account: target_account)
- is_expected.to be_kind_of Mute
- expect(subject).to be_destroyed
- end
- end
-
- context 'not muting target_account' do
- it 'returns nil' do
- is_expected.to be_nil
- end
- end
- end
-
- describe '#unmute_conversation!' do
- let(:conversation) { Fabricate(:conversation) }
-
- subject { account.unmute_conversation!(conversation) }
-
- context 'muting the conversation' do
- it 'returns destroyed ConversationMute' do
- account.conversation_mutes.create(conversation: conversation)
- is_expected.to be_kind_of ConversationMute
- expect(subject).to be_destroyed
- end
- end
-
- context 'not muting the conversation' do
- it 'returns nil' do
- is_expected.to be nil
- end
- end
- end
-
- describe '#unblock_domain!' do
- let(:domain) { 'example.com' }
-
- subject { account.unblock_domain!(domain) }
-
- context 'blocking the domain' do
- it 'returns destroyed AccountDomainBlock' do
- account_domain_block = Fabricate(:account_domain_block, domain: domain)
- account.domain_blocks << account_domain_block
- is_expected.to be_kind_of AccountDomainBlock
- expect(subject).to be_destroyed
- end
- end
-
- context 'unblocking the domain' do
- it 'returns nil' do
- is_expected.to be_nil
- end
- end
- end
-
- describe '#following?' do
- subject { account.following?(target_account) }
-
- context 'following target_account' do
- it 'returns true' do
- account.active_relationships.create(target_account: target_account)
- is_expected.to be true
- end
- end
-
- context 'not following target_account' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#blocking?' do
- subject { account.blocking?(target_account) }
-
- context 'blocking target_account' do
- it 'returns true' do
- account.block_relationships.create(target_account: target_account)
- is_expected.to be true
- end
- end
-
- context 'not blocking target_account' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#domain_blocking?' do
- let(:domain) { 'example.com' }
-
- subject { account.domain_blocking?(domain) }
-
- context 'blocking the domain' do
- it' returns true' do
- account_domain_block = Fabricate(:account_domain_block, domain: domain)
- account.domain_blocks << account_domain_block
- is_expected.to be true
- end
- end
-
- context 'not blocking the domain' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#muting?' do
- subject { account.muting?(target_account) }
-
- context 'muting target_account' do
- it 'returns true' do
- mute = Fabricate(:mute, account: account, target_account: target_account)
- account.mute_relationships << mute
- is_expected.to be true
- end
- end
-
- context 'not muting target_account' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#muting_conversation?' do
- let(:conversation) { Fabricate(:conversation) }
-
- subject { account.muting_conversation?(conversation) }
-
- context 'muting the conversation' do
- it 'returns true' do
- account.conversation_mutes.create(conversation: conversation)
- is_expected.to be true
- end
- end
-
- context 'not muting the conversation' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#muting_notifications?' do
- before do
- mute = Fabricate(:mute, target_account: target_account, account: account, hide_notifications: hide)
- account.mute_relationships << mute
- end
-
- subject { account.muting_notifications?(target_account) }
-
- context 'muting notifications of target_account' do
- let(:hide) { true }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'not muting notifications of target_account' do
- let(:hide) { false }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#requested?' do
- subject { account.requested?(target_account) }
-
- context 'requested by target_account' do
- it 'returns true' do
- Fabricate(:follow_request, account: account, target_account: target_account)
- is_expected.to be true
- end
- end
-
- context 'not requested by target_account' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#favourited?' do
- let(:status) { Fabricate(:status, account: account, favourites: favourites) }
-
- subject { account.favourited?(status) }
-
- context 'favorited' do
- let(:favourites) { [Fabricate(:favourite, account: account)] }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'not favorited' do
- let(:favourites) { [] }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#reblogged?' do
- let(:status) { Fabricate(:status, account: account, reblogs: reblogs) }
-
- subject { account.reblogged?(status) }
-
- context 'reblogged' do
- let(:reblogs) { [Fabricate(:status, account: account)] }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'not reblogged' do
- let(:reblogs) { [] }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#pinned?' do
- let(:status) { Fabricate(:status, account: account) }
-
- subject { account.pinned?(status) }
-
- context 'pinned' do
- it 'returns true' do
- Fabricate(:status_pin, account: account, status: status)
- is_expected.to be true
- end
- end
-
- context 'not pinned' do
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe 'muting an account' do
- let(:me) { Fabricate(:account, username: 'Me') }
- let(:you) { Fabricate(:account, username: 'You') }
-
- context 'with the notifications option unspecified' do
- before do
- me.mute!(you)
- end
-
- it 'defaults to muting notifications' do
- expect(me.muting_notifications?(you)).to be true
- end
- end
-
- context 'with the notifications option set to false' do
- before do
- me.mute!(you, notifications: false)
- end
-
- it 'does not mute notifications' do
- expect(me.muting_notifications?(you)).to be false
- end
- end
-
- context 'with the notifications option set to true' do
- before do
- me.mute!(you, notifications: true)
- end
-
- it 'does mute notifications' do
- expect(me.muting_notifications?(you)).to be true
- end
- end
- end
-
- describe 'ignoring reblogs from an account' do
- before do
- @me = Fabricate(:account, username: 'Me')
- @you = Fabricate(:account, username: 'You')
- end
-
- context 'with the reblogs option unspecified' do
- before do
- @me.follow!(@you)
- end
-
- it 'defaults to showing reblogs' do
- expect(@me.muting_reblogs?(@you)).to be(false)
- end
- end
-
- context 'with the reblogs option set to false' do
- before do
- @me.follow!(@you, reblogs: false)
- end
-
- it 'does mute reblogs' do
- expect(@me.muting_reblogs?(@you)).to be(true)
- end
- end
-
- context 'with the reblogs option set to true' do
- before do
- @me.follow!(@you, reblogs: true)
- end
-
- it 'does not mute reblogs' do
- expect(@me.muting_reblogs?(@you)).to be(false)
- end
- end
- end
-end
diff --git a/spec/models/concerns/remotable_spec.rb b/spec/models/concerns/remotable_spec.rb
deleted file mode 100644
index a4289cc4..00000000
--- a/spec/models/concerns/remotable_spec.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Remotable do
- class Foo
- def initialize
- @attrs = {}
- end
-
- def [](arg)
- @attrs[arg]
- end
-
- def []=(arg1, arg2)
- @attrs[arg1] = arg2
- end
-
- def hoge=(arg); end
-
- def hoge_file_name=(arg); end
-
- def has_attribute?(arg); end
-
- def self.attachment_definitions
- { hoge: nil }
- end
- end
-
- context 'Remotable module is included' do
- before do
- class Foo
- include Remotable
- remotable_attachment :hoge, 1.kilobyte
- end
- end
-
- let(:attribute_name) { "#{hoge}_remote_url".to_sym }
- let(:code) { 200 }
- let(:file) { 'filename="foo.txt"' }
- let(:foo) { Foo.new }
- let(:headers) { { 'content-disposition' => file } }
- let(:hoge) { :hoge }
- let(:url) { 'https://google.com' }
-
- let(:request) do
- stub_request(:get, url)
- .to_return(status: code, headers: headers)
- end
-
- it 'defines a method #hoge_remote_url=' do
- expect(foo).to respond_to(:hoge_remote_url=)
- end
-
- it 'defines a method #reset_hoge!' do
- expect(foo).to respond_to(:reset_hoge!)
- end
-
- describe '#hoge_remote_url' do
- before do
- request
- end
-
- it 'always returns arg' do
- [nil, '', [], {}].each do |arg|
- expect(foo.hoge_remote_url = arg).to be arg
- end
- end
-
- context 'Addressable::URI::InvalidURIError raised' do
- it 'makes no request' do
- allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
- .with(url).with(no_args).and_raise(Addressable::URI::InvalidURIError)
-
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
-
- context 'scheme is neither http nor https' do
- let(:url) { 'ftp://google.com' }
-
- it 'makes no request' do
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
-
- context 'parsed_url.host is empty' do
- it 'makes no request' do
- parsed_url = double(scheme: 'https', host: double(blank?: true))
- allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
- .with(url).with(no_args).and_return(parsed_url)
-
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
-
- context 'parsed_url.host is nil' do
- it 'makes no request' do
- parsed_url = Addressable::URI.parse('https:https://example.com/path/file.png')
- allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
- .with(url).with(no_args).and_return(parsed_url)
-
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
-
- context 'foo[attribute_name] == url' do
- it 'makes no request' do
- allow(foo).to receive(:[]).with(attribute_name).and_return(url)
-
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
-
- context "scheme is https, parsed_url.host isn't empty, and foo[attribute_name] != url" do
- it 'makes a request' do
- foo.hoge_remote_url = url
- expect(request).to have_been_requested
- end
-
- context 'response.code != 200' do
- let(:code) { 500 }
-
- it 'calls not send' do
- expect(foo).not_to receive(:send).with("#{hoge}=", any_args)
- expect(foo).not_to receive(:send).with("#{hoge}_file_name=", any_args)
- foo.hoge_remote_url = url
- end
- end
-
- context 'response.code == 200' do
- let(:code) { 200 }
-
- context 'response contains headers["content-disposition"]' do
- let(:file) { 'filename="foo.txt"' }
- let(:headers) { { 'content-disposition' => file } }
-
- it 'calls send' do
- string_io = StringIO.new('')
- extname = '.txt'
- basename = '0123456789abcdef'
-
- allow(SecureRandom).to receive(:hex).and_return(basename)
- allow(StringIO).to receive(:new).with(anything).and_return(string_io)
-
- expect(foo).to receive(:send).with("#{hoge}=", string_io)
- expect(foo).to receive(:send).with("#{hoge}_file_name=", basename + extname)
- foo.hoge_remote_url = url
- end
- end
-
- context 'if has_attribute?' do
- it 'calls foo[attribute_name] = url' do
- allow(foo).to receive(:has_attribute?).with(attribute_name).and_return(true)
- expect(foo).to receive('[]=').with(attribute_name, url)
- foo.hoge_remote_url = url
- end
- end
-
- context 'unless has_attribute?' do
- it 'calls not foo[attribute_name] = url' do
- allow(foo).to receive(:has_attribute?)
- .with(attribute_name).and_return(false)
- expect(foo).not_to receive('[]=').with(attribute_name, url)
- foo.hoge_remote_url = url
- end
- end
- end
-
- context 'an error raised during the request' do
- let(:request) { stub_request(:get, url).to_raise(error_class) }
-
- error_classes = [
- HTTP::TimeoutError,
- HTTP::ConnectionError,
- OpenSSL::SSL::SSLError,
- Paperclip::Errors::NotIdentifiedByImageMagickError,
- Addressable::URI::InvalidURIError,
- ]
-
- error_classes.each do |error_class|
- let(:error_class) { error_class }
-
- it 'calls Rails.logger.debug' do
- expect(Rails.logger).to receive(:debug).with(/^Error fetching remote #{hoge}: /)
- foo.hoge_remote_url = url
- end
- end
- end
- end
- end
-
- describe '#reset_hoge!' do
- context 'if url.blank?' do
- it 'returns nil, without clearing foo[attribute_name] and calling #hoge_remote_url=' do
- url = nil
- expect(foo).not_to receive(:send).with(:hoge_remote_url=, url)
- foo[attribute_name] = url
- expect(foo.reset_hoge!).to be_nil
- expect(foo[attribute_name]).to be_nil
- end
- end
-
- context 'unless url.blank?' do
- it 'clears foo[attribute_name] and calls #hoge_remote_url=' do
- foo[attribute_name] = url
- expect(foo).to receive(:send).with(:hoge_remote_url=, url)
- foo.reset_hoge!
- expect(foo[attribute_name]).to be ''
- end
- end
- end
- end
-end
diff --git a/spec/models/concerns/status_threading_concern_spec.rb b/spec/models/concerns/status_threading_concern_spec.rb
deleted file mode 100644
index 50286ef7..00000000
--- a/spec/models/concerns/status_threading_concern_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe StatusThreadingConcern do
- describe '#ancestors' do
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
- let!(:jeff) { Fabricate(:account, username: 'jeff') }
- let!(:status) { Fabricate(:status, account: alice) }
- let!(:reply1) { Fabricate(:status, thread: status, account: jeff) }
- let!(:reply2) { Fabricate(:status, thread: reply1, account: bob) }
- let!(:reply3) { Fabricate(:status, thread: reply2, account: alice) }
- let!(:viewer) { Fabricate(:account, username: 'viewer') }
-
- it 'returns conversation history' do
- expect(reply3.ancestors(4)).to include(status, reply1, reply2)
- end
-
- it 'does not return conversation history user is not allowed to see' do
- reply1.update(visibility: :private)
- status.update(visibility: :direct)
-
- expect(reply3.ancestors(4, viewer)).to_not include(reply1, status)
- end
-
- it 'does not return conversation history from blocked users' do
- viewer.block!(jeff)
- expect(reply3.ancestors(4, viewer)).to_not include(reply1)
- end
-
- it 'does not return conversation history from muted users' do
- viewer.mute!(jeff)
- expect(reply3.ancestors(4, viewer)).to_not include(reply1)
- end
-
- it 'does not return conversation history from silenced and not followed users' do
- jeff.silence!
- expect(reply3.ancestors(4, viewer)).to_not include(reply1)
- end
-
- it 'does not return conversation history from blocked domains' do
- viewer.block_domain!('example.com')
- expect(reply3.ancestors(4, viewer)).to_not include(reply2)
- end
-
- it 'ignores deleted records' do
- first_status = Fabricate(:status, account: bob)
- second_status = Fabricate(:status, thread: first_status, account: alice)
-
- # Create cache and delete cached record
- second_status.ancestors(4)
- first_status.destroy
-
- expect(second_status.ancestors(4)).to eq([])
- end
-
- it 'can return more records than previously requested' do
- first_status = Fabricate(:status, account: bob)
- second_status = Fabricate(:status, thread: first_status, account: alice)
- third_status = Fabricate(:status, thread: second_status, account: alice)
-
- # Create cache
- second_status.ancestors(1)
-
- expect(third_status.ancestors(2)).to eq([first_status, second_status])
- end
-
- it 'can return fewer records than previously requested' do
- first_status = Fabricate(:status, account: bob)
- second_status = Fabricate(:status, thread: first_status, account: alice)
- third_status = Fabricate(:status, thread: second_status, account: alice)
-
- # Create cache
- second_status.ancestors(2)
-
- expect(third_status.ancestors(1)).to eq([second_status])
- end
- end
-
- describe '#descendants' do
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
- let!(:jeff) { Fabricate(:account, username: 'jeff') }
- let!(:status) { Fabricate(:status, account: alice) }
- let!(:reply1) { Fabricate(:status, thread: status, account: alice) }
- let!(:reply2) { Fabricate(:status, thread: status, account: bob) }
- let!(:reply3) { Fabricate(:status, thread: reply1, account: jeff) }
- let!(:viewer) { Fabricate(:account, username: 'viewer') }
-
- it 'returns replies' do
- expect(status.descendants(4)).to include(reply1, reply2, reply3)
- end
-
- it 'does not return replies user is not allowed to see' do
- reply1.update(visibility: :private)
- reply3.update(visibility: :direct)
-
- expect(status.descendants(4, viewer)).to_not include(reply1, reply3)
- end
-
- it 'does not return replies from blocked users' do
- viewer.block!(jeff)
- expect(status.descendants(4, viewer)).to_not include(reply3)
- end
-
- it 'does not return replies from muted users' do
- viewer.mute!(jeff)
- expect(status.descendants(4, viewer)).to_not include(reply3)
- end
-
- it 'does not return replies from silenced and not followed users' do
- jeff.silence!
- expect(status.descendants(4, viewer)).to_not include(reply3)
- end
-
- it 'does not return replies from blocked domains' do
- viewer.block_domain!('example.com')
- expect(status.descendants(4, viewer)).to_not include(reply2)
- end
-
- it 'promotes self-replies to the top while leaving the rest in order' do
- a = Fabricate(:status, account: alice)
- d = Fabricate(:status, account: jeff, thread: a)
- e = Fabricate(:status, account: bob, thread: d)
- c = Fabricate(:status, account: alice, thread: a)
- f = Fabricate(:status, account: bob, thread: c)
-
- expect(a.descendants(20)).to eq [c, d, e, f]
- end
- end
-end
diff --git a/spec/models/concerns/streamable_spec.rb b/spec/models/concerns/streamable_spec.rb
deleted file mode 100644
index b5f2d519..00000000
--- a/spec/models/concerns/streamable_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Streamable do
- class Parent
- def title; end
-
- def target; end
-
- def thread; end
-
- def self.has_one(*); end
-
- def self.after_create; end
- end
-
- class Child < Parent
- include Streamable
- end
-
- child = Child.new
-
- describe '#title' do
- it 'calls Parent#title' do
- expect_any_instance_of(Parent).to receive(:title)
- child.title
- end
- end
-
- describe '#content' do
- it 'calls #title' do
- expect_any_instance_of(Parent).to receive(:title)
- child.content
- end
- end
-
- describe '#target' do
- it 'calls Parent#target' do
- expect_any_instance_of(Parent).to receive(:target)
- child.target
- end
- end
-
- describe '#object_type' do
- it 'returns :activity' do
- expect(child.object_type).to eq :activity
- end
- end
-
- describe '#thread' do
- it 'calls Parent#thread' do
- expect_any_instance_of(Parent).to receive(:thread)
- child.thread
- end
- end
-
- describe '#hidden?' do
- it 'returns false' do
- expect(child.hidden?).to be false
- end
- end
-end
diff --git a/spec/models/conversation_mute_spec.rb b/spec/models/conversation_mute_spec.rb
deleted file mode 100644
index 3fc2915d..00000000
--- a/spec/models/conversation_mute_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ConversationMute, type: :model do
-end
diff --git a/spec/models/conversation_spec.rb b/spec/models/conversation_spec.rb
deleted file mode 100644
index 8b5e4fda..00000000
--- a/spec/models/conversation_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Conversation, type: :model do
- describe '#local?' do
- it 'returns true when URI is nil' do
- expect(Fabricate(:conversation).local?).to be true
- end
-
- it 'returns false when URI is not nil' do
- expect(Fabricate(:conversation, uri: 'abc').local?).to be false
- end
- end
-end
diff --git a/spec/models/custom_emoji_filter_spec.rb b/spec/models/custom_emoji_filter_spec.rb
deleted file mode 100644
index d859f5c5..00000000
--- a/spec/models/custom_emoji_filter_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe CustomEmojiFilter do
- describe '#results' do
- let!(:custom_emoji_0) { Fabricate(:custom_emoji, domain: 'a') }
- let!(:custom_emoji_1) { Fabricate(:custom_emoji, domain: 'b') }
- let!(:custom_emoji_2) { Fabricate(:custom_emoji, domain: nil, shortcode: 'hoge') }
-
- subject { described_class.new(params).results }
-
- context 'params have values' do
- context 'local' do
- let(:params) { { local: true } }
-
- it 'returns ActiveRecord::Relation' do
- expect(subject).to be_kind_of(ActiveRecord::Relation)
- expect(subject).to match_array([custom_emoji_2])
- end
- end
-
- context 'remote' do
- let(:params) { { remote: true } }
-
- it 'returns ActiveRecord::Relation' do
- expect(subject).to be_kind_of(ActiveRecord::Relation)
- expect(subject).to match_array([custom_emoji_0, custom_emoji_1])
- end
- end
-
- context 'by_domain' do
- let(:params) { { by_domain: 'a' } }
-
- it 'returns ActiveRecord::Relation' do
- expect(subject).to be_kind_of(ActiveRecord::Relation)
- expect(subject).to match_array([custom_emoji_0])
- end
- end
-
- context 'shortcode' do
- let(:params) { { shortcode: 'hoge' } }
-
- it 'returns ActiveRecord::Relation' do
- expect(subject).to be_kind_of(ActiveRecord::Relation)
- expect(subject).to match_array([custom_emoji_2])
- end
- end
-
- context 'else' do
- let(:params) { { else: 'else' } }
-
- it 'raises RuntimeError' do
- expect do
- subject
- end.to raise_error(RuntimeError, /Unknown filter: else/)
- end
- end
- end
-
- context 'params without value' do
- let(:params) { { hoge: nil } }
-
- it 'returns ActiveRecord::Relation' do
- expect(subject).to be_kind_of(ActiveRecord::Relation)
- expect(subject).to match_array([custom_emoji_0, custom_emoji_1, custom_emoji_2])
- end
- end
- end
-end
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
deleted file mode 100644
index 488fa027..00000000
--- a/spec/models/custom_emoji_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe CustomEmoji, type: :model do
- describe '#search' do
- let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: shortcode) }
-
- subject { described_class.search(search_term) }
-
- context 'shortcode is exact' do
- let(:shortcode) { 'blobpats' }
- let(:search_term) { 'blobpats' }
-
- it 'finds emoji' do
- is_expected.to include(custom_emoji)
- end
- end
-
- context 'shortcode is partial' do
- let(:shortcode) { 'blobpats' }
- let(:search_term) { 'blob' }
-
- it 'finds emoji' do
- is_expected.to include(custom_emoji)
- end
- end
- end
-
- describe '#local?' do
- let(:custom_emoji) { Fabricate(:custom_emoji, domain: domain) }
-
- subject { custom_emoji.local? }
-
- context 'domain is nil' do
- let(:domain) { nil }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'domain is present' do
- let(:domain) { 'example.com' }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe '#object_type' do
- it 'returns :emoji' do
- custom_emoji = Fabricate(:custom_emoji)
- expect(custom_emoji.object_type).to be :emoji
- end
- end
-
- describe '.from_text' do
- let!(:emojo) { Fabricate(:custom_emoji) }
-
- subject { described_class.from_text(text, nil) }
-
- context 'with plain text' do
- let(:text) { 'Hello :coolcat:' }
-
- it 'returns records used via shortcodes in text' do
- is_expected.to include(emojo)
- end
- end
-
- context 'with html' do
- let(:text) { 'Hello :coolcat:
' }
-
- it 'returns records used via shortcodes in text' do
- is_expected.to include(emojo)
- end
- end
- end
-
- describe 'pre_validation' do
- let(:custom_emoji) { Fabricate(:custom_emoji, domain: 'wWw.GaB.cOm') }
-
- it 'should downcase' do
- custom_emoji.valid?
- expect(custom_emoji.domain).to eq('www.gab.com')
- end
- end
-end
diff --git a/spec/models/custom_filter_spec.rb b/spec/models/custom_filter_spec.rb
deleted file mode 100644
index 3943dd5f..00000000
--- a/spec/models/custom_filter_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe CustomFilter, type: :model do
-end
diff --git a/spec/models/domain_block_spec.rb b/spec/models/domain_block_spec.rb
deleted file mode 100644
index 0035fd0f..00000000
--- a/spec/models/domain_block_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe DomainBlock, type: :model do
- describe 'validations' do
- it 'has a valid fabricator' do
- domain_block = Fabricate.build(:domain_block)
- expect(domain_block).to be_valid
- end
-
- it 'is invalid without a domain' do
- domain_block = Fabricate.build(:domain_block, domain: nil)
- domain_block.valid?
- expect(domain_block).to model_have_error_on_field(:domain)
- end
-
- it 'is invalid if the same normalized domain already exists' do
- domain_block_1 = Fabricate(:domain_block, domain: 'ã«ã‚ƒã‚“')
- domain_block_2 = Fabricate.build(:domain_block, domain: 'xn--r9j5b5b')
- domain_block_2.valid?
- expect(domain_block_2).to model_have_error_on_field(:domain)
- end
- end
-
- describe 'blocked?' do
- it 'returns true if the domain is suspended' do
- Fabricate(:domain_block, domain: 'domain', severity: :suspend)
- expect(DomainBlock.blocked?('domain')).to eq true
- end
-
- it 'returns false even if the domain is silenced' do
- Fabricate(:domain_block, domain: 'domain', severity: :silence)
- expect(DomainBlock.blocked?('domain')).to eq false
- end
-
- it 'returns false if the domain is not suspended nor silenced' do
- expect(DomainBlock.blocked?('domain')).to eq false
- end
- end
-
- describe 'stricter_than?' do
- it 'returns true if the new block has suspend severity while the old has lower severity' do
- suspend = DomainBlock.new(domain: 'domain', severity: :suspend)
- silence = DomainBlock.new(domain: 'domain', severity: :silence)
- noop = DomainBlock.new(domain: 'domain', severity: :noop)
- expect(suspend.stricter_than?(silence)).to be true
- expect(suspend.stricter_than?(noop)).to be true
- end
-
- it 'returns false if the new block has lower severity than the old one' do
- suspend = DomainBlock.new(domain: 'domain', severity: :suspend)
- silence = DomainBlock.new(domain: 'domain', severity: :silence)
- noop = DomainBlock.new(domain: 'domain', severity: :noop)
- expect(silence.stricter_than?(suspend)).to be false
- expect(noop.stricter_than?(suspend)).to be false
- expect(noop.stricter_than?(silence)).to be false
- end
-
- it 'returns false if the new block does is less strict regarding reports' do
- older = DomainBlock.new(domain: 'domain', severity: :silence, reject_reports: true)
- newer = DomainBlock.new(domain: 'domain', severity: :silence, reject_reports: false)
- expect(newer.stricter_than?(older)).to be false
- end
-
- it 'returns false if the new block does is less strict regarding media' do
- older = DomainBlock.new(domain: 'domain', severity: :silence, reject_media: true)
- newer = DomainBlock.new(domain: 'domain', severity: :silence, reject_media: false)
- expect(newer.stricter_than?(older)).to be false
- end
- end
-end
diff --git a/spec/models/email_domain_block_spec.rb b/spec/models/email_domain_block_spec.rb
deleted file mode 100644
index efd2853a..00000000
--- a/spec/models/email_domain_block_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe EmailDomainBlock, type: :model do
- describe 'validations' do
- it 'has a valid fabricator' do
- email_domain_block = Fabricate.build(:email_domain_block)
- expect(email_domain_block).to be_valid
- end
- end
-
- describe 'block?' do
- it 'returns true if the domain is registed' do
- Fabricate(:email_domain_block, domain: 'example.com')
- expect(EmailDomainBlock.block?('nyarn@example.com')).to eq true
- end
-
- it 'returns true if the domain is not registed' do
- Fabricate(:email_domain_block, domain: 'example.com')
- expect(EmailDomainBlock.block?('nyarn@example.net')).to eq false
- end
- end
-end
diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb
deleted file mode 100644
index e31deef4..00000000
--- a/spec/models/export_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-require 'rails_helper'
-
-describe Export do
- let(:account) { Fabricate(:account) }
- let(:target_accounts) do
- [ {}, { username: 'one', domain: 'local.host' } ].map(&method(:Fabricate).curry(2).call(:account))
- end
-
- describe 'to_csv' do
- it 'returns a csv of the blocked accounts' do
- target_accounts.each(&account.method(:block!))
-
- export = Export.new(account).to_blocked_accounts_csv
- results = export.strip.split
-
- expect(results.size).to eq 2
- expect(results.first).to eq 'one@local.host'
- end
-
- it 'returns a csv of the muted accounts' do
- target_accounts.each(&account.method(:mute!))
-
- export = Export.new(account).to_muted_accounts_csv
- results = export.strip.split("\n")
-
- expect(results.size).to eq 3
- expect(results.first).to eq 'Account address,Hide notifications'
- expect(results.second).to eq 'one@local.host,true'
- end
-
- it 'returns a csv of the following accounts' do
- target_accounts.each(&account.method(:follow!))
-
- export = Export.new(account).to_following_accounts_csv
- results = export.strip.split("\n")
-
- expect(results.size).to eq 3
- expect(results.first).to eq 'Account address,Show reposts'
- expect(results.second).to eq 'one@local.host,true'
- end
- end
-
- describe 'total_storage' do
- it 'returns the total size of the media attachments' do
- media_attachment = Fabricate(:media_attachment, account: account)
- expect(Export.new(account).total_storage).to eq media_attachment.file_file_size || 0
- end
- end
-
- describe 'total_follows' do
- it 'returns the total number of the followed accounts' do
- target_accounts.each(&account.method(:follow!))
- expect(Export.new(account.reload).total_follows).to eq 2
- end
-
- it 'returns the total number of the blocked accounts' do
- target_accounts.each(&account.method(:block!))
- expect(Export.new(account.reload).total_blocks).to eq 2
- end
-
- it 'returns the total number of the muted accounts' do
- target_accounts.each(&account.method(:mute!))
- expect(Export.new(account.reload).total_mutes).to eq 2
- end
- end
-end
diff --git a/spec/models/favourite_spec.rb b/spec/models/favourite_spec.rb
deleted file mode 100644
index ba1410a4..00000000
--- a/spec/models/favourite_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Favourite, type: :model do
- let(:account) { Fabricate(:account) }
-
- context 'when status is a reblog' do
- let(:reblog) { Fabricate(:status, reblog: nil) }
- let(:status) { Fabricate(:status, reblog: reblog) }
-
- it 'invalidates if the reblogged status is already a favourite' do
- Favourite.create!(account: account, status: reblog)
- expect(Favourite.new(account: account, status: status).valid?).to eq false
- end
-
- it 'replaces status with the reblogged one if it is a reblog' do
- favourite = Favourite.create!(account: account, status: status)
- expect(favourite.status).to eq reblog
- end
- end
-
- context 'when status is not a reblog' do
- let(:status) { Fabricate(:status, reblog: nil) }
-
- it 'saves with the specified status' do
- favourite = Favourite.create!(account: account, status: status)
- expect(favourite.status).to eq status
- end
- end
-end
diff --git a/spec/models/featured_tag_spec.rb b/spec/models/featured_tag_spec.rb
deleted file mode 100644
index 07533e0b..00000000
--- a/spec/models/featured_tag_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FeaturedTag, type: :model do
-end
diff --git a/spec/models/follow_request_spec.rb b/spec/models/follow_request_spec.rb
deleted file mode 100644
index 2cf28b26..00000000
--- a/spec/models/follow_request_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FollowRequest, type: :model do
- describe '#authorize!' do
- let(:follow_request) { Fabricate(:follow_request, account: account, target_account: target_account) }
- let(:account) { Fabricate(:account) }
- let(:target_account) { Fabricate(:account) }
-
- it 'calls Account#follow!, MergeWorker.perform_async, and #destroy!' do
- expect(account).to receive(:follow!).with(target_account, reblogs: true, uri: follow_request.uri)
- expect(MergeWorker).to receive(:perform_async).with(target_account.id, account.id)
- expect(follow_request).to receive(:destroy!)
- follow_request.authorize!
- end
-
- it 'correctly passes show_reblogs when true' do
- follow_request = Fabricate.create(:follow_request, show_reblogs: true)
- follow_request.authorize!
- target = follow_request.target_account
- expect(follow_request.account.muting_reblogs?(target)).to be false
- end
-
- it 'correctly passes show_reblogs when false' do
- follow_request = Fabricate.create(:follow_request, show_reblogs: false)
- follow_request.authorize!
- target = follow_request.target_account
- expect(follow_request.account.muting_reblogs?(target)).to be true
- end
- end
-end
diff --git a/spec/models/follow_spec.rb b/spec/models/follow_spec.rb
deleted file mode 100644
index 0c84e5e7..00000000
--- a/spec/models/follow_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Follow, type: :model do
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:bob) { Fabricate(:account, username: 'bob') }
-
- describe 'validations' do
- subject { Follow.new(account: alice, target_account: bob) }
-
- it 'has a valid fabricator' do
- follow = Fabricate.build(:follow)
- expect(follow).to be_valid
- end
-
- it 'is invalid without an account' do
- follow = Fabricate.build(:follow, account: nil)
- follow.valid?
- expect(follow).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a target_account' do
- follow = Fabricate.build(:follow, target_account: nil)
- follow.valid?
- expect(follow).to model_have_error_on_field(:target_account)
- end
-
- it 'is invalid if account already follows too many people' do
- alice.update(following_count: FollowLimitValidator::LIMIT)
-
- expect(subject).to_not be_valid
- expect(subject).to model_have_error_on_field(:base)
- end
-
- it 'is valid if account is only on the brink of following too many people' do
- alice.update(following_count: FollowLimitValidator::LIMIT - 1)
-
- expect(subject).to be_valid
- expect(subject).to_not model_have_error_on_field(:base)
- end
- end
-
- describe 'recent' do
- it 'sorts so that more recent follows comes earlier' do
- follow0 = Follow.create!(account: alice, target_account: bob)
- follow1 = Follow.create!(account: bob, target_account: alice)
-
- a = Follow.recent.to_a
-
- expect(a.size).to eq 2
- expect(a[0]).to eq follow1
- expect(a[1]).to eq follow0
- end
- end
-
- describe 'revoke_request!' do
- let(:follow) { Fabricate(:follow, account: account, target_account: target_account) }
- let(:account) { Fabricate(:account) }
- let(:target_account) { Fabricate(:account) }
-
- it 'revokes the follow relation' do
- follow.revoke_request!
- expect(account.following?(target_account)).to be false
- end
-
- it 'creates a follow request' do
- follow.revoke_request!
- expect(account.requested?(target_account)).to be true
- end
- end
-end
diff --git a/spec/models/form/status_batch_spec.rb b/spec/models/form/status_batch_spec.rb
deleted file mode 100644
index 00c790a1..00000000
--- a/spec/models/form/status_batch_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'rails_helper'
-
-describe Form::StatusBatch do
- let(:form) { Form::StatusBatch.new(action: action, status_ids: status_ids) }
- let(:status) { Fabricate(:status) }
-
- describe 'with nsfw action' do
- let(:status_ids) { [status.id, nonsensitive_status.id, sensitive_status.id] }
- let(:nonsensitive_status) { Fabricate(:status, sensitive: false) }
- let(:sensitive_status) { Fabricate(:status, sensitive: true) }
- let!(:shown_media_attachment) { Fabricate(:media_attachment, status: nonsensitive_status) }
- let!(:hidden_media_attachment) { Fabricate(:media_attachment, status: sensitive_status) }
-
- context 'nsfw_on' do
- let(:action) { 'nsfw_on' }
-
- it { expect(form.save).to be true }
- it { expect { form.save }.to change { nonsensitive_status.reload.sensitive }.from(false).to(true) }
- it { expect { form.save }.not_to change { sensitive_status.reload.sensitive } }
- it { expect { form.save }.not_to change { status.reload.sensitive } }
- end
-
- context 'nsfw_off' do
- let(:action) { 'nsfw_off' }
-
- it { expect(form.save).to be true }
- it { expect { form.save }.to change { sensitive_status.reload.sensitive }.from(true).to(false) }
- it { expect { form.save }.not_to change { nonsensitive_status.reload.sensitive } }
- it { expect { form.save }.not_to change { status.reload.sensitive } }
- end
- end
-
- describe 'with delete action' do
- let(:status_ids) { [status.id] }
- let(:action) { 'delete' }
- let!(:another_status) { Fabricate(:status) }
-
- before do
- allow(RemovalWorker).to receive(:perform_async)
- end
-
- it 'call RemovalWorker' do
- form.save
- expect(RemovalWorker).to have_received(:perform_async).with(status.id)
- end
-
- it 'do not call RemovalWorker' do
- form.save
- expect(RemovalWorker).not_to have_received(:perform_async).with(another_status.id)
- end
- end
-end
diff --git a/spec/models/group_removed_account_spec.rb b/spec/models/group_removed_account_spec.rb
deleted file mode 100644
index 098f7c18..00000000
--- a/spec/models/group_removed_account_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe GroupRemovedAccount, type: :model do
- pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/models/home_feed_spec.rb b/spec/models/home_feed_spec.rb
deleted file mode 100644
index 3acb997f..00000000
--- a/spec/models/home_feed_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe HomeFeed, type: :model do
- let(:account) { Fabricate(:account) }
-
- subject { described_class.new(account) }
-
- describe '#get' do
- before do
- Fabricate(:status, account: account, id: 1)
- Fabricate(:status, account: account, id: 2)
- Fabricate(:status, account: account, id: 3)
- Fabricate(:status, account: account, id: 10)
- end
-
- context 'when feed is generated' do
- before do
- Redis.current.zadd(
- FeedManager.instance.key(:home, account.id),
- [[4, 4], [3, 3], [2, 2], [1, 1]]
- )
- end
-
- it 'gets statuses with ids in the range from redis' do
- results = subject.get(3)
-
- expect(results.map(&:id)).to eq [3, 2]
- expect(results.first.attributes.keys).to eq %w(id updated_at)
- end
- end
-
- context 'when feed is being generated' do
- before do
- Redis.current.set("account:#{account.id}:regeneration", true)
- end
-
- it 'gets statuses with ids in the range from database' do
- results = subject.get(3)
-
- expect(results.map(&:id)).to eq [10, 3, 2]
- expect(results.first.attributes.keys).to include('id', 'updated_at')
- end
- end
- end
-end
diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb
deleted file mode 100644
index 689c9b79..00000000
--- a/spec/models/identity_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Identity, type: :model do
- describe '.find_for_oauth' do
- let(:auth) { Fabricate(:identity, user: Fabricate(:user)) }
-
- it 'calls .find_or_create_by' do
- expect(described_class).to receive(:find_or_create_by).with(uid: auth.uid, provider: auth.provider)
- described_class.find_for_oauth(auth)
- end
-
- it 'returns an instance of Identity' do
- expect(described_class.find_for_oauth(auth)).to be_instance_of Identity
- end
- end
-end
diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb
deleted file mode 100644
index 32176116..00000000
--- a/spec/models/import_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Import, type: :model do
- let (:account) { Fabricate(:account) }
- let (:type) { 'following' }
- let (:data) { attachment_fixture('imports.txt') }
-
- describe 'validations' do
- it 'has a valid parameters' do
- import = Import.create(account: account, type: type, data: data)
- expect(import).to be_valid
- end
-
- it 'is invalid without an type' do
- import = Import.create(account: account, data: data)
- expect(import).to model_have_error_on_field(:type)
- end
-
- it 'is invalid without a data' do
- import = Import.create(account: account, type: type)
- expect(import).to model_have_error_on_field(:data)
- end
- end
-end
diff --git a/spec/models/invite_spec.rb b/spec/models/invite_spec.rb
deleted file mode 100644
index 0ba1dccb..00000000
--- a/spec/models/invite_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Invite, type: :model do
- describe '#valid_for_use?' do
- it 'returns true when there are no limitations' do
- invite = Invite.new(max_uses: nil, expires_at: nil)
- expect(invite.valid_for_use?).to be true
- end
-
- it 'returns true when not expired' do
- invite = Invite.new(max_uses: nil, expires_at: 1.hour.from_now)
- expect(invite.valid_for_use?).to be true
- end
-
- it 'returns false when expired' do
- invite = Invite.new(max_uses: nil, expires_at: 1.hour.ago)
- expect(invite.valid_for_use?).to be false
- end
-
- it 'returns true when uses still available' do
- invite = Invite.new(max_uses: 250, uses: 249, expires_at: nil)
- expect(invite.valid_for_use?).to be true
- end
-
- it 'returns false when maximum uses reached' do
- invite = Invite.new(max_uses: 250, uses: 250, expires_at: nil)
- expect(invite.valid_for_use?).to be false
- end
- end
-end
diff --git a/spec/models/list_account_spec.rb b/spec/models/list_account_spec.rb
deleted file mode 100644
index a0cf02ef..00000000
--- a/spec/models/list_account_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ListAccount, type: :model do
-end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
deleted file mode 100644
index b780bb1d..00000000
--- a/spec/models/list_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe List, type: :model do
-end
diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb
deleted file mode 100644
index 266cd492..00000000
--- a/spec/models/media_attachment_spec.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe MediaAttachment, type: :model do
- describe 'local?' do
- let(:media_attachment) { Fabricate(:media_attachment, remote_url: remote_url) }
-
- subject { media_attachment.local? }
-
- context 'remote_url is blank' do
- let(:remote_url) { '' }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'remote_url is present' do
- let(:remote_url) { 'remote_url' }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-
- describe 'needs_redownload?' do
- let(:media_attachment) { Fabricate(:media_attachment, remote_url: remote_url, file: file) }
-
- subject { media_attachment.needs_redownload? }
-
- context 'file is blank' do
- let(:file) { nil }
-
- context 'remote_url is blank' do
- let(:remote_url) { '' }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
-
- context 'remote_url is present' do
- let(:remote_url) { 'remote_url' }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
- end
-
- context 'file is present' do
- let(:file) { attachment_fixture('avatar.gif') }
-
- context 'remote_url is blank' do
- let(:remote_url) { '' }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
-
- context 'remote_url is present' do
- let(:remote_url) { 'remote_url' }
-
- it 'returns true' do
- is_expected.to be false
- end
- end
- end
- end
-
- describe '#to_param' do
- let(:media_attachment) { Fabricate(:media_attachment) }
- let(:shortcode) { media_attachment.shortcode }
-
- it 'returns shortcode' do
- expect(media_attachment.to_param).to eq shortcode
- end
- end
-
- describe 'animated gif conversion' do
- let(:media) { MediaAttachment.create(account: Fabricate(:account), file: attachment_fixture('avatar.gif')) }
-
- it 'sets type to gifv' do
- expect(media.type).to eq 'gifv'
- end
-
- it 'converts original file to mp4' do
- expect(media.file_content_type).to eq 'video/mp4'
- end
-
- it 'sets meta' do
- expect(media.file.meta["original"]["width"]).to eq 128
- expect(media.file.meta["original"]["height"]).to eq 128
- end
- end
-
- describe 'non-animated gif non-conversion' do
- fixtures = [
- { filename: 'attachment.gif', width: 600, height: 400, aspect: 1.5 },
- { filename: 'mini-static.gif', width: 32, height: 32, aspect: 1.0 },
- ]
-
- fixtures.each do |fixture|
- context fixture[:filename] do
- let(:media) { MediaAttachment.create(account: Fabricate(:account), file: attachment_fixture(fixture[:filename])) }
-
- it 'sets type to image' do
- expect(media.type).to eq 'image'
- end
-
- it 'leaves original file as-is' do
- expect(media.file_content_type).to eq 'image/gif'
- end
-
- it 'sets meta' do
- expect(media.file.meta["original"]["width"]).to eq fixture[:width]
- expect(media.file.meta["original"]["height"]).to eq fixture[:height]
- expect(media.file.meta["original"]["aspect"]).to eq fixture[:aspect]
- end
- end
- end
- end
-
- describe 'jpeg' do
- let(:media) { MediaAttachment.create(account: Fabricate(:account), file: attachment_fixture('attachment.jpg')) }
-
- it 'sets meta for different style' do
- expect(media.file.meta["original"]["width"]).to eq 600
- expect(media.file.meta["original"]["height"]).to eq 400
- expect(media.file.meta["original"]["aspect"]).to eq 1.5
- expect(media.file.meta["small"]["width"]).to eq 490
- expect(media.file.meta["small"]["height"]).to eq 327
- expect(media.file.meta["small"]["aspect"]).to eq 490.0 / 327
- end
- end
-
- describe 'descriptions for remote attachments' do
- it 'are cut off at 140 characters' do
- media = Fabricate(:media_attachment, description: 'foo' * 1000, remote_url: 'http://example.com/blah.jpg')
-
- expect(media.description.size).to be <= 420
- end
- end
-end
diff --git a/spec/models/mention_spec.rb b/spec/models/mention_spec.rb
deleted file mode 100644
index dbcf6a32..00000000
--- a/spec/models/mention_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Mention, type: :model do
- describe 'validations' do
- it 'has a valid fabricator' do
- mention = Fabricate.build(:mention)
- expect(mention).to be_valid
- end
-
- it 'is invalid without an account' do
- mention = Fabricate.build(:mention, account: nil)
- mention.valid?
- expect(mention).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a status' do
- mention = Fabricate.build(:mention, status: nil)
- mention.valid?
- expect(mention).to model_have_error_on_field(:status)
- end
- end
-end
diff --git a/spec/models/mute_spec.rb b/spec/models/mute_spec.rb
deleted file mode 100644
index 38a87bdf..00000000
--- a/spec/models/mute_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Mute, type: :model do
-end
diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb
deleted file mode 100644
index 59c582cd..00000000
--- a/spec/models/notification_spec.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Notification, type: :model do
- describe '#target_status' do
- let(:notification) { Fabricate(:notification, activity: activity) }
- let(:status) { Fabricate(:status) }
- let(:reblog) { Fabricate(:status, reblog: status) }
- let(:favourite) { Fabricate(:favourite, status: status) }
- let(:mention) { Fabricate(:mention, status: status) }
-
- context 'activity is reblog' do
- let(:activity) { reblog }
-
- it 'returns status' do
- expect(notification.target_status).to eq status
- end
- end
-
- context 'activity is favourite' do
- let(:type) { :favourite }
- let(:activity) { favourite }
-
- it 'returns status' do
- expect(notification.target_status).to eq status
- end
- end
-
- context 'activity is mention' do
- let(:activity) { mention }
-
- it 'returns status' do
- expect(notification.target_status).to eq status
- end
- end
- end
-
- describe '#browserable?' do
- let(:notification) { Fabricate(:notification) }
-
- subject { notification.browserable? }
-
- context 'type is :follow_request' do
- before do
- allow(notification).to receive(:type).and_return(:follow_request)
- end
-
- it 'returns false' do
- is_expected.to be false
- end
- end
-
- context 'type is not :follow_request' do
- before do
- allow(notification).to receive(:type).and_return(:else)
- end
-
- it 'returns true' do
- is_expected.to be true
- end
- end
- end
-
- describe '#type' do
- it 'returns :reblog for a Status' do
- notification = Notification.new(activity: Status.new)
- expect(notification.type).to eq :reblog
- end
-
- it 'returns :mention for a Mention' do
- notification = Notification.new(activity: Mention.new)
- expect(notification.type).to eq :mention
- end
-
- it 'returns :favourite for a Favourite' do
- notification = Notification.new(activity: Favourite.new)
- expect(notification.type).to eq :favourite
- end
-
- it 'returns :follow for a Follow' do
- notification = Notification.new(activity: Follow.new)
- expect(notification.type).to eq :follow
- end
- end
-
- describe '.reload_stale_associations!' do
- context 'account_ids are empty' do
- let(:cached_items) { [] }
-
- subject { described_class.reload_stale_associations!(cached_items) }
-
- it 'returns nil' do
- is_expected.to be nil
- end
- end
-
- context 'account_ids are present' do
- before do
- allow(accounts_with_ids).to receive(:[]).with(stale_account1.id).and_return(account1)
- allow(accounts_with_ids).to receive(:[]).with(stale_account2.id).and_return(account2)
- allow(Account).to receive_message_chain(:where, :includes, :each_with_object).and_return(accounts_with_ids)
- end
-
- let(:cached_items) do
- [
- Fabricate(:notification, activity: Fabricate(:status)),
- Fabricate(:notification, activity: Fabricate(:follow)),
- ]
- end
-
- let(:stale_account1) { cached_items[0].from_account }
- let(:stale_account2) { cached_items[1].from_account }
-
- let(:account1) { Fabricate(:account) }
- let(:account2) { Fabricate(:account) }
-
- let(:accounts_with_ids) { { account1.id => account1, account2.id => account2 } }
-
- it 'reloads associations' do
- expect(cached_items[0].from_account).to be stale_account1
- expect(cached_items[1].from_account).to be stale_account2
-
- described_class.reload_stale_associations!(cached_items)
-
- expect(cached_items[0].from_account).to be account1
- expect(cached_items[1].from_account).to be account2
- end
- end
- end
-end
diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb
deleted file mode 100644
index 666f8ca6..00000000
--- a/spec/models/poll_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Poll, type: :model do
- pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/models/poll_vote_spec.rb b/spec/models/poll_vote_spec.rb
deleted file mode 100644
index 354afd53..00000000
--- a/spec/models/poll_vote_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe PollVote, type: :model do
- pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/models/preview_card_spec.rb b/spec/models/preview_card_spec.rb
deleted file mode 100644
index 45233d1d..00000000
--- a/spec/models/preview_card_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe PreviewCard, type: :model do
-end
diff --git a/spec/models/relay_spec.rb b/spec/models/relay_spec.rb
deleted file mode 100644
index 12dc0f20..00000000
--- a/spec/models/relay_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Relay, type: :model do
-end
diff --git a/spec/models/remote_follow_spec.rb b/spec/models/remote_follow_spec.rb
deleted file mode 100644
index a5d0e0c5..00000000
--- a/spec/models/remote_follow_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe RemoteFollow do
- before do
- stub_request(:get, 'https://quitter.no/.well-known/webfinger?resource=acct:robcolbert@quitter.no').to_return(request_fixture('webfinger.txt'))
- end
-
- let(:attrs) { nil }
- let(:remote_follow) { described_class.new(attrs) }
-
- describe '.initialize' do
- subject { remote_follow.acct }
-
- context 'attrs with acct' do
- let(:attrs) { { acct: 'robcolbert@quitter.no' } }
-
- it 'returns acct' do
- is_expected.to eq 'robcolbert@quitter.no'
- end
- end
-
- context 'attrs without acct' do
- let(:attrs) { {} }
-
- it do
- is_expected.to be_nil
- end
- end
- end
-
- describe '#valid?' do
- subject { remote_follow.valid? }
-
- context 'attrs with acct' do
- let(:attrs) { { acct: 'robcolbert@quitter.no' } }
-
- it do
- is_expected.to be true
- end
- end
-
- context 'attrs without acct' do
- let(:attrs) { {} }
-
- it do
- is_expected.to be false
- end
- end
- end
-
- describe '#subscribe_address_for' do
- before do
- remote_follow.valid?
- end
-
- let(:attrs) { { acct: 'robcolbert@quitter.no' } }
- let(:account) { Fabricate(:account, username: 'alice') }
-
- subject { remote_follow.subscribe_address_for(account) }
-
- it 'returns subscribe address' do
- is_expected.to eq 'https://quitter.no/main/ostatussub?profile=alice%40cb6e6126.ngrok.io'
- end
- end
-end
diff --git a/spec/models/remote_profile_spec.rb b/spec/models/remote_profile_spec.rb
deleted file mode 100644
index cbe55105..00000000
--- a/spec/models/remote_profile_spec.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe RemoteProfile do
- let(:remote_profile) { RemoteProfile.new(body) }
- let(:body) do
- <<-XML
-
- John
- XML
- end
-
- describe '.initialize' do
- it 'calls Nokogiri::XML.parse' do
- expect(Nokogiri::XML).to receive(:parse).with(body, nil, 'utf-8')
- RemoteProfile.new(body)
- end
-
- it 'sets document' do
- remote_profile = RemoteProfile.new(body)
- expect(remote_profile).not_to be nil
- end
- end
-
- describe '#root' do
- let(:document) { remote_profile.document }
-
- it 'callse document.at_xpath' do
- expect(document).to receive(:at_xpath).with(
- '/atom:feed|/atom:entry',
- atom: OStatus::TagManager::XMLNS
- )
-
- remote_profile.root
- end
- end
-
- describe '#author' do
- let(:root) { remote_profile.root }
-
- it 'calls root.at_xpath' do
- expect(root).to receive(:at_xpath).with(
- './atom:author|./dfrn:owner',
- atom: OStatus::TagManager::XMLNS,
- dfrn: OStatus::TagManager::DFRN_XMLNS
- )
-
- remote_profile.author
- end
- end
-
- describe '#hub_link' do
- let(:root) { remote_profile.root }
-
- it 'calls #link_href_from_xml' do
- expect(remote_profile).to receive(:link_href_from_xml).with(root, 'hub')
- remote_profile.hub_link
- end
- end
-
- describe '#display_name' do
- let(:author) { remote_profile.author }
-
- it 'calls author.at_xpath.content' do
- expect(author).to receive_message_chain(:at_xpath, :content).with(
- './poco:displayName',
- poco: OStatus::TagManager::POCO_XMLNS
- ).with(no_args)
-
- remote_profile.display_name
- end
- end
-
- describe '#note' do
- let(:author) { remote_profile.author }
-
- it 'calls author.at_xpath.content' do
- expect(author).to receive_message_chain(:at_xpath, :content).with(
- './atom:summary|./poco:note',
- atom: OStatus::TagManager::XMLNS,
- poco: OStatus::TagManager::POCO_XMLNS
- ).with(no_args)
-
- remote_profile.note
- end
- end
-
- describe '#scope' do
- let(:author) { remote_profile.author }
-
- it 'calls author.at_xpath.content' do
- expect(author).to receive_message_chain(:at_xpath, :content).with(
- './gabsocial:scope',
- gabsocial: OStatus::TagManager::MTDN_XMLNS
- ).with(no_args)
-
- remote_profile.scope
- end
- end
-
- describe '#avatar' do
- let(:author) { remote_profile.author }
-
- it 'calls #link_href_from_xml' do
- expect(remote_profile).to receive(:link_href_from_xml).with(author, 'avatar')
- remote_profile.avatar
- end
- end
-
- describe '#header' do
- let(:author) { remote_profile.author }
-
- it 'calls #link_href_from_xml' do
- expect(remote_profile).to receive(:link_href_from_xml).with(author, 'header')
- remote_profile.header
- end
- end
-
- describe '#locked?' do
- before do
- allow(remote_profile).to receive(:scope).and_return(scope)
- end
-
- subject { remote_profile.locked? }
-
- context 'scope is private' do
- let(:scope) { 'private' }
-
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'scope is not private' do
- let(:scope) { 'public' }
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
-end
diff --git a/spec/models/report_filter_spec.rb b/spec/models/report_filter_spec.rb
deleted file mode 100644
index 099c0731..00000000
--- a/spec/models/report_filter_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'rails_helper'
-
-describe ReportFilter do
- describe 'with empty params' do
- it 'defaults to unresolved reports list' do
- filter = ReportFilter.new({})
-
- expect(filter.results).to eq Report.unresolved
- end
- end
-
- describe 'with invalid params' do
- it 'raises with key error' do
- filter = ReportFilter.new(wrong: true)
-
- expect { filter.results }.to raise_error(/wrong/)
- end
- end
-
- describe 'with valid params' do
- it 'combines filters on Report' do
- filter = ReportFilter.new(account_id: '123', resolved: true, target_account_id: '456')
-
- allow(Report).to receive(:where).and_return(Report.none)
- allow(Report).to receive(:resolved).and_return(Report.none)
- filter.results
- expect(Report).to have_received(:where).with(account_id: '123')
- expect(Report).to have_received(:where).with(target_account_id: '456')
- expect(Report).to have_received(:resolved)
- end
- end
-end
diff --git a/spec/models/report_spec.rb b/spec/models/report_spec.rb
deleted file mode 100644
index a0cd0800..00000000
--- a/spec/models/report_spec.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-require 'rails_helper'
-
-describe Report do
- describe 'statuses' do
- it 'returns the statuses for the report' do
- status = Fabricate(:status)
- _other = Fabricate(:status)
- report = Fabricate(:report, status_ids: [status.id])
-
- expect(report.statuses).to eq [status]
- end
- end
-
- describe 'media_attachments' do
- it 'returns media attachments from statuses' do
- status = Fabricate(:status)
- media_attachment = Fabricate(:media_attachment, status: status)
- _other_media_attachment = Fabricate(:media_attachment)
- report = Fabricate(:report, status_ids: [status.id])
-
- expect(report.media_attachments).to eq [media_attachment]
- end
- end
-
- describe 'assign_to_self!' do
- subject { report.assigned_account_id }
-
- let(:report) { Fabricate(:report, assigned_account_id: original_account) }
- let(:original_account) { Fabricate(:account) }
- let(:current_account) { Fabricate(:account) }
-
- before do
- report.assign_to_self!(current_account)
- end
-
- it 'assigns to a given account' do
- is_expected.to eq current_account.id
- end
- end
-
- describe 'unassign!' do
- subject { report.assigned_account_id }
-
- let(:report) { Fabricate(:report, assigned_account_id: account.id) }
- let(:account) { Fabricate(:account) }
-
- before do
- report.unassign!
- end
-
- it 'unassigns' do
- is_expected.to be_nil
- end
- end
-
- describe 'resolve!' do
- subject(:report) { Fabricate(:report, action_taken: false, action_taken_by_account_id: nil) }
-
- let(:acting_account) { Fabricate(:account) }
-
- before do
- report.resolve!(acting_account)
- end
-
- it 'records action taken' do
- expect(report).to have_attributes(action_taken: true, action_taken_by_account_id: acting_account.id)
- end
- end
-
- describe 'unresolve!' do
- subject(:report) { Fabricate(:report, action_taken: true, action_taken_by_account_id: acting_account.id) }
-
- let(:acting_account) { Fabricate(:account) }
-
- before do
- report.unresolve!
- end
-
- it 'unresolves' do
- expect(report).to have_attributes(action_taken: false, action_taken_by_account_id: nil)
- end
- end
-
- describe 'unresolved?' do
- subject { report.unresolved? }
-
- let(:report) { Fabricate(:report, action_taken: action_taken) }
-
- context 'if action is taken' do
- let(:action_taken) { true }
-
- it { is_expected.to be false }
- end
-
- context 'if action not is taken' do
- let(:action_taken) { false }
-
- it { is_expected.to be true }
- end
- end
-
- describe 'history' do
- subject(:action_logs) { report.history }
-
- let(:report) { Fabricate(:report, target_account_id: target_account.id, status_ids: [status.id], created_at: 3.days.ago, updated_at: 1.day.ago) }
- let(:target_account) { Fabricate(:account) }
- let(:status) { Fabricate(:status) }
-
- before do
- Fabricate('Admin::ActionLog', target_type: 'Report', account_id: target_account.id, target_id: report.id, created_at: 2.days.ago)
- Fabricate('Admin::ActionLog', target_type: 'Account', account_id: target_account.id, target_id: report.target_account_id, created_at: 2.days.ago)
- Fabricate('Admin::ActionLog', target_type: 'Status', account_id: target_account.id, target_id: status.id, created_at: 2.days.ago)
- end
-
- it 'returns right logs' do
- expect(action_logs.count).to eq 3
- end
- end
-
- describe 'validatiions' do
- it 'has a valid fabricator' do
- report = Fabricate(:report)
- report.valid?
- expect(report).to be_valid
- end
-
- it 'is invalid if comment is longer than 1000 characters' do
- report = Fabricate.build(:report, comment: Faker::Lorem.characters(1001))
- report.valid?
- expect(report).to model_have_error_on_field(:comment)
- end
- end
-end
diff --git a/spec/models/scheduled_status_spec.rb b/spec/models/scheduled_status_spec.rb
deleted file mode 100644
index f8c9d8b8..00000000
--- a/spec/models/scheduled_status_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ScheduledStatus, type: :model do
-end
diff --git a/spec/models/session_activation_spec.rb b/spec/models/session_activation_spec.rb
deleted file mode 100644
index 2aa69503..00000000
--- a/spec/models/session_activation_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe SessionActivation, type: :model do
- describe '#detection' do
- let(:session_activation) { Fabricate(:session_activation, user_agent: 'Chrome/62.0.3202.89') }
-
- it 'sets a Browser instance as detection' do
- expect(session_activation.detection).to be_kind_of Browser::Chrome
- end
- end
-
- describe '#browser' do
- before do
- allow(session_activation).to receive(:detection).and_return(detection)
- end
-
- let(:detection) { double(id: 1) }
- let(:session_activation) { Fabricate(:session_activation) }
-
- it 'returns detection.id' do
- expect(session_activation.browser).to be 1
- end
- end
-
- describe '#platform' do
- before do
- allow(session_activation).to receive(:detection).and_return(detection)
- end
-
- let(:session_activation) { Fabricate(:session_activation) }
- let(:detection) { double(platform: double(id: 1)) }
-
- it 'returns detection.platform.id' do
- expect(session_activation.platform).to be 1
- end
- end
-
- describe '.active?' do
- subject { described_class.active?(id) }
-
- context 'id is absent' do
- let(:id) { nil }
-
- it 'returns nil' do
- is_expected.to be nil
- end
- end
-
- context 'id is present' do
- let(:id) { '1' }
- let!(:session_activation) { Fabricate(:session_activation, session_id: id) }
-
- context 'id exists as session_id' do
- it 'returns true' do
- is_expected.to be true
- end
- end
-
- context 'id does not exist as session_id' do
- before do
- session_activation.update!(session_id: '2')
- end
-
- it 'returns false' do
- is_expected.to be false
- end
- end
- end
- end
-
- describe '.activate' do
- let(:options) { { user: Fabricate(:user), session_id: '1' } }
-
- it 'calls create! and purge_old' do
- expect(described_class).to receive(:create!).with(options)
- expect(described_class).to receive(:purge_old)
- described_class.activate(options)
- end
-
- it 'returns an instance of SessionActivation' do
- expect(described_class.activate(options)).to be_kind_of SessionActivation
- end
- end
-
- describe '.deactivate' do
- context 'id is absent' do
- let(:id) { nil }
-
- it 'returns nil' do
- expect(described_class.deactivate(id)).to be nil
- end
- end
-
- context 'id exists' do
- let(:id) { '1' }
-
- it 'calls where.destroy_all' do
- expect(described_class).to receive_message_chain(:where, :destroy_all)
- .with(session_id: id).with(no_args)
-
- described_class.deactivate(id)
- end
- end
- end
-
- describe '.purge_old' do
- it 'calls order.offset.destroy_all' do
- expect(described_class).to receive_message_chain(:order, :offset, :destroy_all)
- .with('created_at desc').with(Rails.configuration.x.max_session_activations).with(no_args)
-
- described_class.purge_old
- end
- end
-
- describe '.exclusive' do
- let(:id) { '1' }
-
- it 'calls where.destroy_all' do
- expect(described_class).to receive_message_chain(:where, :destroy_all)
- .with('session_id != ?', id).with(no_args)
-
- described_class.exclusive(id)
- end
- end
-end
diff --git a/spec/models/setting_spec.rb b/spec/models/setting_spec.rb
deleted file mode 100644
index 1cc52867..00000000
--- a/spec/models/setting_spec.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe Setting, type: :model do
- describe '#to_param' do
- let(:setting) { Fabricate(:setting, var: var) }
- let(:var) { 'var' }
-
- it 'returns setting.var' do
- expect(setting.to_param).to eq var
- end
- end
-
- describe '.[]' do
- before do
- allow(described_class).to receive(:rails_initialized?).and_return(rails_initialized)
- end
-
- let(:key) { 'key' }
-
- context 'rails_initialized? is falsey' do
- let(:rails_initialized) { false }
-
- it 'calls RailsSettings::Base#[]' do
- expect(RailsSettings::Base).to receive(:[]).with(key)
- described_class[key]
- end
- end
-
- context 'rails_initialized? is truthy' do
- before do
- allow(RailsSettings::Base).to receive(:cache_key).with(key, nil).and_return(cache_key)
- end
-
- let(:rails_initialized) { true }
- let(:cache_key) { 'cache-key' }
- let(:cache_value) { 'cache-value' }
-
- it 'calls not RailsSettings::Base#[]' do
- expect(RailsSettings::Base).not_to receive(:[]).with(key)
- described_class[key]
- end
-
- context 'Rails.cache does not exists' do
- before do
- allow(RailsSettings::Settings).to receive(:object).with(key).and_return(object)
- allow(described_class).to receive(:default_settings).and_return(default_settings)
- allow_any_instance_of(Settings::ScopedSettings).to receive(:thing_scoped).and_return(records)
- Rails.cache.delete(cache_key)
- end
-
- let(:object) { nil }
- let(:default_value) { 'default_value' }
- let(:default_settings) { { key => default_value } }
- let(:records) { [Fabricate(:setting, var: key, value: nil)] }
-
- it 'calls RailsSettings::Settings.object' do
- expect(RailsSettings::Settings).to receive(:object).with(key)
- described_class[key]
- end
-
- context 'RailsSettings::Settings.object returns truthy' do
- let(:object) { db_val }
- let(:db_val) { double(value: 'db_val') }
-
- context 'default_value is a Hash' do
- let(:default_value) { { default_value: 'default_value' } }
-
- it 'calls default_value.with_indifferent_access.merge!' do
- expect(default_value).to receive_message_chain(:with_indifferent_access, :merge!)
- .with(db_val.value)
-
- described_class[key]
- end
- end
-
- context 'default_value is not a Hash' do
- let(:default_value) { 'default_value' }
-
- it 'returns db_val.value' do
- expect(described_class[key]).to be db_val.value
- end
- end
- end
-
- context 'RailsSettings::Settings.object returns falsey' do
- let(:object) { nil }
-
- it 'returns default_settings[key]' do
- expect(described_class[key]).to be default_settings[key]
- end
- end
- end
-
- context 'Rails.cache exists' do
- before do
- Rails.cache.write(cache_key, cache_value)
- end
-
- it 'does not query the database' do
- expect do |callback|
- ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
- described_class[key]
- end
- end.not_to yield_control
- end
-
- it 'returns the cached value' do
- expect(described_class[key]).to eq cache_value
- end
- end
- end
- end
-
- describe '.all_as_records' do
- before do
- allow_any_instance_of(Settings::ScopedSettings).to receive(:thing_scoped).and_return(records)
- allow(described_class).to receive(:default_settings).and_return(default_settings)
- end
-
- let(:key) { 'key' }
- let(:default_value) { 'default_value' }
- let(:default_settings) { { key => default_value } }
- let(:original_setting) { Fabricate(:setting, var: key, value: nil) }
- let(:records) { [original_setting] }
-
- it 'returns a Hash' do
- expect(described_class.all_as_records).to be_kind_of Hash
- end
-
- context 'records includes Setting with var as the key' do
- let(:records) { [original_setting] }
-
- it 'includes the original Setting' do
- setting = described_class.all_as_records[key]
- expect(setting).to eq original_setting
- end
- end
-
- context 'records includes nothing' do
- let(:records) { [] }
-
- context 'default_value is not a Hash' do
- it 'includes Setting with value of default_value' do
- setting = described_class.all_as_records[key]
-
- expect(setting).to be_kind_of Setting
- expect(setting).to have_attributes(var: key)
- expect(setting).to have_attributes(value: 'default_value')
- end
- end
-
- context 'default_value is a Hash' do
- let(:default_value) { { 'foo' => 'fuga' } }
-
- it 'returns {}' do
- expect(described_class.all_as_records).to eq({})
- end
- end
- end
- end
-
- describe '.default_settings' do
- before do
- allow(RailsSettings::Default).to receive(:enabled?).and_return(enabled)
- end
-
- subject { described_class.default_settings }
-
- context 'RailsSettings::Default.enabled? is false' do
- let(:enabled) { false }
-
- it 'returns {}' do
- is_expected.to eq({})
- end
- end
-
- context 'RailsSettings::Settings.enabled? is true' do
- let(:enabled) { true }
-
- it 'returns instance of RailsSettings::Default' do
- is_expected.to be_kind_of RailsSettings::Default
- end
- end
- end
-end
diff --git a/spec/models/site_upload_spec.rb b/spec/models/site_upload_spec.rb
deleted file mode 100644
index f7ea0692..00000000
--- a/spec/models/site_upload_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe SiteUpload, type: :model do
- describe '#cache_key' do
- let(:site_upload) { SiteUpload.new(var: 'var') }
-
- it 'returns cache_key' do
- expect(site_upload.cache_key).to eq 'site_uploads/var'
- end
- end
-end
diff --git a/spec/models/status_pin_spec.rb b/spec/models/status_pin_spec.rb
deleted file mode 100644
index 6f0b2feb..00000000
--- a/spec/models/status_pin_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe StatusPin, type: :model do
- describe 'validations' do
- it 'allows pins of own statuses' do
- account = Fabricate(:account)
- status = Fabricate(:status, account: account)
-
- expect(StatusPin.new(account: account, status: status).save).to be true
- end
-
- it 'does not allow pins of statuses by someone else' do
- account = Fabricate(:account)
- status = Fabricate(:status)
-
- expect(StatusPin.new(account: account, status: status).save).to be false
- end
-
- it 'does not allow pins of reblogs' do
- account = Fabricate(:account)
- status = Fabricate(:status, account: account)
- reblog = Fabricate(:status, reblog: status)
-
- expect(StatusPin.new(account: account, status: reblog).save).to be false
- end
-
- it 'does not allow pins of private statuses' do
- account = Fabricate(:account)
- status = Fabricate(:status, account: account, visibility: :private)
-
- expect(StatusPin.new(account: account, status: status).save).to be false
- end
-
- it 'does not allow pins of direct statuses' do
- account = Fabricate(:account)
- status = Fabricate(:status, account: account, visibility: :direct)
-
- expect(StatusPin.new(account: account, status: status).save).to be false
- end
-
- max_pins = 5
- it 'does not allow pins above the max' do
- account = Fabricate(:account)
- status = []
-
- (max_pins + 1).times do |i|
- status[i] = Fabricate(:status, account: account)
- end
-
- max_pins.times do |i|
- expect(StatusPin.new(account: account, status: status[i]).save).to be true
- end
-
- expect(StatusPin.new(account: account, status: status[max_pins]).save).to be false
- end
-
- it 'allows pins above the max for remote accounts' do
- account = Fabricate(:account, domain: 'remote.test', username: 'bob', url: 'https://remote.test/')
- status = []
-
- (max_pins + 1).times do |i|
- status[i] = Fabricate(:status, account: account)
- end
-
- max_pins.times do |i|
- expect(StatusPin.new(account: account, status: status[i]).save).to be true
- end
-
- expect(StatusPin.new(account: account, status: status[max_pins]).save).to be true
- end
- end
-end
diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb
deleted file mode 100644
index 9e7b02d4..00000000
--- a/spec/models/status_spec.rb
+++ /dev/null
@@ -1,696 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Status, type: :model do
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:bob) { Fabricate(:account, username: 'bob') }
- let(:other) { Fabricate(:status, account: bob, text: 'Skulls for the skull god! The enemy\'s gates are sideways!') }
-
- subject { Fabricate(:status, account: alice) }
-
- describe '#local?' do
- it 'returns true when no remote URI is set' do
- expect(subject.local?).to be true
- end
-
- it 'returns false if a remote URI is set' do
- alice.update(domain: 'example.com')
- subject.save
- expect(subject.local?).to be false
- end
-
- it 'returns true if a URI is set and `local` is true' do
- subject.update(uri: 'example.com', local: true)
- expect(subject.local?).to be true
- end
- end
-
- describe '#reblog?' do
- it 'returns true when the status reblogs another status' do
- subject.reblog = other
- expect(subject.reblog?).to be true
- end
-
- it 'returns false if the status is self-contained' do
- expect(subject.reblog?).to be false
- end
- end
-
- describe '#reply?' do
- it 'returns true if the status references another' do
- subject.thread = other
- expect(subject.reply?).to be true
- end
-
- it 'returns false if the status is self-contained' do
- expect(subject.reply?).to be false
- end
- end
-
- describe '#verb' do
- context 'if destroyed?' do
- it 'returns :delete' do
- subject.destroy!
- expect(subject.verb).to be :delete
- end
- end
-
- context 'unless destroyed?' do
- context 'if reblog?' do
- it 'returns :share' do
- subject.reblog = other
- expect(subject.verb).to be :share
- end
- end
-
- context 'unless reblog?' do
- it 'returns :post' do
- subject.reblog = nil
- expect(subject.verb).to be :post
- end
- end
- end
- end
-
- describe '#object_type' do
- it 'is note when the status is self-contained' do
- expect(subject.object_type).to be :note
- end
-
- it 'is comment when the status replies to another' do
- subject.thread = other
- expect(subject.object_type).to be :comment
- end
- end
-
- describe '#title' do
- # rubocop:disable Style/InterpolationCheck
-
- let(:account) { subject.account }
-
- context 'if destroyed?' do
- it 'returns "#{account.acct} deleted status"' do
- subject.destroy!
- expect(subject.title).to eq "#{account.acct} deleted status"
- end
- end
-
- context 'unless destroyed?' do
- context 'if reblog?' do
- it 'returns "#{account.acct} shared a status by #{reblog.account.acct}"' do
- reblog = subject.reblog = other
- expect(subject.title).to eq "#{account.acct} shared a status by #{reblog.account.acct}"
- end
- end
-
- context 'unless reblog?' do
- it 'returns "New status by #{account.acct}"' do
- subject.reblog = nil
- expect(subject.title).to eq "New status by #{account.acct}"
- end
- end
- end
- end
-
- describe '#hidden?' do
- context 'if private_visibility?' do
- it 'returns true' do
- subject.visibility = :private
- expect(subject.hidden?).to be true
- end
- end
-
- context 'if direct_visibility?' do
- it 'returns true' do
- subject.visibility = :direct
- expect(subject.hidden?).to be true
- end
- end
-
- context 'if public_visibility?' do
- it 'returns false' do
- subject.visibility = :public
- expect(subject.hidden?).to be false
- end
- end
-
- context 'if unlisted_visibility?' do
- it 'returns false' do
- subject.visibility = :unlisted
- expect(subject.hidden?).to be false
- end
- end
- end
-
- describe '#content' do
- it 'returns the text of the status if it is not a reblog' do
- expect(subject.content).to eql subject.text
- end
-
- it 'returns the text of the reblogged status' do
- subject.reblog = other
- expect(subject.content).to eql other.text
- end
- end
-
- describe '#target' do
- it 'returns nil if the status is self-contained' do
- expect(subject.target).to be_nil
- end
-
- it 'returns nil if the status is a reply' do
- subject.thread = other
- expect(subject.target).to be_nil
- end
-
- it 'returns the reblogged status' do
- subject.reblog = other
- expect(subject.target).to eq other
- end
- end
-
- describe '#reblogs_count' do
- it 'is the number of reblogs' do
- Fabricate(:status, account: bob, reblog: subject)
- Fabricate(:status, account: alice, reblog: subject)
-
- expect(subject.reblogs_count).to eq 2
- end
-
- it 'is decremented when reblog is removed' do
- reblog = Fabricate(:status, account: bob, reblog: subject)
- expect(subject.reblogs_count).to eq 1
- reblog.destroy
- expect(subject.reblogs_count).to eq 0
- end
-
- it 'does not fail when original is deleted before reblog' do
- reblog = Fabricate(:status, account: bob, reblog: subject)
- expect(subject.reblogs_count).to eq 1
- expect { subject.destroy }.to_not raise_error
- expect(Status.find_by(id: reblog.id)).to be_nil
- end
- end
-
- describe '#replies_count' do
- it 'is the number of replies' do
- reply = Fabricate(:status, account: bob, thread: subject)
- expect(subject.replies_count).to eq 1
- end
-
- it 'is decremented when reply is removed' do
- reply = Fabricate(:status, account: bob, thread: subject)
- expect(subject.replies_count).to eq 1
- reply.destroy
- expect(subject.replies_count).to eq 0
- end
- end
-
- describe '#favourites_count' do
- it 'is the number of favorites' do
- Fabricate(:favourite, account: bob, status: subject)
- Fabricate(:favourite, account: alice, status: subject)
-
- expect(subject.favourites_count).to eq 2
- end
-
- it 'is decremented when favourite is removed' do
- favourite = Fabricate(:favourite, account: bob, status: subject)
- expect(subject.favourites_count).to eq 1
- favourite.destroy
- expect(subject.favourites_count).to eq 0
- end
- end
-
- describe '#proper' do
- it 'is itself for original statuses' do
- expect(subject.proper).to eq subject
- end
-
- it 'is the source status for reblogs' do
- subject.reblog = other
- expect(subject.proper).to eq other
- end
- end
-
- describe '.mutes_map' do
- let(:status) { Fabricate(:status) }
- let(:account) { Fabricate(:account) }
-
- subject { Status.mutes_map([status.conversation.id], account) }
-
- it 'returns a hash' do
- expect(subject).to be_a Hash
- end
-
- it 'contains true value' do
- account.mute_conversation!(status.conversation)
- expect(subject[status.conversation.id]).to be true
- end
- end
-
- describe '.favourites_map' do
- let(:status) { Fabricate(:status) }
- let(:account) { Fabricate(:account) }
-
- subject { Status.favourites_map([status], account) }
-
- it 'returns a hash' do
- expect(subject).to be_a Hash
- end
-
- it 'contains true value' do
- Fabricate(:favourite, status: status, account: account)
- expect(subject[status.id]).to be true
- end
- end
-
- describe '.reblogs_map' do
- let(:status) { Fabricate(:status) }
- let(:account) { Fabricate(:account) }
-
- subject { Status.reblogs_map([status], account) }
-
- it 'returns a hash' do
- expect(subject).to be_a Hash
- end
-
- it 'contains true value' do
- Fabricate(:status, account: account, reblog: status)
- expect(subject[status.id]).to be true
- end
- end
-
- describe '.in_chosen_languages' do
- context 'for accounts with language filters' do
- let(:user) { Fabricate(:user, chosen_languages: ['en']) }
-
- it 'does not include statuses in not in chosen languages' do
- status = Fabricate(:status, language: 'de')
- expect(Status.in_chosen_languages(user.account)).not_to include status
- end
-
- it 'includes status with unknown language' do
- status = Fabricate(:status, language: nil)
- expect(Status.in_chosen_languages(user.account)).to include status
- end
- end
- end
-
- describe '.as_home_timeline' do
- let(:account) { Fabricate(:account) }
- let(:followed) { Fabricate(:account) }
- let(:not_followed) { Fabricate(:account) }
-
- before do
- Fabricate(:follow, account: account, target_account: followed)
-
- @self_status = Fabricate(:status, account: account, visibility: :public)
- @self_direct_status = Fabricate(:status, account: account, visibility: :direct)
- @followed_status = Fabricate(:status, account: followed, visibility: :public)
- @followed_direct_status = Fabricate(:status, account: followed, visibility: :direct)
- @not_followed_status = Fabricate(:status, account: not_followed, visibility: :public)
-
- @results = Status.as_home_timeline(account)
- end
-
- it 'includes statuses from self' do
- expect(@results).to include(@self_status)
- end
-
- it 'does not include direct statuses from self' do
- expect(@results).to_not include(@self_direct_status)
- end
-
- it 'includes statuses from followed' do
- expect(@results).to include(@followed_status)
- end
-
- it 'does not include direct statuses mentioning recipient from followed' do
- Fabricate(:mention, account: account, status: @followed_direct_status)
- expect(@results).to_not include(@followed_direct_status)
- end
-
- it 'does not include direct statuses not mentioning recipient from followed' do
- expect(@results).not_to include(@followed_direct_status)
- end
-
- it 'does not include statuses from non-followed' do
- expect(@results).not_to include(@not_followed_status)
- end
- end
-
- describe '.as_direct_timeline' do
- let(:account) { Fabricate(:account) }
- let(:followed) { Fabricate(:account) }
- let(:not_followed) { Fabricate(:account) }
-
- before do
- Fabricate(:follow, account: account, target_account: followed)
-
- @self_public_status = Fabricate(:status, account: account, visibility: :public)
- @self_direct_status = Fabricate(:status, account: account, visibility: :direct)
- @followed_public_status = Fabricate(:status, account: followed, visibility: :public)
- @followed_direct_status = Fabricate(:status, account: followed, visibility: :direct)
- @not_followed_direct_status = Fabricate(:status, account: not_followed, visibility: :direct)
-
- @results = Status.as_direct_timeline(account)
- end
-
- it 'does not include public statuses from self' do
- expect(@results).to_not include(@self_public_status)
- end
-
- it 'includes direct statuses from self' do
- expect(@results).to include(@self_direct_status)
- end
-
- it 'does not include public statuses from followed' do
- expect(@results).to_not include(@followed_public_status)
- end
-
- it 'does not include direct statuses not mentioning recipient from followed' do
- expect(@results).to_not include(@followed_direct_status)
- end
-
- it 'does not include direct statuses not mentioning recipient from non-followed' do
- expect(@results).to_not include(@not_followed_direct_status)
- end
-
- it 'includes direct statuses mentioning recipient from followed' do
- Fabricate(:mention, account: account, status: @followed_direct_status)
- results2 = Status.as_direct_timeline(account)
- expect(results2).to include(@followed_direct_status)
- end
-
- it 'includes direct statuses mentioning recipient from non-followed' do
- Fabricate(:mention, account: account, status: @not_followed_direct_status)
- results2 = Status.as_direct_timeline(account)
- expect(results2).to include(@not_followed_direct_status)
- end
- end
-
- describe '.as_public_timeline' do
- it 'only includes statuses with public visibility' do
- public_status = Fabricate(:status, visibility: :public)
- private_status = Fabricate(:status, visibility: :private)
-
- results = Status.as_public_timeline
- expect(results).to include(public_status)
- expect(results).not_to include(private_status)
- end
-
- it 'does not include replies' do
- status = Fabricate(:status)
- reply = Fabricate(:status, in_reply_to_id: status.id)
-
- results = Status.as_public_timeline
- expect(results).to include(status)
- expect(results).not_to include(reply)
- end
-
- it 'does not include reposts' do
- status = Fabricate(:status)
- repost = Fabricate(:status, reblog_of_id: status.id)
-
- results = Status.as_public_timeline
- expect(results).to include(status)
- expect(results).not_to include(repost)
- end
-
- it 'filters out silenced accounts' do
- account = Fabricate(:account)
- silenced_account = Fabricate(:account, silenced: true)
- status = Fabricate(:status, account: account)
- silenced_status = Fabricate(:status, account: silenced_account)
-
- results = Status.as_public_timeline
- expect(results).to include(status)
- expect(results).not_to include(silenced_status)
- end
-
- context 'without local_only option' do
- let(:viewer) { nil }
-
- let!(:local_account) { Fabricate(:account, domain: nil) }
- let!(:remote_account) { Fabricate(:account, domain: 'test.com') }
- let!(:local_status) { Fabricate(:status, account: local_account) }
- let!(:remote_status) { Fabricate(:status, account: remote_account) }
-
- subject { Status.as_public_timeline(viewer, false) }
-
- context 'without a viewer' do
- let(:viewer) { nil }
-
- it 'includes remote instances statuses' do
- expect(subject).to include(remote_status)
- end
-
- it 'includes local statuses' do
- expect(subject).to include(local_status)
- end
- end
-
- context 'with a viewer' do
- let(:viewer) { Fabricate(:account, username: 'viewer') }
-
- it 'includes remote instances statuses' do
- expect(subject).to include(remote_status)
- end
-
- it 'includes local statuses' do
- expect(subject).to include(local_status)
- end
- end
- end
-
- context 'with a local_only option set' do
- let!(:local_account) { Fabricate(:account, domain: nil) }
- let!(:remote_account) { Fabricate(:account, domain: 'test.com') }
- let!(:local_status) { Fabricate(:status, account: local_account) }
- let!(:remote_status) { Fabricate(:status, account: remote_account) }
-
- subject { Status.as_public_timeline(viewer, true) }
-
- context 'without a viewer' do
- let(:viewer) { nil }
-
- it 'does not include remote instances statuses' do
- expect(subject).to include(local_status)
- expect(subject).not_to include(remote_status)
- end
- end
-
- context 'with a viewer' do
- let(:viewer) { Fabricate(:account, username: 'viewer') }
-
- it 'does not include remote instances statuses' do
- expect(subject).to include(local_status)
- expect(subject).not_to include(remote_status)
- end
-
- it 'is not affected by personal domain blocks' do
- viewer.block_domain!('test.com')
- expect(subject).to include(local_status)
- expect(subject).not_to include(remote_status)
- end
- end
- end
-
- describe 'with an account passed in' do
- before do
- @account = Fabricate(:account)
- end
-
- it 'excludes statuses from accounts blocked by the account' do
- blocked = Fabricate(:account)
- Fabricate(:block, account: @account, target_account: blocked)
- blocked_status = Fabricate(:status, account: blocked)
-
- results = Status.as_public_timeline(@account)
- expect(results).not_to include(blocked_status)
- end
-
- it 'excludes statuses from accounts who have blocked the account' do
- blocked = Fabricate(:account)
- Fabricate(:block, account: blocked, target_account: @account)
- blocked_status = Fabricate(:status, account: blocked)
-
- results = Status.as_public_timeline(@account)
- expect(results).not_to include(blocked_status)
- end
-
- it 'excludes statuses from accounts muted by the account' do
- muted = Fabricate(:account)
- Fabricate(:mute, account: @account, target_account: muted)
- muted_status = Fabricate(:status, account: muted)
-
- results = Status.as_public_timeline(@account)
- expect(results).not_to include(muted_status)
- end
-
- it 'excludes statuses from accounts from personally blocked domains' do
- blocked = Fabricate(:account, domain: 'example.com')
- @account.block_domain!(blocked.domain)
- blocked_status = Fabricate(:status, account: blocked)
-
- results = Status.as_public_timeline(@account)
- expect(results).not_to include(blocked_status)
- end
-
- context 'with language preferences' do
- it 'excludes statuses in languages not allowed by the account user' do
- user = Fabricate(:user, chosen_languages: [:en, :es])
- @account.update(user: user)
- en_status = Fabricate(:status, language: 'en')
- es_status = Fabricate(:status, language: 'es')
- fr_status = Fabricate(:status, language: 'fr')
-
- results = Status.as_public_timeline(@account)
- expect(results).to include(en_status)
- expect(results).to include(es_status)
- expect(results).not_to include(fr_status)
- end
-
- it 'includes all languages when user does not have a setting' do
- user = Fabricate(:user, chosen_languages: nil)
- @account.update(user: user)
-
- en_status = Fabricate(:status, language: 'en')
- es_status = Fabricate(:status, language: 'es')
-
- results = Status.as_public_timeline(@account)
- expect(results).to include(en_status)
- expect(results).to include(es_status)
- end
-
- it 'includes all languages when account does not have a user' do
- expect(@account.user).to be_nil
- en_status = Fabricate(:status, language: 'en')
- es_status = Fabricate(:status, language: 'es')
-
- results = Status.as_public_timeline(@account)
- expect(results).to include(en_status)
- expect(results).to include(es_status)
- end
- end
- end
- end
-
- describe '.as_tag_timeline' do
- it 'includes statuses with a tag' do
- tag = Fabricate(:tag)
- status = Fabricate(:status, tags: [tag])
- other = Fabricate(:status)
-
- results = Status.as_tag_timeline(tag)
- expect(results).to include(status)
- expect(results).not_to include(other)
- end
-
- it 'allows replies to be included' do
- original = Fabricate(:status)
- tag = Fabricate(:tag)
- status = Fabricate(:status, tags: [tag], in_reply_to_id: original.id)
-
- results = Status.as_tag_timeline(tag)
- expect(results).to include(status)
- end
- end
-
- describe '.permitted_for' do
- subject { described_class.permitted_for(target_account, account).pluck(:visibility) }
-
- let(:target_account) { alice }
- let(:account) { bob }
- let!(:public_status) { Fabricate(:status, account: target_account, visibility: 'public') }
- let!(:unlisted_status) { Fabricate(:status, account: target_account, visibility: 'unlisted') }
- let!(:private_status) { Fabricate(:status, account: target_account, visibility: 'private') }
-
- let!(:direct_status) do
- Fabricate(:status, account: target_account, visibility: 'direct').tap do |status|
- Fabricate(:mention, status: status, account: account)
- end
- end
-
- let!(:other_direct_status) do
- Fabricate(:status, account: target_account, visibility: 'direct').tap do |status|
- Fabricate(:mention, status: status)
- end
- end
-
- context 'given nil' do
- let(:account) { nil }
- let(:direct_status) { nil }
- it { is_expected.to eq(%w(unlisted public)) }
- end
-
- context 'given blocked account' do
- before do
- target_account.block!(account)
- end
-
- it { is_expected.to be_empty }
- end
-
- context 'given same account' do
- let(:account) { target_account }
- it { is_expected.to eq(%w(direct direct private unlisted public)) }
- end
-
- context 'given followed account' do
- before do
- account.follow!(target_account)
- end
-
- it { is_expected.to eq(%w(direct private unlisted public)) }
- end
-
- context 'given unfollowed account' do
- it { is_expected.to eq(%w(direct unlisted public)) }
- end
- end
-
- describe 'before_validation' do
- it 'sets account being replied to correctly over intermediary nodes' do
- first_status = Fabricate(:status, account: bob)
- intermediary = Fabricate(:status, thread: first_status, account: alice)
- final = Fabricate(:status, thread: intermediary, account: alice)
-
- expect(final.in_reply_to_account_id).to eq bob.id
- end
-
- it 'creates new conversation for stand-alone status' do
- expect(Status.create(account: alice, text: 'First').conversation_id).to_not be_nil
- end
-
- it 'keeps conversation of parent node' do
- parent = Fabricate(:status, text: 'First')
- expect(Status.create(account: alice, thread: parent, text: 'Response').conversation_id).to eq parent.conversation_id
- end
-
- it 'sets `local` to true for status by local account' do
- expect(Status.create(account: alice, text: 'foo').local).to be true
- end
-
- it 'sets `local` to false for status by remote account' do
- alice.update(domain: 'example.com')
- expect(Status.create(account: alice, text: 'foo').local).to be false
- end
- end
-
- describe 'validation' do
- it 'disallow empty uri for remote status' do
- alice.update(domain: 'example.com')
- status = Fabricate.build(:status, uri: '', account: alice)
- expect(status).to model_have_error_on_field(:uri)
- end
- end
-
- describe 'after_create' do
- it 'saves ActivityPub uri as uri for local status' do
- status = Status.create(account: alice, text: 'foo')
- status.reload
- expect(status.uri).to start_with('https://')
- end
- end
-end
diff --git a/spec/models/status_stat_spec.rb b/spec/models/status_stat_spec.rb
deleted file mode 100644
index af1a6f28..00000000
--- a/spec/models/status_stat_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe StatusStat, type: :model do
-end
diff --git a/spec/models/stream_entry_spec.rb b/spec/models/stream_entry_spec.rb
deleted file mode 100644
index 8f8bfbd5..00000000
--- a/spec/models/stream_entry_spec.rb
+++ /dev/null
@@ -1,192 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe StreamEntry, type: :model do
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:bob) { Fabricate(:account, username: 'bob') }
- let(:status) { Fabricate(:status, account: alice) }
- let(:reblog) { Fabricate(:status, account: bob, reblog: status) }
- let(:reply) { Fabricate(:status, account: bob, thread: status) }
- let(:stream_entry) { Fabricate(:stream_entry, activity: activity) }
- let(:activity) { reblog }
-
- describe '#object_type' do
- before do
- allow(stream_entry).to receive(:orphaned?).and_return(orphaned)
- allow(stream_entry).to receive(:targeted?).and_return(targeted)
- end
-
- subject { stream_entry.object_type }
-
- context 'orphaned? is true' do
- let(:orphaned) { true }
- let(:targeted) { false }
-
- it 'returns :activity' do
- is_expected.to be :activity
- end
- end
-
- context 'targeted? is true' do
- let(:orphaned) { false }
- let(:targeted) { true }
-
- it 'returns :activity' do
- is_expected.to be :activity
- end
- end
-
- context 'orphaned? and targeted? are false' do
- let(:orphaned) { false }
- let(:targeted) { false }
-
- context 'activity is reblog' do
- let(:activity) { reblog }
-
- it 'returns :note' do
- is_expected.to be :note
- end
- end
-
- context 'activity is reply' do
- let(:activity) { reply }
-
- it 'returns :comment' do
- is_expected.to be :comment
- end
- end
- end
- end
-
- describe '#verb' do
- before do
- allow(stream_entry).to receive(:orphaned?).and_return(orphaned)
- end
-
- subject { stream_entry.verb }
-
- context 'orphaned? is true' do
- let(:orphaned) { true }
-
- it 'returns :delete' do
- is_expected.to be :delete
- end
- end
-
- context 'orphaned? is false' do
- let(:orphaned) { false }
-
- context 'activity is reblog' do
- let(:activity) { reblog }
-
- it 'returns :share' do
- is_expected.to be :share
- end
- end
-
- context 'activity is reply' do
- let(:activity) { reply }
-
- it 'returns :post' do
- is_expected.to be :post
- end
- end
- end
- end
-
- describe '#mentions' do
- before do
- allow(stream_entry).to receive(:orphaned?).and_return(orphaned)
- end
-
- subject { stream_entry.mentions }
-
- context 'orphaned? is true' do
- let(:orphaned) { true }
-
- it 'returns []' do
- is_expected.to eq []
- end
- end
-
- context 'orphaned? is false' do
- before do
- reblog.mentions << Fabricate(:mention, account: alice)
- reblog.mentions << Fabricate(:mention, account: bob)
- end
-
- let(:orphaned) { false }
-
- it 'returns [Account] includes alice and bob' do
- is_expected.to eq [alice, bob]
- end
- end
- end
-
- describe '#targeted?' do
- it 'returns true for a reblog' do
- expect(reblog.stream_entry.targeted?).to be true
- end
-
- it 'returns false otherwise' do
- expect(status.stream_entry.targeted?).to be false
- end
- end
-
- describe '#threaded?' do
- it 'returns true for a reply' do
- expect(reply.stream_entry.threaded?).to be true
- end
-
- it 'returns false otherwise' do
- expect(status.stream_entry.threaded?).to be false
- end
- end
-
- describe 'delegated methods' do
- context 'with a nil status' do
- subject { described_class.new(status: nil) }
-
- it 'returns nil for target' do
- expect(subject.target).to be_nil
- end
-
- it 'returns nil for title' do
- expect(subject.title).to be_nil
- end
-
- it 'returns nil for content' do
- expect(subject.content).to be_nil
- end
-
- it 'returns nil for thread' do
- expect(subject.thread).to be_nil
- end
- end
-
- context 'with a real status' do
- let(:original) { Fabricate(:status, text: 'Test status') }
- let(:status) { Fabricate(:status, reblog: original, thread: original) }
- subject { described_class.new(status: status) }
-
- it 'delegates target' do
- expect(status.target).not_to be_nil
- expect(subject.target).to eq(status.target)
- end
-
- it 'delegates title' do
- expect(status.title).not_to be_nil
- expect(subject.title).to eq(status.title)
- end
-
- it 'delegates content' do
- expect(status.content).not_to be_nil
- expect(subject.content).to eq(status.content)
- end
-
- it 'delegates thread' do
- expect(status.thread).not_to be_nil
- expect(subject.thread).to eq(status.thread)
- end
- end
- end
-end
diff --git a/spec/models/subscription_spec.rb b/spec/models/subscription_spec.rb
deleted file mode 100644
index b83979d1..00000000
--- a/spec/models/subscription_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Subscription, type: :model do
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- subject { Fabricate(:subscription, account: alice) }
-
- describe '#expired?' do
- it 'return true when expires_at is past' do
- subject.expires_at = 2.days.ago
- expect(subject.expired?).to be true
- end
-
- it 'return false when expires_at is future' do
- subject.expires_at = 2.days.from_now
- expect(subject.expired?).to be false
- end
- end
-
- describe 'lease_seconds' do
- it 'returns the time remaining until expiration' do
- datetime = 1.day.from_now
- subscription = Subscription.new(expires_at: datetime)
- travel_to(datetime - 12.hours) do
- expect(subscription.lease_seconds).to eq(12.hours)
- end
- end
- end
-
- describe 'lease_seconds=' do
- it 'sets expires_at to min expiration when small value is provided' do
- subscription = Subscription.new
- datetime = 1.day.from_now
- too_low = Subscription::MIN_EXPIRATION - 1000
- travel_to(datetime) do
- subscription.lease_seconds = too_low
- end
-
- expected = datetime + Subscription::MIN_EXPIRATION.seconds
- expect(subscription.expires_at).to be_within(1.0).of(expected)
- end
-
- it 'sets expires_at to value when valid value is provided' do
- subscription = Subscription.new
- datetime = 1.day.from_now
- valid = Subscription::MIN_EXPIRATION + 1000
- travel_to(datetime) do
- subscription.lease_seconds = valid
- end
-
- expected = datetime + valid.seconds
- expect(subscription.expires_at).to be_within(1.0).of(expected)
- end
-
- it 'sets expires_at to max expiration when large value is provided' do
- subscription = Subscription.new
- datetime = 1.day.from_now
- too_high = Subscription::MAX_EXPIRATION + 1000
- travel_to(datetime) do
- subscription.lease_seconds = too_high
- end
-
- expected = datetime + Subscription::MAX_EXPIRATION.seconds
- expect(subscription.expires_at).to be_within(1.0).of(expected)
- end
- end
-end
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
deleted file mode 100644
index 1ca50cc2..00000000
--- a/spec/models/tag_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Tag, type: :model do
- describe 'validations' do
- it 'invalid with #' do
- expect(Tag.new(name: '#hello_world')).to_not be_valid
- end
-
- it 'invalid with .' do
- expect(Tag.new(name: '.abcdef123')).to_not be_valid
- end
-
- it 'invalid with spaces' do
- expect(Tag.new(name: 'hello world')).to_not be_valid
- end
-
- it 'valid with ï½ï½…sthetic' do
- expect(Tag.new(name: 'ï½ï½…sthetic')).to be_valid
- end
- end
-
- describe 'HASHTAG_RE' do
- subject { Tag::HASHTAG_RE }
-
- it 'does not match URLs with anchors with non-hashtag characters' do
- expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
- end
-
- it 'does not match URLs with hashtag-like anchors' do
- expect(subject.match('https://en.wikipedia.org/wiki/Ghostbusters_(song)#Lawsuit')).to be_nil
- end
-
- it 'matches #ï½ï½…sthetic' do
- expect(subject.match('this is #ï½ï½…sthetic')).to_not be_nil
- end
- end
-
- describe '#to_param' do
- it 'returns name' do
- tag = Fabricate(:tag, name: 'foo')
- expect(tag.to_param).to eq 'foo'
- end
- end
-
- describe '.search_for' do
- it 'finds tag records with matching names' do
- tag = Fabricate(:tag, name: "match")
- _miss_tag = Fabricate(:tag, name: "miss")
-
- results = Tag.search_for("match")
-
- expect(results).to eq [tag]
- end
-
- it 'finds tag records in case insensitive' do
- tag = Fabricate(:tag, name: "MATCH")
- _miss_tag = Fabricate(:tag, name: "miss")
-
- results = Tag.search_for("match")
-
- expect(results).to eq [tag]
- end
-
- it 'finds the exact matching tag as the first item' do
- similar_tag = Fabricate(:tag, name: "matchlater")
- tag = Fabricate(:tag, name: "match")
-
- results = Tag.search_for("match")
-
- expect(results).to eq [tag, similar_tag]
- end
- end
-end
diff --git a/spec/models/user_invite_request_spec.rb b/spec/models/user_invite_request_spec.rb
deleted file mode 100644
index 1be38d8a..00000000
--- a/spec/models/user_invite_request_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe UserInviteRequest, type: :model do
-end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
deleted file mode 100644
index f545c297..00000000
--- a/spec/models/user_spec.rb
+++ /dev/null
@@ -1,529 +0,0 @@
-require 'rails_helper'
-require 'devise_two_factor/spec_helpers'
-
-RSpec.describe User, type: :model do
- it_behaves_like 'two_factor_backupable'
-
- describe 'otp_secret' do
- it 'is encrypted with OTP_SECRET environment variable' do
- user = Fabricate(:user,
- encrypted_otp_secret: "Fttsy7QAa0edaDfdfSz094rRLAxc8cJweDQ4BsWH/zozcdVA8o9GLqcKhn2b\nGi/V\n",
- encrypted_otp_secret_iv: 'rys3THICkr60BoWC',
- encrypted_otp_secret_salt: '_LMkAGvdg7a+sDIKjI3mR2Q==')
-
- expect(user.otp_secret).to eq 'anotpsecretthatshouldbeencrypted'
- end
- end
-
- describe 'validations' do
- it 'is invalid without an account' do
- user = Fabricate.build(:user, account: nil)
- user.valid?
- expect(user).to model_have_error_on_field(:account)
- end
-
- it 'is invalid without a valid locale' do
- user = Fabricate.build(:user, locale: 'toto')
- user.valid?
- expect(user).to model_have_error_on_field(:locale)
- end
-
- it 'is invalid without a valid email' do
- user = Fabricate.build(:user, email: 'john@')
- user.valid?
- expect(user).to model_have_error_on_field(:email)
- end
-
- it 'is valid with an invalid e-mail that has already been saved' do
- user = Fabricate.build(:user, email: 'invalid-email')
- user.save(validate: false)
- expect(user.valid?).to be true
- end
-
- it 'cleans out empty string from languages' do
- user = Fabricate.build(:user, chosen_languages: [''])
- user.valid?
- expect(user.chosen_languages).to eq nil
- end
- end
-
- describe 'scopes' do
- describe 'recent' do
- it 'returns an array of recent users ordered by id' do
- user_1 = Fabricate(:user)
- user_2 = Fabricate(:user)
- expect(User.recent).to eq [user_2, user_1]
- end
- end
-
- describe 'admins' do
- it 'returns an array of users who are admin' do
- user_1 = Fabricate(:user, admin: false)
- user_2 = Fabricate(:user, admin: true)
- expect(User.admins).to match_array([user_2])
- end
- end
-
- describe 'confirmed' do
- it 'returns an array of users who are confirmed' do
- user_1 = Fabricate(:user, confirmed_at: nil)
- user_2 = Fabricate(:user, confirmed_at: Time.zone.now)
- expect(User.confirmed).to match_array([user_2])
- end
- end
-
- describe 'inactive' do
- it 'returns a relation of inactive users' do
- specified = Fabricate(:user, current_sign_in_at: 15.days.ago)
- Fabricate(:user, current_sign_in_at: 6.days.ago)
-
- expect(User.inactive).to match_array([specified])
- end
- end
-
- describe 'matches_email' do
- it 'returns a relation of users whose email starts with the given string' do
- specified = Fabricate(:user, email: 'specified@spec')
- Fabricate(:user, email: 'unspecified@spec')
-
- expect(User.matches_email('specified')).to match_array([specified])
- end
- end
- end
-
- let(:account) { Fabricate(:account, username: 'alice') }
- let(:password) { 'abcd1234' }
-
- describe 'blacklist' do
- around(:each) do |example|
- old_blacklist = Rails.configuration.x.email_blacklist
-
- Rails.configuration.x.email_domains_blacklist = 'mvrht.com'
-
- example.run
-
- Rails.configuration.x.email_domains_blacklist = old_blacklist
- end
-
- it 'should allow a non-blacklisted user to be created' do
- user = User.new(email: 'foo@example.com', account: account, password: password, agreement: true)
-
- expect(user.valid?).to be_truthy
- end
-
- it 'should not allow a blacklisted user to be created' do
- user = User.new(email: 'foo@mvrht.com', account: account, password: password, agreement: true)
-
- expect(user.valid?).to be_falsey
- end
-
- it 'should not allow a subdomain blacklisted user to be created' do
- user = User.new(email: 'foo@mvrht.com.topdomain.tld', account: account, password: password, agreement: true)
-
- expect(user.valid?).to be_falsey
- end
- end
-
- describe '#confirmed?' do
- it 'returns true when a confirmed_at is set' do
- user = Fabricate.build(:user, confirmed_at: Time.now.utc)
- expect(user.confirmed?).to be true
- end
-
- it 'returns false if a confirmed_at is nil' do
- user = Fabricate.build(:user, confirmed_at: nil)
- expect(user.confirmed?).to be false
- end
- end
-
- describe '#confirm' do
- it 'sets email to unconfirmed_email' do
- user = Fabricate.build(:user, confirmed_at: Time.now.utc, unconfirmed_email: 'new-email@example.com')
- user.confirm
- expect(user.email).to eq 'new-email@example.com'
- end
- end
-
- describe '#disable_two_factor!' do
- it 'saves false for otp_required_for_login' do
- user = Fabricate.build(:user, otp_required_for_login: true)
- user.disable_two_factor!
- expect(user.reload.otp_required_for_login).to be false
- end
-
- it 'saves cleared otp_backup_codes' do
- user = Fabricate.build(:user, otp_backup_codes: %w(dummy dummy))
- user.disable_two_factor!
- expect(user.reload.otp_backup_codes.empty?).to be true
- end
- end
-
- describe '#send_confirmation_instructions' do
- around do |example|
- queue_adapter = ActiveJob::Base.queue_adapter
- example.run
- ActiveJob::Base.queue_adapter = queue_adapter
- end
-
- it 'delivers confirmation instructions later' do
- user = Fabricate(:user)
- ActiveJob::Base.queue_adapter = :test
-
- expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::DeliveryJob)
- end
- end
-
- describe 'settings' do
- it 'is instance of Settings::ScopedSettings' do
- user = Fabricate(:user)
- expect(user.settings).to be_kind_of Settings::ScopedSettings
- end
- end
-
- describe '#setting_default_privacy' do
- it 'returns default privacy setting if user has configured' do
- user = Fabricate(:user)
- user.settings[:default_privacy] = 'unlisted'
- expect(user.setting_default_privacy).to eq 'unlisted'
- end
-
- it "returns 'private' if user has not configured default privacy setting and account is locked" do
- user = Fabricate(:user, account: Fabricate(:account, locked: true))
- expect(user.setting_default_privacy).to eq 'private'
- end
-
- it "returns 'public' if user has not configured default privacy setting and account is not locked" do
- user = Fabricate(:user, account: Fabricate(:account, locked: false))
- expect(user.setting_default_privacy).to eq 'public'
- end
- end
-
- describe 'whitelist' do
- around(:each) do |example|
- old_whitelist = Rails.configuration.x.email_whitelist
-
- Rails.configuration.x.email_domains_whitelist = 'gab.space'
-
- example.run
-
- Rails.configuration.x.email_domains_whitelist = old_whitelist
- end
-
- it 'should not allow a user to be created unless they are whitelisted' do
- user = User.new(email: 'foo@example.com', account: account, password: password, agreement: true)
- expect(user.valid?).to be_falsey
- end
-
- it 'should allow a user to be created if they are whitelisted' do
- user = User.new(email: 'foo@gab.space', account: account, password: password, agreement: true)
- expect(user.valid?).to be_truthy
- end
-
- it 'should not allow a user with a whitelisted top domain as subdomain in their email address to be created' do
- user = User.new(email: 'foo@gab.space.userdomain.com', account: account, password: password, agreement: true)
- expect(user.valid?).to be_falsey
- end
-
- context do
- around do |example|
- old_blacklist = Rails.configuration.x.email_blacklist
- example.run
- Rails.configuration.x.email_domains_blacklist = old_blacklist
- end
-
- it 'should not allow a user to be created with a specific blacklisted subdomain even if the top domain is whitelisted' do
- Rails.configuration.x.email_domains_blacklist = 'blacklisted.gab.space'
-
- user = User.new(email: 'foo@blacklisted.gab.space', account: account, password: password)
- expect(user.valid?).to be_falsey
- end
- end
- end
-
- it_behaves_like 'Settings-extended' do
- def create!
- User.create!(account: Fabricate(:account), email: 'foo@gab.space', password: 'abcd1234', agreement: true)
- end
-
- def fabricate
- Fabricate(:user)
- end
- end
-
- describe 'token_for_app' do
- let(:user) { Fabricate(:user) }
- let(:app) { Fabricate(:application, owner: user) }
-
- it 'returns a token' do
- expect(user.token_for_app(app)).to be_a(Doorkeeper::AccessToken)
- end
-
- it 'persists a token' do
- t = user.token_for_app(app)
- expect(user.token_for_app(app)).to eql(t)
- end
-
- it 'is nil if user does not own app' do
- app.update!(owner: nil)
-
- expect(user.token_for_app(app)).to be_nil
- end
- end
-
- describe '#role' do
- it 'returns admin for admin' do
- user = User.new(admin: true)
- expect(user.role).to eq 'admin'
- end
-
- it 'returns moderator for moderator' do
- user = User.new(moderator: true)
- expect(user.role).to eq 'moderator'
- end
-
- it 'returns user otherwise' do
- user = User.new
- expect(user.role).to eq 'user'
- end
- end
-
- describe '#role?' do
- it 'returns false when invalid role requested' do
- user = User.new(admin: true)
- expect(user.role?('disabled')).to be false
- end
-
- it 'returns true when exact role match' do
- user = User.new
- mod = User.new(moderator: true)
- admin = User.new(admin: true)
-
- expect(user.role?('user')).to be true
- expect(mod.role?('moderator')).to be true
- expect(admin.role?('admin')).to be true
- end
-
- it 'returns true when role higher than needed' do
- mod = User.new(moderator: true)
- admin = User.new(admin: true)
-
- expect(mod.role?('user')).to be true
- expect(admin.role?('user')).to be true
- expect(admin.role?('moderator')).to be true
- end
- end
-
- describe '#disable!' do
- subject(:user) { Fabricate(:user, disabled: false, current_sign_in_at: current_sign_in_at, last_sign_in_at: nil) }
- let(:current_sign_in_at) { Time.zone.now }
-
- before do
- user.disable!
- end
-
- it 'disables user' do
- expect(user).to have_attributes(disabled: true, current_sign_in_at: nil, last_sign_in_at: current_sign_in_at)
- end
- end
-
- describe '#disable!' do
- subject(:user) { Fabricate(:user, disabled: false, current_sign_in_at: current_sign_in_at, last_sign_in_at: nil) }
- let(:current_sign_in_at) { Time.zone.now }
-
- before do
- user.disable!
- end
-
- it 'disables user' do
- expect(user).to have_attributes(disabled: true, current_sign_in_at: nil, last_sign_in_at: current_sign_in_at)
- end
- end
-
- describe '#enable!' do
- subject(:user) { Fabricate(:user, disabled: true) }
-
- before do
- user.enable!
- end
-
- it 'enables user' do
- expect(user).to have_attributes(disabled: false)
- end
- end
-
- describe '#confirm!' do
- subject(:user) { Fabricate(:user, confirmed_at: confirmed_at) }
-
- before do
- ActionMailer::Base.deliveries.clear
- user.confirm!
- end
-
- after { ActionMailer::Base.deliveries.clear }
-
- context 'when user is new' do
- let(:confirmed_at) { nil }
-
- it 'confirms user' do
- expect(user.confirmed_at).to be_present
- end
-
- it 'delivers mails' do
- expect(ActionMailer::Base.deliveries.count).to eq 2
- end
- end
-
- context 'when user is not new' do
- let(:confirmed_at) { Time.zone.now }
-
- it 'confirms user' do
- expect(user.confirmed_at).to be_present
- end
-
- it 'does not deliver mail' do
- expect(ActionMailer::Base.deliveries.count).to eq 0
- end
- end
- end
-
- describe '#promote!' do
- subject(:user) { Fabricate(:user, admin: is_admin, moderator: is_moderator) }
-
- before do
- user.promote!
- end
-
- context 'when user is an admin' do
- let(:is_admin) { true }
-
- context 'when user is a moderator' do
- let(:is_moderator) { true }
-
- it 'changes moderator filed false' do
- expect(user).to be_admin
- expect(user).not_to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:is_moderator) { false }
-
- it 'does not change status' do
- expect(user).to be_admin
- expect(user).not_to be_moderator
- end
- end
- end
-
- context 'when user is not admin' do
- let(:is_admin) { false }
-
- context 'when user is a moderator' do
- let(:is_moderator) { true }
-
- it 'changes user into an admin' do
- expect(user).to be_admin
- expect(user).not_to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:is_moderator) { false }
-
- it 'changes user into a moderator' do
- expect(user).not_to be_admin
- expect(user).to be_moderator
- end
- end
- end
- end
-
- describe '#demote!' do
- subject(:user) { Fabricate(:user, admin: admin, moderator: moderator) }
-
- before do
- user.demote!
- end
-
- context 'when user is an admin' do
- let(:admin) { true }
-
- context 'when user is a moderator' do
- let(:moderator) { true }
-
- it 'changes user into a moderator' do
- expect(user).not_to be_admin
- expect(user).to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:moderator) { false }
-
- it 'changes user into a moderator' do
- expect(user).not_to be_admin
- expect(user).to be_moderator
- end
- end
- end
-
- context 'when user is not an admin' do
- let(:admin) { false }
-
- context 'when user is a moderator' do
- let(:moderator) { true }
-
- it 'changes user into a plain user' do
- expect(user).not_to be_admin
- expect(user).not_to be_moderator
- end
- end
-
- context 'when user is not a moderator' do
- let(:moderator) { false }
-
- it 'does not change any fields' do
- expect(user).not_to be_admin
- expect(user).not_to be_moderator
- end
- end
- end
- end
-
- describe '#active_for_authentication?' do
- subject { user.active_for_authentication? }
- let(:user) { Fabricate(:user, disabled: disabled, confirmed_at: confirmed_at) }
-
- context 'when user is disabled' do
- let(:disabled) { true }
-
- context 'when user is confirmed' do
- let(:confirmed_at) { Time.zone.now }
-
- it { is_expected.to be true }
- end
-
- context 'when user is not confirmed' do
- let(:confirmed_at) { nil }
-
- it { is_expected.to be false }
- end
- end
-
- context 'when user is not disabled' do
- let(:disabled) { false }
-
- context 'when user is confirmed' do
- let(:confirmed_at) { Time.zone.now }
-
- it { is_expected.to be true }
- end
-
- context 'when user is not confirmed' do
- let(:confirmed_at) { nil }
-
- it { is_expected.to be false }
- end
- end
- end
-end
diff --git a/spec/models/web/push_subscription_spec.rb b/spec/models/web/push_subscription_spec.rb
deleted file mode 100644
index c6665611..00000000
--- a/spec/models/web/push_subscription_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Web::PushSubscription, type: :model do
- let(:alerts) { { mention: true, reblog: false, follow: true, follow_request: false, favourite: true } }
- let(:push_subscription) { Web::PushSubscription.new(data: { alerts: alerts }) }
-
- describe '#pushable?' do
- it 'obeys alert settings' do
- expect(push_subscription.send(:pushable?, Notification.new(activity_type: 'Mention'))).to eq true
- expect(push_subscription.send(:pushable?, Notification.new(activity_type: 'Status'))).to eq false
- expect(push_subscription.send(:pushable?, Notification.new(activity_type: 'Follow'))).to eq true
- expect(push_subscription.send(:pushable?, Notification.new(activity_type: 'FollowRequest'))).to eq false
- expect(push_subscription.send(:pushable?, Notification.new(activity_type: 'Favourite'))).to eq true
- end
- end
-end
diff --git a/spec/models/web/setting_spec.rb b/spec/models/web/setting_spec.rb
deleted file mode 100644
index 6657d403..00000000
--- a/spec/models/web/setting_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe Web::Setting, type: :model do
-end
diff --git a/spec/policies/account_moderation_note_policy_spec.rb b/spec/policies/account_moderation_note_policy_spec.rb
deleted file mode 100644
index bb7af94e..00000000
--- a/spec/policies/account_moderation_note_policy_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe AccountModerationNotePolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :create? do
- context 'staff' do
- it 'grants to create' do
- expect(subject).to permit(admin, AccountModerationNotePolicy)
- end
- end
-
- context 'not staff' do
- it 'denies to create' do
- expect(subject).to_not permit(john, AccountModerationNotePolicy)
- end
- end
- end
-
- permissions :destroy? do
- let(:account_moderation_note) do
- Fabricate(:account_moderation_note,
- account: john,
- target_account: Fabricate(:account))
- end
-
- context 'admin' do
- it 'grants to destroy' do
- expect(subject).to permit(admin, AccountModerationNotePolicy)
- end
- end
-
- context 'owner' do
- it 'grants to destroy' do
- expect(subject).to permit(john, account_moderation_note)
- end
- end
-
- context 'neither admin nor owner' do
- let(:kevin) { Fabricate(:user).account }
-
- it 'denies to destroy' do
- expect(subject).to_not permit(kevin, account_moderation_note)
- end
- end
- end
-end
diff --git a/spec/policies/account_policy_spec.rb b/spec/policies/account_policy_spec.rb
deleted file mode 100644
index 6648b088..00000000
--- a/spec/policies/account_policy_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe AccountPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index?, :show?, :unsuspend?, :unsilence?, :remove_avatar?, :remove_header? do
- context 'staff' do
- it 'permits' do
- expect(subject).to permit(admin)
- end
- end
-
- context 'not staff' do
- it 'denies' do
- expect(subject).to_not permit(john)
- end
- end
- end
-
- permissions :redownload?, :subscribe?, :unsubscribe? do
- context 'admin' do
- it 'permits' do
- expect(subject).to permit(admin)
- end
- end
-
- context 'not admin' do
- it 'denies' do
- expect(subject).to_not permit(john)
- end
- end
- end
-
- permissions :suspend?, :silence? do
- let(:staff) { Fabricate(:user, admin: true).account }
-
- context 'staff' do
- context 'record is staff' do
- it 'denies' do
- expect(subject).to_not permit(admin, staff)
- end
- end
-
- context 'record is not staff' do
- it 'permits' do
- expect(subject).to permit(admin, john)
- end
- end
- end
-
- context 'not staff' do
- it 'denies' do
- expect(subject).to_not permit(john, Account)
- end
- end
- end
-
- permissions :memorialize? do
- let(:other_admin) { Fabricate(:user, admin: true).account }
-
- context 'admin' do
- context 'record is admin' do
- it 'denies' do
- expect(subject).to_not permit(admin, other_admin)
- end
- end
-
- context 'record is not admin' do
- it 'permits' do
- expect(subject).to permit(admin, john)
- end
- end
- end
-
- context 'not admin' do
- it 'denies' do
- expect(subject).to_not permit(john, Account)
- end
- end
- end
-end
diff --git a/spec/policies/backup_policy_spec.rb b/spec/policies/backup_policy_spec.rb
deleted file mode 100644
index 80407e12..00000000
--- a/spec/policies/backup_policy_spec.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe BackupPolicy do
- let(:subject) { described_class }
- let(:john) { Fabricate(:user).account }
-
- permissions :create? do
- context 'not user_signed_in?' do
- it 'denies' do
- expect(subject).to_not permit(nil, Backup)
- end
- end
-
- context 'user_signed_in?' do
- context 'no backups' do
- it 'permits' do
- expect(subject).to permit(john, Backup)
- end
- end
-
- context 'backups are too old' do
- it 'permits' do
- travel(-8.days) do
- Fabricate(:backup, user: john.user)
- end
-
- expect(subject).to permit(john, Backup)
- end
- end
-
- context 'backups are newer' do
- it 'denies' do
- travel(-3.days) do
- Fabricate(:backup, user: john.user)
- end
-
- expect(subject).to_not permit(john, Backup)
- end
- end
- end
- end
-end
diff --git a/spec/policies/custom_emoji_policy_spec.rb b/spec/policies/custom_emoji_policy_spec.rb
deleted file mode 100644
index 8def8821..00000000
--- a/spec/policies/custom_emoji_policy_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe CustomEmojiPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index?, :enable?, :disable? do
- context 'staff' do
- it 'permits' do
- expect(subject).to permit(admin, CustomEmoji)
- end
- end
-
- context 'not staff' do
- it 'denies' do
- expect(subject).to_not permit(john, CustomEmoji)
- end
- end
- end
-
- permissions :create?, :update?, :copy?, :destroy? do
- context 'admin' do
- it 'permits' do
- expect(subject).to permit(admin, CustomEmoji)
- end
- end
-
- context 'not admin' do
- it 'denies' do
- expect(subject).to_not permit(john, CustomEmoji)
- end
- end
- end
-end
diff --git a/spec/policies/domain_block_policy_spec.rb b/spec/policies/domain_block_policy_spec.rb
deleted file mode 100644
index aea50ec0..00000000
--- a/spec/policies/domain_block_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe DomainBlockPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index?, :show?, :create?, :destroy? do
- context 'admin' do
- it 'permits' do
- expect(subject).to permit(admin, DomainBlock)
- end
- end
-
- context 'not admin' do
- it 'denies' do
- expect(subject).to_not permit(john, DomainBlock)
- end
- end
- end
-end
diff --git a/spec/policies/email_domain_block_policy_spec.rb b/spec/policies/email_domain_block_policy_spec.rb
deleted file mode 100644
index a3e825e0..00000000
--- a/spec/policies/email_domain_block_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe EmailDomainBlockPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index?, :create?, :destroy? do
- context 'admin' do
- it 'permits' do
- expect(subject).to permit(admin, EmailDomainBlock)
- end
- end
-
- context 'not admin' do
- it 'denies' do
- expect(subject).to_not permit(john, EmailDomainBlock)
- end
- end
- end
-end
diff --git a/spec/policies/instance_policy_spec.rb b/spec/policies/instance_policy_spec.rb
deleted file mode 100644
index 77a3bde3..00000000
--- a/spec/policies/instance_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe InstancePolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index? do
- context 'admin' do
- it 'permits' do
- expect(subject).to permit(admin, Instance)
- end
- end
-
- context 'not admin' do
- it 'denies' do
- expect(subject).to_not permit(john, Instance)
- end
- end
- end
-end
diff --git a/spec/policies/invite_policy_spec.rb b/spec/policies/invite_policy_spec.rb
deleted file mode 100644
index e391455b..00000000
--- a/spec/policies/invite_policy_spec.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe InvitePolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index? do
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, Invite)
- end
- end
- end
-
- permissions :create? do
- context 'min_required_role?' do
- it 'permits' do
- allow_any_instance_of(described_class).to receive(:min_required_role?) { true }
- expect(subject).to permit(john, Invite)
- end
- end
-
- context 'not min_required_role?' do
- it 'denies' do
- allow_any_instance_of(described_class).to receive(:min_required_role?) { false }
- expect(subject).to_not permit(john, Invite)
- end
- end
- end
-
- permissions :deactivate_all? do
- context 'admin?' do
- it 'permits' do
- expect(subject).to permit(admin, Invite)
- end
- end
-
- context 'not admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, Invite)
- end
- end
- end
-
- permissions :destroy? do
- context 'owner?' do
- it 'permits' do
- expect(subject).to permit(john, Fabricate(:invite, user: john.user))
- end
- end
-
- context 'not owner?' do
- context 'Setting.min_invite_role == "admin"' do
- before do
- Setting.min_invite_role = 'admin'
- end
-
- context 'admin?' do
- it 'permits' do
- expect(subject).to permit(admin, Fabricate(:invite))
- end
- end
-
- context 'not admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, Fabricate(:invite))
- end
- end
- end
-
- context 'Setting.min_invite_role != "admin"' do
- before do
- Setting.min_invite_role = 'else'
- end
-
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, Fabricate(:invite))
- end
- end
-
- context 'not staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, Fabricate(:invite))
- end
- end
- end
- end
- end
-end
diff --git a/spec/policies/relay_policy_spec.rb b/spec/policies/relay_policy_spec.rb
deleted file mode 100644
index 640f27d5..00000000
--- a/spec/policies/relay_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe RelayPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :update? do
- context 'admin?' do
- it 'permits' do
- expect(subject).to permit(admin, Relay)
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, Relay)
- end
- end
- end
-end
diff --git a/spec/policies/report_note_policy_spec.rb b/spec/policies/report_note_policy_spec.rb
deleted file mode 100644
index 596d7d7a..00000000
--- a/spec/policies/report_note_policy_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe ReportNotePolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :create? do
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, ReportNote)
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, ReportNote)
- end
- end
- end
-
- permissions :destroy? do
- context 'admin?' do
- it 'permit' do
- expect(subject).to permit(admin, ReportNote)
- end
- end
-
- context 'admin?' do
- context 'owner?' do
- it 'permit' do
- report_note = Fabricate(:report_note, account: john)
- expect(subject).to permit(john, report_note)
- end
- end
-
- context '!owner?' do
- it 'denies' do
- report_note = Fabricate(:report_note)
- expect(subject).to_not permit(john, report_note)
- end
- end
- end
- end
-end
diff --git a/spec/policies/report_policy_spec.rb b/spec/policies/report_policy_spec.rb
deleted file mode 100644
index c9ae1e87..00000000
--- a/spec/policies/report_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe ReportPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :update?, :index?, :show? do
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, Report)
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, Report)
- end
- end
- end
-end
diff --git a/spec/policies/settings_policy_spec.rb b/spec/policies/settings_policy_spec.rb
deleted file mode 100644
index 92f1f486..00000000
--- a/spec/policies/settings_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe SettingsPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :update?, :show? do
- context 'admin?' do
- it 'permits' do
- expect(subject).to permit(admin, Settings)
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, Settings)
- end
- end
- end
-end
diff --git a/spec/policies/status_policy_spec.rb b/spec/policies/status_policy_spec.rb
deleted file mode 100644
index 1cddf4ab..00000000
--- a/spec/policies/status_policy_spec.rb
+++ /dev/null
@@ -1,137 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe StatusPolicy, type: :model do
- subject { described_class }
-
- let(:admin) { Fabricate(:user, admin: true) }
- let(:alice) { Fabricate(:account, username: 'alice') }
- let(:bob) { Fabricate(:account, username: 'bob') }
- let(:status) { Fabricate(:status, account: alice) }
-
- permissions :show?, :reblog? do
- it 'grants access when no viewer' do
- expect(subject).to permit(nil, status)
- end
-
- it 'denies access when viewer is blocked' do
- block = Fabricate(:block)
- status.visibility = :private
- status.account = block.target_account
-
- expect(subject).to_not permit(block.account, status)
- end
- end
-
- permissions :show? do
- it 'grants access when direct and account is viewer' do
- status.visibility = :direct
-
- expect(subject).to permit(status.account, status)
- end
-
- it 'grants access when direct and viewer is mentioned' do
- status.visibility = :direct
- status.mentions = [Fabricate(:mention, account: alice)]
-
- expect(subject).to permit(alice, status)
- end
-
- it 'denies access when direct and viewer is not mentioned' do
- viewer = Fabricate(:account)
- status.visibility = :direct
-
- expect(subject).to_not permit(viewer, status)
- end
-
- it 'grants access when private and account is viewer' do
- status.visibility = :private
-
- expect(subject).to permit(status.account, status)
- end
-
- it 'grants access when private and account is following viewer' do
- follow = Fabricate(:follow)
- status.visibility = :private
- status.account = follow.target_account
-
- expect(subject).to permit(follow.account, status)
- end
-
- it 'grants access when private and viewer is mentioned' do
- status.visibility = :private
- status.mentions = [Fabricate(:mention, account: alice)]
-
- expect(subject).to permit(alice, status)
- end
-
- it 'denies access when private and viewer is not mentioned or followed' do
- viewer = Fabricate(:account)
- status.visibility = :private
-
- expect(subject).to_not permit(viewer, status)
- end
- end
-
- permissions :reblog? do
- it 'denies access when private' do
- viewer = Fabricate(:account)
- status.visibility = :private
-
- expect(subject).to_not permit(viewer, status)
- end
-
- it 'denies access when direct' do
- viewer = Fabricate(:account)
- status.visibility = :direct
-
- expect(subject).to_not permit(viewer, status)
- end
- end
-
- permissions :destroy?, :unreblog? do
- it 'grants access when account is deleter' do
- expect(subject).to permit(status.account, status)
- end
-
- it 'grants access when account is admin' do
- expect(subject).to permit(admin.account, status)
- end
-
- it 'denies access when account is not deleter' do
- expect(subject).to_not permit(bob, status)
- end
-
- it 'denies access when no deleter' do
- expect(subject).to_not permit(nil, status)
- end
- end
-
- permissions :favourite? do
- it 'grants access when viewer is not blocked' do
- follow = Fabricate(:follow)
- status.account = follow.target_account
-
- expect(subject).to permit(follow.account, status)
- end
-
- it 'denies when viewer is blocked' do
- block = Fabricate(:block)
- status.account = block.target_account
-
- expect(subject).to_not permit(block.account, status)
- end
- end
-
- permissions :index?, :update? do
- it 'grants access if staff' do
- expect(subject).to permit(admin.account)
- end
-
- it 'denies access unless staff' do
- expect(subject).to_not permit(alice)
- end
- end
-end
diff --git a/spec/policies/subscription_policy_spec.rb b/spec/policies/subscription_policy_spec.rb
deleted file mode 100644
index 21d60c15..00000000
--- a/spec/policies/subscription_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe SubscriptionPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index? do
- context 'admin?' do
- it 'permits' do
- expect(subject).to permit(admin, Subscription)
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, Subscription)
- end
- end
- end
-end
diff --git a/spec/policies/tag_policy_spec.rb b/spec/policies/tag_policy_spec.rb
deleted file mode 100644
index c7afaa7c..00000000
--- a/spec/policies/tag_policy_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe TagPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :index?, :hide?, :unhide? do
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, Tag)
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, Tag)
- end
- end
- end
-end
diff --git a/spec/policies/user_policy_spec.rb b/spec/policies/user_policy_spec.rb
deleted file mode 100644
index e37904f0..00000000
--- a/spec/policies/user_policy_spec.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-require 'pundit/rspec'
-
-RSpec.describe UserPolicy do
- let(:subject) { described_class }
- let(:admin) { Fabricate(:user, admin: true).account }
- let(:john) { Fabricate(:user).account }
-
- permissions :reset_password?, :change_email? do
- context 'staff?' do
- context '!record.staff?' do
- it 'permits' do
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context 'record.staff?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :disable_2fa? do
- context 'admin?' do
- context '!record.staff?' do
- it 'permits' do
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context 'record.staff?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :confirm? do
- context 'staff?' do
- context '!record.confirmed?' do
- it 'permits' do
- john.user.update(confirmed_at: nil)
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context 'record.confirmed?' do
- it 'denies' do
- john.user.confirm!
- expect(subject).to_not permit(admin, john.user)
- end
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :enable? do
- context 'staff?' do
- it 'permits' do
- expect(subject).to permit(admin, User)
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :disable? do
- context 'staff?' do
- context '!record.admin?' do
- it 'permits' do
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context 'record.admin?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!staff?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :promote? do
- context 'admin?' do
- context 'promoteable?' do
- it 'permits' do
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context '!promoteable?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-
- permissions :demote? do
- context 'admin?' do
- context '!record.admin?' do
- context 'demoteable?' do
- it 'permits' do
- john.user.update(moderator: true)
- expect(subject).to permit(admin, john.user)
- end
- end
-
- context '!demoteable?' do
- it 'denies' do
- expect(subject).to_not permit(admin, john.user)
- end
- end
- end
-
- context 'record.admin?' do
- it 'denies' do
- expect(subject).to_not permit(admin, admin.user)
- end
- end
- end
-
- context '!admin?' do
- it 'denies' do
- expect(subject).to_not permit(john, User)
- end
- end
- end
-end
diff --git a/spec/presenters/account_relationships_presenter_spec.rb b/spec/presenters/account_relationships_presenter_spec.rb
deleted file mode 100644
index f8b048d3..00000000
--- a/spec/presenters/account_relationships_presenter_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe AccountRelationshipsPresenter do
- describe '.initialize' do
- before do
- allow(Account).to receive(:following_map).with(account_ids, current_account_id).and_return(default_map)
- allow(Account).to receive(:followed_by_map).with(account_ids, current_account_id).and_return(default_map)
- allow(Account).to receive(:blocking_map).with(account_ids, current_account_id).and_return(default_map)
- allow(Account).to receive(:muting_map).with(account_ids, current_account_id).and_return(default_map)
- allow(Account).to receive(:requested_map).with(account_ids, current_account_id).and_return(default_map)
- allow(Account).to receive(:domain_blocking_map).with(account_ids, current_account_id).and_return(default_map)
- end
-
- let(:presenter) { AccountRelationshipsPresenter.new(account_ids, current_account_id, options) }
- let(:current_account_id) { Fabricate(:account).id }
- let(:account_ids) { [Fabricate(:account).id] }
- let(:default_map) { { 1 => true } }
-
- context 'options are not set' do
- let(:options) { {} }
-
- it 'sets default maps' do
- expect(presenter.following).to eq default_map
- expect(presenter.followed_by).to eq default_map
- expect(presenter.blocking).to eq default_map
- expect(presenter.muting).to eq default_map
- expect(presenter.requested).to eq default_map
- expect(presenter.domain_blocking).to eq default_map
- end
- end
-
- context 'options[:following_map] is set' do
- let(:options) { { following_map: { 2 => true } } }
-
- it 'sets @following merged with default_map and options[:following_map]' do
- expect(presenter.following).to eq default_map.merge(options[:following_map])
- end
- end
-
- context 'options[:followed_by_map] is set' do
- let(:options) { { followed_by_map: { 3 => true } } }
-
- it 'sets @followed_by merged with default_map and options[:followed_by_map]' do
- expect(presenter.followed_by).to eq default_map.merge(options[:followed_by_map])
- end
- end
-
- context 'options[:blocking_map] is set' do
- let(:options) { { blocking_map: { 4 => true } } }
-
- it 'sets @blocking merged with default_map and options[:blocking_map]' do
- expect(presenter.blocking).to eq default_map.merge(options[:blocking_map])
- end
- end
-
- context 'options[:muting_map] is set' do
- let(:options) { { muting_map: { 5 => true } } }
-
- it 'sets @muting merged with default_map and options[:muting_map]' do
- expect(presenter.muting).to eq default_map.merge(options[:muting_map])
- end
- end
-
- context 'options[:requested_map] is set' do
- let(:options) { { requested_map: { 6 => true } } }
-
- it 'sets @requested merged with default_map and options[:requested_map]' do
- expect(presenter.requested).to eq default_map.merge(options[:requested_map])
- end
- end
-
- context 'options[:domain_blocking_map] is set' do
- let(:options) { { domain_blocking_map: { 7 => true } } }
-
- it 'sets @domain_blocking merged with default_map and options[:domain_blocking_map]' do
- expect(presenter.domain_blocking).to eq default_map.merge(options[:domain_blocking_map])
- end
- end
- end
-end
diff --git a/spec/presenters/instance_presenter_spec.rb b/spec/presenters/instance_presenter_spec.rb
deleted file mode 100644
index df3fc0f0..00000000
--- a/spec/presenters/instance_presenter_spec.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-require 'rails_helper'
-
-describe InstancePresenter do
- let(:instance_presenter) { InstancePresenter.new }
-
- context do
- around do |example|
- site_description = Setting.site_description
- example.run
- Setting.site_description = site_description
- end
-
- it "delegates site_description to Setting" do
- Setting.site_description = "Site desc"
-
- expect(instance_presenter.site_description).to eq "Site desc"
- end
- end
-
- context do
- around do |example|
- site_extended_description = Setting.site_extended_description
- example.run
- Setting.site_extended_description = site_extended_description
- end
-
- it "delegates site_extended_description to Setting" do
- Setting.site_extended_description = "Extended desc"
-
- expect(instance_presenter.site_extended_description).to eq "Extended desc"
- end
- end
-
- context do
- around do |example|
- site_contact_email = Setting.site_contact_email
- example.run
- Setting.site_contact_email = site_contact_email
- end
-
- it "delegates contact_email to Setting" do
- Setting.site_contact_email = "admin@example.com"
-
- expect(instance_presenter.site_contact_email).to eq "admin@example.com"
- end
- end
-
- describe "contact_account" do
- around do |example|
- site_contact_username = Setting.site_contact_username
- example.run
- Setting.site_contact_username = site_contact_username
- end
-
- it "returns the account for the site contact username" do
- Setting.site_contact_username = "aaa"
- account = Fabricate(:account, username: "aaa")
-
- expect(instance_presenter.contact_account).to eq(account)
- end
- end
-
- describe "user_count" do
- it "returns the number of site users" do
- Rails.cache.write 'user_count', 123
-
- expect(instance_presenter.user_count).to eq(123)
- end
- end
-
- describe "status_count" do
- it "returns the number of local statuses" do
- Rails.cache.write 'local_status_count', 234
-
- expect(instance_presenter.status_count).to eq(234)
- end
- end
-
- describe "domain_count" do
- it "returns the number of known domains" do
- Rails.cache.write 'distinct_domain_count', 345
-
- expect(instance_presenter.domain_count).to eq(345)
- end
- end
-
- describe '#version_number' do
- it 'returns GabSocial::Version' do
- expect(instance_presenter.version_number).to be(GabSocial::Version)
- end
- end
-
- describe '#source_url' do
- it 'returns "https://code.gab.com/gab/social/gab-social"' do
- expect(instance_presenter.source_url).to eq('https://code.gab.com/gab/social/gab-social')
- end
- end
-
- describe '#thumbnail' do
- it 'returns SiteUpload' do
- thumbnail = Fabricate(:site_upload, var: 'thumbnail')
- expect(instance_presenter.thumbnail).to eq(thumbnail)
- end
- end
-
- describe '#hero' do
- it 'returns SiteUpload' do
- hero = Fabricate(:site_upload, var: 'hero')
- expect(instance_presenter.hero).to eq(hero)
- end
- end
-
- describe '#mascot' do
- it 'returns SiteUpload' do
- mascot = Fabricate(:site_upload, var: 'mascot')
- expect(instance_presenter.mascot).to eq(mascot)
- end
- end
-end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
deleted file mode 100644
index 7407e60a..00000000
--- a/spec/rails_helper.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-ENV['RAILS_ENV'] ||= 'test'
-require File.expand_path('../../config/environment', __FILE__)
-
-abort("The Rails environment is running in production mode!") if Rails.env.production?
-
-require 'spec_helper'
-require 'rspec/rails'
-require 'webmock/rspec'
-require 'paperclip/matchers'
-require 'capybara/rspec'
-
-Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
-
-ActiveRecord::Migration.maintain_test_schema!
-WebMock.disable_net_connect!
-Redis.current = Redis::Namespace.new("gabsocial_test#{ENV['TEST_ENV_NUMBER']}", redis: Redis.current)
-Sidekiq::Testing.inline!
-Sidekiq::Logging.logger = nil
-
-Devise::Test::ControllerHelpers.module_eval do
- alias_method :original_sign_in, :sign_in
-
- def sign_in(resource, _deprecated = nil, scope: nil)
- original_sign_in(resource, scope: scope)
-
- SessionActivation.deactivate warden.cookies.signed['_session_id']
-
- warden.cookies.signed['_session_id'] = {
- value: resource.activate_session(warden.request),
- expires: 1.year.from_now,
- httponly: true,
- }
- end
-end
-
-RSpec.configure do |config|
- config.fixture_path = "#{::Rails.root}/spec/fixtures"
- config.use_transactional_fixtures = true
- config.order = 'random'
- config.infer_spec_type_from_file_location!
- config.filter_rails_from_backtrace!
-
- config.include Devise::Test::ControllerHelpers, type: :controller
- config.include Devise::Test::ControllerHelpers, type: :view
- config.include Paperclip::Shoulda::Matchers
- config.include ActiveSupport::Testing::TimeHelpers
-
- config.before :each, type: :feature do
- https = ENV['LOCAL_HTTPS'] == 'true'
- Capybara.app_host = "http#{https ? 's' : ''}://#{ENV.fetch('LOCAL_DOMAIN')}"
- end
-
- config.before :each, type: :controller do
- stub_jsonld_contexts!
- end
-
- config.before :each, type: :service do
- stub_jsonld_contexts!
- end
-
- config.after :each do
- Rails.cache.clear
-
- keys = Redis.current.keys
- Redis.current.del(keys) if keys.any?
- end
-end
-
-RSpec::Sidekiq.configure do |config|
- config.warn_when_jobs_not_processed_by_sidekiq = false
-end
-
-def request_fixture(name)
- File.read(Rails.root.join('spec', 'fixtures', 'requests', name))
-end
-
-def attachment_fixture(name)
- File.open(Rails.root.join('spec', 'fixtures', 'files', name))
-end
-
-def stub_jsonld_contexts!
- stub_request(:get, 'https://www.w3.org/ns/activitystreams').to_return(request_fixture('json-ld.activitystreams.txt'))
- stub_request(:get, 'https://w3id.org/identity/v1').to_return(request_fixture('json-ld.identity.txt'))
- stub_request(:get, 'https://w3id.org/security/v1').to_return(request_fixture('json-ld.security.txt'))
-end
diff --git a/spec/requests/account_show_page_spec.rb b/spec/requests/account_show_page_spec.rb
deleted file mode 100644
index 4e51cf7e..00000000
--- a/spec/requests/account_show_page_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'The account show page' do
- it 'Has an h-feed with correct number of h-entry objects in it' do
- alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
- _status = Fabricate(:status, account: alice, text: 'Hello World')
- _status2 = Fabricate(:status, account: alice, text: 'Hello World Again')
- _status3 = Fabricate(:status, account: alice, text: 'Are You Still There World?')
-
- get '/@alice'
-
- expect(h_feed_entries.size).to eq(3)
- end
-
- it 'has valid opengraph tags' do
- alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
- _status = Fabricate(:status, account: alice, text: 'Hello World')
-
- get '/@alice'
-
- expect(head_meta_content('og:title')).to match alice.display_name
- expect(head_meta_content('og:type')).to eq 'profile'
- expect(head_meta_content('og:image')).to match '.+'
- expect(head_meta_content('og:url')).to match 'http://.+'
- end
-
- def head_meta_content(property)
- head_section.meta("[@property='#{property}']")[:content]
- end
-
- def head_section
- Nokogiri::Slop(response.body).html.head
- end
-
- def h_feed_entries
- Nokogiri::HTML(response.body).search('.h-feed .h-entry')
- end
-end
diff --git a/spec/requests/catch_all_route_request_spec.rb b/spec/requests/catch_all_route_request_spec.rb
deleted file mode 100644
index 22ce1cf5..00000000
--- a/spec/requests/catch_all_route_request_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require "rails_helper"
-
-describe "The catch all route" do
- describe "with a simple value" do
- it "returns a 404 page as html" do
- get "/test"
-
- expect(response.status).to eq 404
- expect(response.content_type).to eq "text/html"
- end
- end
-
- describe "with an implied format" do
- it "returns a 404 page as html" do
- get "/test.test"
-
- expect(response.status).to eq 404
- expect(response.content_type).to eq "text/html"
- end
- end
-end
diff --git a/spec/requests/host_meta_request_spec.rb b/spec/requests/host_meta_request_spec.rb
deleted file mode 100644
index beb33a85..00000000
--- a/spec/requests/host_meta_request_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require "rails_helper"
-
-describe "The host_meta route" do
- describe "requested without accepts headers" do
- it "returns an xml response" do
- get host_meta_url
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq "application/xrd+xml"
- end
- end
-end
diff --git a/spec/requests/link_headers_spec.rb b/spec/requests/link_headers_spec.rb
deleted file mode 100644
index 3dc408d9..00000000
--- a/spec/requests/link_headers_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'Link headers' do
- describe 'on the account show page' do
- let(:account) { Fabricate(:account, username: 'test') }
-
- before do
- get short_account_path(username: account)
- end
-
- it 'contains webfinger url in link header' do
- link_header = link_header_with_type('application/xrd+xml')
-
- expect(link_header.href).to match 'http://www.example.com/.well-known/webfinger?resource=acct%3Atest%40cb6e6126.ngrok.io'
- expect(link_header.attr_pairs.first).to eq %w(rel lrdd)
- end
-
- it 'contains atom url in link header' do
- link_header = link_header_with_type('application/atom+xml')
-
- expect(link_header.href).to eq 'http://www.example.com/users/test.atom'
- expect(link_header.attr_pairs.first).to eq %w(rel alternate)
- end
-
- def link_header_with_type(type)
- response.headers['Link'].links.find do |link|
- link.attr_pairs.any? { |pair| pair == ['type', type] }
- end
- end
- end
-end
diff --git a/spec/requests/localization_spec.rb b/spec/requests/localization_spec.rb
deleted file mode 100644
index 496a885e..00000000
--- a/spec/requests/localization_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'Localization' do
- after(:all) do
- I18n.locale = I18n.default_locale
- end
-
- it 'uses a specific region when provided' do
- headers = { 'Accept-Language' => 'zh-HK' }
-
- get "/about", headers: headers
-
- expect(response.body).to include(
- I18n.t('about.tagline', locale: 'zh-HK')
- )
- end
-
- it 'falls back to a locale when region missing' do
- headers = { 'Accept-Language' => 'es-FAKE' }
-
- get "/about", headers: headers
-
- expect(response.body).to include(
- I18n.t('about.tagline', locale: 'es')
- )
- end
- it 'falls back to english when locale is missing' do
- headers = { 'Accept-Language' => '12-FAKE' }
-
- get "/about", headers: headers
-
- expect(response.body).to include(
- I18n.t('about.tagline', locale: 'en')
- )
- end
-end
diff --git a/spec/requests/webfinger_request_spec.rb b/spec/requests/webfinger_request_spec.rb
deleted file mode 100644
index 7f9e1162..00000000
--- a/spec/requests/webfinger_request_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'rails_helper'
-
-describe 'The webfinger route' do
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- describe 'requested with standard accepts headers' do
- it 'returns a json response' do
- get webfinger_url(resource: alice.to_webfinger_s)
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/jrd+json'
- end
- end
-
- describe 'asking for xml format' do
- it 'returns an xml response for xml format' do
- get webfinger_url(resource: alice.to_webfinger_s, format: :xml)
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/xrd+xml'
- end
-
- it 'returns an xml response for xml accept header' do
- headers = { 'HTTP_ACCEPT' => 'application/xrd+xml' }
- get webfinger_url(resource: alice.to_webfinger_s), headers: headers
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/xrd+xml'
- end
- end
-
- describe 'asking for json format' do
- it 'returns a json response for json format' do
- get webfinger_url(resource: alice.to_webfinger_s, format: :json)
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/jrd+json'
- end
-
- it 'returns a json response for json accept header' do
- headers = { 'HTTP_ACCEPT' => 'application/jrd+json' }
- get webfinger_url(resource: alice.to_webfinger_s), headers: headers
-
- expect(response).to have_http_status(200)
- expect(response.content_type).to eq 'application/jrd+json'
- end
- end
-end
diff --git a/spec/routing/accounts_routing_spec.rb b/spec/routing/accounts_routing_spec.rb
deleted file mode 100644
index d04cb27f..00000000
--- a/spec/routing/accounts_routing_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'rails_helper'
-
-describe 'Routes under accounts/' do
- describe 'the route for accounts who are followers of an account' do
- it 'routes to the followers action with the right username' do
- expect(get('/users/name/followers')).
- to route_to('follower_accounts#index', account_username: 'name')
- end
- end
-
- describe 'the route for accounts who are followed by an account' do
- it 'routes to the following action with the right username' do
- expect(get('/users/name/following')).
- to route_to('following_accounts#index', account_username: 'name')
- end
- end
-
- describe 'the route for following an account' do
- it 'routes to the follow create action with the right username' do
- expect(post('/users/name/follow')).
- to route_to('account_follow#create', account_username: 'name')
- end
- end
-
- describe 'the route for unfollowing an account' do
- it 'routes to the unfollow create action with the right username' do
- expect(post('/users/name/unfollow')).
- to route_to('account_unfollow#create', account_username: 'name')
- end
- end
-end
diff --git a/spec/routing/api_routing_spec.rb b/spec/routing/api_routing_spec.rb
deleted file mode 100644
index 2683ccb8..00000000
--- a/spec/routing/api_routing_spec.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'API routes' do
- describe 'Credentials routes' do
- it 'routes to verify credentials' do
- expect(get('/api/v1/accounts/verify_credentials')).
- to route_to('api/v1/accounts/credentials#show')
- end
-
- it 'routes to update credentials' do
- expect(patch('/api/v1/accounts/update_credentials')).
- to route_to('api/v1/accounts/credentials#update')
- end
- end
-
- describe 'Account routes' do
- it 'routes to statuses' do
- expect(get('/api/v1/accounts/user/statuses')).
- to route_to('api/v1/accounts/statuses#index', account_id: 'user')
- end
-
- it 'routes to followers' do
- expect(get('/api/v1/accounts/user/followers')).
- to route_to('api/v1/accounts/follower_accounts#index', account_id: 'user')
- end
-
- it 'routes to following' do
- expect(get('/api/v1/accounts/user/following')).
- to route_to('api/v1/accounts/following_accounts#index', account_id: 'user')
- end
-
- it 'routes to search' do
- expect(get('/api/v1/accounts/search')).
- to route_to('api/v1/accounts/search#show')
- end
-
- it 'routes to relationships' do
- expect(get('/api/v1/accounts/relationships')).
- to route_to('api/v1/accounts/relationships#index')
- end
- end
-
- describe 'Statuses routes' do
- it 'routes reblogged_by' do
- expect(get('/api/v1/statuses/123/reblogged_by')).
- to route_to('api/v1/statuses/reblogged_by_accounts#index', status_id: '123')
- end
-
- it 'routes favourited_by' do
- expect(get('/api/v1/statuses/123/favourited_by')).
- to route_to('api/v1/statuses/favourited_by_accounts#index', status_id: '123')
- end
-
- it 'routes reblog' do
- expect(post('/api/v1/statuses/123/reblog')).
- to route_to('api/v1/statuses/reblogs#create', status_id: '123')
- end
-
- it 'routes unreblog' do
- expect(post('/api/v1/statuses/123/unreblog')).
- to route_to('api/v1/statuses/reblogs#destroy', status_id: '123')
- end
-
- it 'routes favourite' do
- expect(post('/api/v1/statuses/123/favourite')).
- to route_to('api/v1/statuses/favourites#create', status_id: '123')
- end
-
- it 'routes unfavourite' do
- expect(post('/api/v1/statuses/123/unfavourite')).
- to route_to('api/v1/statuses/favourites#destroy', status_id: '123')
- end
-
- it 'routes mute' do
- expect(post('/api/v1/statuses/123/mute')).
- to route_to('api/v1/statuses/mutes#create', status_id: '123')
- end
-
- it 'routes unmute' do
- expect(post('/api/v1/statuses/123/unmute')).
- to route_to('api/v1/statuses/mutes#destroy', status_id: '123')
- end
- end
-
- describe 'Timeline routes' do
- it 'routes to home timeline' do
- expect(get('/api/v1/timelines/home')).
- to route_to('api/v1/timelines/home#show')
- end
-
- it 'routes to public timeline' do
- expect(get('/api/v1/timelines/public')).
- to route_to('api/v1/timelines/public#show')
- end
-
- it 'routes to tag timeline' do
- expect(get('/api/v1/timelines/tag/test')).
- to route_to('api/v1/timelines/tag#show', id: 'test')
- end
- end
-end
diff --git a/spec/routing/well_known_routes_spec.rb b/spec/routing/well_known_routes_spec.rb
deleted file mode 100644
index 2e25605c..00000000
--- a/spec/routing/well_known_routes_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe 'the host-meta route' do
- it 'routes to correct place with xml format' do
- expect(get('/.well-known/host-meta')).
- to route_to('well_known/host_meta#show', format: 'xml')
- end
-end
-
-describe 'the webfinger route' do
- it 'routes to correct place with json format' do
- expect(get('/.well-known/webfinger')).
- to route_to('well_known/webfinger#show')
- end
-end
diff --git a/spec/serializers/activitypub/note_spec.rb b/spec/serializers/activitypub/note_spec.rb
deleted file mode 100644
index 55bfbc16..00000000
--- a/spec/serializers/activitypub/note_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ActivityPub::NoteSerializer do
- let!(:account) { Fabricate(:account) }
- let!(:other) { Fabricate(:account) }
- let!(:parent) { Fabricate(:status, account: account, visibility: :public) }
- let!(:reply1) { Fabricate(:status, account: account, thread: parent, visibility: :public) }
- let!(:reply2) { Fabricate(:status, account: account, thread: parent, visibility: :public) }
- let!(:reply3) { Fabricate(:status, account: other, thread: parent, visibility: :public) }
- let!(:reply4) { Fabricate(:status, account: account, thread: parent, visibility: :public) }
- let!(:reply5) { Fabricate(:status, account: account, thread: parent, visibility: :direct) }
-
- before(:each) do
- @serialization = ActiveModelSerializers::SerializableResource.new(parent, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
- end
-
- subject { JSON.parse(@serialization.to_json) }
-
- it 'has a Note type' do
- expect(subject['type']).to eql('Note')
- end
-
- it 'has a replies collection' do
- expect(subject['replies']['type']).to eql('Collection')
- end
-
- it 'has a replies collection with a first Page' do
- expect(subject['replies']['first']['type']).to eql('CollectionPage')
- end
-
- it 'includes public self-replies in its replies collection' do
- expect(subject['replies']['first']['items']).to include(reply1.uri, reply2.uri, reply4.uri)
- end
-
- it 'does not include replies from others in its replies collection' do
- expect(subject['replies']['first']['items']).to_not include(reply3.uri)
- end
-
- it 'does not include replies with direct visibility in its replies collection' do
- expect(subject['replies']['first']['items']).to_not include(reply5.uri)
- end
-end
diff --git a/spec/services/account_search_service_spec.rb b/spec/services/account_search_service_spec.rb
deleted file mode 100644
index 7b071b37..00000000
--- a/spec/services/account_search_service_spec.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-require 'rails_helper'
-
-describe AccountSearchService, type: :service do
- describe '.call' do
- describe 'with a query to ignore' do
- it 'returns empty array for missing query' do
- results = subject.call('', nil, limit: 10)
-
- expect(results).to eq []
- end
- it 'returns empty array for hashtag query' do
- results = subject.call('#tag', nil, limit: 10)
-
- expect(results).to eq []
- end
- it 'returns empty array for limit zero' do
- Fabricate(:account, username: 'match')
- results = subject.call('match', nil, limit: 0)
-
- expect(results).to eq []
- end
- end
-
- describe 'searching for a simple term that is not an exact match' do
- it 'does not return a nil entry in the array for the exact match' do
- match = Fabricate(:account, username: 'matchingusername')
-
- results = subject.call('match', nil, limit: 5)
- expect(results).to eq [match]
- end
- end
-
- describe 'searching local and remote users' do
- describe "when only '@'" do
- before do
- allow(Account).to receive(:find_local)
- allow(Account).to receive(:search_for)
- subject.call('@', nil, limit: 10)
- end
-
- it 'uses find_local with empty query to look for local accounts' do
- expect(Account).to have_received(:find_local).with('')
- end
- end
-
- describe 'when no domain' do
- before do
- allow(Account).to receive(:find_local)
- allow(Account).to receive(:search_for)
- subject.call('one', nil, limit: 10)
- end
-
- it 'uses find_local to look for local accounts' do
- expect(Account).to have_received(:find_local).with('one')
- end
-
- it 'uses search_for to find matches' do
- expect(Account).to have_received(:search_for).with('one', 10, 0)
- end
- end
-
- describe 'when there is a domain' do
- before do
- allow(Account).to receive(:find_remote)
- end
-
- it 'uses find_remote to look for remote accounts' do
- subject.call('two@example.com', nil, limit: 10)
- expect(Account).to have_received(:find_remote).with('two', 'example.com')
- end
-
- describe 'and there is no account provided' do
- it 'uses search_for to find matches' do
- allow(Account).to receive(:search_for)
- subject.call('two@example.com', nil, limit: 10, resolve: false)
-
- expect(Account).to have_received(:search_for).with('two example.com', 10, 0)
- end
- end
-
- describe 'and there is an account provided' do
- it 'uses advanced_search_for to find matches' do
- account = Fabricate(:account)
- allow(Account).to receive(:advanced_search_for)
- subject.call('two@example.com', account, limit: 10, resolve: false)
-
- expect(Account).to have_received(:advanced_search_for).with('two example.com', account, 10, nil, 0)
- end
- end
- end
- end
-
- describe 'with an exact match' do
- it 'returns exact match first, and does not return duplicates' do
- partial = Fabricate(:account, username: 'exactness')
- exact = Fabricate(:account, username: 'exact')
-
- results = subject.call('exact', nil, limit: 10)
- expect(results.size).to eq 2
- expect(results).to eq [exact, partial]
- end
- end
-
- describe 'when there is a local domain' do
- around do |example|
- before = Rails.configuration.x.local_domain
- example.run
- Rails.configuration.x.local_domain = before
- end
-
- it 'returns exact match first' do
- remote = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e')
- remote_too = Fabricate(:account, username: 'b', domain: 'remote', display_name: 'e')
- exact = Fabricate(:account, username: 'e')
- Rails.configuration.x.local_domain = 'example.com'
-
- results = subject.call('e@example.com', nil, limit: 2)
- expect(results.size).to eq 2
- expect(results).to eq([exact, remote]).or eq([exact, remote_too])
- end
- end
-
- describe 'when there is a domain but no exact match' do
- it 'follows the remote account when resolve is true' do
- service = double(call: nil)
- allow(ResolveAccountService).to receive(:new).and_return(service)
-
- results = subject.call('newuser@remote.com', nil, limit: 10, resolve: true)
- expect(service).to have_received(:call).with('newuser@remote.com')
- end
-
- it 'does not follow the remote account when resolve is false' do
- service = double(call: nil)
- allow(ResolveAccountService).to receive(:new).and_return(service)
-
- results = subject.call('newuser@remote.com', nil, limit: 10, resolve: false)
- expect(service).not_to have_received(:call)
- end
- end
-
- describe 'should not include suspended accounts' do
- it 'returns the fuzzy match first, and does not return suspended exacts' do
- partial = Fabricate(:account, username: 'exactness')
- exact = Fabricate(:account, username: 'exact', suspended: true)
-
- results = subject.call('exact', nil, limit: 10)
- expect(results.size).to eq 1
- expect(results).to eq [partial]
- end
-
- it "does not return suspended remote accounts" do
- remote = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true)
-
- results = subject.call('a@example.com', nil, limit: 2)
- expect(results.size).to eq 0
- expect(results).to eq []
- end
- end
- end
-end
diff --git a/spec/services/activitypub/fetch_remote_account_service_spec.rb b/spec/services/activitypub/fetch_remote_account_service_spec.rb
deleted file mode 100644
index aa13f0a9..00000000
--- a/spec/services/activitypub/fetch_remote_account_service_spec.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
- subject { ActivityPub::FetchRemoteAccountService.new }
-
- let!(:actor) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'https://example.com/alice',
- type: 'Person',
- preferredUsername: 'alice',
- name: 'Alice',
- summary: 'Foo bar',
- inbox: 'http://example.com/alice/inbox',
- }
- end
-
- describe '#call' do
- let(:account) { subject.call('https://example.com/alice', id: true) }
-
- shared_examples 'sets profile data' do
- it 'returns an account' do
- expect(account).to be_an Account
- end
-
- it 'sets display name' do
- expect(account.display_name).to eq 'Alice'
- end
-
- it 'sets note' do
- expect(account.note).to eq 'Foo bar'
- end
-
- it 'sets URL' do
- expect(account.url).to eq 'https://example.com/alice'
- end
- end
-
- context 'when the account does not have a inbox' do
- let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
-
- before do
- actor[:inbox] = nil
-
- stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
- stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
- end
-
- it 'fetches resource' do
- account
- expect(a_request(:get, 'https://example.com/alice')).to have_been_made.once
- end
-
- it 'looks up webfinger' do
- account
- expect(a_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com')).to have_been_made.once
- end
-
- it 'returns nil' do
- expect(account).to be_nil
- end
- end
-
- context 'when URI and WebFinger share the same host' do
- let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
-
- before do
- stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
- stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
- end
-
- it 'fetches resource' do
- account
- expect(a_request(:get, 'https://example.com/alice')).to have_been_made.once
- end
-
- it 'looks up webfinger' do
- account
- expect(a_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com')).to have_been_made.once
- end
-
- it 'sets username and domain from webfinger' do
- expect(account.username).to eq 'alice'
- expect(account.domain).to eq 'example.com'
- end
-
- include_examples 'sets profile data'
- end
-
- context 'when WebFinger presents different domain than URI' do
- let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
-
- before do
- stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
- stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
- stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
- end
-
- it 'fetches resource' do
- account
- expect(a_request(:get, 'https://example.com/alice')).to have_been_made.once
- end
-
- it 'looks up webfinger' do
- account
- expect(a_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com')).to have_been_made.once
- end
-
- it 'looks up "redirected" webfinger' do
- account
- expect(a_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af')).to have_been_made.once
- end
-
- it 'sets username and domain from final webfinger' do
- expect(account.username).to eq 'alice'
- expect(account.domain).to eq 'iscool.af'
- end
-
- include_examples 'sets profile data'
- end
-
- context 'with wrong id' do
- it 'does not create account' do
- expect(subject.call('https://fake.address/@foo', prefetched_body: Oj.dump(actor))).to be_nil
- end
- end
- end
-end
diff --git a/spec/services/activitypub/fetch_remote_status_service_spec.rb b/spec/services/activitypub/fetch_remote_status_service_spec.rb
deleted file mode 100644
index 9ae40999..00000000
--- a/spec/services/activitypub/fetch_remote_status_service_spec.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::FetchRemoteStatusService, type: :service do
- include ActionView::Helpers::TextHelper
-
- let(:sender) { Fabricate(:account) }
- let(:recipient) { Fabricate(:account) }
- let(:valid_domain) { Rails.configuration.x.local_domain }
-
- let(:note) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: "https://#{valid_domain}/@foo/1234",
- type: 'Note',
- content: 'Lorem ipsum',
- attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
- }
- end
-
- subject { described_class.new }
-
- describe '#call' do
- before do
- sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender))
-
- stub_request(:head, 'https://example.com/watch?v=12345').to_return(status: 404, body: '')
- subject.call(object[:id], prefetched_body: Oj.dump(object))
- end
-
- context 'with Note object' do
- let(:object) { note }
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
- end
-
- context 'with Video object' do
- let(:object) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: "https://#{valid_domain}/@foo/1234",
- type: 'Video',
- name: 'Nyan Cat 10 hours remix',
- attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
- url: [
- {
- type: 'Link',
- mimeType: 'application/x-bittorrent',
- href: "https://#{valid_domain}/12345.torrent",
- },
-
- {
- type: 'Link',
- mimeType: 'text/html',
- href: "https://#{valid_domain}/watch?v=12345",
- },
- ],
- }
- end
-
- it 'creates status' do
- status = sender.statuses.first
-
- expect(status).to_not be_nil
- expect(status.url).to eq "https://#{valid_domain}/watch?v=12345"
- expect(strip_tags(status.text)).to eq "Nyan Cat 10 hours remix https://#{valid_domain}/watch?v=12345"
- end
- end
-
- context 'with wrong id' do
- let(:note) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: "https://real.address/@foo/1234",
- type: 'Note',
- content: 'Lorem ipsum',
- attributedTo: ActivityPub::TagManager.instance.uri_for(sender),
- }
- end
-
- let(:object) do
- temp = note.dup
- temp[:id] = 'https://fake.address/@foo/5678'
- temp
- end
-
- it 'does not create status' do
- expect(sender.statuses.first).to be_nil
- end
- end
- end
-end
diff --git a/spec/services/activitypub/fetch_replies_service_spec.rb b/spec/services/activitypub/fetch_replies_service_spec.rb
deleted file mode 100644
index 65c45334..00000000
--- a/spec/services/activitypub/fetch_replies_service_spec.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::FetchRepliesService, type: :service do
- let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }
- let(:status) { Fabricate(:status, account: actor) }
- let(:collection_uri) { 'http://example.com/replies/1' }
-
- let(:items) do
- [
- 'http://example.com/self-reply-1',
- 'http://example.com/self-reply-2',
- 'http://example.com/self-reply-3',
- 'http://other.com/other-reply-1',
- 'http://other.com/other-reply-2',
- 'http://other.com/other-reply-3',
- 'http://example.com/self-reply-4',
- 'http://example.com/self-reply-5',
- 'http://example.com/self-reply-6',
- ]
- end
-
- let(:payload) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- type: 'Collection',
- id: collection_uri,
- items: items,
- }.with_indifferent_access
- end
-
- subject { described_class.new }
-
- describe '#call' do
- context 'when the payload is a Collection with inlined replies' do
- context 'when passing the collection itself' do
- it 'spawns workers for up to 5 replies on the same server' do
- allow(FetchReplyWorker).to receive(:push_bulk)
- subject.call(status, payload)
- expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1', 'http://example.com/self-reply-2', 'http://example.com/self-reply-3', 'http://example.com/self-reply-4', 'http://example.com/self-reply-5'])
- end
- end
-
- context 'when passing the URL to the collection' do
- before do
- stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload))
- end
-
- it 'spawns workers for up to 5 replies on the same server' do
- allow(FetchReplyWorker).to receive(:push_bulk)
- subject.call(status, collection_uri)
- expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1', 'http://example.com/self-reply-2', 'http://example.com/self-reply-3', 'http://example.com/self-reply-4', 'http://example.com/self-reply-5'])
- end
- end
- end
-
- context 'when the payload is an OrderedCollection with inlined replies' do
- let(:payload) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- type: 'OrderedCollection',
- id: collection_uri,
- orderedItems: items,
- }.with_indifferent_access
- end
-
- context 'when passing the collection itself' do
- it 'spawns workers for up to 5 replies on the same server' do
- allow(FetchReplyWorker).to receive(:push_bulk)
- subject.call(status, payload)
- expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1', 'http://example.com/self-reply-2', 'http://example.com/self-reply-3', 'http://example.com/self-reply-4', 'http://example.com/self-reply-5'])
- end
- end
-
- context 'when passing the URL to the collection' do
- before do
- stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload))
- end
-
- it 'spawns workers for up to 5 replies on the same server' do
- allow(FetchReplyWorker).to receive(:push_bulk)
- subject.call(status, collection_uri)
- expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1', 'http://example.com/self-reply-2', 'http://example.com/self-reply-3', 'http://example.com/self-reply-4', 'http://example.com/self-reply-5'])
- end
- end
- end
-
- context 'when the payload is a paginated Collection with inlined replies' do
- let(:payload) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- type: 'Collection',
- id: collection_uri,
- first: {
- type: 'CollectionPage',
- partOf: collection_uri,
- items: items,
- }
- }.with_indifferent_access
- end
-
- context 'when passing the collection itself' do
- it 'spawns workers for up to 5 replies on the same server' do
- allow(FetchReplyWorker).to receive(:push_bulk)
- subject.call(status, payload)
- expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1', 'http://example.com/self-reply-2', 'http://example.com/self-reply-3', 'http://example.com/self-reply-4', 'http://example.com/self-reply-5'])
- end
- end
-
- context 'when passing the URL to the collection' do
- before do
- stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload))
- end
-
- it 'spawns workers for up to 5 replies on the same server' do
- allow(FetchReplyWorker).to receive(:push_bulk)
- subject.call(status, collection_uri)
- expect(FetchReplyWorker).to have_received(:push_bulk).with(['http://example.com/self-reply-1', 'http://example.com/self-reply-2', 'http://example.com/self-reply-3', 'http://example.com/self-reply-4', 'http://example.com/self-reply-5'])
- end
- end
- end
- end
-end
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
deleted file mode 100644
index 5141e3f1..00000000
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::ProcessAccountService, type: :service do
- subject { described_class.new }
-
- context 'property values' do
- let(:payload) do
- {
- id: 'https://foo.test',
- type: 'Actor',
- inbox: 'https://foo.test/inbox',
- attachment: [
- { type: 'PropertyValue', name: 'Pronouns', value: 'They/them' },
- { type: 'PropertyValue', name: 'Occupation', value: 'Unit test' },
- ],
- }.with_indifferent_access
- end
-
- it 'parses out of attachment' do
- account = subject.call('alice', 'example.com', payload)
- expect(account.fields).to be_a Array
- expect(account.fields.size).to eq 2
- expect(account.fields[0]).to be_a Account::Field
- expect(account.fields[0].name).to eq 'Pronouns'
- expect(account.fields[0].value).to eq 'They/them'
- expect(account.fields[1]).to be_a Account::Field
- expect(account.fields[1].name).to eq 'Occupation'
- expect(account.fields[1].value).to eq 'Unit test'
- end
- end
-
- context 'identity proofs' do
- let(:payload) do
- {
- id: 'https://foo.test',
- type: 'Actor',
- inbox: 'https://foo.test/inbox',
- attachment: [
- { type: 'IdentityProof', name: 'Alice', signatureAlgorithm: 'keybase', signatureValue: 'a' * 66 },
- ],
- }.with_indifferent_access
- end
-
- it 'parses out of attachment' do
- allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
-
- account = subject.call('alice', 'example.com', payload)
-
- expect(account.identity_proofs.count).to eq 1
-
- proof = account.identity_proofs.first
-
- expect(proof.provider).to eq 'keybase'
- expect(proof.provider_username).to eq 'Alice'
- expect(proof.token).to eq 'a' * 66
- end
-
- it 'removes no longer present proofs' do
- allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
-
- account = Fabricate(:account, username: 'alice', domain: 'example.com')
- old_proof = Fabricate(:account_identity_proof, account: account, provider: 'keybase', provider_username: 'Bob', token: 'b' * 66)
-
- subject.call('alice', 'example.com', payload)
-
- expect(account.identity_proofs.count).to eq 1
- expect(account.identity_proofs.find_by(id: old_proof.id)).to be_nil
- end
-
- it 'queues a validity check on the proof' do
- allow(ProofProvider::Keybase::Worker).to receive(:perform_async)
- account = subject.call('alice', 'example.com', payload)
- expect(ProofProvider::Keybase::Worker).to have_received(:perform_async)
- end
- end
-end
diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb
deleted file mode 100644
index b3baf6b6..00000000
--- a/spec/services/activitypub/process_collection_service_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
- let(:actor) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }
-
- let(:payload) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'foo',
- type: 'Create',
- actor: ActivityPub::TagManager.instance.uri_for(actor),
- object: {
- id: 'bar',
- type: 'Note',
- content: 'Lorem ipsum',
- },
- }
- end
-
- let(:json) { Oj.dump(payload) }
-
- subject { described_class.new }
-
- describe '#call' do
- context 'when actor is the sender'
- context 'when actor differs from sender' do
- let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') }
-
- it 'does not process payload if no signature exists' do
- expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(nil)
- expect(ActivityPub::Activity).not_to receive(:factory)
-
- subject.call(json, forwarder)
- end
-
- it 'processes payload with actor if valid signature exists' do
- payload['signature'] = { 'type' => 'RsaSignature2017' }
-
- expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(actor)
- expect(ActivityPub::Activity).to receive(:factory).with(instance_of(Hash), actor, instance_of(Hash))
-
- subject.call(json, forwarder)
- end
-
- it 'does not process payload if invalid signature exists' do
- payload['signature'] = { 'type' => 'RsaSignature2017' }
-
- expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(nil)
- expect(ActivityPub::Activity).not_to receive(:factory)
-
- subject.call(json, forwarder)
- end
- end
- end
-end
diff --git a/spec/services/after_block_domain_from_account_service_spec.rb b/spec/services/after_block_domain_from_account_service_spec.rb
deleted file mode 100644
index 006e3f4d..00000000
--- a/spec/services/after_block_domain_from_account_service_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AfterBlockDomainFromAccountService, type: :service do
- let!(:wolf) { Fabricate(:account, username: 'wolf', domain: 'evil.org', inbox_url: 'https://evil.org/inbox', protocol: :activitypub) }
- let!(:alice) { Fabricate(:account, username: 'alice') }
-
- subject { AfterBlockDomainFromAccountService.new }
-
- before do
- stub_jsonld_contexts!
- allow(ActivityPub::DeliveryWorker).to receive(:perform_async)
- end
-
- it 'purge followers from blocked domain' do
- wolf.follow!(alice)
- subject.call(alice, 'evil.org')
- expect(wolf.following?(alice)).to be false
- end
-
- it 'sends Reject->Follow to followers from blocked domain' do
- wolf.follow!(alice)
- subject.call(alice, 'evil.org')
- expect(ActivityPub::DeliveryWorker).to have_received(:perform_async).once
- end
-end
diff --git a/spec/services/after_block_service_spec.rb b/spec/services/after_block_service_spec.rb
deleted file mode 100644
index f63b2045..00000000
--- a/spec/services/after_block_service_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AfterBlockService, type: :service do
- subject do
- -> { described_class.new.call(account, target_account) }
- end
-
- let(:account) { Fabricate(:account) }
- let(:target_account) { Fabricate(:account) }
-
- describe 'home timeline' do
- let(:status) { Fabricate(:status, account: target_account) }
- let(:other_account_status) { Fabricate(:status) }
- let(:home_timeline_key) { FeedManager.instance.key(:home, account.id) }
-
- before do
- Redis.current.del(home_timeline_key)
- end
-
- it "clears account's statuses" do
- FeedManager.instance.push_to_home(account, status)
- FeedManager.instance.push_to_home(account, other_account_status)
-
- is_expected.to change {
- Redis.current.zrange(home_timeline_key, 0, -1)
- }.from([status.id.to_s, other_account_status.id.to_s]).to([other_account_status.id.to_s])
- end
- end
-end
diff --git a/spec/services/app_sign_up_service_spec.rb b/spec/services/app_sign_up_service_spec.rb
deleted file mode 100644
index 7948bb53..00000000
--- a/spec/services/app_sign_up_service_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AppSignUpService, type: :service do
- let(:app) { Fabricate(:application, scopes: 'read write') }
- let(:good_params) { { username: 'alice', password: '12345678', email: 'good@email.com', agreement: true } }
-
- subject { described_class.new }
-
- describe '#call' do
- it 'returns nil when registrations are closed' do
- tmp = Setting.registrations_mode
- Setting.registrations_mode = 'none'
- expect(subject.call(app, good_params)).to be_nil
- Setting.registrations_mode = tmp
- end
-
- it 'raises an error when params are missing' do
- expect { subject.call(app, {}) }.to raise_error ActiveRecord::RecordInvalid
- end
-
- it 'creates an unconfirmed user with access token' do
- access_token = subject.call(app, good_params)
- expect(access_token).to_not be_nil
- user = User.find_by(id: access_token.resource_owner_id)
- expect(user).to_not be_nil
- expect(user.confirmed?).to be false
- end
-
- it 'creates access token with the app\'s scopes' do
- access_token = subject.call(app, good_params)
- expect(access_token).to_not be_nil
- expect(access_token.scopes.to_s).to eq 'read write'
- end
-
- it 'creates an account' do
- access_token = subject.call(app, good_params)
- expect(access_token).to_not be_nil
- user = User.find_by(id: access_token.resource_owner_id)
- expect(user).to_not be_nil
- expect(user.account).to_not be_nil
- end
- end
-end
diff --git a/spec/services/authorize_follow_service_spec.rb b/spec/services/authorize_follow_service_spec.rb
deleted file mode 100644
index 562ef004..00000000
--- a/spec/services/authorize_follow_service_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe AuthorizeFollowService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { AuthorizeFollowService.new }
-
- describe 'local' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- FollowRequest.create(account: bob, target_account: sender)
- subject.call(bob, sender)
- end
-
- it 'removes follow request' do
- expect(bob.requested?(sender)).to be false
- end
-
- it 'creates follow relation' do
- expect(bob.following?(sender)).to be true
- end
- end
-
- describe 'remote OStatus' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
-
- before do
- FollowRequest.create(account: bob, target_account: sender)
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(bob, sender)
- end
-
- it 'removes follow request' do
- expect(bob.requested?(sender)).to be false
- end
-
- it 'creates follow relation' do
- expect(bob.following?(sender)).to be true
- end
-
- it 'sends a follow request authorization salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:authorize])
- }).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox')).account }
-
- before do
- FollowRequest.create(account: bob, target_account: sender)
- stub_request(:post, bob.inbox_url).to_return(status: 200)
- subject.call(bob, sender)
- end
-
- it 'removes follow request' do
- expect(bob.requested?(sender)).to be false
- end
-
- it 'creates follow relation' do
- expect(bob.following?(sender)).to be true
- end
-
- it 'sends an accept activity' do
- expect(a_request(:post, bob.inbox_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/batched_remove_status_service_spec.rb b/spec/services/batched_remove_status_service_spec.rb
deleted file mode 100644
index e5362344..00000000
--- a/spec/services/batched_remove_status_service_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe BatchedRemoveStatusService, type: :service do
- subject { BatchedRemoveStatusService.new }
-
- let!(:alice) { Fabricate(:account) }
- let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://example.com/salmon') }
- let!(:jeff) { Fabricate(:user).account }
- let!(:hank) { Fabricate(:account, username: 'hank', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
-
- let(:status1) { PostStatusService.new.call(alice, text: 'Hello @bob@example.com') }
- let(:status2) { PostStatusService.new.call(alice, text: 'Another status') }
-
- before do
- allow(Redis.current).to receive_messages(publish: nil)
-
- stub_request(:post, 'http://example.com/push').to_return(status: 200, body: '', headers: {})
- stub_request(:post, 'http://example.com/salmon').to_return(status: 200, body: '', headers: {})
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
-
- Fabricate(:subscription, account: alice, callback_url: 'http://example.com/push', confirmed: true, expires_at: 30.days.from_now)
- jeff.user.update(current_sign_in_at: Time.zone.now)
- jeff.follow!(alice)
- hank.follow!(alice)
-
- status1
- status2
-
- subject.call([status1, status2])
- end
-
- it 'removes statuses from author\'s home feed' do
- expect(HomeFeed.new(alice).get(10)).to_not include([status1.id, status2.id])
- end
-
- it 'removes statuses from local follower\'s home feed' do
- expect(HomeFeed.new(jeff).get(10)).to_not include([status1.id, status2.id])
- end
-
- it 'notifies streaming API of followers' do
- expect(Redis.current).to have_received(:publish).with("timeline:#{jeff.id}", any_args).at_least(:once)
- end
-
- it 'notifies streaming API of author' do
- expect(Redis.current).to have_received(:publish).with("timeline:#{alice.id}", any_args).at_least(:once)
- end
-
- it 'notifies streaming API of public timeline' do
- expect(Redis.current).to have_received(:publish).with('timeline:public', any_args).at_least(:once)
- end
-
- it 'sends PuSH update to PuSH subscribers' do
- expect(a_request(:post, 'http://example.com/push').with { |req|
- matches = req.body.match(OStatus::TagManager::VERBS[:delete])
- }).to have_been_made.at_least_once
- end
-
- it 'sends Salmon slap to previously mentioned users' do
- expect(a_request(:post, "http://example.com/salmon").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:delete])
- }).to have_been_made.once
- end
-
- it 'sends delete activity to followers' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.at_least_once
- end
-end
diff --git a/spec/services/block_domain_service_spec.rb b/spec/services/block_domain_service_spec.rb
deleted file mode 100644
index c689b57e..00000000
--- a/spec/services/block_domain_service_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe BlockDomainService, type: :service do
- let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }
- let!(:bad_status1) { Fabricate(:status, account: bad_account, text: 'You suck') }
- let!(:bad_status2) { Fabricate(:status, account: bad_account, text: 'Hahaha') }
- let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status2, file: attachment_fixture('attachment.jpg')) }
- let!(:already_banned_account) { Fabricate(:account, username: 'badguy', domain: 'evil.org', suspended: true, silenced: true) }
-
- subject { BlockDomainService.new }
-
- describe 'for a suspension' do
- before do
- subject.call(DomainBlock.create!(domain: 'evil.org', severity: :suspend))
- end
-
- it 'creates a domain block' do
- expect(DomainBlock.blocked?('evil.org')).to be true
- end
-
- it 'removes remote accounts from that domain' do
- expect(Account.find_remote('badguy666', 'evil.org').suspended?).to be true
- end
-
- it 'records suspension date appropriately' do
- expect(Account.find_remote('badguy666', 'evil.org').suspended_at).to eq DomainBlock.find_by(domain: 'evil.org').created_at
- end
-
- it 'keeps already-banned accounts banned' do
- expect(Account.find_remote('badguy', 'evil.org').suspended?).to be true
- end
-
- it 'does not overwrite suspension date of already-banned accounts' do
- expect(Account.find_remote('badguy', 'evil.org').suspended_at).to_not eq DomainBlock.find_by(domain: 'evil.org').created_at
- end
-
- it 'removes the remote accounts\'s statuses and media attachments' do
- expect { bad_status1.reload }.to raise_exception ActiveRecord::RecordNotFound
- expect { bad_status2.reload }.to raise_exception ActiveRecord::RecordNotFound
- expect { bad_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound
- end
- end
-
- describe 'for a silence with reject media' do
- before do
- subject.call(DomainBlock.create!(domain: 'evil.org', severity: :silence, reject_media: true))
- end
-
- it 'does not create a domain block' do
- expect(DomainBlock.blocked?('evil.org')).to be false
- end
-
- it 'silences remote accounts from that domain' do
- expect(Account.find_remote('badguy666', 'evil.org').silenced?).to be true
- end
-
- it 'records suspension date appropriately' do
- expect(Account.find_remote('badguy666', 'evil.org').silenced_at).to eq DomainBlock.find_by(domain: 'evil.org').created_at
- end
-
- it 'keeps already-banned accounts banned' do
- expect(Account.find_remote('badguy', 'evil.org').silenced?).to be true
- end
-
- it 'does not overwrite suspension date of already-banned accounts' do
- expect(Account.find_remote('badguy', 'evil.org').silenced_at).to_not eq DomainBlock.find_by(domain: 'evil.org').created_at
- end
-
- it 'leaves the domains status and attachements, but clears media' do
- expect { bad_status1.reload }.not_to raise_error
- expect { bad_status2.reload }.not_to raise_error
- expect { bad_attachment.reload }.not_to raise_error
- expect(bad_attachment.file.exists?).to be false
- end
- end
-end
diff --git a/spec/services/block_service_spec.rb b/spec/services/block_service_spec.rb
deleted file mode 100644
index 6584bb90..00000000
--- a/spec/services/block_service_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe BlockService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { BlockService.new }
-
- describe 'local' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- subject.call(sender, bob)
- end
-
- it 'creates a blocking relation' do
- expect(sender.blocking?(bob)).to be true
- end
- end
-
- describe 'remote OStatus' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
-
- before do
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, bob)
- end
-
- it 'creates a blocking relation' do
- expect(sender.blocking?(bob)).to be true
- end
-
- it 'sends a block salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:block])
- }).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox')).account }
-
- before do
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- subject.call(sender, bob)
- end
-
- it 'creates a blocking relation' do
- expect(sender.blocking?(bob)).to be true
- end
-
- it 'sends a block activity' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/bootstrap_timeline_service_spec.rb b/spec/services/bootstrap_timeline_service_spec.rb
deleted file mode 100644
index a765de79..00000000
--- a/spec/services/bootstrap_timeline_service_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe BootstrapTimelineService, type: :service do
- subject { described_class.new }
-
- describe '#call' do
- let(:source_account) { Fabricate(:account) }
-
- context 'when setting is empty' do
- let!(:admin) { Fabricate(:user, admin: true) }
-
- before do
- Setting.bootstrap_timeline_accounts = nil
- subject.call(source_account)
- end
-
- it 'follows admin accounts from account' do
- expect(source_account.following?(admin.account)).to be true
- end
- end
-
- context 'when setting is set' do
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:bob) { Fabricate(:account, username: 'bob') }
-
- before do
- Setting.bootstrap_timeline_accounts = 'alice, bob'
- subject.call(source_account)
- end
-
- it 'follows found accounts from account' do
- expect(source_account.following?(alice)).to be true
- expect(source_account.following?(bob)).to be true
- end
- end
- end
-end
diff --git a/spec/services/fan_out_on_write_service_spec.rb b/spec/services/fan_out_on_write_service_spec.rb
deleted file mode 100644
index b7fc7f7e..00000000
--- a/spec/services/fan_out_on_write_service_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FanOutOnWriteService, type: :service do
- let(:author) { Fabricate(:account, username: 'tom') }
- let(:status) { Fabricate(:status, text: 'Hello @alice #test', account: author) }
- let(:alice) { Fabricate(:user, account: Fabricate(:account, username: 'alice')).account }
- let(:follower) { Fabricate(:account, username: 'bob') }
-
- subject { FanOutOnWriteService.new }
-
- before do
- alice
- follower.follow!(author)
-
- ProcessMentionsService.new.call(status)
- ProcessHashtagsService.new.call(status)
-
- subject.call(status)
- end
-
- it 'delivers status to home timeline' do
- expect(HomeFeed.new(author).get(10).map(&:id)).to include status.id
- end
-
- it 'delivers status to local followers' do
- pending 'some sort of problem in test environment causes this to sometimes fail'
- expect(HomeFeed.new(follower).get(10).map(&:id)).to include status.id
- end
-
- it 'delivers status to hashtag' do
- expect(Tag.find_by!(name: 'test').statuses.pluck(:id)).to include status.id
- end
-
- it 'delivers status to public timeline' do
- expect(Status.as_public_timeline(alice).map(&:id)).to include status.id
- end
-end
diff --git a/spec/services/favourite_service_spec.rb b/spec/services/favourite_service_spec.rb
deleted file mode 100644
index 0a20ccf6..00000000
--- a/spec/services/favourite_service_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FavouriteService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { FavouriteService.new }
-
- describe 'local' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
- let(:status) { Fabricate(:status, account: bob) }
-
- before do
- subject.call(sender, status)
- end
-
- it 'creates a favourite' do
- expect(status.favourites.first).to_not be_nil
- end
- end
-
- describe 'remote OStatus' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
- let(:status) { Fabricate(:status, account: bob, uri: 'tag:example.com:blahblah') }
-
- before do
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, status)
- end
-
- it 'creates a favourite' do
- expect(status.favourites.first).to_not be_nil
- end
-
- it 'sends a salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:favorite])
- }).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, protocol: :activitypub, username: 'bob', domain: 'example.com', inbox_url: 'http://example.com/inbox')).account }
- let(:status) { Fabricate(:status, account: bob) }
-
- before do
- stub_request(:post, "http://example.com/inbox").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, status)
- end
-
- it 'creates a favourite' do
- expect(status.favourites.first).to_not be_nil
- end
-
- it 'sends a like activity' do
- expect(a_request(:post, "http://example.com/inbox")).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/fetch_atom_service_spec.rb b/spec/services/fetch_atom_service_spec.rb
deleted file mode 100644
index 49554000..00000000
--- a/spec/services/fetch_atom_service_spec.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FetchAtomService, type: :service do
- describe '#call' do
- let(:url) { 'http://example.com' }
- subject { FetchAtomService.new.call(url) }
-
- context 'url is blank' do
- let(:url) { '' }
- it { is_expected.to be_nil }
- end
-
- context 'request failed' do
- before do
- WebMock.stub_request(:get, url).to_return(status: 500, body: '', headers: {})
- end
-
- it { is_expected.to be_nil }
- end
-
- context 'raise OpenSSL::SSL::SSLError' do
- before do
- allow(Request).to receive_message_chain(:new, :add_headers, :perform).and_raise(OpenSSL::SSL::SSLError)
- end
-
- it 'output log and return nil' do
- expect_any_instance_of(ActiveSupport::Logger).to receive(:debug).with('SSL error: OpenSSL::SSL::SSLError')
- is_expected.to be_nil
- end
- end
-
- context 'raise HTTP::ConnectionError' do
- before do
- allow(Request).to receive_message_chain(:new, :add_headers, :perform).and_raise(HTTP::ConnectionError)
- end
-
- it 'output log and return nil' do
- expect_any_instance_of(ActiveSupport::Logger).to receive(:debug).with('HTTP ConnectionError: HTTP::ConnectionError')
- is_expected.to be_nil
- end
- end
-
- context 'response success' do
- let(:body) { '' }
- let(:headers) { { 'Content-Type' => content_type } }
- let(:json) {
- { id: 1,
- '@context': ActivityPub::TagManager::CONTEXT,
- type: 'Note',
- }.to_json
- }
-
- before do
- WebMock.stub_request(:get, url).to_return(status: 200, body: body, headers: headers)
- end
-
- context 'content type is application/atom+xml' do
- let(:content_type) { 'application/atom+xml' }
-
- it { is_expected.to eq [url, { :prefetched_body => "" }, :ostatus] }
- end
-
- context 'content_type is activity+json' do
- let(:content_type) { 'application/activity+json; charset=utf-8' }
- let(:body) { json }
-
- it { is_expected.to eq [1, { prefetched_body: body, id: true }, :activitypub] }
- end
-
- context 'content_type is ld+json with profile' do
- let(:content_type) { 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' }
- let(:body) { json }
-
- it { is_expected.to eq [1, { prefetched_body: body, id: true }, :activitypub] }
- end
-
- before do
- WebMock.stub_request(:get, url).to_return(status: 200, body: body, headers: headers)
- WebMock.stub_request(:get, 'http://example.com/foo').to_return(status: 200, body: json, headers: { 'Content-Type' => 'application/activity+json' })
- end
-
- context 'has link header' do
- let(:headers) { { 'Link' => '; rel="alternate"; type="application/activity+json"', } }
-
- it { is_expected.to eq [1, { prefetched_body: json, id: true }, :activitypub] }
- end
-
- context 'content type is text/html' do
- let(:content_type) { 'text/html' }
- let(:body) { ' ' }
-
- it { is_expected.to eq [1, { prefetched_body: json, id: true }, :activitypub] }
- end
- end
- end
-end
diff --git a/spec/services/fetch_link_card_service_spec.rb b/spec/services/fetch_link_card_service_spec.rb
deleted file mode 100644
index bd50499e..00000000
--- a/spec/services/fetch_link_card_service_spec.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FetchLinkCardService, type: :service do
- subject { FetchLinkCardService.new }
-
- before do
- stub_request(:head, 'http://example.xn--fiqs8s/').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.xn--fiqs8s/').to_return(request_fixture('idn.txt'))
- stub_request(:head, 'http://example.com/sjis').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.com/sjis').to_return(request_fixture('sjis.txt'))
- stub_request(:head, 'http://example.com/sjis_with_wrong_charset').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.com/sjis_with_wrong_charset').to_return(request_fixture('sjis_with_wrong_charset.txt'))
- stub_request(:head, 'http://example.com/koi8-r').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.com/koi8-r').to_return(request_fixture('koi8-r.txt'))
- stub_request(:head, 'http://example.com/日本語').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.com/日本語').to_return(request_fixture('sjis.txt'))
- stub_request(:head, 'https://github.com/qbi/WannaCry').to_return(status: 404)
- stub_request(:head, 'http://example.com/test-').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.com/test-').to_return(request_fixture('idn.txt'))
- stub_request(:head, 'http://example.com/windows-1251').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
- stub_request(:get, 'http://example.com/windows-1251').to_return(request_fixture('windows-1251.txt'))
-
- subject.call(status)
- end
-
- context 'in a local status' do
- context do
- let(:status) { Fabricate(:status, text: 'Check out http://example.ä¸å›½') }
-
- it 'works with IDN URLs' do
- expect(a_request(:get, 'http://example.xn--fiqs8s/')).to have_been_made.at_least_once
- end
- end
-
- context do
- let(:status) { Fabricate(:status, text: 'Check out http://example.com/sjis') }
-
- it 'works with SJIS' do
- expect(a_request(:get, 'http://example.com/sjis')).to have_been_made.at_least_once
- expect(status.preview_cards.first.title).to eq("SJISã®ãƒšãƒ¼ã‚¸")
- end
- end
-
- context do
- let(:status) { Fabricate(:status, text: 'Check out http://example.com/sjis_with_wrong_charset') }
-
- it 'works with SJIS even with wrong charset header' do
- expect(a_request(:get, 'http://example.com/sjis_with_wrong_charset')).to have_been_made.at_least_once
- expect(status.preview_cards.first.title).to eq("SJISã®ãƒšãƒ¼ã‚¸")
- end
- end
-
- context do
- let(:status) { Fabricate(:status, text: 'Check out http://example.com/koi8-r') }
-
- it 'works with koi8-r' do
- expect(a_request(:get, 'http://example.com/koi8-r')).to have_been_made.at_least_once
- expect(status.preview_cards.first.title).to eq("МоÑÐºÐ¾Ð²Ñ Ð½Ð°Ñ‡Ð¸Ð½Ð°ÐµÑ‚ÑŠ только въ XVI ÑÑ‚. привлекать внимане иноÑтранцевъ.")
- end
- end
-
- context do
- let(:status) { Fabricate(:status, text: 'Check out http://example.com/windows-1251') }
-
- it 'works with windows-1251' do
- expect(a_request(:get, 'http://example.com/windows-1251')).to have_been_made.at_least_once
- expect(status.preview_cards.first.title).to eq('ÑÑмпл текÑÑ‚')
- end
- end
-
- context do
- let(:status) { Fabricate(:status, text: 'テストhttp://example.com/日本語') }
-
- it 'works with Japanese path string' do
- expect(a_request(:get, 'http://example.com/日本語')).to have_been_made.at_least_once
- expect(status.preview_cards.first.title).to eq("SJISã®ãƒšãƒ¼ã‚¸")
- end
- end
-
- context do
- let(:status) { Fabricate(:status, text: 'test http://example.com/test-') }
-
- it 'works with a URL ending with a hyphen' do
- expect(a_request(:get, 'http://example.com/test-')).to have_been_made.at_least_once
- end
- end
- end
-
- context 'in a remote status' do
- let(:status) { Fabricate(:status, account: Fabricate(:account, domain: 'example.com'), text: 'Habt ihr ein paar gute Links zu #Wannacry herumfliegen? Ich will mal unter https://github.com/qbi/WannaCry was sammeln. !security ') }
-
- it 'parses out URLs' do
- expect(a_request(:head, 'https://github.com/qbi/WannaCry')).to have_been_made.at_least_once
- end
-
- it 'ignores URLs to hashtags' do
- expect(a_request(:head, 'https://quitter.se/tag/wannacry')).to_not have_been_made
- end
- end
-end
diff --git a/spec/services/fetch_oembed_service_spec.rb b/spec/services/fetch_oembed_service_spec.rb
deleted file mode 100644
index 5789fb53..00000000
--- a/spec/services/fetch_oembed_service_spec.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe FetchOEmbedService, type: :service do
- subject { described_class.new }
-
- before do
- stub_request(:get, "https://host.test/provider.json").to_return(status: 404)
- stub_request(:get, "https://host.test/provider.xml").to_return(status: 404)
- stub_request(:get, "https://host.test/empty_provider.json").to_return(status: 200)
- end
-
- describe 'discover_provider' do
- context 'when status code is 200 and MIME type is text/html' do
- context 'Both of JSON and XML provider are discoverable' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_json_xml.html')
- )
- end
-
- it 'returns new OEmbed::Provider for JSON provider if :format option is set to :json' do
- subject.call('https://host.test/oembed.html', format: :json)
- expect(subject.endpoint_url).to eq 'https://host.test/provider.json'
- expect(subject.format).to eq :json
- end
-
- it 'returns new OEmbed::Provider for XML provider if :format option is set to :xml' do
- subject.call('https://host.test/oembed.html', format: :xml)
- expect(subject.endpoint_url).to eq 'https://host.test/provider.xml'
- expect(subject.format).to eq :xml
- end
- end
-
- context 'JSON provider is discoverable while XML provider is not' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_json.html')
- )
- end
-
- it 'returns new OEmbed::Provider for JSON provider' do
- subject.call('https://host.test/oembed.html')
- expect(subject.endpoint_url).to eq 'https://host.test/provider.json'
- expect(subject.format).to eq :json
- end
- end
-
- context 'XML provider is discoverable while JSON provider is not' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_xml.html')
- )
- end
-
- it 'returns new OEmbed::Provider for XML provider' do
- subject.call('https://host.test/oembed.html')
- expect(subject.endpoint_url).to eq 'https://host.test/provider.xml'
- expect(subject.format).to eq :xml
- end
- end
-
- context 'Invalid XML provider is discoverable while JSON provider is not' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_invalid_xml.html')
- )
- end
-
- it 'returns nil' do
- expect(subject.call('https://host.test/oembed.html')).to be_nil
- end
- end
-
- context 'Neither of JSON and XML provider is discoverable' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_undiscoverable.html')
- )
- end
-
- it 'returns nil' do
- expect(subject.call('https://host.test/oembed.html')).to be_nil
- end
- end
-
- context 'Empty JSON provider is discoverable' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_json_empty.html')
- )
- end
-
- it 'returns new OEmbed::Provider for JSON provider' do
- subject.call('https://host.test/oembed.html')
- expect(subject.endpoint_url).to eq 'https://host.test/empty_provider.json'
- expect(subject.format).to eq :json
- end
- end
-
- end
-
- context 'when status code is not 200' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 400,
- headers: { 'Content-Type': 'text/html' },
- body: request_fixture('oembed_xml.html')
- )
- end
-
- it 'returns nil' do
- expect(subject.call('https://host.test/oembed.html')).to be_nil
- end
- end
-
- context 'when MIME type is not text/html' do
- before do
- stub_request(:get, 'https://host.test/oembed.html').to_return(
- status: 200,
- body: request_fixture('oembed_xml.html')
- )
- end
-
- it 'returns nil' do
- expect(subject.call('https://host.test/oembed.html')).to be_nil
- end
- end
- end
-end
diff --git a/spec/services/fetch_remote_account_service_spec.rb b/spec/services/fetch_remote_account_service_spec.rb
deleted file mode 100644
index afc76379..00000000
--- a/spec/services/fetch_remote_account_service_spec.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FetchRemoteAccountService, type: :service do
- let(:url) { 'https://example.com/alice' }
- let(:prefetched_body) { nil }
- let(:protocol) { :ostatus }
- subject { FetchRemoteAccountService.new.call(url, prefetched_body, protocol) }
-
- let(:actor) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'https://example.com/alice',
- type: 'Person',
- preferredUsername: 'alice',
- name: 'Alice',
- summary: 'Foo bar',
- inbox: 'http://example.com/alice/inbox',
- }
- end
-
- let(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
- let(:xml) { File.read(Rails.root.join('spec', 'fixtures', 'xml', 'gabsocial.atom')) }
-
- shared_examples 'return Account' do
- it { is_expected.to be_an Account }
- end
-
- context 'protocol is :activitypub' do
- let(:prefetched_body) { Oj.dump(actor) }
- let(:protocol) { :activitypub }
-
- before do
- stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
- end
-
- include_examples 'return Account'
- end
-
- context 'protocol is :ostatus' do
- let(:prefetched_body) { xml }
- let(:protocol) { :ostatus }
-
- before do
- stub_request(:get, "https://kickass.zone/.well-known/webfinger?resource=acct:localhost@kickass.zone").to_return(request_fixture('webfinger-hacker3.txt'))
- stub_request(:get, "https://kickass.zone/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
- end
-
- include_examples 'return Account'
-
- it 'does not update account information if XML comes from an unverified domain' do
- feed_xml = <<-XML.squish
-
-
-
- http://activitystrea.ms/schema/1.0/person
- http://kickass.zone/users/localhost
- localhost
- localhost
- Villain!!!
-
-
- XML
-
- returned_account = described_class.new.call('https://real-fake-domains.com/alice', feed_xml, :ostatus)
- expect(returned_account.display_name).to_not eq 'Villain!!!'
- end
- end
-
- context 'when prefetched_body is nil' do
- context 'protocol is :activitypub' do
- before do
- stub_request(:get, url).to_return(status: 200, body: Oj.dump(actor), headers: { 'Content-Type' => 'application/activity+json' })
- stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
- end
-
- include_examples 'return Account'
- end
-
- context 'protocol is :ostatus' do
- before do
- stub_request(:get, url).to_return(status: 200, body: xml, headers: { 'Content-Type' => 'application/atom+xml' })
- stub_request(:get, "https://kickass.zone/.well-known/webfinger?resource=acct:localhost@kickass.zone").to_return(request_fixture('webfinger-hacker3.txt'))
- stub_request(:get, "https://kickass.zone/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
- end
-
- include_examples 'return Account'
- end
- end
-end
diff --git a/spec/services/fetch_remote_status_service_spec.rb b/spec/services/fetch_remote_status_service_spec.rb
deleted file mode 100644
index aa27c404..00000000
--- a/spec/services/fetch_remote_status_service_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FetchRemoteStatusService, type: :service do
- let(:account) { Fabricate(:account) }
- let(:prefetched_body) { nil }
- let(:valid_domain) { Rails.configuration.x.local_domain }
-
- let(:note) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: "https://#{valid_domain}/@foo/1234",
- type: 'Note',
- content: 'Lorem ipsum',
- attributedTo: ActivityPub::TagManager.instance.uri_for(account),
- }
- end
-
- context 'protocol is :activitypub' do
- subject { described_class.new.call(note[:id], prefetched_body, protocol) }
- let(:prefetched_body) { Oj.dump(note) }
- let(:protocol) { :activitypub }
-
- before do
- account.update(uri: ActivityPub::TagManager.instance.uri_for(account))
- subject
- end
-
- it 'creates status' do
- status = account.statuses.first
-
- expect(status).to_not be_nil
- expect(status.text).to eq 'Lorem ipsum'
- end
- end
-
- context 'protocol is :ostatus' do
- subject { described_class.new }
-
- before do
- Fabricate(:account, username: 'tracer', domain: 'real.domain', remote_url: 'https://real.domain/users/tracer')
- end
-
- it 'does not create status with author at different domain' do
- status_body = <<-XML.squish
-
-
- tag:real.domain,2017-04-27:objectId=4487555:objectType=Status
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- https://real.domain/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://real.domain/users/tracer
- tracer
-
- Overwatch rocks
-
- XML
-
- expect(subject.call('https://fake.domain/foo', status_body, :ostatus)).to be_nil
- end
-
- it 'does not create status with wrong id when id uses http format' do
- status_body = <<-XML.squish
-
-
- https://other-real.domain/statuses/123
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- https://real.domain/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://real.domain/users/tracer
- tracer
-
- Overwatch rocks
-
- XML
-
- expect(subject.call('https://real.domain/statuses/456', status_body, :ostatus)).to be_nil
- end
- end
-end
diff --git a/spec/services/follow_service_spec.rb b/spec/services/follow_service_spec.rb
deleted file mode 100644
index 3c4ec59b..00000000
--- a/spec/services/follow_service_spec.rb
+++ /dev/null
@@ -1,183 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe FollowService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { FollowService.new }
-
- context 'local account' do
- describe 'locked account' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, locked: true, username: 'bob')).account }
-
- before do
- subject.call(sender, bob.acct)
- end
-
- it 'creates a follow request with reblogs' do
- expect(FollowRequest.find_by(account: sender, target_account: bob, show_reblogs: true)).to_not be_nil
- end
- end
-
- describe 'locked account, no reblogs' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, locked: true, username: 'bob')).account }
-
- before do
- subject.call(sender, bob.acct, reblogs: false)
- end
-
- it 'creates a follow request without reblogs' do
- expect(FollowRequest.find_by(account: sender, target_account: bob, show_reblogs: false)).to_not be_nil
- end
- end
-
- describe 'unlocked account' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- subject.call(sender, bob.acct)
- end
-
- it 'creates a following relation with reblogs' do
- expect(sender.following?(bob)).to be true
- expect(sender.muting_reblogs?(bob)).to be false
- end
- end
-
- describe 'unlocked account, no reblogs' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- subject.call(sender, bob.acct, reblogs: false)
- end
-
- it 'creates a following relation without reblogs' do
- expect(sender.following?(bob)).to be true
- expect(sender.muting_reblogs?(bob)).to be true
- end
- end
-
- describe 'already followed account' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- sender.follow!(bob)
- subject.call(sender, bob.acct)
- end
-
- it 'keeps a following relation' do
- expect(sender.following?(bob)).to be true
- end
- end
-
- describe 'already followed account, turning reblogs off' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- sender.follow!(bob, reblogs: true)
- subject.call(sender, bob.acct, reblogs: false)
- end
-
- it 'disables reblogs' do
- expect(sender.muting_reblogs?(bob)).to be true
- end
- end
-
- describe 'already followed account, turning reblogs on' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- sender.follow!(bob, reblogs: false)
- subject.call(sender, bob.acct, reblogs: true)
- end
-
- it 'disables reblogs' do
- expect(sender.muting_reblogs?(bob)).to be false
- end
- end
- end
-
- context 'remote OStatus account' do
- describe 'locked account' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, protocol: :ostatus, locked: true, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
-
- before do
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, bob.acct)
- end
-
- it 'creates a follow request' do
- expect(FollowRequest.find_by(account: sender, target_account: bob)).to_not be_nil
- end
-
- it 'sends a follow request salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:request_friend])
- }).to have_been_made.once
- end
- end
-
- describe 'unlocked account' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, protocol: :ostatus, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com', hub_url: 'http://hub.example.com')).account }
-
- before do
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- stub_request(:post, "http://hub.example.com/").to_return(status: 202)
- subject.call(sender, bob.acct)
- end
-
- it 'creates a following relation' do
- expect(sender.following?(bob)).to be true
- end
-
- it 'sends a follow salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:follow])
- }).to have_been_made.once
- end
-
- it 'subscribes to PuSH' do
- expect(a_request(:post, "http://hub.example.com/")).to have_been_made.once
- end
- end
-
- describe 'already followed account' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, protocol: :ostatus, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com', hub_url: 'http://hub.example.com')).account }
-
- before do
- sender.follow!(bob)
- subject.call(sender, bob.acct)
- end
-
- it 'keeps a following relation' do
- expect(sender.following?(bob)).to be true
- end
-
- it 'does not send a follow salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/")).not_to have_been_made
- end
-
- it 'does not subscribe to PuSH' do
- expect(a_request(:post, "http://hub.example.com/")).not_to have_been_made
- end
- end
- end
-
- context 'remote ActivityPub account' do
- let(:bob) { Fabricate(:user, account: Fabricate(:account, username: 'bob', domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox')).account }
-
- before do
- stub_request(:post, "http://example.com/inbox").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, bob.acct)
- end
-
- it 'creates follow request' do
- expect(FollowRequest.find_by(account: sender, target_account: bob)).to_not be_nil
- end
-
- it 'sends a follow activity to the inbox' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/hashtag_query_service_spec.rb b/spec/services/hashtag_query_service_spec.rb
deleted file mode 100644
index 24282d2f..00000000
--- a/spec/services/hashtag_query_service_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-require 'rails_helper'
-
-describe HashtagQueryService, type: :service do
- describe '.call' do
- let(:account) { Fabricate(:account) }
- let(:tag1) { Fabricate(:tag) }
- let(:tag2) { Fabricate(:tag) }
- let!(:status1) { Fabricate(:status, tags: [tag1]) }
- let!(:status2) { Fabricate(:status, tags: [tag2]) }
- let!(:both) { Fabricate(:status, tags: [tag1, tag2]) }
-
- it 'can add tags in "any" mode' do
- results = subject.call(tag1, { any: [tag2.name] })
- expect(results).to include status1
- expect(results).to include status2
- expect(results).to include both
- end
-
- it 'can remove tags in "all" mode' do
- results = subject.call(tag1, { all: [tag2.name] })
- expect(results).to_not include status1
- expect(results).to_not include status2
- expect(results).to include both
- end
-
- it 'can remove tags in "none" mode' do
- results = subject.call(tag1, { none: [tag2.name] })
- expect(results).to include status1
- expect(results).to_not include status2
- expect(results).to_not include both
- end
-
- it 'ignores an invalid mode' do
- results = subject.call(tag1, { wark: [tag2.name] })
- expect(results).to include status1
- expect(results).to_not include status2
- expect(results).to include both
- end
-
- it 'handles being passed non existant tag names' do
- results = subject.call(tag1, { any: ['wark'] })
- expect(results).to include status1
- expect(results).to_not include status2
- expect(results).to include both
- end
-
- it 'can restrict to an account' do
- BlockService.new.call(account, status1.account)
- results = subject.call(tag1, { none: [tag2.name] }, account)
- expect(results).to_not include status1
- end
-
- it 'can restrict to local' do
- status1.account.update(domain: 'example.com')
- status1.update(local: false, uri: 'example.com/toot')
- results = subject.call(tag1, { any: [tag2.name] }, nil, true)
- expect(results).to_not include status1
- end
- end
-end
diff --git a/spec/services/import_service_spec.rb b/spec/services/import_service_spec.rb
deleted file mode 100644
index 8f07fc15..00000000
--- a/spec/services/import_service_spec.rb
+++ /dev/null
@@ -1,169 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ImportService, type: :service do
- let!(:account) { Fabricate(:account, locked: false) }
- let!(:bob) { Fabricate(:account, username: 'bob', locked: false) }
- let!(:eve) { Fabricate(:account, username: 'eve', domain: 'example.com', locked: false) }
-
- context 'import old-style list of muted users' do
- subject { ImportService.new }
-
- let(:csv) { attachment_fixture('mute-imports.txt') }
-
- describe 'when no accounts are muted' do
- let(:import) { Import.create(account: account, type: 'muting', data: csv) }
- it 'mutes the listed accounts, including notifications' do
- subject.call(import)
- expect(account.muting.count).to eq 2
- expect(Mute.find_by(account: account, target_account: bob).hide_notifications).to be true
- end
- end
-
- describe 'when some accounts are muted and overwrite is not set' do
- let(:import) { Import.create(account: account, type: 'muting', data: csv) }
-
- it 'mutes the listed accounts, including notifications' do
- account.mute!(bob, notifications: false)
- subject.call(import)
- expect(account.muting.count).to eq 2
- expect(Mute.find_by(account: account, target_account: bob).hide_notifications).to be true
- end
- end
-
- describe 'when some accounts are muted and overwrite is set' do
- let(:import) { Import.create(account: account, type: 'muting', data: csv, overwrite: true) }
-
- it 'mutes the listed accounts, including notifications' do
- account.mute!(bob, notifications: false)
- subject.call(import)
- expect(account.muting.count).to eq 2
- expect(Mute.find_by(account: account, target_account: bob).hide_notifications).to be true
- end
- end
- end
-
- context 'import new-style list of muted users' do
- subject { ImportService.new }
-
- let(:csv) { attachment_fixture('new-mute-imports.txt') }
-
- describe 'when no accounts are muted' do
- let(:import) { Import.create(account: account, type: 'muting', data: csv) }
- it 'mutes the listed accounts, respecting notifications' do
- subject.call(import)
- expect(account.muting.count).to eq 2
- expect(Mute.find_by(account: account, target_account: bob).hide_notifications).to be true
- expect(Mute.find_by(account: account, target_account: eve).hide_notifications).to be false
- end
- end
-
- describe 'when some accounts are muted and overwrite is not set' do
- let(:import) { Import.create(account: account, type: 'muting', data: csv) }
-
- it 'mutes the listed accounts, respecting notifications' do
- account.mute!(bob, notifications: true)
- subject.call(import)
- expect(account.muting.count).to eq 2
- expect(Mute.find_by(account: account, target_account: bob).hide_notifications).to be true
- expect(Mute.find_by(account: account, target_account: eve).hide_notifications).to be false
- end
- end
-
- describe 'when some accounts are muted and overwrite is set' do
- let(:import) { Import.create(account: account, type: 'muting', data: csv, overwrite: true) }
-
- it 'mutes the listed accounts, respecting notifications' do
- account.mute!(bob, notifications: true)
- subject.call(import)
- expect(account.muting.count).to eq 2
- expect(Mute.find_by(account: account, target_account: bob).hide_notifications).to be true
- expect(Mute.find_by(account: account, target_account: eve).hide_notifications).to be false
- end
- end
- end
-
- context 'import old-style list of followed users' do
- subject { ImportService.new }
-
- let(:csv) { attachment_fixture('mute-imports.txt') }
-
- before do
- allow(NotificationWorker).to receive(:perform_async)
- end
-
- describe 'when no accounts are followed' do
- let(:import) { Import.create(account: account, type: 'following', data: csv) }
- it 'follows the listed accounts, including reposts' do
- subject.call(import)
- expect(account.following.count).to eq 2
- expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true
- end
- end
-
- describe 'when some accounts are already followed and overwrite is not set' do
- let(:import) { Import.create(account: account, type: 'following', data: csv) }
-
- it 'follows the listed accounts, including notifications' do
- account.follow!(bob, reblogs: false)
- subject.call(import)
- expect(account.following.count).to eq 2
- expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true
- end
- end
-
- describe 'when some accounts are already followed and overwrite is set' do
- let(:import) { Import.create(account: account, type: 'following', data: csv, overwrite: true) }
-
- it 'mutes the listed accounts, including notifications' do
- account.follow!(bob, reblogs: false)
- subject.call(import)
- expect(account.following.count).to eq 2
- expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true
- end
- end
- end
-
- context 'import new-style list of followed users' do
- subject { ImportService.new }
-
- let(:csv) { attachment_fixture('new-following-imports.txt') }
-
- before do
- allow(NotificationWorker).to receive(:perform_async)
- end
-
- describe 'when no accounts are followed' do
- let(:import) { Import.create(account: account, type: 'following', data: csv) }
- it 'follows the listed accounts, respecting reposts' do
- subject.call(import)
- expect(account.following.count).to eq 2
- expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true
- expect(Follow.find_by(account: account, target_account: eve).show_reblogs).to be false
- end
- end
-
- describe 'when some accounts are already followed and overwrite is not set' do
- let(:import) { Import.create(account: account, type: 'following', data: csv) }
-
- it 'mutes the listed accounts, respecting notifications' do
- account.follow!(bob, reblogs: true)
- subject.call(import)
- expect(account.following.count).to eq 2
- expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true
- expect(Follow.find_by(account: account, target_account: eve).show_reblogs).to be false
- end
- end
-
- describe 'when some accounts are already followed and overwrite is set' do
- let(:import) { Import.create(account: account, type: 'following', data: csv, overwrite: true) }
-
- it 'mutes the listed accounts, respecting notifications' do
- account.follow!(bob, reblogs: true)
- subject.call(import)
- expect(account.following.count).to eq 2
- expect(Follow.find_by(account: account, target_account: bob).show_reblogs).to be true
- expect(Follow.find_by(account: account, target_account: eve).show_reblogs).to be false
- end
- end
- end
-end
diff --git a/spec/services/mute_service_spec.rb b/spec/services/mute_service_spec.rb
deleted file mode 100644
index 4bb839b8..00000000
--- a/spec/services/mute_service_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe MuteService, type: :service do
- subject do
- -> { described_class.new.call(account, target_account) }
- end
-
- let(:account) { Fabricate(:account) }
- let(:target_account) { Fabricate(:account) }
-
- describe 'home timeline' do
- let(:status) { Fabricate(:status, account: target_account) }
- let(:other_account_status) { Fabricate(:status) }
- let(:home_timeline_key) { FeedManager.instance.key(:home, account.id) }
-
- before do
- Redis.current.del(home_timeline_key)
- end
-
- it "clears account's statuses" do
- FeedManager.instance.push_to_home(account, status)
- FeedManager.instance.push_to_home(account, other_account_status)
-
- is_expected.to change {
- Redis.current.zrange(home_timeline_key, 0, -1)
- }.from([status.id.to_s, other_account_status.id.to_s]).to([other_account_status.id.to_s])
- end
- end
-
- it 'mutes account' do
- is_expected.to change {
- account.muting?(target_account)
- }.from(false).to(true)
- end
-
- context 'without specifying a notifications parameter' do
- it 'mutes notifications from the account' do
- is_expected.to change {
- account.muting_notifications?(target_account)
- }.from(false).to(true)
- end
- end
-
- context 'with a true notifications parameter' do
- subject do
- -> { described_class.new.call(account, target_account, notifications: true) }
- end
-
- it 'mutes notifications from the account' do
- is_expected.to change {
- account.muting_notifications?(target_account)
- }.from(false).to(true)
- end
- end
-
- context 'with a false notifications parameter' do
- subject do
- -> { described_class.new.call(account, target_account, notifications: false) }
- end
-
- it 'does not mute notifications from the account' do
- is_expected.to_not change {
- account.muting_notifications?(target_account)
- }.from(false)
- end
- end
-end
diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb
deleted file mode 100644
index 440018ac..00000000
--- a/spec/services/notify_service_spec.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe NotifyService, type: :service do
- subject do
- -> { described_class.new.call(recipient, activity) }
- end
-
- let(:user) { Fabricate(:user) }
- let(:recipient) { user.account }
- let(:sender) { Fabricate(:account, domain: 'example.com') }
- let(:activity) { Fabricate(:follow, account: sender, target_account: recipient) }
-
- it { is_expected.to change(Notification, :count).by(1) }
-
- it 'does not notify when sender is blocked' do
- recipient.block!(sender)
- is_expected.to_not change(Notification, :count)
- end
-
- it 'does not notify when sender is muted with hide_notifications' do
- recipient.mute!(sender, notifications: true)
- is_expected.to_not change(Notification, :count)
- end
-
- it 'does notify when sender is muted without hide_notifications' do
- recipient.mute!(sender, notifications: false)
- is_expected.to change(Notification, :count)
- end
-
- it 'does not notify when sender\'s domain is blocked' do
- recipient.block_domain!(sender.domain)
- is_expected.to_not change(Notification, :count)
- end
-
- it 'does still notify when sender\'s domain is blocked but sender is followed' do
- recipient.block_domain!(sender.domain)
- recipient.follow!(sender)
- is_expected.to change(Notification, :count)
- end
-
- it 'does not notify when sender is silenced and not followed' do
- sender.silence!
- is_expected.to_not change(Notification, :count)
- end
-
- it 'does not notify when recipient is suspended' do
- recipient.suspend!
- is_expected.to_not change(Notification, :count)
- end
-
- context 'for direct messages' do
- let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct)) }
-
- before do
- user.settings.interactions = user.settings.interactions.merge('must_be_following_dm' => enabled)
- end
-
- context 'if recipient is supposed to be following sender' do
- let(:enabled) { true }
-
- it 'does not notify' do
- is_expected.to_not change(Notification, :count)
- end
-
- context 'if the message chain initiated by recipient, but is not direct message' do
- let(:reply_to) { Fabricate(:status, account: recipient) }
- let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct, thread: reply_to)) }
-
- it 'does not notify' do
- is_expected.to_not change(Notification, :count)
- end
- end
-
- context 'if the message chain initiated by recipient and is direct message' do
- let(:reply_to) { Fabricate(:status, account: recipient, visibility: :direct) }
- let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct, thread: reply_to)) }
-
- it 'does notify' do
- is_expected.to change(Notification, :count)
- end
- end
- end
-
- context 'if recipient is NOT supposed to be following sender' do
- let(:enabled) { false }
-
- it 'does notify' do
- is_expected.to change(Notification, :count)
- end
- end
- end
-
- describe 'reblogs' do
- let(:status) { Fabricate(:status, account: Fabricate(:account)) }
- let(:activity) { Fabricate(:status, account: sender, reblog: status) }
-
- it 'shows reblogs by default' do
- recipient.follow!(sender)
- is_expected.to change(Notification, :count)
- end
-
- it 'shows reblogs when explicitly enabled' do
- recipient.follow!(sender, reblogs: true)
- is_expected.to change(Notification, :count)
- end
-
- it 'shows reblogs when disabled' do
- recipient.follow!(sender, reblogs: false)
- is_expected.to change(Notification, :count)
- end
- end
-
- context do
- let(:asshole) { Fabricate(:account, username: 'asshole') }
- let(:reply_to) { Fabricate(:status, account: asshole) }
- let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, thread: reply_to)) }
-
- it 'does not notify when conversation is muted' do
- recipient.mute_conversation!(activity.status.conversation)
- is_expected.to_not change(Notification, :count)
- end
-
- it 'does not notify when it is a reply to a blocked user' do
- recipient.block!(asshole)
- is_expected.to_not change(Notification, :count)
- end
- end
-
- context do
- let(:sender) { recipient }
-
- it 'does not notify when recipient is the sender' do
- is_expected.to_not change(Notification, :count)
- end
- end
-
- describe 'email' do
- before do
- ActionMailer::Base.deliveries.clear
-
- notification_emails = user.settings.notification_emails
- user.settings.notification_emails = notification_emails.merge('follow' => enabled)
- end
-
- context 'when email notification is enabled' do
- let(:enabled) { true }
-
- it 'sends email' do
- is_expected.to change(ActionMailer::Base.deliveries, :count).by(1)
- end
- end
-
- context 'when email notification is disabled' do
- let(:enabled) { false }
-
- it "doesn't send email" do
- is_expected.to_not change(ActionMailer::Base.deliveries, :count).from(0)
- end
- end
- end
-end
diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb
deleted file mode 100644
index 11db7fb2..00000000
--- a/spec/services/post_status_service_spec.rb
+++ /dev/null
@@ -1,243 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe PostStatusService, type: :service do
- subject { PostStatusService.new }
-
- it 'creates a new status' do
- account = Fabricate(:account)
- text = "test status update"
-
- status = subject.call(account, text: text)
-
- expect(status).to be_persisted
- expect(status.text).to eq text
- end
-
- it 'creates a new response status' do
- in_reply_to_status = Fabricate(:status)
- account = Fabricate(:account)
- text = "test status update"
-
- status = subject.call(account, text: text, thread: in_reply_to_status)
-
- expect(status).to be_persisted
- expect(status.text).to eq text
- expect(status.thread).to eq in_reply_to_status
- end
-
- it 'schedules a status' do
- account = Fabricate(:account)
- future = Time.now.utc + 2.hours
-
- status = subject.call(account, text: 'Hi future!', scheduled_at: future)
-
- expect(status).to be_a ScheduledStatus
- expect(status.scheduled_at).to eq future
- expect(status.params['text']).to eq 'Hi future!'
- end
-
- it 'does not immediately create a status when scheduling a status' do
- account = Fabricate(:account)
- media = Fabricate(:media_attachment)
- future = Time.now.utc + 2.hours
-
- status = subject.call(account, text: 'Hi future!', media_ids: [media.id], scheduled_at: future)
-
- expect(status).to be_a ScheduledStatus
- expect(status.scheduled_at).to eq future
- expect(status.params['text']).to eq 'Hi future!'
- expect(media.reload.status).to be_nil
- expect(Status.where(text: 'Hi future!').exists?).to be_falsey
- end
-
- it 'creates response to the original status of repost' do
- reposted_status = Fabricate(:status)
- in_reply_to_status = Fabricate(:status, reblog: reposted_status)
- account = Fabricate(:account)
- text = "test status update"
-
- status = subject.call(account, text: text, thread: in_reply_to_status)
-
- expect(status).to be_persisted
- expect(status.text).to eq text
- expect(status.thread).to eq reposted_status
- end
-
- it 'creates a sensitive status' do
- status = create_status_with_options(sensitive: true)
-
- expect(status).to be_persisted
- expect(status).to be_sensitive
- end
-
- it 'creates a status with spoiler text' do
- spoiler_text = "spoiler text"
-
- status = create_status_with_options(spoiler_text: spoiler_text)
-
- expect(status).to be_persisted
- expect(status.spoiler_text).to eq spoiler_text
- end
-
- it 'creates a status with empty default spoiler text' do
- status = create_status_with_options(spoiler_text: nil)
-
- expect(status).to be_persisted
- expect(status.spoiler_text).to eq ''
- end
-
- it 'creates a status with the given visibility' do
- status = create_status_with_options(visibility: :private)
-
- expect(status).to be_persisted
- expect(status.visibility).to eq "private"
- end
-
- it 'creates a status with limited visibility for silenced users' do
- status = subject.call(Fabricate(:account, silenced: true), text: 'test', visibility: :public)
-
- expect(status).to be_persisted
- expect(status.visibility).to eq "unlisted"
- end
-
- it 'creates a status for the given application' do
- application = Fabricate(:application)
-
- status = create_status_with_options(application: application)
-
- expect(status).to be_persisted
- expect(status.application).to eq application
- end
-
- it 'creates a status with a language set' do
- account = Fabricate(:account)
- text = 'This is an English text.'
-
- status = subject.call(account, text: text)
-
- expect(status.language).to eq 'en'
- end
-
- it 'processes mentions' do
- mention_service = double(:process_mentions_service)
- allow(mention_service).to receive(:call)
- allow(ProcessMentionsService).to receive(:new).and_return(mention_service)
- account = Fabricate(:account)
-
- status = subject.call(account, text: "test status update")
-
- expect(ProcessMentionsService).to have_received(:new)
- expect(mention_service).to have_received(:call).with(status)
- end
-
- it 'processes hashtags' do
- hashtags_service = double(:process_hashtags_service)
- allow(hashtags_service).to receive(:call)
- allow(ProcessHashtagsService).to receive(:new).and_return(hashtags_service)
- account = Fabricate(:account)
-
- status = subject.call(account, text: "test status update")
-
- expect(ProcessHashtagsService).to have_received(:new)
- expect(hashtags_service).to have_received(:call).with(status)
- end
-
- it 'gets distributed' do
- allow(DistributionWorker).to receive(:perform_async)
- allow(Pubsubhubbub::DistributionWorker).to receive(:perform_async)
- allow(ActivityPub::DistributionWorker).to receive(:perform_async)
-
- account = Fabricate(:account)
-
- status = subject.call(account, text: "test status update")
-
- expect(DistributionWorker).to have_received(:perform_async).with(status.id)
- expect(Pubsubhubbub::DistributionWorker).to have_received(:perform_async).with(status.stream_entry.id)
- expect(ActivityPub::DistributionWorker).to have_received(:perform_async).with(status.id)
- end
-
- it 'crawls links' do
- allow(LinkCrawlWorker).to receive(:perform_async)
- account = Fabricate(:account)
-
- status = subject.call(account, text: "test status update")
-
- expect(LinkCrawlWorker).to have_received(:perform_async).with(status.id)
- end
-
- it 'attaches the given media to the created status' do
- account = Fabricate(:account)
- media = Fabricate(:media_attachment, account: account)
-
- status = subject.call(
- account,
- text: "test status update",
- media_ids: [media.id],
- )
-
- expect(media.reload.status).to eq status
- end
-
- it 'does not attach media from another account to the created status' do
- account = Fabricate(:account)
- media = Fabricate(:media_attachment, account: Fabricate(:account))
-
- status = subject.call(
- account,
- text: "test status update",
- media_ids: [media.id],
- )
-
- expect(media.reload.status).to eq nil
- end
-
- it 'does not allow attaching more than 4 files' do
- account = Fabricate(:account)
-
- expect do
- subject.call(
- account,
- text: "test status update",
- media_ids: [
- Fabricate(:media_attachment, account: account),
- Fabricate(:media_attachment, account: account),
- Fabricate(:media_attachment, account: account),
- Fabricate(:media_attachment, account: account),
- Fabricate(:media_attachment, account: account),
- ].map(&:id),
- )
- end.to raise_error(
- GabSocial::ValidationError,
- I18n.t('media_attachments.validations.too_many'),
- )
- end
-
- it 'does not allow attaching both videos and images' do
- account = Fabricate(:account)
-
- expect do
- subject.call(
- account,
- text: "test status update",
- media_ids: [
- Fabricate(:media_attachment, type: :video, account: account),
- Fabricate(:media_attachment, type: :image, account: account),
- ].map(&:id),
- )
- end.to raise_error(
- GabSocial::ValidationError,
- I18n.t('media_attachments.validations.images_and_video'),
- )
- end
-
- it 'returns existing status when used twice with idempotency key' do
- account = Fabricate(:account)
- status1 = subject.call(account, text: 'test', idempotency: 'meepmeep')
- status2 = subject.call(account, text: 'test', idempotency: 'meepmeep')
- expect(status2.id).to eq status1.id
- end
-
- def create_status_with_options(**options)
- subject.call(Fabricate(:account), options.merge(text: 'test'))
- end
-end
diff --git a/spec/services/precompute_feed_service_spec.rb b/spec/services/precompute_feed_service_spec.rb
deleted file mode 100644
index 1f6b6ed8..00000000
--- a/spec/services/precompute_feed_service_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe PrecomputeFeedService, type: :service do
- subject { PrecomputeFeedService.new }
-
- describe 'call' do
- let(:account) { Fabricate(:account) }
- it 'fills a user timeline with statuses' do
- account = Fabricate(:account)
- status = Fabricate(:status, account: account)
-
- subject.call(account)
-
- expect(Redis.current.zscore(FeedManager.instance.key(:home, account.id), status.id)).to be_within(0.1).of(status.id.to_f)
- end
-
- it 'does not raise an error even if it could not find any status' do
- account = Fabricate(:account)
- subject.call(account)
- end
-
- it 'filters statuses' do
- account = Fabricate(:account)
- muted_account = Fabricate(:account)
- Fabricate(:mute, account: account, target_account: muted_account)
- reblog = Fabricate(:status, account: muted_account)
- status = Fabricate(:status, account: account, reblog: reblog)
-
- subject.call(account)
-
- expect(Redis.current.zscore(FeedManager.instance.key(:home, account.id), reblog.id)).to eq nil
- end
- end
-end
diff --git a/spec/services/process_feed_service_spec.rb b/spec/services/process_feed_service_spec.rb
deleted file mode 100644
index ed3e592c..00000000
--- a/spec/services/process_feed_service_spec.rb
+++ /dev/null
@@ -1,252 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ProcessFeedService, type: :service do
- subject { ProcessFeedService.new }
-
- describe 'processing a feed' do
- let(:body) { File.read(Rails.root.join('spec', 'fixtures', 'xml', 'gabsocial.atom')) }
- let(:account) { Fabricate(:account, username: 'localhost', domain: 'kickass.zone') }
-
- before do
- stub_request(:post, "https://pubsubhubbub.superfeedr.com/").to_return(:status => 200, :body => "", :headers => {})
- stub_request(:head, "http://kickass.zone/media/2").to_return(:status => 404)
- stub_request(:head, "http://kickass.zone/media/3").to_return(:status => 404)
- stub_request(:get, "http://kickass.zone/system/accounts/avatars/000/000/001/large/eris.png").to_return(request_fixture('avatar.txt'))
- stub_request(:get, "http://kickass.zone/system/media_attachments/files/000/000/002/original/morpheus_linux.jpg?1476059910").to_return(request_fixture('attachment1.txt'))
- stub_request(:get, "http://kickass.zone/system/media_attachments/files/000/000/003/original/gizmo.jpg?1476060065").to_return(request_fixture('attachment2.txt'))
- end
-
- context 'when domain does not reject media' do
- before do
- subject.call(body, account)
- end
-
- it 'updates remote user\'s account information' do
- account.reload
- expect(account.display_name).to eq '::1'
- expect(account).to have_attached_file(:avatar)
- expect(account.avatar_file_name).not_to be_nil
- end
-
- it 'creates posts' do
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=1:objectType=Status')).to_not be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=2:objectType=Status')).to_not be_nil
- end
-
- it 'marks replies as replies' do
- status = Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=2:objectType=Status')
- expect(status.reply?).to be true
- end
-
- it 'sets account being replied to when possible' do
- status = Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=2:objectType=Status')
- expect(status.in_reply_to_account_id).to eq status.account_id
- end
-
- it 'ignores delete statuses unless they existed before' do
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=3:objectType=Status')).to be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=12:objectType=Status')).to be_nil
- end
-
- it 'does not create statuses for follows' do
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=1:objectType=Follow')).to be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=2:objectType=Follow')).to be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=4:objectType=Follow')).to be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=7:objectType=Follow')).to be_nil
- end
-
- it 'does not create statuses for favourites' do
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=2:objectType=Favourite')).to be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=3:objectType=Favourite')).to be_nil
- end
-
- it 'creates posts with media' do
- status = Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=14:objectType=Status')
-
- expect(status).to_not be_nil
- expect(status.media_attachments.first).to have_attached_file(:file)
- expect(status.media_attachments.first.image?).to be true
- expect(status.media_attachments.first.file_file_name).not_to be_nil
- end
- end
-
- context 'when domain is set to reject media' do
- let!(:domain_block) { Fabricate(:domain_block, domain: 'kickass.zone', reject_media: true) }
-
- before do
- subject.call(body, account)
- end
-
- it 'updates remote user\'s account information' do
- account.reload
- expect(account.display_name).to eq '::1'
- end
-
- it 'rejects remote user\'s avatar' do
- account.reload
- expect(account.display_name).to eq '::1'
- expect(account.avatar_file_name).to be_nil
- end
-
- it 'creates posts' do
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=1:objectType=Status')).to_not be_nil
- expect(Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=2:objectType=Status')).to_not be_nil
- end
-
- it 'creates posts with remote-only media' do
- status = Status.find_by(uri: 'tag:kickass.zone,2016-10-10:objectId=14:objectType=Status')
-
- expect(status).to_not be_nil
- expect(status.media_attachments.first.file_file_name).to be_nil
- expect(status.media_attachments.first.unknown?).to be true
- end
- end
- end
-
- it 'does not accept tampered reblogs' do
- good_actor = Fabricate(:account, username: 'tracer', domain: 'overwatch.com')
-
- real_body = <
-
- tag:overwatch.com,2017-04-27:objectId=4467137:objectType=Status
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- https://overwatch.com/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://overwatch.com/users/tracer
- tracer
-
- Overwatch rocks
-
-XML
-
- stub_request(:get, 'https://overwatch.com/users/tracer/updates/1').to_return(status: 200, body: real_body, headers: { 'Content-Type' => 'application/atom+xml' })
-
- bad_actor = Fabricate(:account, username: 'sombra', domain: 'talon.xyz')
-
- body = <
-
- tag:talon.xyz,2017-04-27:objectId=4467137:objectType=Status
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
-
- https://talon.xyz/users/sombra
- http://activitystrea.ms/schema/1.0/person
- https://talon.xyz/users/sombra
- sombra
-
- http://activitystrea.ms/schema/1.0/activity
- http://activitystrea.ms/schema/1.0/share
- Overwatch SUCKS AHAHA
-
- tag:overwatch.com,2017-04-27:objectId=4467137:objectType=Status
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- https://overwatch.com/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://overwatch.com/users/tracer
- tracer
-
- Overwatch SUCKS AHAHA
-
-
-
-XML
- created_statuses = subject.call(body, bad_actor)
-
- expect(created_statuses.first.reblog?).to be true
- expect(created_statuses.first.account_id).to eq bad_actor.id
- expect(created_statuses.first.reblog.account_id).to eq good_actor.id
- expect(created_statuses.first.reblog.text).to eq 'Overwatch rocks'
- end
-
- it 'ignores reblogs if it failed to retrieve reblogged statuses' do
- stub_request(:get, 'https://overwatch.com/users/tracer/updates/1').to_return(status: 404)
-
- actor = Fabricate(:account, username: 'tracer', domain: 'overwatch.com')
-
- body = <
-
- tag:overwatch.com,2017-04-27:objectId=4467137:objectType=Status
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
-
- https://overwatch.com/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://overwatch.com/users/tracer
- tracer
-
- http://activitystrea.ms/schema/1.0/activity
- http://activitystrea.ms/schema/1.0/share
- Overwatch rocks
-
- tag:overwatch.com,2017-04-27:objectId=4467137:objectType=Status
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- https://overwatch.com/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://overwatch.com/users/tracer
- tracer
-
- Overwatch rocks
-
-
-XML
-
- created_statuses = subject.call(body, actor)
-
- expect(created_statuses).to eq []
- end
-
- it 'ignores statuses with an out-of-order delete' do
- sender = Fabricate(:account, username: 'tracer', domain: 'overwatch.com')
-
- delete_body = <
-
- tag:overwatch.com,2017-04-27:objectId=4487555:objectType=Status
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/delete
-
- https://overwatch.com/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://overwatch.com/users/tracer
- tracer
-
-
-XML
-
- status_body = <
-
- tag:overwatch.com,2017-04-27:objectId=4487555:objectType=Status
- 2017-04-27T13:49:25Z
- 2017-04-27T13:49:25Z
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
-
- https://overwatch.com/users/tracer
- http://activitystrea.ms/schema/1.0/person
- https://overwatch.com/users/tracer
- tracer
-
- Overwatch rocks
-
-XML
-
- subject.call(delete_body, sender)
- created_statuses = subject.call(status_body, sender)
-
- expect(created_statuses).to be_empty
- end
-end
diff --git a/spec/services/process_interaction_service_spec.rb b/spec/services/process_interaction_service_spec.rb
deleted file mode 100644
index b858c19d..00000000
--- a/spec/services/process_interaction_service_spec.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ProcessInteractionService, type: :service do
- let(:receiver) { Fabricate(:user, email: 'alice@example.com', account: Fabricate(:account, username: 'alice')).account }
- let(:sender) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
- let(:remote_sender) { Fabricate(:account, username: 'carol', domain: 'localdomain.com', uri: 'https://webdomain.com/users/carol') }
-
- subject { ProcessInteractionService.new }
-
- describe 'status delete slap' do
- let(:remote_status) { Fabricate(:status, account: remote_sender) }
- let(:envelope) { OStatus2::Salmon.new.pack(payload, sender.keypair) }
- let(:payload) {
- <<~XML
-
-
- carol@localdomain.com
- carol
- https://webdomain.com/users/carol
-
-
- #{remote_status.id}
- http://activitystrea.ms/schema/1.0/delete
-
- XML
- }
-
- before do
- receiver.update(locked: true)
- remote_sender.update(private_key: sender.private_key, public_key: remote_sender.public_key)
- end
-
- it 'deletes a record' do
- expect(RemovalWorker).to receive(:perform_async).with(remote_status.id)
- subject.call(envelope, receiver)
- end
- end
-
- describe 'follow request slap' do
- before do
- receiver.update(locked: true)
-
- payload = <
-
- bob
- https://cb6e6126.ngrok.io/users/bob
-
-
- someIdHere
- http://activitystrea.ms/schema/1.0/request-friend
-
-XML
-
- envelope = OStatus2::Salmon.new.pack(payload, sender.keypair)
- subject.call(envelope, receiver)
- end
-
- it 'creates a record' do
- expect(FollowRequest.find_by(account: sender, target_account: receiver)).to_not be_nil
- end
- end
-
- describe 'follow request slap from known remote user identified by email' do
- before do
- receiver.update(locked: true)
- # Copy already-generated key
- remote_sender.update(private_key: sender.private_key, public_key: remote_sender.public_key)
-
- payload = <
-
- carol@localdomain.com
- carol
- https://webdomain.com/users/carol
-
-
- someIdHere
- http://activitystrea.ms/schema/1.0/request-friend
-
-XML
-
- envelope = OStatus2::Salmon.new.pack(payload, remote_sender.keypair)
- subject.call(envelope, receiver)
- end
-
- it 'creates a record' do
- expect(FollowRequest.find_by(account: remote_sender, target_account: receiver)).to_not be_nil
- end
- end
-
- describe 'follow request authorization slap' do
- before do
- receiver.update(locked: true)
- FollowRequest.create(account: sender, target_account: receiver)
-
- payload = <
-
- alice
- https://cb6e6126.ngrok.io/users/alice
-
-
- someIdHere
- http://activitystrea.ms/schema/1.0/authorize
-
-XML
-
- envelope = OStatus2::Salmon.new.pack(payload, receiver.keypair)
- subject.call(envelope, sender)
- end
-
- it 'creates a follow relationship' do
- expect(Follow.find_by(account: sender, target_account: receiver)).to_not be_nil
- end
-
- it 'removes the follow request' do
- expect(FollowRequest.find_by(account: sender, target_account: receiver)).to be_nil
- end
- end
-
- describe 'follow request rejection slap' do
- before do
- receiver.update(locked: true)
- FollowRequest.create(account: sender, target_account: receiver)
-
- payload = <
-
- alice
- https://cb6e6126.ngrok.io/users/alice
-
-
- someIdHere
- http://activitystrea.ms/schema/1.0/reject
-
-XML
-
- envelope = OStatus2::Salmon.new.pack(payload, receiver.keypair)
- subject.call(envelope, sender)
- end
-
- it 'does not create a follow relationship' do
- expect(Follow.find_by(account: sender, target_account: receiver)).to be_nil
- end
-
- it 'removes the follow request' do
- expect(FollowRequest.find_by(account: sender, target_account: receiver)).to be_nil
- end
- end
-end
diff --git a/spec/services/process_mentions_service_spec.rb b/spec/services/process_mentions_service_spec.rb
deleted file mode 100644
index 4ce55697..00000000
--- a/spec/services/process_mentions_service_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ProcessMentionsService, type: :service do
- let(:account) { Fabricate(:account, username: 'alice') }
- let(:visibility) { :public }
- let(:status) { Fabricate(:status, account: account, text: "Hello @#{remote_user.acct}", visibility: visibility) }
-
- context 'OStatus with public gab' do
- let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') }
-
- subject { ProcessMentionsService.new }
-
- before do
- stub_request(:post, remote_user.salmon_url)
- subject.call(status)
- end
-
- it 'creates a mention' do
- expect(remote_user.mentions.where(status: status).count).to eq 1
- end
-
- it 'posts to remote user\'s Salmon end point' do
- expect(a_request(:post, remote_user.salmon_url)).to have_been_made.once
- end
- end
-
- context 'OStatus with private gab' do
- let(:visibility) { :private }
- let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com') }
-
- subject { ProcessMentionsService.new }
-
- before do
- stub_request(:post, remote_user.salmon_url)
- subject.call(status)
- end
-
- it 'does not create a mention' do
- expect(remote_user.mentions.where(status: status).count).to eq 0
- end
-
- it 'does not post to remote user\'s Salmon end point' do
- expect(a_request(:post, remote_user.salmon_url)).to_not have_been_made
- end
- end
-
- context 'ActivityPub' do
- let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
-
- subject { ProcessMentionsService.new }
-
- before do
- stub_request(:post, remote_user.inbox_url)
- subject.call(status)
- end
-
- it 'creates a mention' do
- expect(remote_user.mentions.where(status: status).count).to eq 1
- end
-
- it 'sends activity to the inbox' do
- expect(a_request(:post, remote_user.inbox_url)).to have_been_made.once
- end
- end
-
- context 'Temporarily-unreachable ActivityPub user' do
- let(:remote_user) { Fabricate(:account, username: 'remote_user', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox', last_webfingered_at: nil) }
-
- subject { ProcessMentionsService.new }
-
- before do
- stub_request(:get, "https://example.com/.well-known/host-meta").to_return(status: 404)
- stub_request(:get, "https://example.com/.well-known/webfinger?resource=acct:remote_user@example.com").to_return(status: 500)
- stub_request(:post, remote_user.inbox_url)
- subject.call(status)
- end
-
- it 'creates a mention' do
- expect(remote_user.mentions.where(status: status).count).to eq 1
- end
-
- it 'sends activity to the inbox' do
- expect(a_request(:post, remote_user.inbox_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/pubsubhubbub/subscribe_service_spec.rb b/spec/services/pubsubhubbub/subscribe_service_spec.rb
deleted file mode 100644
index 01c95623..00000000
--- a/spec/services/pubsubhubbub/subscribe_service_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Pubsubhubbub::SubscribeService, type: :service do
- describe '#call' do
- subject { described_class.new }
- let(:user_account) { Fabricate(:account) }
-
- context 'with a nil account' do
- it 'returns the invalid topic status results' do
- result = service_call(account: nil)
-
- expect(result).to eq invalid_topic_status
- end
- end
-
- context 'with an invalid callback url' do
- it 'returns invalid callback status when callback is blank' do
- result = service_call(callback: '')
-
- expect(result).to eq invalid_callback_status
- end
- it 'returns invalid callback status when callback is not a URI' do
- result = service_call(callback: 'invalid-hostname')
-
- expect(result).to eq invalid_callback_status
- end
- end
-
- context 'with a blocked domain in the callback' do
- it 'returns callback not allowed' do
- Fabricate(:domain_block, domain: 'test.host', severity: :suspend)
- result = service_call(callback: 'https://test.host/api')
-
- expect(result).to eq not_allowed_callback_status
- end
- end
-
- context 'with a valid account and callback' do
- it 'returns success status and confirms subscription' do
- allow(Pubsubhubbub::ConfirmationWorker).to receive(:perform_async).and_return(nil)
- subscription = Fabricate(:subscription, account: user_account)
-
- result = service_call(callback: subscription.callback_url)
- expect(result).to eq success_status
- expect(Pubsubhubbub::ConfirmationWorker).to have_received(:perform_async).with(subscription.id, 'subscribe', 'asdf', 3600)
- end
- end
- end
-
- def service_call(account: user_account, callback: 'https://callback.host', secret: 'asdf', lease_seconds: 3600)
- subject.call(account, callback, secret, lease_seconds)
- end
-
- def invalid_topic_status
- ['Invalid topic URL', 422]
- end
-
- def invalid_callback_status
- ['Invalid callback URL', 422]
- end
-
- def not_allowed_callback_status
- ['Callback URL not allowed', 403]
- end
-
- def success_status
- ['', 202]
- end
-end
diff --git a/spec/services/pubsubhubbub/unsubscribe_service_spec.rb b/spec/services/pubsubhubbub/unsubscribe_service_spec.rb
deleted file mode 100644
index 7ed9fc5a..00000000
--- a/spec/services/pubsubhubbub/unsubscribe_service_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Pubsubhubbub::UnsubscribeService, type: :service do
- describe '#call' do
- subject { described_class.new }
-
- context 'with a nil account' do
- it 'returns an invalid topic status' do
- result = subject.call(nil, 'callback.host')
-
- expect(result).to eq invalid_topic_status
- end
- end
-
- context 'with a valid account' do
- let(:account) { Fabricate(:account) }
-
- it 'returns a valid topic status and does not run confirm when no subscription' do
- allow(Pubsubhubbub::ConfirmationWorker).to receive(:perform_async).and_return(nil)
- result = subject.call(account, 'callback.host')
-
- expect(result).to eq valid_topic_status
- expect(Pubsubhubbub::ConfirmationWorker).not_to have_received(:perform_async)
- end
-
- it 'returns a valid topic status and does run confirm when there is a subscription' do
- subscription = Fabricate(:subscription, account: account, callback_url: 'callback.host')
- allow(Pubsubhubbub::ConfirmationWorker).to receive(:perform_async).and_return(nil)
- result = subject.call(account, 'callback.host')
-
- expect(result).to eq valid_topic_status
- expect(Pubsubhubbub::ConfirmationWorker).to have_received(:perform_async).with(subscription.id, 'unsubscribe')
- end
- end
-
- def invalid_topic_status
- ['Invalid topic URL', 422]
- end
-
- def valid_topic_status
- ['', 202]
- end
- end
-end
diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb
deleted file mode 100644
index 8363a9a7..00000000
--- a/spec/services/reblog_service_spec.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ReblogService, type: :service do
- let(:alice) { Fabricate(:account, username: 'alice') }
-
- context 'creates a reblog with appropriate visibility' do
- let(:visibility) { :public }
- let(:reblog_visibility) { :public }
- let(:status) { Fabricate(:status, account: alice, visibility: visibility) }
-
- subject { ReblogService.new }
-
- before do
- subject.call(alice, status, visibility: reblog_visibility)
- end
-
- describe 'reposting privately' do
- let(:reblog_visibility) { :private }
-
- it 'reblogs privately' do
- expect(status.reblogs.first.visibility).to eq 'private'
- end
- end
-
- describe 'public reblogs of private toots should remain private' do
- let(:visibility) { :private }
- let(:reblog_visibility) { :public }
-
- it 'reblogs privately' do
- expect(status.reblogs.first.visibility).to eq 'private'
- end
- end
- end
-
- context 'OStatus' do
- let(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com') }
- let(:status) { Fabricate(:status, account: bob, uri: 'tag:example.com;something:something') }
-
- subject { ReblogService.new }
-
- before do
- stub_request(:post, 'http://salmon.example.com')
- subject.call(alice, status)
- end
-
- it 'creates a reblog' do
- expect(status.reblogs.count).to eq 1
- end
-
- it 'sends a Salmon slap for a remote reblog' do
- expect(a_request(:post, 'http://salmon.example.com')).to have_been_made
- end
- end
-
- context 'ActivityPub' do
- let(:bob) { Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
- let(:status) { Fabricate(:status, account: bob) }
-
- subject { ReblogService.new }
-
- before do
- stub_request(:post, bob.inbox_url)
- allow(ActivityPub::DistributionWorker).to receive(:perform_async)
- subject.call(alice, status)
- end
-
- it 'creates a reblog' do
- expect(status.reblogs.count).to eq 1
- end
-
- describe 'after_create_commit :store_uri' do
- it 'keeps consistent reblog count' do
- expect(status.reblogs.count).to eq 1
- end
- end
-
- it 'distributes to followers' do
- expect(ActivityPub::DistributionWorker).to have_received(:perform_async)
- end
-
- it 'sends an announce activity to the author' do
- expect(a_request(:post, bob.inbox_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/reject_follow_service_spec.rb b/spec/services/reject_follow_service_spec.rb
deleted file mode 100644
index e5ac37ed..00000000
--- a/spec/services/reject_follow_service_spec.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe RejectFollowService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { RejectFollowService.new }
-
- describe 'local' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- FollowRequest.create(account: bob, target_account: sender)
- subject.call(bob, sender)
- end
-
- it 'removes follow request' do
- expect(bob.requested?(sender)).to be false
- end
-
- it 'does not create follow relation' do
- expect(bob.following?(sender)).to be false
- end
- end
-
- describe 'remote OStatus' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
-
- before do
- FollowRequest.create(account: bob, target_account: sender)
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(bob, sender)
- end
-
- it 'removes follow request' do
- expect(bob.requested?(sender)).to be false
- end
-
- it 'does not create follow relation' do
- expect(bob.following?(sender)).to be false
- end
-
- it 'sends a follow request rejection salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:reject])
- }).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox')).account }
-
- before do
- FollowRequest.create(account: bob, target_account: sender)
- stub_request(:post, bob.inbox_url).to_return(status: 200)
- subject.call(bob, sender)
- end
-
- it 'removes follow request' do
- expect(bob.requested?(sender)).to be false
- end
-
- it 'does not create follow relation' do
- expect(bob.following?(sender)).to be false
- end
-
- it 'sends a reject activity' do
- expect(a_request(:post, bob.inbox_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb
deleted file mode 100644
index 7bba83a6..00000000
--- a/spec/services/remove_status_service_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe RemoveStatusService, type: :service do
- subject { RemoveStatusService.new }
-
- let!(:alice) { Fabricate(:account) }
- let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://example.com/salmon') }
- let!(:jeff) { Fabricate(:account) }
- let!(:hank) { Fabricate(:account, username: 'hank', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
- let!(:bill) { Fabricate(:account, username: 'bill', protocol: :activitypub, domain: 'example2.com', inbox_url: 'http://example2.com/inbox') }
-
- before do
- stub_request(:post, 'http://example.com/push').to_return(status: 200, body: '', headers: {})
- stub_request(:post, 'http://example.com/salmon').to_return(status: 200, body: '', headers: {})
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- stub_request(:post, 'http://example2.com/inbox').to_return(status: 200)
-
- Fabricate(:subscription, account: alice, callback_url: 'http://example.com/push', confirmed: true, expires_at: 30.days.from_now)
- jeff.follow!(alice)
- hank.follow!(alice)
-
- @status = PostStatusService.new.call(alice, text: 'Hello @bob@example.com')
- Fabricate(:status, account: bill, reblog: @status, uri: 'hoge')
- subject.call(@status)
- end
-
- it 'removes status from author\'s home feed' do
- expect(HomeFeed.new(alice).get(10)).to_not include(@status.id)
- end
-
- it 'removes status from local follower\'s home feed' do
- expect(HomeFeed.new(jeff).get(10)).to_not include(@status.id)
- end
-
- it 'sends PuSH update to PuSH subscribers' do
- expect(a_request(:post, 'http://example.com/push').with { |req|
- req.body.match(OStatus::TagManager::VERBS[:delete])
- }).to have_been_made
- end
-
- it 'sends delete activity to followers' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.twice
- end
-
- it 'sends Salmon slap to previously mentioned users' do
- expect(a_request(:post, "http://example.com/salmon").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:delete])
- }).to have_been_made.once
- end
-
- it 'sends delete activity to rebloggers' do
- expect(a_request(:post, 'http://example2.com/inbox')).to have_been_made
- end
-end
diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb
deleted file mode 100644
index 454e4d89..00000000
--- a/spec/services/report_service_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ReportService, type: :service do
- subject { described_class.new }
-
- let(:source_account) { Fabricate(:user).account }
-
- context 'for a remote account' do
- let(:remote_account) { Fabricate(:account, domain: 'example.com', protocol: :activitypub, inbox_url: 'http://example.com/inbox') }
-
- before do
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- end
-
- it 'sends ActivityPub payload when forward is true' do
- subject.call(source_account, remote_account, forward: true)
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made
- end
-
- it 'does not send anything when forward is false' do
- subject.call(source_account, remote_account, forward: false)
- expect(a_request(:post, 'http://example.com/inbox')).to_not have_been_made
- end
-
- it 'has an uri' do
- report = subject.call(source_account, remote_account, forward: true)
- expect(report.uri).to_not be_nil
- end
- end
-
- context 'when other reports already exist for the same target' do
- let!(:target_account) { Fabricate(:account) }
- let!(:other_report) { Fabricate(:report, target_account: target_account) }
-
- subject do
- -> { described_class.new.call(source_account, target_account) }
- end
-
- before do
- ActionMailer::Base.deliveries.clear
- source_account.user.settings.notification_emails['report'] = true
- end
-
- it 'does not send an e-mail' do
- is_expected.to_not change(ActionMailer::Base.deliveries, :count).from(0)
- end
- end
-end
diff --git a/spec/services/resolve_account_service_spec.rb b/spec/services/resolve_account_service_spec.rb
deleted file mode 100644
index 2dcfa838..00000000
--- a/spec/services/resolve_account_service_spec.rb
+++ /dev/null
@@ -1,146 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe ResolveAccountService, type: :service do
- subject { described_class.new }
-
- before do
- stub_request(:get, "https://quitter.no/.well-known/host-meta").to_return(request_fixture('.host-meta.txt'))
- stub_request(:get, "https://example.com/.well-known/webfinger?resource=acct:catsrgr8@example.com").to_return(status: 404)
- stub_request(:get, "https://redirected.com/.well-known/host-meta").to_return(request_fixture('redirected.host-meta.txt'))
- stub_request(:get, "https://example.com/.well-known/host-meta").to_return(status: 404)
- stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:robcolbert@quitter.no").to_return(request_fixture('webfinger.txt'))
- stub_request(:get, "https://redirected.com/.well-known/webfinger?resource=acct:robcolbert@redirected.com").to_return(request_fixture('webfinger.txt'))
- stub_request(:get, "https://redirected.com/.well-known/webfinger?resource=acct:hacker1@redirected.com").to_return(request_fixture('webfinger-hacker1.txt'))
- stub_request(:get, "https://redirected.com/.well-known/webfinger?resource=acct:hacker2@redirected.com").to_return(request_fixture('webfinger-hacker2.txt'))
- stub_request(:get, "https://quitter.no/.well-known/webfinger?resource=acct:catsrgr8@quitter.no").to_return(status: 404)
- stub_request(:get, "https://quitter.no/api/statuses/user_timeline/7477.atom").to_return(request_fixture('feed.txt'))
- stub_request(:get, "https://quitter.no/avatar/7477-300-20160211190340.png").to_return(request_fixture('avatar.txt'))
- stub_request(:get, "https://localdomain.com/.well-known/host-meta").to_return(request_fixture('localdomain-hostmeta.txt'))
- stub_request(:get, "https://localdomain.com/.well-known/webfinger?resource=acct:foo@localdomain.com").to_return(status: 404)
- stub_request(:get, "https://webdomain.com/.well-known/webfinger?resource=acct:foo@localdomain.com").to_return(request_fixture('localdomain-webfinger.txt'))
- stub_request(:get, "https://webdomain.com/users/foo.atom").to_return(request_fixture('localdomain-feed.txt'))
- end
-
- it 'raises error if no such user can be resolved via webfinger' do
- expect(subject.call('catsrgr8@quitter.no')).to be_nil
- end
-
- it 'raises error if the domain does not have webfinger' do
- expect(subject.call('catsrgr8@example.com')).to be_nil
- end
-
- it 'prevents hijacking existing accounts' do
- account = subject.call('hacker1@redirected.com')
- expect(account.salmon_url).to_not eq 'https://hacker.com/main/salmon/user/7477'
- end
-
- it 'prevents hijacking inexisting accounts' do
- expect(subject.call('hacker2@redirected.com')).to be_nil
- end
-
- context 'with an OStatus account' do
- it 'returns an already existing remote account' do
- old_account = Fabricate(:account, username: 'robcolbert', domain: 'quitter.no')
- returned_account = subject.call('robcolbert@quitter.no')
-
- expect(old_account.id).to eq returned_account.id
- end
-
- it 'returns a new remote account' do
- account = subject.call('robcolbert@quitter.no')
-
- expect(account.username).to eq 'robcolbert'
- expect(account.domain).to eq 'quitter.no'
- expect(account.remote_url).to eq 'https://quitter.no/api/statuses/user_timeline/7477.atom'
- end
-
- it 'follows a legitimate account redirection' do
- account = subject.call('robcolbert@redirected.com')
-
- expect(account.username).to eq 'robcolbert'
- expect(account.domain).to eq 'quitter.no'
- expect(account.remote_url).to eq 'https://quitter.no/api/statuses/user_timeline/7477.atom'
- end
-
- it 'returns a new remote account' do
- account = subject.call('foo@localdomain.com')
-
- expect(account.username).to eq 'foo'
- expect(account.domain).to eq 'localdomain.com'
- expect(account.remote_url).to eq 'https://webdomain.com/users/foo.atom'
- end
- end
-
- context 'with an ActivityPub account' do
- before do
- stub_request(:get, "https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com").to_return(request_fixture('activitypub-webfinger.txt'))
- stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor.txt'))
- stub_request(:get, "https://ap.example.com/users/foo.atom").to_return(request_fixture('activitypub-feed.txt'))
- stub_request(:get, %r{https://ap.example.com/users/foo/\w+}).to_return(status: 404)
- end
-
- it 'fallback to OStatus if actor json could not be fetched' do
- stub_request(:get, "https://ap.example.com/users/foo").to_return(status: 404)
-
- account = subject.call('foo@ap.example.com')
-
- expect(account.ostatus?).to eq true
- expect(account.remote_url).to eq 'https://ap.example.com/users/foo.atom'
- end
-
- it 'fallback to OStatus if actor json did not have inbox_url' do
- stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor-noinbox.txt'))
-
- account = subject.call('foo@ap.example.com')
-
- expect(account.ostatus?).to eq true
- expect(account.remote_url).to eq 'https://ap.example.com/users/foo.atom'
- end
-
- it 'returns new remote account' do
- account = subject.call('foo@ap.example.com')
-
- expect(account.activitypub?).to eq true
- expect(account.domain).to eq 'ap.example.com'
- expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox'
- end
-
- context 'with multiple types' do
- before do
- stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor-individual.txt'))
- end
-
- it 'returns new remote account' do
- account = subject.call('foo@ap.example.com')
-
- expect(account.activitypub?).to eq true
- expect(account.domain).to eq 'ap.example.com'
- expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox'
- expect(account.actor_type).to eq 'Person'
- end
- end
- end
-
- it 'processes one remote account at a time using locks' do
- wait_for_start = true
- fail_occurred = false
- return_values = []
-
- threads = Array.new(5) do
- Thread.new do
- true while wait_for_start
- begin
- return_values << described_class.new.call('foo@localdomain.com')
- rescue ActiveRecord::RecordNotUnique
- fail_occurred = true
- end
- end
- end
-
- wait_for_start = false
- threads.each(&:join)
-
- expect(fail_occurred).to be false
- expect(return_values).to_not include(nil)
- end
-end
diff --git a/spec/services/resolve_url_service_spec.rb b/spec/services/resolve_url_service_spec.rb
deleted file mode 100644
index 7bb5d194..00000000
--- a/spec/services/resolve_url_service_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ResolveURLService, type: :service do
- subject { described_class.new }
-
- describe '#call' do
- it 'returns nil when there is no atom url' do
- url = 'http://example.com/missing-atom'
- service = double
- allow(FetchAtomService).to receive(:new).and_return service
- allow(service).to receive(:call).with(url).and_return(nil)
-
- result = subject.call(url)
- expect(result).to be_nil
- end
-
- it 'fetches remote accounts for feed types' do
- url = 'http://example.com/atom-feed'
- service = double
- allow(FetchAtomService).to receive(:new).and_return service
- feed_url = 'http://feed-url'
- feed_content = 'contents '
- allow(service).to receive(:call).with(url).and_return([feed_url, { prefetched_body: feed_content }])
-
- account_service = double
- allow(FetchRemoteAccountService).to receive(:new).and_return(account_service)
- allow(account_service).to receive(:call)
-
- _result = subject.call(url)
-
- expect(account_service).to have_received(:call).with(feed_url, feed_content, nil)
- end
-
- it 'fetches remote statuses for entry types' do
- url = 'http://example.com/atom-entry'
- service = double
- allow(FetchAtomService).to receive(:new).and_return service
- feed_url = 'http://feed-url'
- feed_content = 'contents '
- allow(service).to receive(:call).with(url).and_return([feed_url, { prefetched_body: feed_content }])
-
- account_service = double
- allow(FetchRemoteStatusService).to receive(:new).and_return(account_service)
- allow(account_service).to receive(:call)
-
- _result = subject.call(url)
-
- expect(account_service).to have_received(:call).with(feed_url, feed_content, nil)
- end
- end
-end
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
deleted file mode 100644
index d064cd9b..00000000
--- a/spec/services/search_service_spec.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe SearchService, type: :service do
- subject { described_class.new }
-
- describe '#call' do
- describe 'with a blank query' do
- it 'returns empty results without searching' do
- allow(AccountSearchService).to receive(:new)
- allow(Tag).to receive(:search_for)
- results = subject.call('', nil, 10)
-
- expect(results).to eq(empty_results)
- expect(AccountSearchService).not_to have_received(:new)
- expect(Tag).not_to have_received(:search_for)
- end
- end
-
- describe 'with an url query' do
- before do
- @query = 'http://test.host/query'
- end
-
- context 'that does not find anything' do
- it 'returns the empty results' do
- service = double(call: nil)
- allow(ResolveURLService).to receive(:new).and_return(service)
- results = subject.call(@query, nil, 10)
-
- expect(service).to have_received(:call).with(@query, on_behalf_of: nil)
- expect(results).to eq empty_results
- end
- end
-
- context 'that finds an account' do
- it 'includes the account in the results' do
- account = Account.new
- service = double(call: account)
- allow(ResolveURLService).to receive(:new).and_return(service)
-
- results = subject.call(@query, nil, 10)
- expect(service).to have_received(:call).with(@query, on_behalf_of: nil)
- expect(results).to eq empty_results.merge(accounts: [account])
- end
- end
-
- context 'that finds a status' do
- it 'includes the status in the results' do
- status = Status.new
- service = double(call: status)
- allow(ResolveURLService).to receive(:new).and_return(service)
-
- results = subject.call(@query, nil, 10)
- expect(service).to have_received(:call).with(@query, on_behalf_of: nil)
- expect(results).to eq empty_results.merge(statuses: [status])
- end
- end
- end
-
- describe 'with a non-url query' do
- context 'that matches an account' do
- it 'includes the account in the results' do
- query = 'username'
- account = Account.new
- service = double(call: [account])
- allow(AccountSearchService).to receive(:new).and_return(service)
-
- results = subject.call(query, nil, 10)
- expect(service).to have_received(:call).with(query, nil, limit: 10, offset: 0, resolve: false)
- expect(results).to eq empty_results.merge(accounts: [account])
- end
- end
-
- context 'that matches a tag' do
- it 'includes the tag in the results' do
- query = '#tag'
- tag = Tag.new
- allow(Tag).to receive(:search_for).with('tag', 10, 0).and_return([tag])
-
- results = subject.call(query, nil, 10)
- expect(Tag).to have_received(:search_for).with('tag', 10, 0)
- expect(results).to eq empty_results.merge(hashtags: [tag])
- end
- it 'does not include tag when starts with @ character' do
- query = '@username'
- allow(Tag).to receive(:search_for)
-
- results = subject.call(query, nil, 10)
- expect(Tag).not_to have_received(:search_for)
- expect(results).to eq empty_results
- end
- end
- end
- end
-
- def empty_results
- { accounts: [], hashtags: [], statuses: [] }
- end
-end
diff --git a/spec/services/send_interaction_service_spec.rb b/spec/services/send_interaction_service_spec.rb
deleted file mode 100644
index 710d8184..00000000
--- a/spec/services/send_interaction_service_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe SendInteractionService, type: :service do
- subject { SendInteractionService.new }
-
- it 'sends an XML envelope to the Salmon end point of remote user'
-end
diff --git a/spec/services/subscribe_service_spec.rb b/spec/services/subscribe_service_spec.rb
deleted file mode 100644
index 9de83f5f..00000000
--- a/spec/services/subscribe_service_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe SubscribeService, type: :service do
- let(:account) { Fabricate(:account, username: 'bob', domain: 'example.com', hub_url: 'http://hub.example.com') }
- subject { SubscribeService.new }
-
- it 'sends subscription request to PuSH hub' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 202)
- subject.call(account)
- expect(a_request(:post, 'http://hub.example.com/')).to have_been_made.once
- end
-
- it 'generates and keeps PuSH secret on successful call' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 202)
- subject.call(account)
- expect(account.secret).to_not be_blank
- end
-
- it 'fails silently if PuSH hub forbids subscription' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 403)
- subject.call(account)
- end
-
- it 'fails silently if PuSH hub is not found' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 404)
- subject.call(account)
- end
-
- it 'fails loudly if there is a network error' do
- stub_request(:post, 'http://hub.example.com/').to_raise(HTTP::Error)
- expect { subject.call(account) }.to raise_error HTTP::Error
- end
-
- it 'fails loudly if PuSH hub is unavailable' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 503)
- expect { subject.call(account) }.to raise_error GabSocial::UnexpectedResponseError
- end
-
- it 'fails loudly if rate limited' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 429)
- expect { subject.call(account) }.to raise_error GabSocial::UnexpectedResponseError
- end
-end
diff --git a/spec/services/suspend_account_service_spec.rb b/spec/services/suspend_account_service_spec.rb
deleted file mode 100644
index 6f45762a..00000000
--- a/spec/services/suspend_account_service_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe SuspendAccountService, type: :service do
- describe '#call on local account' do
- before do
- stub_request(:post, "https://alice.com/inbox").to_return(status: 201)
- stub_request(:post, "https://bob.com/inbox").to_return(status: 201)
- end
-
- subject do
- -> { described_class.new.call(account) }
- end
-
- let!(:account) { Fabricate(:account) }
- let!(:status) { Fabricate(:status, account: account) }
- let!(:media_attachment) { Fabricate(:media_attachment, account: account) }
- let!(:notification) { Fabricate(:notification, account: account) }
- let!(:favourite) { Fabricate(:favourite, account: account) }
- let!(:active_relationship) { Fabricate(:follow, account: account) }
- let!(:passive_relationship) { Fabricate(:follow, target_account: account) }
- let!(:subscription) { Fabricate(:subscription, account: account) }
- let!(:remote_alice) { Fabricate(:account, inbox_url: 'https://alice.com/inbox', protocol: :activitypub) }
- let!(:remote_bob) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
-
- it 'deletes associated records' do
- is_expected.to change {
- [
- account.statuses,
- account.media_attachments,
- account.stream_entries,
- account.notifications,
- account.favourites,
- account.active_relationships,
- account.passive_relationships,
- account.subscriptions
- ].map(&:count)
- }.from([1, 1, 1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0, 0, 0])
- end
-
- it 'sends a delete actor activity to all known inboxes' do
- subject.call
- expect(a_request(:post, "https://alice.com/inbox")).to have_been_made.once
- expect(a_request(:post, "https://bob.com/inbox")).to have_been_made.once
- end
- end
-
- describe '#call on remote account' do
- before do
- stub_request(:post, "https://alice.com/inbox").to_return(status: 201)
- stub_request(:post, "https://bob.com/inbox").to_return(status: 201)
- end
-
- subject do
- -> { described_class.new.call(remote_bob) }
- end
-
- let!(:account) { Fabricate(:account) }
- let!(:remote_alice) { Fabricate(:account, inbox_url: 'https://alice.com/inbox', protocol: :activitypub) }
- let!(:remote_bob) { Fabricate(:account, inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
- let!(:status) { Fabricate(:status, account: remote_bob) }
- let!(:media_attachment) { Fabricate(:media_attachment, account: remote_bob) }
- let!(:notification) { Fabricate(:notification, account: remote_bob) }
- let!(:favourite) { Fabricate(:favourite, account: remote_bob) }
- let!(:active_relationship) { Fabricate(:follow, account: remote_bob, target_account: account) }
- let!(:passive_relationship) { Fabricate(:follow, target_account: remote_bob) }
- let!(:subscription) { Fabricate(:subscription, account: remote_bob) }
-
- it 'deletes associated records' do
- is_expected.to change {
- [
- remote_bob.statuses,
- remote_bob.media_attachments,
- remote_bob.stream_entries,
- remote_bob.notifications,
- remote_bob.favourites,
- remote_bob.active_relationships,
- remote_bob.passive_relationships,
- remote_bob.subscriptions
- ].map(&:count)
- }.from([1, 1, 1, 1, 1, 1, 1, 1]).to([0, 0, 0, 0, 0, 0, 0, 0])
- end
-
- it 'sends a reject follow to follwer inboxes' do
- subject.call
- expect(a_request(:post, remote_bob.inbox_url)).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/unblock_domain_service_spec.rb b/spec/services/unblock_domain_service_spec.rb
deleted file mode 100644
index 619aefb5..00000000
--- a/spec/services/unblock_domain_service_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe UnblockDomainService, type: :service do
- subject { described_class.new }
-
- describe 'call' do
- before do
- @independently_suspended = Fabricate(:account, domain: 'example.com', suspended_at: 1.hour.ago)
- @independently_silenced = Fabricate(:account, domain: 'example.com', silenced_at: 1.hour.ago)
- @domain_block = Fabricate(:domain_block, domain: 'example.com')
- @silenced = Fabricate(:account, domain: 'example.com', silenced_at: @domain_block.created_at)
- @suspended = Fabricate(:account, domain: 'example.com', suspended_at: @domain_block.created_at)
- end
-
- it 'unsilences accounts and removes block' do
- @domain_block.update(severity: :silence)
-
- subject.call(@domain_block)
- expect_deleted_domain_block
- expect(@silenced.reload.silenced?).to be false
- expect(@suspended.reload.suspended?).to be true
- expect(@independently_suspended.reload.suspended?).to be true
- expect(@independently_silenced.reload.silenced?).to be true
- end
-
- it 'unsuspends accounts and removes block' do
- @domain_block.update(severity: :suspend)
-
- subject.call(@domain_block)
- expect_deleted_domain_block
- expect(@suspended.reload.suspended?).to be false
- expect(@silenced.reload.silenced?).to be true
- expect(@independently_suspended.reload.suspended?).to be true
- expect(@independently_silenced.reload.silenced?).to be true
- end
- end
-
- def expect_deleted_domain_block
- expect { @domain_block.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-end
diff --git a/spec/services/unblock_service_spec.rb b/spec/services/unblock_service_spec.rb
deleted file mode 100644
index 5835b912..00000000
--- a/spec/services/unblock_service_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe UnblockService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { UnblockService.new }
-
- describe 'local' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- sender.block!(bob)
- subject.call(sender, bob)
- end
-
- it 'destroys the blocking relation' do
- expect(sender.blocking?(bob)).to be false
- end
- end
-
- describe 'remote OStatus' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
-
- before do
- sender.block!(bob)
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, bob)
- end
-
- it 'destroys the blocking relation' do
- expect(sender.blocking?(bob)).to be false
- end
-
- it 'sends an unblock salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:unblock])
- }).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox')).account }
-
- before do
- sender.block!(bob)
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- subject.call(sender, bob)
- end
-
- it 'destroys the blocking relation' do
- expect(sender.blocking?(bob)).to be false
- end
-
- it 'sends an unblock activity' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/unfollow_service_spec.rb b/spec/services/unfollow_service_spec.rb
deleted file mode 100644
index 8a2881ab..00000000
--- a/spec/services/unfollow_service_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe UnfollowService, type: :service do
- let(:sender) { Fabricate(:account, username: 'alice') }
-
- subject { UnfollowService.new }
-
- describe 'local' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
-
- before do
- sender.follow!(bob)
- subject.call(sender, bob)
- end
-
- it 'destroys the following relation' do
- expect(sender.following?(bob)).to be false
- end
- end
-
- describe 'remote OStatus' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :ostatus, domain: 'example.com', salmon_url: 'http://salmon.example.com')).account }
-
- before do
- sender.follow!(bob)
- stub_request(:post, "http://salmon.example.com/").to_return(:status => 200, :body => "", :headers => {})
- subject.call(sender, bob)
- end
-
- it 'destroys the following relation' do
- expect(sender.following?(bob)).to be false
- end
-
- it 'sends an unfollow salmon slap' do
- expect(a_request(:post, "http://salmon.example.com/").with { |req|
- xml = OStatus2::Salmon.new.unpack(req.body)
- xml.match(OStatus::TagManager::VERBS[:unfollow])
- }).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox')).account }
-
- before do
- sender.follow!(bob)
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- subject.call(sender, bob)
- end
-
- it 'destroys the following relation' do
- expect(sender.following?(bob)).to be false
- end
-
- it 'sends an unfollow activity' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
- end
- end
-
- describe 'remote ActivityPub (reverse)' do
- let(:bob) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox')).account }
-
- before do
- bob.follow!(sender)
- stub_request(:post, 'http://example.com/inbox').to_return(status: 200)
- subject.call(bob, sender)
- end
-
- it 'destroys the following relation' do
- expect(bob.following?(sender)).to be false
- end
-
- it 'sends a reject activity' do
- expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
- end
- end
-end
diff --git a/spec/services/unmute_service_spec.rb b/spec/services/unmute_service_spec.rb
deleted file mode 100644
index 8463eb28..00000000
--- a/spec/services/unmute_service_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe UnmuteService, type: :service do
- subject { UnmuteService.new }
-end
diff --git a/spec/services/unsubscribe_service_spec.rb b/spec/services/unsubscribe_service_spec.rb
deleted file mode 100644
index 54d4b1b5..00000000
--- a/spec/services/unsubscribe_service_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe UnsubscribeService, type: :service do
- let(:account) { Fabricate(:account, username: 'bob', domain: 'example.com', hub_url: 'http://hub.example.com') }
- subject { UnsubscribeService.new }
-
- it 'removes the secret and resets expiration on account' do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 204)
- subject.call(account)
- account.reload
-
- expect(account.secret).to be_blank
- expect(account.subscription_expires_at).to be_blank
- end
-
- it 'logs error on subscription failure' do
- logger = stub_logger
- stub_request(:post, 'http://hub.example.com/').to_return(status: 404)
- subject.call(account)
-
- expect(logger).to have_received(:debug).with(/unsubscribe for bob@example.com failed/)
- end
-
- it 'logs error on connection failure' do
- logger = stub_logger
- stub_request(:post, 'http://hub.example.com/').to_raise(HTTP::Error)
- subject.call(account)
-
- expect(logger).to have_received(:debug).with(/unsubscribe for bob@example.com failed/)
- end
-
- def stub_logger
- double(debug: nil).tap do |logger|
- allow(Rails).to receive(:logger).and_return(logger)
- end
- end
-end
diff --git a/spec/services/update_remote_profile_service_spec.rb b/spec/services/update_remote_profile_service_spec.rb
deleted file mode 100644
index f3ea70b8..00000000
--- a/spec/services/update_remote_profile_service_spec.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe UpdateRemoteProfileService, type: :service do
- let(:xml) { File.read(Rails.root.join('spec', 'fixtures', 'push', 'feed.atom')) }
-
- subject { UpdateRemoteProfileService.new }
-
- before do
- stub_request(:get, 'https://quitter.no/avatar/7477-300-20160211190340.png').to_return(request_fixture('avatar.txt'))
- end
-
- context 'with updated details' do
- let(:remote_account) { Fabricate(:account, username: 'bob', domain: 'example.com') }
-
- before do
- subject.call(xml, remote_account)
- end
-
- it 'downloads new avatar' do
- expect(a_request(:get, 'https://quitter.no/avatar/7477-300-20160211190340.png')).to have_been_made
- end
-
- it 'sets the avatar remote url' do
- expect(remote_account.reload.avatar_remote_url).to eq 'https://quitter.no/avatar/7477-300-20160211190340.png'
- end
-
- it 'sets display name' do
- expect(remote_account.reload.display_name).to eq 'DIGITAL CAT'
- end
-
- it 'sets note' do
- expect(remote_account.reload.note).to eq 'Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes'
- end
- end
-
- context 'with unchanged details' do
- let(:remote_account) { Fabricate(:account, username: 'bob', domain: 'example.com', display_name: 'DIGITAL CAT', note: 'Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes', avatar_remote_url: 'https://quitter.no/avatar/7477-300-20160211190340.png') }
-
- before do
- subject.call(xml, remote_account)
- end
-
- it 'does not re-download avatar' do
- expect(a_request(:get, 'https://quitter.no/avatar/7477-300-20160211190340.png')).to have_been_made.once
- end
-
- it 'sets the avatar remote url' do
- expect(remote_account.reload.avatar_remote_url).to eq 'https://quitter.no/avatar/7477-300-20160211190340.png'
- end
-
- it 'sets display name' do
- expect(remote_account.reload.display_name).to eq 'DIGITAL CAT'
- end
-
- it 'sets note' do
- expect(remote_account.reload.note).to eq 'Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes'
- end
- end
-
- context 'with updated details from a domain set to reject media' do
- let(:remote_account) { Fabricate(:account, username: 'bob', domain: 'example.com') }
- let!(:domain_block) { Fabricate(:domain_block, domain: 'example.com', reject_media: true) }
-
- before do
- subject.call(xml, remote_account)
- end
-
- it 'does not the avatar remote url' do
- expect(remote_account.reload.avatar_remote_url).to be_nil
- end
-
- it 'sets display name' do
- expect(remote_account.reload.display_name).to eq 'DIGITAL CAT'
- end
-
- it 'sets note' do
- expect(remote_account.reload.note).to eq 'Software engineer, free time musician and DIGITAL SPORTS enthusiast. Likes cats. Warning: May contain memes'
- end
-
- it 'does not set store the avatar' do
- expect(remote_account.reload.avatar_file_name).to be_nil
- end
- end
-end
diff --git a/spec/services/verify_link_service_spec.rb b/spec/services/verify_link_service_spec.rb
deleted file mode 100644
index efe977a7..00000000
--- a/spec/services/verify_link_service_spec.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-require 'rails_helper'
-
-RSpec.describe VerifyLinkService, type: :service do
- subject { described_class.new }
-
- context 'given a local account' do
- let(:account) { Fabricate(:account, username: 'alice') }
- let(:field) { Account::Field.new(account, 'name' => 'Website', 'value' => 'http://example.com') }
-
- before do
- stub_request(:head, 'https://redirect.me/abc').to_return(status: 301, headers: { 'Location' => ActivityPub::TagManager.instance.url_for(account) })
- stub_request(:get, 'http://example.com').to_return(status: 200, body: html)
- subject.call(field)
- end
-
- context 'when a link contains an back' do
- let(:html) do
- <<-HTML
-
-
- Follow me on Gab Social
-
- HTML
- end
-
- it 'marks the field as verified' do
- expect(field.verified?).to be true
- end
- end
-
- context 'when a link contains an back' do
- let(:html) do
- <<-HTML
-
-
- Follow me on Gab Social
-
- HTML
- end
-
- it 'marks the field as verified' do
- expect(field.verified?).to be true
- end
- end
-
- context 'when a link contains a back' do
- let(:html) do
- <<-HTML
-
-
-
-
- HTML
- end
-
- it 'marks the field as verified' do
- expect(field.verified?).to be true
- end
- end
-
- context 'when a link goes through a redirect back' do
- let(:html) do
- <<-HTML
-
-
-
-
- HTML
- end
-
- it 'marks the field as verified' do
- expect(field.verified?).to be true
- end
- end
-
- context 'when a link does not contain a link back' do
- let(:html) { '' }
-
- it 'marks the field as verified' do
- expect(field.verified?).to be false
- end
- end
- end
-
- context 'given a remote account' do
- let(:account) { Fabricate(:account, username: 'alice', domain: 'example.com', url: 'https://profile.example.com/alice') }
- let(:field) { Account::Field.new(account, 'name' => 'Website', 'value' => 'http:// example.com ') }
-
- before do
- stub_request(:get, 'http://example.com').to_return(status: 200, body: html)
- subject.call(field)
- end
-
- context 'when a link contains an back' do
- let(:html) do
- <<-HTML
-
-
- Follow me on Gab Social
-
- HTML
- end
-
- it 'marks the field as verified' do
- expect(field.verified?).to be true
- end
- end
- end
-end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
deleted file mode 100644
index 0cd1f91d..00000000
--- a/spec/spec_helper.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-GC.disable
-
-if ENV['DISABLE_SIMPLECOV'] != 'true'
- require 'simplecov'
- SimpleCov.start 'rails' do
- add_group 'Services', 'app/services'
- add_group 'Presenters', 'app/presenters'
- add_group 'Validators', 'app/validators'
- end
-end
-
-gc_counter = -1
-
-RSpec.configure do |config|
- config.expect_with :rspec do |expectations|
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
- end
-
- config.mock_with :rspec do |mocks|
- mocks.verify_partial_doubles = true
-
- config.around(:example, :without_verify_partial_doubles) do |example|
- mocks.verify_partial_doubles = false
- example.call
- mocks.verify_partial_doubles = true
- end
- end
-
- config.before :suite do
- Chewy.strategy(:bypass)
- end
-
- config.after :suite do
- gc_counter = 0
- FileUtils.rm_rf(Dir["#{Rails.root}/spec/test_files/"])
- end
-
- config.after :each do
- gc_counter += 1
-
- if gc_counter > 19
- GC.enable
- GC.start
- GC.disable
-
- gc_counter = 0
- end
- end
-end
-
-def body_as_json
- json_str_to_hash(response.body)
-end
-
-def json_str_to_hash(str)
- JSON.parse(str, symbolize_names: true)
-end
diff --git a/spec/support/examples/lib/settings/scoped_settings.rb b/spec/support/examples/lib/settings/scoped_settings.rb
deleted file mode 100644
index 2457dcfb..00000000
--- a/spec/support/examples/lib/settings/scoped_settings.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-shared_examples 'ScopedSettings' do
- describe '[]' do
- it 'inherits default settings' do
- expect(Setting.boost_modal).to eq false
- expect(Setting.interactions['must_be_follower']).to eq false
-
- settings = create!
-
- expect(settings['boost_modal']).to eq false
- expect(settings['interactions']['must_be_follower']).to eq false
- end
- end
-
- describe 'all_as_records' do
- # expecting [] and []= works
-
- it 'returns records merged with default values except hashes' do
- expect(Setting.boost_modal).to eq false
- expect(Setting.delete_modal).to eq true
-
- settings = create!
- settings['boost_modal'] = true
-
- records = settings.all_as_records
-
- expect(records['boost_modal'].value).to eq true
- expect(records['delete_modal'].value).to eq true
- end
- end
-
- describe 'missing methods' do
- # expecting [] and []= works.
-
- it 'reads settings' do
- expect(Setting.boost_modal).to eq false
- settings = create!
- expect(settings.boost_modal).to eq false
- end
-
- it 'updates settings' do
- settings = fabricate
- settings.boost_modal = true
- expect(settings['boost_modal']).to eq true
- end
- end
-
- it 'can update settings with [] and can read with []=' do
- settings = fabricate
-
- settings['boost_modal'] = true
- settings['interactions'] = settings['interactions'].merge('must_be_follower' => true)
-
- Setting.save!
-
- expect(settings['boost_modal']).to eq true
- expect(settings['interactions']['must_be_follower']).to eq true
-
- Rails.cache.clear
-
- expect(settings['boost_modal']).to eq true
- expect(settings['interactions']['must_be_follower']).to eq true
- end
-
- xit 'does not mutate defaults via the cache' do
- fabricate['interactions']['must_be_follower'] = true
- # TODO
- # This mutates the global settings default such that future
- # instances will inherit the incorrect starting values
-
- expect(fabricate.settings['interactions']['must_be_follower']).to eq false
- end
-end
diff --git a/spec/support/examples/lib/settings/settings_extended.rb b/spec/support/examples/lib/settings/settings_extended.rb
deleted file mode 100644
index 5a9d34bb..00000000
--- a/spec/support/examples/lib/settings/settings_extended.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-shared_examples 'Settings-extended' do
- describe 'settings' do
- def fabricate
- super.settings
- end
-
- def create!
- super.settings
- end
-
- it_behaves_like 'ScopedSettings'
- end
-end
diff --git a/spec/support/examples/models/concerns/account_avatar.rb b/spec/support/examples/models/concerns/account_avatar.rb
deleted file mode 100644
index f2a8a245..00000000
--- a/spec/support/examples/models/concerns/account_avatar.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-shared_examples 'AccountAvatar' do |fabricator|
- describe 'static avatars' do
- describe 'when GIF' do
- it 'creates a png static style' do
- account = Fabricate(fabricator, avatar: attachment_fixture('avatar.gif'))
- expect(account.avatar_static_url).to_not eq account.avatar_original_url
- end
- end
-
- describe 'when non-GIF' do
- it 'does not create extra static style' do
- account = Fabricate(fabricator, avatar: attachment_fixture('attachment.jpg'))
- expect(account.avatar_static_url).to eq account.avatar_original_url
- end
- end
- end
-end
diff --git a/spec/support/matchers/model/model_have_error_on_field.rb b/spec/support/matchers/model/model_have_error_on_field.rb
deleted file mode 100644
index a5dfbf45..00000000
--- a/spec/support/matchers/model/model_have_error_on_field.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-RSpec::Matchers.define :model_have_error_on_field do |expected|
- match do |record|
- if record.errors.empty?
- record.valid?
- end
-
- record.errors.has_key?(expected)
- end
-
- failure_message do |record|
- keys = record.errors.keys
-
- "expect record.errors(#{keys}) to include #{expected}"
- end
-end
diff --git a/spec/validators/blacklisted_email_validator_spec.rb b/spec/validators/blacklisted_email_validator_spec.rb
deleted file mode 100644
index ccc5dc0f..00000000
--- a/spec/validators/blacklisted_email_validator_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe BlacklistedEmailValidator, type: :validator do
- describe '#validate' do
- let(:user) { double(email: 'info@mail.com', errors: errors) }
- let(:errors) { double(add: nil) }
-
- before do
- allow(user).to receive(:valid_invitation?) { false }
- allow_any_instance_of(described_class).to receive(:blocked_email?) { blocked_email }
- described_class.new.validate(user)
- end
-
- context 'blocked_email?' do
- let(:blocked_email) { true }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add).with(:email, I18n.t('users.invalid_email'))
- end
- end
-
- context '!blocked_email?' do
- let(:blocked_email) { false }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(:email, I18n.t('users.invalid_email'))
- end
- end
- end
-end
diff --git a/spec/validators/disallowed_hashtags_validator_spec.rb b/spec/validators/disallowed_hashtags_validator_spec.rb
deleted file mode 100644
index 8ec1302a..00000000
--- a/spec/validators/disallowed_hashtags_validator_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe DisallowedHashtagsValidator, type: :validator do
- describe '#validate' do
- before do
- allow_any_instance_of(described_class).to receive(:select_tags) { tags }
- described_class.new.validate(status)
- end
-
- let(:status) { double(errors: errors, local?: local, reblog?: reblog, text: '') }
- let(:errors) { double(add: nil) }
-
- context 'unless status.local? && !status.reblog?' do
- let(:local) { false }
- let(:reblog) { true }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(:text, any_args)
- end
- end
-
- context 'status.local? && !status.reblog?' do
- let(:local) { true }
- let(:reblog) { false }
-
- context 'tags.empty?' do
- let(:tags) { [] }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(:text, any_args)
- end
- end
-
- context '!tags.empty?' do
- let(:tags) { %w(a b c) }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add)
- .with(:text, I18n.t('statuses.disallowed_hashtags', tags: tags.join(', '), count: tags.size))
- end
- end
- end
- end
-end
diff --git a/spec/validators/email_mx_validator_spec.rb b/spec/validators/email_mx_validator_spec.rb
deleted file mode 100644
index 48e17a4f..00000000
--- a/spec/validators/email_mx_validator_spec.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe EmailMxValidator do
- describe '#validate' do
- let(:user) { double(email: 'foo@example.com', errors: double(add: nil)) }
-
- it 'adds an error if there are no DNS records for the e-mail domain' do
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
-
- it 'adds an error if a MX record exists but does not lead to an IP' do
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([double(exchange: 'mail.example.com')])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
-
- it 'adds an error if the A record is blacklisted' do
- EmailDomainBlock.create!(domain: '1.2.3.4')
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([double(address: '1.2.3.4')])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
-
- it 'adds an error if the AAAA record is blacklisted' do
- EmailDomainBlock.create!(domain: 'fd00::1')
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([double(address: 'fd00::1')])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
-
- it 'adds an error if the MX record is blacklisted' do
- EmailDomainBlock.create!(domain: '2.3.4.5')
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([double(exchange: 'mail.example.com')])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([double(address: '2.3.4.5')])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
-
- it 'adds an error if the MX IPv6 record is blacklisted' do
- EmailDomainBlock.create!(domain: 'fd00::2')
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([double(exchange: 'mail.example.com')])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([double(address: 'fd00::2')])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
-
- it 'adds an error if the MX hostname is blacklisted' do
- EmailDomainBlock.create!(domain: 'mail.example.com')
- resolver = double
-
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([double(exchange: 'mail.example.com')])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
- allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([double(address: '2.3.4.5')])
- allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([double(address: 'fd00::2')])
- allow(resolver).to receive(:timeouts=).and_return(nil)
- allow(Resolv::DNS).to receive(:open).and_yield(resolver)
-
- subject.validate(user)
- expect(user.errors).to have_received(:add)
- end
- end
-end
diff --git a/spec/validators/follow_limit_validator_spec.rb b/spec/validators/follow_limit_validator_spec.rb
deleted file mode 100644
index cc8fbb63..00000000
--- a/spec/validators/follow_limit_validator_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe FollowLimitValidator, type: :validator do
- describe '#validate' do
- before do
- allow_any_instance_of(described_class).to receive(:limit_reached?).with(account) do
- limit_reached
- end
-
- described_class.new.validate(follow)
- end
-
- let(:follow) { double(account: account, errors: errors) }
- let(:errors) { double(add: nil) }
- let(:account) { double(nil?: _nil, local?: local, following_count: 0, followers_count: 0) }
- let(:_nil) { true }
- let(:local) { false }
-
- context 'follow.account.nil? || !follow.account.local?' do
- let(:_nil) { true }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(:base, any_args)
- end
- end
-
- context '!(follow.account.nil? || !follow.account.local?)' do
- let(:_nil) { false }
- let(:local) { true }
-
- context 'limit_reached?' do
- let(:limit_reached) { true }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add)
- .with(:base, I18n.t('users.follow_limit_reached', limit: FollowLimitValidator::LIMIT))
- end
- end
-
- context '!limit_reached?' do
- let(:limit_reached) { false }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(:base, any_args)
- end
- end
- end
- end
-end
diff --git a/spec/validators/poll_validator_spec.rb b/spec/validators/poll_validator_spec.rb
deleted file mode 100644
index 941b8340..00000000
--- a/spec/validators/poll_validator_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe PollValidator, type: :validator do
- describe '#validate' do
- before do
- validator.validate(poll)
- end
-
- let(:validator) { described_class.new }
- let(:poll) { double(options: options, expires_at: expires_at, errors: errors) }
- let(:errors) { double(add: nil) }
- let(:options) { %w(foo bar) }
- let(:expires_at) { 1.day.from_now }
-
- it 'have no errors' do
- expect(errors).not_to have_received(:add)
- end
-
- context 'expires just 5 min ago' do
- let(:expires_at) { 5.minutes.from_now }
- it 'not calls errors add' do
- expect(errors).not_to have_received(:add)
- end
- end
- end
-end
diff --git a/spec/validators/status_length_validator_spec.rb b/spec/validators/status_length_validator_spec.rb
deleted file mode 100644
index 11e55f93..00000000
--- a/spec/validators/status_length_validator_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe StatusLengthValidator do
- describe '#validate' do
- it 'does not add errors onto remote statuses' do
- status = double(local?: false)
- subject.validate(status)
- expect(status).not_to receive(:errors)
- end
-
- it 'does not add errors onto local reblogs' do
- status = double(local?: false, reblog?: true)
- subject.validate(status)
- expect(status).not_to receive(:errors)
- end
-
- it 'adds an error when content warning is over 500 characters' do
- status = double(spoiler_text: 'a' * 520, text: '', errors: double(add: nil), local?: true, reblog?: false)
- subject.validate(status)
- expect(status.errors).to have_received(:add)
- end
-
- it 'adds an error when text is over 500 characters' do
- status = double(spoiler_text: '', text: 'a' * 520, errors: double(add: nil), local?: true, reblog?: false)
- subject.validate(status)
- expect(status.errors).to have_received(:add)
- end
-
- it 'adds an error when text and content warning are over 500 characters total' do
- status = double(spoiler_text: 'a' * 250, text: 'b' * 251, errors: double(add: nil), local?: true, reblog?: false)
- subject.validate(status)
- expect(status.errors).to have_received(:add)
- end
-
- it 'counts URLs as 23 characters flat' do
- text = ('a' * 476) + " http://#{'b' * 30}.com/example"
- status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
-
- subject.validate(status)
- expect(status.errors).to_not have_received(:add)
- end
-
- it 'counts only the front part of remote usernames' do
- text = ('a' * 475) + " @alice@#{'b' * 30}.com"
- status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
-
- subject.validate(status)
- expect(status.errors).to_not have_received(:add)
- end
- end
-end
diff --git a/spec/validators/status_pin_validator_spec.rb b/spec/validators/status_pin_validator_spec.rb
deleted file mode 100644
index 06532e5b..00000000
--- a/spec/validators/status_pin_validator_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe StatusPinValidator, type: :validator do
- describe '#validate' do
- before do
- subject.validate(pin)
- end
-
- let(:pin) { double(account: account, errors: errors, status: status, account_id: pin_account_id) }
- let(:status) { double(reblog?: reblog, account_id: status_account_id, visibility: visibility) }
- let(:account) { double(status_pins: status_pins, local?: local) }
- let(:status_pins) { double(count: count) }
- let(:errors) { double(add: nil) }
- let(:pin_account_id) { 1 }
- let(:status_account_id) { 1 }
- let(:visibility) { 'public' }
- let(:local) { false }
- let(:reblog) { false }
- let(:count) { 0 }
-
- context 'pin.status.reblog?' do
- let(:reblog) { true }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.reblog'))
- end
- end
-
- context 'pin.account_id != pin.status.account_id' do
- let(:pin_account_id) { 1 }
- let(:status_account_id) { 2 }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.ownership'))
- end
- end
-
- context 'unless %w(public unlisted).include?(pin.status.visibility)' do
- let(:visibility) { '' }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.private'))
- end
- end
-
- context 'pin.account.status_pins.count > 4 && pin.account.local?' do
- let(:count) { 5 }
- let(:local) { true }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.limit'))
- end
- end
- end
-end
diff --git a/spec/validators/unique_username_validator_spec.rb b/spec/validators/unique_username_validator_spec.rb
deleted file mode 100644
index c2e2eedf..00000000
--- a/spec/validators/unique_username_validator_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe UniqueUsernameValidator do
- describe '#validate' do
- it 'does not add errors if username is nil' do
- account = double(username: nil, persisted?: false, errors: double(add: nil))
- subject.validate(account)
- expect(account.errors).to_not have_received(:add)
- end
-
- it 'does not add errors when existing one is subject itself' do
- account = Fabricate(:account, username: 'abcdef')
- expect(account).to be_valid
- end
-
- it 'adds an error when the username is already used with ignoring cases' do
- Fabricate(:account, username: 'ABCdef')
- account = double(username: 'abcDEF', persisted?: false, errors: double(add: nil))
- subject.validate(account)
- expect(account.errors).to have_received(:add)
- end
- end
-end
diff --git a/spec/validators/unreserved_username_validator_spec.rb b/spec/validators/unreserved_username_validator_spec.rb
deleted file mode 100644
index 0187941b..00000000
--- a/spec/validators/unreserved_username_validator_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe UnreservedUsernameValidator, type: :validator do
- describe '#validate' do
- before do
- allow(validator).to receive(:reserved_username?) { reserved_username }
- validator.validate(account)
- end
-
- let(:validator) { described_class.new }
- let(:account) { double(username: username, errors: errors) }
- let(:errors ) { double(add: nil) }
-
- context '@username.nil?' do
- let(:username) { nil }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(:username, any_args)
- end
- end
-
- context '!@username.nil?' do
- let(:username) { '' }
-
- context 'reserved_username?' do
- let(:reserved_username) { true }
-
- it 'calls erros.add' do
- expect(errors).to have_received(:add).with(:username, I18n.t('accounts.reserved_username'))
- end
- end
-
- context '!reserved_username?' do
- let(:reserved_username) { false }
-
- it 'not calls erros.add' do
- expect(errors).not_to have_received(:add).with(:username, any_args)
- end
- end
- end
- end
-end
diff --git a/spec/validators/url_validator_spec.rb b/spec/validators/url_validator_spec.rb
deleted file mode 100644
index e8d0e649..00000000
--- a/spec/validators/url_validator_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe UrlValidator, type: :validator do
- describe '#validate_each' do
- before do
- allow(validator).to receive(:compliant?).with(value) { compliant }
- validator.validate_each(record, attribute, value)
- end
-
- let(:validator) { described_class.new(attributes: [attribute]) }
- let(:record) { double(errors: errors) }
- let(:errors) { double(add: nil) }
- let(:value) { '' }
- let(:attribute) { :foo }
-
- context 'unless compliant?' do
- let(:compliant) { false }
-
- it 'calls errors.add' do
- expect(errors).to have_received(:add).with(attribute, I18n.t('applications.invalid_url'))
- end
- end
-
- context 'if compliant?' do
- let(:compliant) { true }
-
- it 'not calls errors.add' do
- expect(errors).not_to have_received(:add).with(attribute, any_args)
- end
- end
- end
-end
diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb
deleted file mode 100644
index 43553e86..00000000
--- a/spec/views/about/show.html.haml_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'about/show.html.haml', without_verify_partial_doubles: true do
- before do
- allow(view).to receive(:site_hostname).and_return('example.com')
- allow(view).to receive(:site_title).and_return('example site')
- allow(view).to receive(:new_user).and_return(User.new)
- allow(view).to receive(:use_seamless_external_login?).and_return(false)
- end
-
- it 'has valid open graph tags' do
- instance_presenter = double(
- :instance_presenter,
- site_title: 'something',
- site_short_description: 'something',
- site_description: 'something',
- version_number: '1.0',
- source_url: 'https://code.gab.com/gab/social/gab-social',
- open_registrations: false,
- thumbnail: nil,
- hero: nil,
- mascot: nil,
- user_count: 420,
- status_count: 69,
- active_user_count: 420,
- contact_account: nil,
- sample_accounts: []
- )
-
- assign(:instance_presenter, instance_presenter)
- render
-
- header_tags = view.content_for(:header_tags)
-
- expect(header_tags).to match(%r{ })
- expect(header_tags).to match(%r{ })
- expect(header_tags).to match(%r{ })
- expect(header_tags).to match(%r{ })
- end
-end
diff --git a/spec/views/stream_entries/show.html.haml_spec.rb b/spec/views/stream_entries/show.html.haml_spec.rb
deleted file mode 100644
index 93f0adb9..00000000
--- a/spec/views/stream_entries/show.html.haml_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true do
- before do
- double(:api_oembed_url => '')
- double(:account_stream_entry_url => '')
- allow(view).to receive(:show_landing_strip?).and_return(true)
- allow(view).to receive(:site_title).and_return('example site')
- allow(view).to receive(:site_hostname).and_return('example.com')
- allow(view).to receive(:full_asset_url).and_return('//asset.host/image.svg')
- allow(view).to receive(:local_time)
- allow(view).to receive(:local_time_ago)
- allow(view).to receive(:current_account).and_return(nil)
- assign(:instance_presenter, InstancePresenter.new)
- end
-
- it 'has valid author h-card and basic data for a detailed_status' do
- alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
- bob = Fabricate(:account, username: 'bob', display_name: 'Bob')
- status = Fabricate(:status, account: alice, text: 'Hello World')
- reply = Fabricate(:status, account: bob, thread: status, text: 'Hello Alice')
-
- assign(:status, status)
- assign(:stream_entry, status.stream_entry)
- assign(:account, alice)
- assign(:type, status.stream_entry.activity_type.downcase)
- assign(:descendant_threads, [])
-
- render
-
- mf2 = Microformats.parse(rendered)
-
- expect(mf2.entry.url.to_s).not_to be_empty
- expect(mf2.entry.author.name.to_s).to eq alice.display_name
- expect(mf2.entry.author.url.to_s).not_to be_empty
- end
-
- it 'has valid h-cites for p-in-reply-to and p-comment' do
- alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
- bob = Fabricate(:account, username: 'bob', display_name: 'Bob')
- carl = Fabricate(:account, username: 'carl', display_name: 'Carl')
- status = Fabricate(:status, account: alice, text: 'Hello World')
- reply = Fabricate(:status, account: bob, thread: status, text: 'Hello Alice')
- comment = Fabricate(:status, account: carl, thread: reply, text: 'Hello Bob')
-
- assign(:status, reply)
- assign(:stream_entry, reply.stream_entry)
- assign(:account, alice)
- assign(:type, reply.stream_entry.activity_type.downcase)
- assign(:ancestors, reply.stream_entry.activity.ancestors(1, bob))
- assign(:descendant_threads, [{ statuses: reply.stream_entry.activity.descendants(1) }])
-
- render
-
- mf2 = Microformats.parse(rendered)
-
- expect(mf2.entry.url.to_s).not_to be_empty
- expect(mf2.entry.comment.url.to_s).not_to be_empty
- expect(mf2.entry.comment.author.name.to_s).to eq carl.display_name
- expect(mf2.entry.comment.author.url.to_s).not_to be_empty
-
- expect(mf2.entry.in_reply_to.url.to_s).not_to be_empty
- expect(mf2.entry.in_reply_to.author.name.to_s).to eq alice.display_name
- expect(mf2.entry.in_reply_to.author.url.to_s).not_to be_empty
- end
-
- it 'has valid opengraph tags' do
- alice = Fabricate(:account, username: 'alice', display_name: 'Alice')
- status = Fabricate(:status, account: alice, text: 'Hello World')
-
- assign(:status, status)
- assign(:stream_entry, status.stream_entry)
- assign(:account, alice)
- assign(:type, status.stream_entry.activity_type.downcase)
- assign(:descendant_threads, [])
-
- render
-
- header_tags = view.content_for(:header_tags)
-
- expect(header_tags).to match(%r{ })
- expect(header_tags).to match(%r{ })
- expect(header_tags).to match(%r{ })
- expect(header_tags).to match(%r{ })
- end
-end
diff --git a/spec/workers/activitypub/delivery_worker_spec.rb b/spec/workers/activitypub/delivery_worker_spec.rb
deleted file mode 100644
index c46b8b81..00000000
--- a/spec/workers/activitypub/delivery_worker_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ActivityPub::DeliveryWorker do
- subject { described_class.new }
-
- let(:sender) { Fabricate(:account) }
- let(:payload) { 'test' }
-
- describe 'perform' do
- it 'performs a request' do
- stub_request(:post, 'https://example.com/api').to_return(status: 200)
- subject.perform(payload, sender.id, 'https://example.com/api')
- expect(a_request(:post, 'https://example.com/api')).to have_been_made.once
- end
-
- it 'raises when request fails' do
- stub_request(:post, 'https://example.com/api').to_return(status: 500)
- expect { subject.perform(payload, sender.id, 'https://example.com/api') }.to raise_error GabSocial::UnexpectedResponseError
- end
- end
-end
diff --git a/spec/workers/activitypub/distribution_worker_spec.rb b/spec/workers/activitypub/distribution_worker_spec.rb
deleted file mode 100644
index 368ca025..00000000
--- a/spec/workers/activitypub/distribution_worker_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'rails_helper'
-
-describe ActivityPub::DistributionWorker do
- subject { described_class.new }
-
- let(:status) { Fabricate(:status) }
- let(:follower) { Fabricate(:account, protocol: :activitypub, inbox_url: 'http://example.com') }
-
- describe '#perform' do
- before do
- allow(ActivityPub::DeliveryWorker).to receive(:push_bulk)
- follower.follow!(status.account)
- end
-
- context 'with public status' do
- before do
- status.update(visibility: :public)
- end
-
- it 'delivers to followers' do
- subject.perform(status.id)
- expect(ActivityPub::DeliveryWorker).to have_received(:push_bulk).with(['http://example.com'])
- end
- end
-
- context 'with private status' do
- before do
- status.update(visibility: :private)
- end
-
- it 'delivers to followers' do
- subject.perform(status.id)
- expect(ActivityPub::DeliveryWorker).to have_received(:push_bulk).with(['http://example.com'])
- end
- end
-
- context 'with direct status' do
- before do
- status.update(visibility: :direct)
- end
-
- it 'does nothing' do
- subject.perform(status.id)
- expect(ActivityPub::DeliveryWorker).to_not have_received(:push_bulk)
- end
- end
- end
-end
diff --git a/spec/workers/activitypub/fetch_replies_worker_spec.rb b/spec/workers/activitypub/fetch_replies_worker_spec.rb
deleted file mode 100644
index ddb5aaa3..00000000
--- a/spec/workers/activitypub/fetch_replies_worker_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe ActivityPub::FetchRepliesWorker do
- subject { described_class.new }
-
- let(:account) { Fabricate(:account, uri: 'https://example.com/user/1') }
- let(:status) { Fabricate(:status, account: account) }
-
- let(:payload) do
- {
- '@context': 'https://www.w3.org/ns/activitystreams',
- id: 'https://example.com/statuses_replies/1',
- type: 'Collection',
- items: [],
- }
- end
-
- let(:json) { Oj.dump(payload) }
-
- describe 'perform' do
- it 'performs a request if the collection URI is from the same host' do
- stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json)
- subject.perform(status.id, 'https://example.com/statuses_replies/1')
- expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once
- end
-
- it 'does not perform a request if the collection URI is from a different host' do
- stub_request(:get, 'https://other.com/statuses_replies/1').to_return(status: 200)
- subject.perform(status.id, 'https://other.com/statuses_replies/1')
- expect(a_request(:get, 'https://other.com/statuses_replies/1')).to_not have_been_made
- end
-
- it 'raises when request fails' do
- stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 500)
- expect { subject.perform(status.id, 'https://example.com/statuses_replies/1') }.to raise_error GabSocial::UnexpectedResponseError
- end
- end
-end
diff --git a/spec/workers/activitypub/processing_worker_spec.rb b/spec/workers/activitypub/processing_worker_spec.rb
deleted file mode 100644
index b42c0bdb..00000000
--- a/spec/workers/activitypub/processing_worker_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe ActivityPub::ProcessingWorker do
- subject { described_class.new }
-
- let(:account) { Fabricate(:account) }
-
- describe '#perform' do
- it 'delegates to ActivityPub::ProcessCollectionService' do
- allow(ActivityPub::ProcessCollectionService).to receive(:new).and_return(double(:service, call: nil))
- subject.perform(account.id, '')
- expect(ActivityPub::ProcessCollectionService).to have_received(:new)
- end
- end
-end
diff --git a/spec/workers/activitypub/update_distribution_worker_spec.rb b/spec/workers/activitypub/update_distribution_worker_spec.rb
deleted file mode 100644
index 688a424d..00000000
--- a/spec/workers/activitypub/update_distribution_worker_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'rails_helper'
-
-describe ActivityPub::UpdateDistributionWorker do
- subject { described_class.new }
-
- let(:account) { Fabricate(:account) }
- let(:follower) { Fabricate(:account, protocol: :activitypub, inbox_url: 'http://example.com') }
-
- describe '#perform' do
- before do
- allow(ActivityPub::DeliveryWorker).to receive(:push_bulk)
- follower.follow!(account)
- end
-
- it 'delivers to followers' do
- subject.perform(account.id)
- expect(ActivityPub::DeliveryWorker).to have_received(:push_bulk).with(['http://example.com'])
- end
- end
-end
diff --git a/spec/workers/after_remote_follow_request_worker_spec.rb b/spec/workers/after_remote_follow_request_worker_spec.rb
deleted file mode 100644
index bd623cca..00000000
--- a/spec/workers/after_remote_follow_request_worker_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe AfterRemoteFollowRequestWorker do
- subject { described_class.new }
- let(:follow_request) { Fabricate(:follow_request) }
- describe 'perform' do
- context 'when the follow_request does not exist' do
- it 'catches a raise and returns true' do
- allow(FollowService).to receive(:new)
- result = subject.perform('aaa')
-
- expect(result).to eq(true)
- expect(FollowService).not_to have_received(:new)
- end
- end
-
- context 'when the account cannot be updated' do
- it 'returns nil and does not call service when account is nil' do
- allow(FollowService).to receive(:new)
- service = double(call: nil)
- allow(FetchRemoteAccountService).to receive(:new).and_return(service)
-
- result = subject.perform(follow_request.id)
-
- expect(result).to be_nil
- expect(FollowService).not_to have_received(:new)
- end
-
- it 'returns nil and does not call service when account is locked' do
- allow(FollowService).to receive(:new)
- service = double(call: double(locked?: true))
- allow(FetchRemoteAccountService).to receive(:new).and_return(service)
-
- result = subject.perform(follow_request.id)
-
- expect(result).to be_nil
- expect(FollowService).not_to have_received(:new)
- end
- end
-
- context 'when the account is updated' do
- it 'calls the follow service and destroys the follow' do
- follow_service = double(call: nil)
- allow(FollowService).to receive(:new).and_return(follow_service)
- account = Fabricate(:account, locked: false)
- service = double(call: account)
- allow(FetchRemoteAccountService).to receive(:new).and_return(service)
-
- result = subject.perform(follow_request.id)
-
- expect(result).to be_nil
- expect(follow_service).to have_received(:call).with(follow_request.account, account.acct)
- expect { follow_request.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
- end
-end
diff --git a/spec/workers/after_remote_follow_worker_spec.rb b/spec/workers/after_remote_follow_worker_spec.rb
deleted file mode 100644
index d93c469f..00000000
--- a/spec/workers/after_remote_follow_worker_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe AfterRemoteFollowWorker do
- subject { described_class.new }
- let(:follow) { Fabricate(:follow) }
- describe 'perform' do
- context 'when the follow does not exist' do
- it 'catches a raise and returns true' do
- allow(FollowService).to receive(:new)
- result = subject.perform('aaa')
-
- expect(result).to eq(true)
- expect(FollowService).not_to have_received(:new)
- end
- end
-
- context 'when the account cannot be updated' do
- it 'returns nil and does not call service when account is nil' do
- allow(FollowService).to receive(:new)
- service = double(call: nil)
- allow(FetchRemoteAccountService).to receive(:new).and_return(service)
-
- result = subject.perform(follow.id)
-
- expect(result).to be_nil
- expect(FollowService).not_to have_received(:new)
- end
-
- it 'returns nil and does not call service when account is not locked' do
- allow(FollowService).to receive(:new)
- service = double(call: double(locked?: false))
- allow(FetchRemoteAccountService).to receive(:new).and_return(service)
-
- result = subject.perform(follow.id)
-
- expect(result).to be_nil
- expect(FollowService).not_to have_received(:new)
- end
- end
-
- context 'when the account is updated' do
- it 'calls the follow service and destroys the follow' do
- follow_service = double(call: nil)
- allow(FollowService).to receive(:new).and_return(follow_service)
- account = Fabricate(:account, locked: true)
- service = double(call: account)
- allow(FetchRemoteAccountService).to receive(:new).and_return(service)
-
- result = subject.perform(follow.id)
-
- expect(result).to be_nil
- expect(follow_service).to have_received(:call).with(follow.account, account.acct)
- expect { follow.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
- end
-end
diff --git a/spec/workers/digest_mailer_worker_spec.rb b/spec/workers/digest_mailer_worker_spec.rb
deleted file mode 100644
index db3b1390..00000000
--- a/spec/workers/digest_mailer_worker_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe DigestMailerWorker do
- describe 'perform' do
- let(:user) { Fabricate(:user, last_emailed_at: 3.days.ago) }
-
- context 'for a user who receives digests' do
- it 'sends the email' do
- service = double(deliver_now!: nil)
- allow(NotificationMailer).to receive(:digest).and_return(service)
- update_user_digest_setting(true)
- described_class.perform_async(user.id)
-
- expect(NotificationMailer).to have_received(:digest)
- expect(user.reload.last_emailed_at).to be_within(1).of(Time.now.utc)
- end
- end
-
- context 'for a user who does not receive digests' do
- it 'does not send the email' do
- allow(NotificationMailer).to receive(:digest)
- update_user_digest_setting(false)
- described_class.perform_async(user.id)
-
- expect(NotificationMailer).not_to have_received(:digest)
- expect(user.last_emailed_at).to be_within(1).of(3.days.ago)
- end
- end
-
- def update_user_digest_setting(value)
- user.settings['notification_emails'] = user.settings['notification_emails'].merge('digest' => value)
- end
- end
-end
diff --git a/spec/workers/domain_block_worker_spec.rb b/spec/workers/domain_block_worker_spec.rb
deleted file mode 100644
index c4138501..00000000
--- a/spec/workers/domain_block_worker_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe DomainBlockWorker do
- subject { described_class.new }
-
- describe 'perform' do
- let(:domain_block) { Fabricate(:domain_block) }
-
- it 'returns true for non-existent domain block' do
- service = double(call: nil)
- allow(BlockDomainService).to receive(:new).and_return(service)
- result = subject.perform(domain_block.id)
-
- expect(result).to be_nil
- expect(service).to have_received(:call).with(domain_block)
- end
-
- it 'calls domain block service for relevant domain block' do
- result = subject.perform('aaa')
-
- expect(result).to eq(true)
- end
- end
-end
diff --git a/spec/workers/feed_insert_worker_spec.rb b/spec/workers/feed_insert_worker_spec.rb
deleted file mode 100644
index 3509f1f5..00000000
--- a/spec/workers/feed_insert_worker_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe FeedInsertWorker do
- subject { described_class.new }
-
- describe 'perform' do
- let(:follower) { Fabricate(:account) }
- let(:status) { Fabricate(:status) }
-
- context 'when there are no records' do
- it 'skips push with missing status' do
- instance = double(push_to_home: nil)
- allow(FeedManager).to receive(:instance).and_return(instance)
- result = subject.perform(nil, follower.id)
-
- expect(result).to eq true
- expect(instance).not_to have_received(:push_to_home)
- end
-
- it 'skips push with missing account' do
- instance = double(push_to_home: nil)
- allow(FeedManager).to receive(:instance).and_return(instance)
- result = subject.perform(status.id, nil)
-
- expect(result).to eq true
- expect(instance).not_to have_received(:push_to_home)
- end
- end
-
- context 'when there are real records' do
- it 'skips the push when there is a filter' do
- instance = double(push_to_home: nil, filter?: true)
- allow(FeedManager).to receive(:instance).and_return(instance)
- result = subject.perform(status.id, follower.id)
-
- expect(result).to be_nil
- expect(instance).not_to have_received(:push_to_home)
- end
-
- it 'pushes the status onto the home timeline without filter' do
- instance = double(push_to_home: nil, filter?: false)
- allow(FeedManager).to receive(:instance).and_return(instance)
- result = subject.perform(status.id, follower.id)
-
- expect(result).to be_nil
- expect(instance).to have_received(:push_to_home).with(follower, status)
- end
- end
- end
-end
diff --git a/spec/workers/publish_scheduled_status_worker_spec.rb b/spec/workers/publish_scheduled_status_worker_spec.rb
deleted file mode 100644
index f8547e6f..00000000
--- a/spec/workers/publish_scheduled_status_worker_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe PublishScheduledStatusWorker do
- subject { described_class.new }
-
- let(:scheduled_status) { Fabricate(:scheduled_status, params: { text: 'Hello world, future!' }) }
-
- describe 'perform' do
- before do
- subject.perform(scheduled_status.id)
- end
-
- it 'creates a status' do
- expect(scheduled_status.account.statuses.first.text).to eq 'Hello world, future!'
- end
-
- it 'removes the scheduled status' do
- expect(ScheduledStatus.find_by(id: scheduled_status.id)).to be_nil
- end
- end
-end
diff --git a/spec/workers/pubsubhubbub/confirmation_worker_spec.rb b/spec/workers/pubsubhubbub/confirmation_worker_spec.rb
deleted file mode 100644
index 1eecdd2b..00000000
--- a/spec/workers/pubsubhubbub/confirmation_worker_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Pubsubhubbub::ConfirmationWorker do
- include RoutingHelper
-
- subject { described_class.new }
-
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:subscription) { Fabricate(:subscription, account: alice, callback_url: 'http://example.com/api', confirmed: false, expires_at: 3.days.from_now, secret: nil) }
-
- describe 'perform' do
- describe 'with subscribe mode' do
- it 'confirms and updates subscription when challenge matches' do
- stub_random_value
- stub_request(:get, url_for_mode('subscribe'))
- .with(headers: http_headers)
- .to_return(status: 200, body: challenge_value, headers: {})
-
- seconds = 10.days.seconds.to_i
- subject.perform(subscription.id, 'subscribe', 'asdf', seconds)
-
- subscription.reload
- expect(subscription.secret).to eq 'asdf'
- expect(subscription.confirmed).to eq true
- expect(subscription.expires_at).to be_within(5).of(10.days.from_now)
- end
-
- it 'does not update subscription when challenge does not match' do
- stub_random_value
- stub_request(:get, url_for_mode('subscribe'))
- .with(headers: http_headers)
- .to_return(status: 200, body: 'wrong value', headers: {})
-
- seconds = 10.days.seconds.to_i
- subject.perform(subscription.id, 'subscribe', 'asdf', seconds)
-
- subscription.reload
- expect(subscription.secret).to be_blank
- expect(subscription.confirmed).to eq false
- expect(subscription.expires_at).to be_within(5).of(3.days.from_now)
- end
- end
-
- describe 'with unsubscribe mode' do
- it 'confirms and destroys subscription when challenge matches' do
- stub_random_value
- stub_request(:get, url_for_mode('unsubscribe'))
- .with(headers: http_headers)
- .to_return(status: 200, body: challenge_value, headers: {})
-
- seconds = 10.days.seconds.to_i
- subject.perform(subscription.id, 'unsubscribe', 'asdf', seconds)
-
- expect { subscription.reload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'does not destroy subscription when challenge does not match' do
- stub_random_value
- stub_request(:get, url_for_mode('unsubscribe'))
- .with(headers: http_headers)
- .to_return(status: 200, body: 'wrong value', headers: {})
-
- seconds = 10.days.seconds.to_i
- subject.perform(subscription.id, 'unsubscribe', 'asdf', seconds)
-
- expect { subscription.reload }.not_to raise_error
- end
- end
- end
-
- def url_for_mode(mode)
- "http://example.com/api?hub.challenge=#{challenge_value}&hub.lease_seconds=863999&hub.mode=#{mode}&hub.topic=https://#{Rails.configuration.x.local_domain}/users/alice.atom"
- end
-
- def stub_random_value
- allow(SecureRandom).to receive(:hex).and_return(challenge_value)
- end
-
- def challenge_value
- '1a2s3d4f'
- end
-
- def http_headers
- { 'Connection' => 'close', 'Host' => 'example.com' }
- end
-end
diff --git a/spec/workers/pubsubhubbub/delivery_worker_spec.rb b/spec/workers/pubsubhubbub/delivery_worker_spec.rb
deleted file mode 100644
index da000fcb..00000000
--- a/spec/workers/pubsubhubbub/delivery_worker_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe Pubsubhubbub::DeliveryWorker do
- include RoutingHelper
- subject { described_class.new }
-
- let(:payload) { 'test' }
-
- describe 'perform' do
- it 'raises when subscription does not exist' do
- expect { subject.perform 123, payload }.to raise_error(ActiveRecord::RecordNotFound)
- end
-
- it 'does not attempt to deliver when domain blocked' do
- _domain_block = Fabricate(:domain_block, domain: 'example.com', severity: :suspend)
- subscription = Fabricate(:subscription, callback_url: 'https://example.com/api', last_successful_delivery_at: 2.days.ago)
-
- subject.perform(subscription.id, payload)
-
- expect(subscription.reload.last_successful_delivery_at).to be_within(2).of(2.days.ago)
- end
-
- it 'raises when request fails' do
- subscription = Fabricate(:subscription)
-
- stub_request_to_respond_with(subscription, 500)
- expect { subject.perform(subscription.id, payload) }.to raise_error GabSocial::UnexpectedResponseError
- end
-
- it 'updates subscriptions when delivery succeeds' do
- subscription = Fabricate(:subscription)
-
- stub_request_to_respond_with(subscription, 200)
- subject.perform(subscription.id, payload)
-
- expect(subscription.reload.last_successful_delivery_at).to be_within(2).of(Time.now.utc)
- end
-
- it 'updates subscription without a secret when delivery succeeds' do
- subscription = Fabricate(:subscription, secret: nil)
-
- stub_request_to_respond_with(subscription, 200)
- subject.perform(subscription.id, payload)
-
- expect(subscription.reload.last_successful_delivery_at).to be_within(2).of(Time.now.utc)
- end
-
- def stub_request_to_respond_with(subscription, code)
- stub_request(:post, 'http://example.com/callback')
- .with(body: payload, headers: expected_headers(subscription))
- .to_return(status: code, body: '', headers: {})
- end
-
- def expected_headers(subscription)
- {
- 'Connection' => 'close',
- 'Content-Type' => 'application/atom+xml',
- 'Host' => 'example.com',
- 'Link' => "; rel=\"hub\", ; rel=\"self\"",
- }.tap do |basic|
- known_digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), subscription.secret.to_s, payload)
- basic.merge('X-Hub-Signature' => "sha1=#{known_digest}") if subscription.secret?
- end
- end
- end
-end
diff --git a/spec/workers/pubsubhubbub/distribution_worker_spec.rb b/spec/workers/pubsubhubbub/distribution_worker_spec.rb
deleted file mode 100644
index 58448507..00000000
--- a/spec/workers/pubsubhubbub/distribution_worker_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'rails_helper'
-
-describe Pubsubhubbub::DistributionWorker do
- subject { Pubsubhubbub::DistributionWorker.new }
-
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example2.com') }
- let!(:anonymous_subscription) { Fabricate(:subscription, account: alice, callback_url: 'http://example1.com', confirmed: true, lease_seconds: 3600) }
- let!(:subscription_with_follower) { Fabricate(:subscription, account: alice, callback_url: 'http://example2.com', confirmed: true, lease_seconds: 3600) }
-
- before do
- bob.follow!(alice)
- end
-
- describe 'with public status' do
- let(:status) { Fabricate(:status, account: alice, text: 'Hello', visibility: :public) }
-
- it 'delivers payload to all subscriptions' do
- allow(Pubsubhubbub::DeliveryWorker).to receive(:push_bulk)
- subject.perform(status.stream_entry.id)
- expect(Pubsubhubbub::DeliveryWorker).to have_received(:push_bulk).with([anonymous_subscription.id, subscription_with_follower.id])
- end
- end
-
- context 'when OStatus privacy is not used' do
- describe 'with private status' do
- let(:status) { Fabricate(:status, account: alice, text: 'Hello', visibility: :private) }
-
- it 'does not deliver anything' do
- allow(Pubsubhubbub::DeliveryWorker).to receive(:push_bulk)
- subject.perform(status.stream_entry.id)
- expect(Pubsubhubbub::DeliveryWorker).to_not have_received(:push_bulk)
- end
- end
-
- describe 'with direct status' do
- let(:status) { Fabricate(:status, account: alice, text: 'Hello', visibility: :direct) }
-
- it 'does not deliver payload' do
- allow(Pubsubhubbub::DeliveryWorker).to receive(:push_bulk)
- subject.perform(status.stream_entry.id)
- expect(Pubsubhubbub::DeliveryWorker).to_not have_received(:push_bulk)
- end
- end
- end
-end
diff --git a/spec/workers/regeneration_worker_spec.rb b/spec/workers/regeneration_worker_spec.rb
deleted file mode 100644
index c6bdfa0e..00000000
--- a/spec/workers/regeneration_worker_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe RegenerationWorker do
- subject { described_class.new }
-
- describe 'perform' do
- let(:account) { Fabricate(:account) }
-
- it 'calls the precompute feed service for the account' do
- service = double(call: nil)
- allow(PrecomputeFeedService).to receive(:new).and_return(service)
- result = subject.perform(account.id)
-
- expect(result).to be_nil
- expect(service).to have_received(:call).with(account)
- end
-
- it 'fails when account does not exist' do
- result = subject.perform('aaa')
-
- expect(result).to eq(true)
- end
- end
-end
diff --git a/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb b/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb
deleted file mode 100644
index 7fae680b..00000000
--- a/spec/workers/scheduler/feed_cleanup_scheduler_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'rails_helper'
-
-describe Scheduler::FeedCleanupScheduler do
- subject { described_class.new }
-
- let!(:active_user) { Fabricate(:user, current_sign_in_at: 2.days.ago) }
- let!(:inactive_user) { Fabricate(:user, current_sign_in_at: 22.days.ago) }
-
- it 'clears feeds of inactives' do
- Redis.current.zadd(feed_key_for(inactive_user), 1, 1)
- Redis.current.zadd(feed_key_for(active_user), 1, 1)
- Redis.current.zadd(feed_key_for(inactive_user, 'reblogs'), 2, 2)
- Redis.current.sadd(feed_key_for(inactive_user, 'reblogs:2'), 3)
-
- subject.perform
-
- expect(Redis.current.zcard(feed_key_for(inactive_user))).to eq 0
- expect(Redis.current.zcard(feed_key_for(active_user))).to eq 1
- expect(Redis.current.exists(feed_key_for(inactive_user, 'reblogs'))).to be false
- expect(Redis.current.exists(feed_key_for(inactive_user, 'reblogs:2'))).to be false
- end
-
- def feed_key_for(user, subtype = nil)
- FeedManager.instance.key(:home, user.account_id, subtype)
- end
-end
diff --git a/spec/workers/scheduler/media_cleanup_scheduler_spec.rb b/spec/workers/scheduler/media_cleanup_scheduler_spec.rb
deleted file mode 100644
index 8a0da67e..00000000
--- a/spec/workers/scheduler/media_cleanup_scheduler_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe Scheduler::MediaCleanupScheduler do
- subject { described_class.new }
-
- let!(:old_media) { Fabricate(:media_attachment, account_id: nil, created_at: 10.days.ago) }
- let!(:new_media) { Fabricate(:media_attachment, account_id: nil, created_at: 1.hour.ago) }
-
- it 'removes old media records' do
- subject.perform
-
- expect { old_media.reload }.to raise_error(ActiveRecord::RecordNotFound)
- expect(new_media.reload).to be_persisted
- end
-end
diff --git a/spec/workers/scheduler/subscriptions_scheduler_spec.rb b/spec/workers/scheduler/subscriptions_scheduler_spec.rb
deleted file mode 100644
index a7d1046d..00000000
--- a/spec/workers/scheduler/subscriptions_scheduler_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require 'rails_helper'
-
-describe Scheduler::SubscriptionsScheduler do
- subject { Scheduler::SubscriptionsScheduler.new }
-
- let!(:expiring_account1) { Fabricate(:account, subscription_expires_at: 20.minutes.from_now, domain: 'example.com', followers_count: 1, hub_url: 'http://hub.example.com') }
- let!(:expiring_account2) { Fabricate(:account, subscription_expires_at: 4.hours.from_now, domain: 'example.org', followers_count: 1, hub_url: 'http://hub.example.org') }
-
- before do
- stub_request(:post, 'http://hub.example.com/').to_return(status: 202)
- stub_request(:post, 'http://hub.example.org/').to_return(status: 202)
- end
-
- it 're-subscribes for all expiring accounts' do
- subject.perform
- expect(a_request(:post, 'http://hub.example.com/')).to have_been_made.once
- expect(a_request(:post, 'http://hub.example.org/')).to have_been_made.once
- end
-end
diff --git a/streaming/index.js b/streaming/index.js
index 7d292ce9..5148d32d 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -422,7 +422,7 @@ const startWorker = (workerId) => {
];
if (accountDomain) {
- queries.push(client.query('SELECT 1 FROM account_domain_blocks WHERE account_id = $1 AND domain = $2', [req.accountId, accountDomain]));
+ // queries.push(client.query('SELECT 1 FROM account_domain_blocks WHERE account_id = $1 AND domain = $2', [req.accountId, accountDomain]));
}
Promise.all(queries).then(values => {
@@ -536,24 +536,6 @@ const startWorker = (workerId) => {
streamFrom(`timeline:${req.accountId}`, req, streamToHttp(req, res), streamHttpEnd(req), false, true);
});
- app.get('/api/v1/streaming/list', (req, res) => {
- const listId = req.query.list;
-
- authorizeListAccess(listId, req, authorized => {
- if (!authorized) {
- httpNotFound(res);
- return;
- }
-
- const channel = `timeline:list:${listId}`;
- streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req, subscriptionHeartbeat(channel)));
- });
- });
-
- app.get('/api/v1/streaming/pro', (req, res) => {
- streamFrom('timeline:pro', req, streamToHttp(req, res), streamHttpEnd(req, subscriptionHeartbeat(channel)));
- });
-
const wss = new WebSocketServer({ server, verifyClient: wsVerifyClient });
wss.on('connection', (ws, req) => {
@@ -564,9 +546,6 @@ const startWorker = (workerId) => {
let channel;
switch (location.query.stream) {
- case 'pro':
- streamFrom('timeline:pro', req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel)));
- break;
case 'statuscard':
channel = `statuscard:${req.accountId}`;
streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel)));
@@ -578,19 +557,6 @@ const startWorker = (workerId) => {
case 'user:notification':
streamFrom(`timeline:${req.accountId}`, req, streamToWs(req, ws), streamWsEnd(req, ws), false, true);
break;
- case 'list':
- const listId = location.query.list;
-
- authorizeListAccess(listId, req, authorized => {
- if (!authorized) {
- ws.close();
- return;
- }
-
- channel = `timeline:list:${listId}`;
- streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel)));
- });
- break;
default:
ws.close();
}
diff --git a/yarn.lock b/yarn.lock
index 131c46e3..53e79795 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -18,7 +18,7 @@
invariant "^2.2.4"
semver "^5.5.0"
-"@babel/core@^7.1.0", "@babel/core@^7.3.4", "@babel/core@^7.4.5":
+"@babel/core@^7.3.4", "@babel/core@^7.4.5":
version "7.9.0"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e"
integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==
@@ -40,7 +40,7 @@
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/generator@^7.4.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5":
+"@babel/generator@^7.9.0", "@babel/generator@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9"
integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==
@@ -269,7 +269,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0":
+"@babel/parser@^7.1.0", "@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0":
version "7.9.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8"
integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==
@@ -414,7 +414,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.0":
+"@babel/plugin-syntax-object-rest-spread@^7.8.0":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
@@ -849,7 +849,7 @@
dependencies:
regenerator-runtime "^0.13.4"
-"@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
+"@babel/template@^7.8.3", "@babel/template@^7.8.6":
version "7.8.6"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b"
integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==
@@ -858,7 +858,7 @@
"@babel/parser" "^7.8.6"
"@babel/types" "^7.8.6"
-"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
+"@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2"
integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==
@@ -873,7 +873,7 @@
globals "^11.1.0"
lodash "^4.17.13"
-"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
+"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
version "7.9.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444"
integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==
@@ -887,168 +887,12 @@
resolved "https://registry.yarnpkg.com/@clusterws/cws/-/cws-0.14.0.tgz#242824b6884454001340222a836db6f6c5e62bfb"
integrity sha512-knZj3KZNHIAGsX7TUc/0Q5gcx2bKMMcTPsAOZomLKdK5a4o/umKFlttWRH84Yr1nVlQy+UMO23qfDR8gRZ/4cw==
-"@cnakazawa/watch@^1.0.3":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
- integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==
- dependencies:
- exec-sh "^0.3.2"
- minimist "^1.2.0"
-
-"@jest/console@^24.7.1", "@jest/console@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0"
- integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==
- dependencies:
- "@jest/source-map" "^24.9.0"
- chalk "^2.0.1"
- slash "^2.0.0"
-
-"@jest/core@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4"
- integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==
- dependencies:
- "@jest/console" "^24.7.1"
- "@jest/reporters" "^24.9.0"
- "@jest/test-result" "^24.9.0"
- "@jest/transform" "^24.9.0"
- "@jest/types" "^24.9.0"
- ansi-escapes "^3.0.0"
- chalk "^2.0.1"
- exit "^0.1.2"
- graceful-fs "^4.1.15"
- jest-changed-files "^24.9.0"
- jest-config "^24.9.0"
- jest-haste-map "^24.9.0"
- jest-message-util "^24.9.0"
- jest-regex-util "^24.3.0"
- jest-resolve "^24.9.0"
- jest-resolve-dependencies "^24.9.0"
- jest-runner "^24.9.0"
- jest-runtime "^24.9.0"
- jest-snapshot "^24.9.0"
- jest-util "^24.9.0"
- jest-validate "^24.9.0"
- jest-watcher "^24.9.0"
- micromatch "^3.1.10"
- p-each-series "^1.0.0"
- realpath-native "^1.1.0"
- rimraf "^2.5.4"
- slash "^2.0.0"
- strip-ansi "^5.0.0"
-
-"@jest/environment@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18"
- integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==
- dependencies:
- "@jest/fake-timers" "^24.9.0"
- "@jest/transform" "^24.9.0"
- "@jest/types" "^24.9.0"
- jest-mock "^24.9.0"
-
-"@jest/fake-timers@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93"
- integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==
- dependencies:
- "@jest/types" "^24.9.0"
- jest-message-util "^24.9.0"
- jest-mock "^24.9.0"
-
-"@jest/reporters@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43"
- integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==
- dependencies:
- "@jest/environment" "^24.9.0"
- "@jest/test-result" "^24.9.0"
- "@jest/transform" "^24.9.0"
- "@jest/types" "^24.9.0"
- chalk "^2.0.1"
- exit "^0.1.2"
- glob "^7.1.2"
- istanbul-lib-coverage "^2.0.2"
- istanbul-lib-instrument "^3.0.1"
- istanbul-lib-report "^2.0.4"
- istanbul-lib-source-maps "^3.0.1"
- istanbul-reports "^2.2.6"
- jest-haste-map "^24.9.0"
- jest-resolve "^24.9.0"
- jest-runtime "^24.9.0"
- jest-util "^24.9.0"
- jest-worker "^24.6.0"
- node-notifier "^5.4.2"
- slash "^2.0.0"
- source-map "^0.6.0"
- string-length "^2.0.0"
-
-"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714"
- integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==
- dependencies:
- callsites "^3.0.0"
- graceful-fs "^4.1.15"
- source-map "^0.6.0"
-
-"@jest/test-result@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca"
- integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==
- dependencies:
- "@jest/console" "^24.9.0"
- "@jest/types" "^24.9.0"
- "@types/istanbul-lib-coverage" "^2.0.0"
-
-"@jest/test-sequencer@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31"
- integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==
- dependencies:
- "@jest/test-result" "^24.9.0"
- jest-haste-map "^24.9.0"
- jest-runner "^24.9.0"
- jest-runtime "^24.9.0"
-
-"@jest/transform@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56"
- integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==
- dependencies:
- "@babel/core" "^7.1.0"
- "@jest/types" "^24.9.0"
- babel-plugin-istanbul "^5.1.0"
- chalk "^2.0.1"
- convert-source-map "^1.4.0"
- fast-json-stable-stringify "^2.0.0"
- graceful-fs "^4.1.15"
- jest-haste-map "^24.9.0"
- jest-regex-util "^24.9.0"
- jest-util "^24.9.0"
- micromatch "^3.1.10"
- pirates "^4.0.1"
- realpath-native "^1.1.0"
- slash "^2.0.0"
- source-map "^0.6.1"
- write-file-atomic "2.4.1"
-
-"@jest/types@^24.9.0":
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59"
- integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==
- dependencies:
- "@types/istanbul-lib-coverage" "^2.0.0"
- "@types/istanbul-reports" "^1.1.1"
- "@types/yargs" "^13.0.0"
-
"@popperjs/core@^2.4.4":
version "2.4.4"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.4.tgz#11d5db19bd178936ec89cd84519c4de439574398"
integrity sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg==
-"@types/babel__core@^7.1.0", "@types/babel__core@^7.1.2":
+"@types/babel__core@^7.1.2":
version "7.1.7"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89"
integrity sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==
@@ -1074,7 +918,7 @@
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
-"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
+"@types/babel__traverse@*":
version "7.0.10"
resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.10.tgz#d9a99f017317d9b3d1abc2ced45d3bca68df0daf"
integrity sha512-74fNdUGrWsgIB/V9kTO5FGHPWYY6Eqn+3Z7L6Hc4e/BxjYV7puvBqp5HwsVYYfLm6iURYBNCx4Ut37OF9yitCw==
@@ -1095,26 +939,6 @@
"@types/minimatch" "*"
"@types/node" "*"
-"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
- integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==
-
-"@types/istanbul-lib-report@*":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
- integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
- dependencies:
- "@types/istanbul-lib-coverage" "*"
-
-"@types/istanbul-reports@^1.1.1":
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a"
- integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==
- dependencies:
- "@types/istanbul-lib-coverage" "*"
- "@types/istanbul-lib-report" "*"
-
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -1142,23 +966,6 @@
dependencies:
csstype "^2.2.0"
-"@types/stack-utils@^1.0.1":
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
- integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
-
-"@types/yargs-parser@*":
- version "15.0.0"
- resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
- integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
-
-"@types/yargs@^13.0.0":
- version "13.0.8"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.8.tgz#a38c22def2f1c2068f8971acb3ea734eb3c64a99"
- integrity sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==
- dependencies:
- "@types/yargs-parser" "*"
-
"@webassemblyjs/ast@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
@@ -1314,11 +1121,6 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
-abab@^2.0.0:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
- integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
-
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@@ -1327,35 +1129,17 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
mime-types "~2.1.24"
negotiator "0.6.2"
-acorn-globals@^4.1.0:
- version "4.3.4"
- resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
- integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
- dependencies:
- acorn "^6.0.1"
- acorn-walk "^6.0.1"
-
acorn-jsx@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
-acorn-walk@^6.0.1:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
- integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
-
acorn-walk@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.1.1.tgz#345f0dffad5c735e7373d2fec9a1023e6a44b83e"
integrity sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==
-acorn@^5.5.3:
- version "5.7.4"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
- integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
-
-acorn@^6.0.1, acorn@^6.0.7, acorn@^6.4.1:
+acorn@^6.0.7, acorn@^6.4.1:
version "6.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
@@ -1365,22 +1149,6 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==
-airbnb-prop-types@^2.15.0:
- version "2.15.0"
- resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz#5287820043af1eb469f5b0af0d6f70da6c52aaef"
- integrity sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==
- dependencies:
- array.prototype.find "^2.1.0"
- function.prototype.name "^1.1.1"
- has "^1.0.3"
- is-regex "^1.0.4"
- object-is "^1.0.1"
- object.assign "^4.1.0"
- object.entries "^1.1.0"
- prop-types "^15.7.2"
- prop-types-exact "^1.2.0"
- react-is "^16.9.0"
-
ajv-errors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
@@ -1391,7 +1159,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
-ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5, ajv@^6.9.1:
+ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.9.1:
version "6.12.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7"
integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==
@@ -1411,7 +1179,7 @@ ansi-colors@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
-ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
+ansi-escapes@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
@@ -1431,7 +1199,7 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
-ansi-regex@^4.0.0, ansi-regex@^4.1.0:
+ansi-regex@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
@@ -1499,16 +1267,6 @@ arr-union@^3.1.0:
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
-array-equal@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
- integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
-
-array-filter@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
- integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
-
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
@@ -1545,22 +1303,6 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
-array.prototype.find@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.1.tgz#3baca26108ca7affb08db06bf0be6cb3115a969c"
- integrity sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.4"
-
-array.prototype.flat@^1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b"
- integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
-
asap@~2.0.3:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
@@ -1575,18 +1317,6 @@ asn1.js@^4.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
-asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
- dependencies:
- safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
assert@^1.1.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
@@ -1627,11 +1357,6 @@ async@^2.6.2:
dependencies:
lodash "^4.17.14"
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
-
atob@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
@@ -1657,16 +1382,6 @@ autoprefixer@^9.5.1:
postcss "^7.0.27"
postcss-value-parser "^4.0.3"
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.8.0:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
- integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
-
axios@^0.19.0:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
@@ -1691,19 +1406,6 @@ babel-eslint@^10.0.1:
eslint-visitor-keys "^1.0.0"
resolve "^1.12.0"
-babel-jest@^24.8.0, babel-jest@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54"
- integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==
- dependencies:
- "@jest/transform" "^24.9.0"
- "@jest/types" "^24.9.0"
- "@types/babel__core" "^7.1.0"
- babel-plugin-istanbul "^5.1.0"
- babel-preset-jest "^24.9.0"
- chalk "^2.4.2"
- slash "^2.0.0"
-
babel-loader@^8.0.5:
version "8.1.0"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
@@ -1722,23 +1424,6 @@ babel-plugin-dynamic-import-node@^2.3.0:
dependencies:
object.assign "^4.1.0"
-babel-plugin-istanbul@^5.1.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854"
- integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==
- dependencies:
- "@babel/helper-plugin-utils" "^7.0.0"
- find-up "^3.0.0"
- istanbul-lib-instrument "^3.3.0"
- test-exclude "^5.2.3"
-
-babel-plugin-jest-hoist@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756"
- integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==
- dependencies:
- "@types/babel__traverse" "^7.0.6"
-
babel-plugin-lodash@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/babel-plugin-lodash/-/babel-plugin-lodash-3.3.4.tgz#4f6844358a1340baed182adbeffa8df9967bc196"
@@ -1783,14 +1468,6 @@ babel-plugin-transform-react-remove-prop-types@^0.4.24:
resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
-babel-preset-jest@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc"
- integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==
- dependencies:
- "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
- babel-plugin-jest-hoist "^24.9.0"
-
babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
@@ -1834,13 +1511,6 @@ batch@0.6.1:
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
- dependencies:
- tweetnacl "^0.14.3"
-
bfj@^6.1.1:
version "6.1.2"
resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f"
@@ -1950,18 +1620,6 @@ brorand@^1.0.1:
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
-browser-process-hrtime@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
- integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
-
-browser-resolve@^1.11.3:
- version "1.11.3"
- resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
- integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==
- dependencies:
- resolve "1.1.7"
-
browserify-aes@^1.0.0, browserify-aes@^1.0.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
@@ -2031,13 +1689,6 @@ browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.8.5, browserslist@^4.
node-releases "^1.1.53"
pkg-up "^2.0.0"
-bser@2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
- integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
- dependencies:
- node-int64 "^0.4.0"
-
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -2162,7 +1813,7 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1:
+camelcase@^5.0.0, camelcase@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
@@ -2182,19 +1833,7 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001038, caniuse-lite@^1.0.30001039:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001040.tgz#103fc8e6eb1d7397e95134cd0e996743353d58ea"
integrity sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==
-capture-exit@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
- integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==
- dependencies:
- rsvp "^4.8.4"
-
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
-chalk@2.4.2, chalk@^2.0, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
+chalk@2.4.2, chalk@^2.0, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2224,18 +1863,6 @@ check-types@^8.0.3:
resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
-cheerio@^1.0.0-rc.3:
- version "1.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6"
- integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==
- dependencies:
- css-select "~1.2.0"
- dom-serializer "~0.1.1"
- entities "~1.1.1"
- htmlparser2 "^3.9.1"
- lodash "^4.15.0"
- parse5 "^3.0.1"
-
chokidar@^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
@@ -2267,11 +1894,6 @@ chrome-trace-event@^1.0.2:
dependencies:
tslib "^1.9.0"
-ci-info@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
- integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
-
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
@@ -2325,11 +1947,6 @@ cliui@^5.0.0:
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
- integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
-
coa@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
@@ -2385,14 +2002,7 @@ color@^3.0.0:
color-convert "^1.9.1"
color-string "^1.5.2"
-combined-stream@^1.0.6, combined-stream@~1.0.6:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
- integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
- dependencies:
- delayed-stream "~1.0.0"
-
-commander@^2.11.0, commander@^2.18.0, commander@^2.19.0, commander@^2.20.0, commander@~2.20.3:
+commander@^2.11.0, commander@^2.18.0, commander@^2.20.0, commander@~2.20.3:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -2491,7 +2101,7 @@ content-type@~1.0.4:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-convert-source-map@^1.4.0, convert-source-map@^1.7.0:
+convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@@ -2543,7 +2153,7 @@ core-js@^3.6.5:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
-core-util-is@1.0.2, core-util-is@~1.0.0:
+core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
@@ -2727,16 +2337,6 @@ css-select@^2.0.0:
domutils "^1.7.0"
nth-check "^1.0.2"
-css-select@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
- integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=
- dependencies:
- boolbase "~1.0.0"
- css-what "2.1"
- domutils "1.5.1"
- nth-check "~1.0.1"
-
css-system-font-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz#85c6f086aba4eb32c571a3086affc434b84823ed"
@@ -2763,11 +2363,6 @@ css-vars-ponyfill@^2.2.1:
resolved "https://registry.yarnpkg.com/css-vars-ponyfill/-/css-vars-ponyfill-2.2.1.tgz#c97dcfb3efc93b479661af58afa04cb0ef5b97e6"
integrity sha512-bFdKEQbCtwoDl4/iPaqjGDMZRgnVn6k7c6XUlOrW+OzMIweWV6b5YbajR99dUiAsB1WpfbGGiiE9T1cnSh2pgA==
-css-what@2.1:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
- integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
-
css-what@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1"
@@ -2853,18 +2448,6 @@ csso@^4.0.2:
dependencies:
css-tree "1.0.0-alpha.39"
-cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
- version "0.3.8"
- resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
- integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
-
-cssstyle@^1.0.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
- integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==
- dependencies:
- cssom "0.3.x"
-
csstype@^2.2.0:
version "2.6.10"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
@@ -2888,22 +2471,6 @@ damerau-levenshtein@^1.0.4:
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791"
integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
- dependencies:
- assert-plus "^1.0.0"
-
-data-urls@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
- integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
- dependencies:
- abab "^2.0.0"
- whatwg-mimetype "^2.2.0"
- whatwg-url "^7.0.0"
-
date-fns@^2.0.1:
version "2.12.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.12.0.tgz#01754c8a2f3368fc1119cf4625c3dad8c1845ee6"
@@ -3019,11 +2586,6 @@ del@^4.1.1:
pify "^4.0.1"
rimraf "^2.6.3"
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
-
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
@@ -3052,11 +2614,6 @@ detect-file@^1.0.0:
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
-detect-newline@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
- integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
-
detect-node@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
@@ -3067,11 +2624,6 @@ detect-passive-events@^1.0.2:
resolved "https://registry.yarnpkg.com/detect-passive-events/-/detect-passive-events-1.0.4.tgz#6ed477e6e5bceb79079735dcd357789d37f9a91a"
integrity sha1-btR35uW863kHlzXc01d4nTf5qRo=
-diff-sequences@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
- integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
-
diffie-hellman@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
@@ -3081,11 +2633,6 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
-discontinuous-range@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
- integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=
-
dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
@@ -3143,20 +2690,12 @@ dom-serializer@0, dom-serializer@^0.2.1:
domelementtype "^2.0.1"
entities "^2.0.0"
-dom-serializer@~0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0"
- integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==
- dependencies:
- domelementtype "^1.3.0"
- entities "^1.1.1"
-
domain-browser@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
-domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1:
+domelementtype@1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
@@ -3166,20 +2705,6 @@ domelementtype@^2.0.1:
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==
-domexception@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
- integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
- dependencies:
- webidl-conversions "^4.0.2"
-
-domhandler@^2.3.0:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
- integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
- dependencies:
- domelementtype "1"
-
domhandler@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9"
@@ -3187,15 +2712,7 @@ domhandler@^3.0.0:
dependencies:
domelementtype "^2.0.1"
-domutils@1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
- integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=
- dependencies:
- dom-serializer "0"
- domelementtype "1"
-
-domutils@^1.5.1, domutils@^1.7.0:
+domutils@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
@@ -3258,14 +2775,6 @@ duplexify@^3.4.2, duplexify@^3.6.0:
readable-stream "^2.0.0"
stream-shift "^1.0.0"
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
- dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
-
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -3350,79 +2859,11 @@ enhanced-resolve@^4.1.0:
memory-fs "^0.5.0"
tapable "^1.0.0"
-entities@^1.1.1, entities@~1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
- integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
-
entities@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
-enzyme-adapter-react-16@^1.7.1:
- version "1.15.2"
- resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz#b16db2f0ea424d58a808f9df86ab6212895a4501"
- integrity sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q==
- dependencies:
- enzyme-adapter-utils "^1.13.0"
- enzyme-shallow-equal "^1.0.1"
- has "^1.0.3"
- object.assign "^4.1.0"
- object.values "^1.1.1"
- prop-types "^15.7.2"
- react-is "^16.12.0"
- react-test-renderer "^16.0.0-0"
- semver "^5.7.0"
-
-enzyme-adapter-utils@^1.13.0:
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz#01c885dde2114b4690bf741f8dc94cee3060eb78"
- integrity sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ==
- dependencies:
- airbnb-prop-types "^2.15.0"
- function.prototype.name "^1.1.2"
- object.assign "^4.1.0"
- object.fromentries "^2.0.2"
- prop-types "^15.7.2"
- semver "^5.7.1"
-
-enzyme-shallow-equal@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz#7afe03db3801c9b76de8440694096412a8d9d49e"
- integrity sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ==
- dependencies:
- has "^1.0.3"
- object-is "^1.0.2"
-
-enzyme@^3.8.0:
- version "3.11.0"
- resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.11.0.tgz#71d680c580fe9349f6f5ac6c775bc3e6b7a79c28"
- integrity sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==
- dependencies:
- array.prototype.flat "^1.2.3"
- cheerio "^1.0.0-rc.3"
- enzyme-shallow-equal "^1.0.1"
- function.prototype.name "^1.1.2"
- has "^1.0.3"
- html-element-map "^1.2.0"
- is-boolean-object "^1.0.1"
- is-callable "^1.1.5"
- is-number-object "^1.0.4"
- is-regex "^1.0.5"
- is-string "^1.0.5"
- is-subset "^0.1.1"
- lodash.escape "^4.0.1"
- lodash.isequal "^4.5.0"
- object-inspect "^1.7.0"
- object-is "^1.0.2"
- object.assign "^4.1.0"
- object.entries "^1.1.1"
- object.values "^1.1.1"
- raf "^3.4.1"
- rst-selector-parser "^2.2.3"
- string.prototype.trim "^1.2.1"
-
errno@^0.1.3, errno@~0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
@@ -3437,7 +2878,7 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5:
+es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5:
version "1.17.5"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9"
integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==
@@ -3499,18 +2940,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-escodegen@^1.9.1:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457"
- integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==
- dependencies:
- esprima "^4.0.1"
- estraverse "^4.2.0"
- esutils "^2.0.2"
- optionator "^0.8.1"
- optionalDependencies:
- source-map "~0.6.1"
-
eslint-import-resolver-node@^0.3.1:
version "0.3.3"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404"
@@ -3647,7 +3076,7 @@ espree@^5.0.1:
acorn-jsx "^5.0.0"
eslint-visitor-keys "^1.0.0"
-esprima@^4.0.0, esprima@^4.0.1:
+esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
@@ -3666,7 +3095,7 @@ esrecurse@^4.1.0:
dependencies:
estraverse "^4.1.0"
-estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.1.0, estraverse@^4.1.1:
version "4.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
@@ -3716,11 +3145,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
-exec-sh@^0.3.2:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5"
- integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==
-
execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
@@ -3739,11 +3163,6 @@ exif-js@^2.3.0:
resolved "https://registry.yarnpkg.com/exif-js/-/exif-js-2.3.0.tgz#9d10819bf571f873813e7640241255ab9ce1a814"
integrity sha1-nRCBm/Vx+HOBPnZAJBJVq5zhqBQ=
-exit@^0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
- integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
-
expand-brackets@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@@ -3764,18 +3183,6 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2:
dependencies:
homedir-polyfill "^1.0.1"
-expect@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca"
- integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==
- dependencies:
- "@jest/types" "^24.9.0"
- ansi-styles "^3.2.0"
- jest-get-type "^24.9.0"
- jest-matcher-utils "^24.9.0"
- jest-message-util "^24.9.0"
- jest-regex-util "^24.9.0"
-
express@^4.16.3, express@^4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
@@ -3834,11 +3241,6 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
-extend@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
@@ -3862,16 +3264,6 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
fast-deep-equal@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
@@ -3901,13 +3293,6 @@ faye-websocket@~0.11.1:
dependencies:
websocket-driver ">=0.5.1"
-fb-watchman@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85"
- integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==
- dependencies:
- bser "2.1.1"
-
fbjs-css-vars@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8"
@@ -4061,20 +3446,6 @@ for-in@^1.0.2:
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
-form-data@~2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
- integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.6"
- mime-types "^2.1.12"
-
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -4137,25 +3508,11 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
-function.prototype.name@^1.1.1, function.prototype.name@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45"
- integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- functions-have-names "^1.2.0"
-
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
-functions-have-names@^1.2.0:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.1.tgz#a981ac397fa0c9964551402cdc5533d7a4d52f91"
- integrity sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==
-
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -4202,13 +3559,6 @@ get-value@^2.0.3, get-value@^2.0.6:
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
glob-parent@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
@@ -4286,11 +3636,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
-growly@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
- integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
-
gud@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
@@ -4309,19 +3654,6 @@ handle-thing@^2.0.0:
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.1.3:
- version "5.1.3"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
- integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
- dependencies:
- ajv "^6.5.5"
- har-schema "^2.0.0"
-
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
@@ -4483,42 +3815,11 @@ html-comment-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7"
integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==
-html-element-map@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.2.0.tgz#dfbb09efe882806af63d990cf6db37993f099f22"
- integrity sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw==
- dependencies:
- array-filter "^1.0.0"
-
-html-encoding-sniffer@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
- integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
- dependencies:
- whatwg-encoding "^1.0.1"
-
html-entities@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44"
integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==
-html-escaper@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
- integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
-
-htmlparser2@^3.9.1:
- version "3.10.1"
- resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
- integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
- dependencies:
- domelementtype "^1.3.1"
- domhandler "^2.3.0"
- domutils "^1.5.1"
- entities "^1.1.1"
- inherits "^2.0.1"
- readable-stream "^3.1.1"
-
htmlparser2@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78"
@@ -4595,15 +3896,6 @@ http-proxy@^1.17.0:
follow-redirects "^1.0.0"
requires-port "^1.0.0"
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
https-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
@@ -4886,11 +4178,6 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
-is-boolean-object@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e"
- integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==
-
is-buffer@^1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@@ -4901,13 +4188,6 @@ is-callable@^1.1.4, is-callable@^1.1.5:
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
-is-ci@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
- integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
- dependencies:
- ci-info "^2.0.0"
-
is-color-stop@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
@@ -4991,11 +4271,6 @@ is-fullwidth-code-point@^2.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
-is-generator-fn@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
- integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
-
is-glob@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
@@ -5017,11 +4292,6 @@ is-nan@^1.2.1:
dependencies:
define-properties "^1.1.3"
-is-number-object@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197"
- integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==
-
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -5087,11 +4357,6 @@ is-string@^1.0.5:
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
-is-subset@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6"
- integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=
-
is-svg@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75"
@@ -5106,11 +4371,6 @@ is-symbol@^1.0.2:
dependencies:
has-symbols "^1.0.1"
-is-typedarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-
is-windows@^1.0.1, is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@@ -5156,410 +4416,6 @@ isomorphic-fetch@^2.1.1:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
-istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
- integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
-
-istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
- integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
- dependencies:
- "@babel/generator" "^7.4.0"
- "@babel/parser" "^7.4.3"
- "@babel/template" "^7.4.0"
- "@babel/traverse" "^7.4.3"
- "@babel/types" "^7.4.0"
- istanbul-lib-coverage "^2.0.5"
- semver "^6.0.0"
-
-istanbul-lib-report@^2.0.4:
- version "2.0.8"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
- integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
- dependencies:
- istanbul-lib-coverage "^2.0.5"
- make-dir "^2.1.0"
- supports-color "^6.1.0"
-
-istanbul-lib-source-maps@^3.0.1:
- version "3.0.6"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
- integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
- dependencies:
- debug "^4.1.1"
- istanbul-lib-coverage "^2.0.5"
- make-dir "^2.1.0"
- rimraf "^2.6.3"
- source-map "^0.6.1"
-
-istanbul-reports@^2.2.6:
- version "2.2.7"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.7.tgz#5d939f6237d7b48393cc0959eab40cd4fd056931"
- integrity sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==
- dependencies:
- html-escaper "^2.0.0"
-
-jest-changed-files@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039"
- integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==
- dependencies:
- "@jest/types" "^24.9.0"
- execa "^1.0.0"
- throat "^4.0.0"
-
-jest-cli@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af"
- integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==
- dependencies:
- "@jest/core" "^24.9.0"
- "@jest/test-result" "^24.9.0"
- "@jest/types" "^24.9.0"
- chalk "^2.0.1"
- exit "^0.1.2"
- import-local "^2.0.0"
- is-ci "^2.0.0"
- jest-config "^24.9.0"
- jest-util "^24.9.0"
- jest-validate "^24.9.0"
- prompts "^2.0.1"
- realpath-native "^1.1.0"
- yargs "^13.3.0"
-
-jest-config@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5"
- integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==
- dependencies:
- "@babel/core" "^7.1.0"
- "@jest/test-sequencer" "^24.9.0"
- "@jest/types" "^24.9.0"
- babel-jest "^24.9.0"
- chalk "^2.0.1"
- glob "^7.1.1"
- jest-environment-jsdom "^24.9.0"
- jest-environment-node "^24.9.0"
- jest-get-type "^24.9.0"
- jest-jasmine2 "^24.9.0"
- jest-regex-util "^24.3.0"
- jest-resolve "^24.9.0"
- jest-util "^24.9.0"
- jest-validate "^24.9.0"
- micromatch "^3.1.10"
- pretty-format "^24.9.0"
- realpath-native "^1.1.0"
-
-jest-diff@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
- integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==
- dependencies:
- chalk "^2.0.1"
- diff-sequences "^24.9.0"
- jest-get-type "^24.9.0"
- pretty-format "^24.9.0"
-
-jest-docblock@^24.3.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2"
- integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==
- dependencies:
- detect-newline "^2.1.0"
-
-jest-each@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05"
- integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==
- dependencies:
- "@jest/types" "^24.9.0"
- chalk "^2.0.1"
- jest-get-type "^24.9.0"
- jest-util "^24.9.0"
- pretty-format "^24.9.0"
-
-jest-environment-jsdom@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b"
- integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==
- dependencies:
- "@jest/environment" "^24.9.0"
- "@jest/fake-timers" "^24.9.0"
- "@jest/types" "^24.9.0"
- jest-mock "^24.9.0"
- jest-util "^24.9.0"
- jsdom "^11.5.1"
-
-jest-environment-node@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3"
- integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==
- dependencies:
- "@jest/environment" "^24.9.0"
- "@jest/fake-timers" "^24.9.0"
- "@jest/types" "^24.9.0"
- jest-mock "^24.9.0"
- jest-util "^24.9.0"
-
-jest-get-type@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e"
- integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==
-
-jest-haste-map@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d"
- integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==
- dependencies:
- "@jest/types" "^24.9.0"
- anymatch "^2.0.0"
- fb-watchman "^2.0.0"
- graceful-fs "^4.1.15"
- invariant "^2.2.4"
- jest-serializer "^24.9.0"
- jest-util "^24.9.0"
- jest-worker "^24.9.0"
- micromatch "^3.1.10"
- sane "^4.0.3"
- walker "^1.0.7"
- optionalDependencies:
- fsevents "^1.2.7"
-
-jest-jasmine2@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0"
- integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==
- dependencies:
- "@babel/traverse" "^7.1.0"
- "@jest/environment" "^24.9.0"
- "@jest/test-result" "^24.9.0"
- "@jest/types" "^24.9.0"
- chalk "^2.0.1"
- co "^4.6.0"
- expect "^24.9.0"
- is-generator-fn "^2.0.0"
- jest-each "^24.9.0"
- jest-matcher-utils "^24.9.0"
- jest-message-util "^24.9.0"
- jest-runtime "^24.9.0"
- jest-snapshot "^24.9.0"
- jest-util "^24.9.0"
- pretty-format "^24.9.0"
- throat "^4.0.0"
-
-jest-leak-detector@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a"
- integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==
- dependencies:
- jest-get-type "^24.9.0"
- pretty-format "^24.9.0"
-
-jest-matcher-utils@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073"
- integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==
- dependencies:
- chalk "^2.0.1"
- jest-diff "^24.9.0"
- jest-get-type "^24.9.0"
- pretty-format "^24.9.0"
-
-jest-message-util@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3"
- integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- "@jest/test-result" "^24.9.0"
- "@jest/types" "^24.9.0"
- "@types/stack-utils" "^1.0.1"
- chalk "^2.0.1"
- micromatch "^3.1.10"
- slash "^2.0.0"
- stack-utils "^1.0.1"
-
-jest-mock@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6"
- integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==
- dependencies:
- "@jest/types" "^24.9.0"
-
-jest-pnp-resolver@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a"
- integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==
-
-jest-regex-util@^24.3.0, jest-regex-util@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636"
- integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==
-
-jest-resolve-dependencies@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab"
- integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==
- dependencies:
- "@jest/types" "^24.9.0"
- jest-regex-util "^24.3.0"
- jest-snapshot "^24.9.0"
-
-jest-resolve@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321"
- integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==
- dependencies:
- "@jest/types" "^24.9.0"
- browser-resolve "^1.11.3"
- chalk "^2.0.1"
- jest-pnp-resolver "^1.2.1"
- realpath-native "^1.1.0"
-
-jest-runner@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42"
- integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==
- dependencies:
- "@jest/console" "^24.7.1"
- "@jest/environment" "^24.9.0"
- "@jest/test-result" "^24.9.0"
- "@jest/types" "^24.9.0"
- chalk "^2.4.2"
- exit "^0.1.2"
- graceful-fs "^4.1.15"
- jest-config "^24.9.0"
- jest-docblock "^24.3.0"
- jest-haste-map "^24.9.0"
- jest-jasmine2 "^24.9.0"
- jest-leak-detector "^24.9.0"
- jest-message-util "^24.9.0"
- jest-resolve "^24.9.0"
- jest-runtime "^24.9.0"
- jest-util "^24.9.0"
- jest-worker "^24.6.0"
- source-map-support "^0.5.6"
- throat "^4.0.0"
-
-jest-runtime@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac"
- integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==
- dependencies:
- "@jest/console" "^24.7.1"
- "@jest/environment" "^24.9.0"
- "@jest/source-map" "^24.3.0"
- "@jest/transform" "^24.9.0"
- "@jest/types" "^24.9.0"
- "@types/yargs" "^13.0.0"
- chalk "^2.0.1"
- exit "^0.1.2"
- glob "^7.1.3"
- graceful-fs "^4.1.15"
- jest-config "^24.9.0"
- jest-haste-map "^24.9.0"
- jest-message-util "^24.9.0"
- jest-mock "^24.9.0"
- jest-regex-util "^24.3.0"
- jest-resolve "^24.9.0"
- jest-snapshot "^24.9.0"
- jest-util "^24.9.0"
- jest-validate "^24.9.0"
- realpath-native "^1.1.0"
- slash "^2.0.0"
- strip-bom "^3.0.0"
- yargs "^13.3.0"
-
-jest-serializer@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73"
- integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==
-
-jest-snapshot@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba"
- integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==
- dependencies:
- "@babel/types" "^7.0.0"
- "@jest/types" "^24.9.0"
- chalk "^2.0.1"
- expect "^24.9.0"
- jest-diff "^24.9.0"
- jest-get-type "^24.9.0"
- jest-matcher-utils "^24.9.0"
- jest-message-util "^24.9.0"
- jest-resolve "^24.9.0"
- mkdirp "^0.5.1"
- natural-compare "^1.4.0"
- pretty-format "^24.9.0"
- semver "^6.2.0"
-
-jest-util@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162"
- integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==
- dependencies:
- "@jest/console" "^24.9.0"
- "@jest/fake-timers" "^24.9.0"
- "@jest/source-map" "^24.9.0"
- "@jest/test-result" "^24.9.0"
- "@jest/types" "^24.9.0"
- callsites "^3.0.0"
- chalk "^2.0.1"
- graceful-fs "^4.1.15"
- is-ci "^2.0.0"
- mkdirp "^0.5.1"
- slash "^2.0.0"
- source-map "^0.6.0"
-
-jest-validate@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab"
- integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==
- dependencies:
- "@jest/types" "^24.9.0"
- camelcase "^5.3.1"
- chalk "^2.0.1"
- jest-get-type "^24.9.0"
- leven "^3.1.0"
- pretty-format "^24.9.0"
-
-jest-watcher@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b"
- integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==
- dependencies:
- "@jest/test-result" "^24.9.0"
- "@jest/types" "^24.9.0"
- "@types/yargs" "^13.0.0"
- ansi-escapes "^3.0.0"
- chalk "^2.0.1"
- jest-util "^24.9.0"
- string-length "^2.0.0"
-
-jest-worker@^24.6.0, jest-worker@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5"
- integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==
- dependencies:
- merge-stream "^2.0.0"
- supports-color "^6.1.0"
-
-jest@^24.8.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171"
- integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==
- dependencies:
- import-local "^2.0.0"
- jest-cli "^24.9.0"
-
js-base64@^2.1.9:
version "2.5.2"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209"
@@ -5583,43 +4439,6 @@ js-yaml@^3.13.0, js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-jsdom@^11.5.1:
- version "11.12.0"
- resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
- integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==
- dependencies:
- abab "^2.0.0"
- acorn "^5.5.3"
- acorn-globals "^4.1.0"
- array-equal "^1.0.0"
- cssom ">= 0.3.2 < 0.4.0"
- cssstyle "^1.0.0"
- data-urls "^1.0.0"
- domexception "^1.0.1"
- escodegen "^1.9.1"
- html-encoding-sniffer "^1.0.2"
- left-pad "^1.3.0"
- nwsapi "^2.0.7"
- parse5 "4.0.0"
- pn "^1.1.0"
- request "^2.87.0"
- request-promise-native "^1.0.5"
- sax "^1.2.4"
- symbol-tree "^3.2.2"
- tough-cookie "^2.3.4"
- w3c-hr-time "^1.0.1"
- webidl-conversions "^4.0.2"
- whatwg-encoding "^1.0.3"
- whatwg-mimetype "^2.1.0"
- whatwg-url "^6.4.1"
- ws "^5.2.0"
- xml-name-validator "^3.0.0"
-
jsesc@^2.5.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -5640,11 +4459,6 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
@@ -5657,11 +4471,6 @@ json-stable-stringify@^1.0.1:
dependencies:
jsonify "~0.0.0"
-json-stringify-safe@~5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
- integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
json3@^3.3.2:
version "3.3.3"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
@@ -5698,16 +4507,6 @@ jsonify@~0.0.0:
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
-
jsx-ast-utils@^2.0.1, jsx-ast-utils@^2.2.1:
version "2.2.3"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f"
@@ -5750,11 +4549,6 @@ kind-of@^6.0.0, kind-of@^6.0.2:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
-kleur@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
- integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-
lcid@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
@@ -5762,11 +4556,6 @@ lcid@^2.0.0:
dependencies:
invert-kv "^2.0.0"
-left-pad@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
- integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
-
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@@ -5802,16 +4591,6 @@ load-json-file@^2.0.0:
pify "^2.0.0"
strip-bom "^3.0.0"
-load-json-file@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
- integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^4.0.0"
- pify "^3.0.0"
- strip-bom "^3.0.0"
-
loader-runner@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
@@ -5876,21 +4655,11 @@ lodash.defaults@^4.0.1:
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
-lodash.escape@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
- integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
-
lodash.escaperegexp@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
-lodash.flattendeep@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
- integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
-
lodash.get@^4.0:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
@@ -5941,11 +4710,6 @@ lodash.pick@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
-lodash.sortby@^4.7.0:
- version "4.7.0"
- resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
- integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
-
lodash.throttle@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
@@ -5961,7 +4725,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
+lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -5985,7 +4749,7 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
-make-dir@^2.0.0, make-dir@^2.1.0:
+make-dir@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
@@ -5993,13 +4757,6 @@ make-dir@^2.0.0, make-dir@^2.1.0:
pify "^4.0.1"
semver "^5.6.0"
-makeerror@1.0.x:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
- integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=
- dependencies:
- tmpl "1.0.x"
-
map-age-cleaner@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
@@ -6078,11 +4835,6 @@ merge-descriptors@1.0.1:
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
-merge-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
- integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
@@ -6120,7 +4872,7 @@ mime-db@1.43.0, "mime-db@>= 1.43.0 < 2":
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
-mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
+mime-types@~2.1.17, mime-types@~2.1.24:
version "2.1.26"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06"
integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==
@@ -6173,7 +4925,7 @@ minimatch@^3.0.3, minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
-minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
+minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
@@ -6226,11 +4978,6 @@ moment-timezone@^0.5.x:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
-moo@^0.5.0:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4"
- integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==
-
mousetrap@^1.5.2:
version "1.6.5"
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
@@ -6308,17 +5055,6 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
-nearley@^2.7.10:
- version "2.19.1"
- resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.19.1.tgz#4af4006e16645ff800e9f993c3af039857d9dbdc"
- integrity sha512-xq47GIUGXxU9vQg7g/y1o1xuKnkO7ev4nRWqftmQrLkfnE/FjRqDaGOUakM8XHPn/6pW3bGjU2wgoJyId90rqg==
- dependencies:
- commander "^2.19.0"
- moo "^0.5.0"
- railroad-diagrams "^1.0.0"
- randexp "0.4.6"
- semver "^5.4.1"
-
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@@ -6352,11 +5088,6 @@ node-forge@0.9.0:
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
-node-int64@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
- integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
-
node-libs-browser@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
@@ -6386,22 +5117,6 @@ node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
-node-modules-regexp@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
- integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
-
-node-notifier@^5.4.2:
- version "5.4.3"
- resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50"
- integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==
- dependencies:
- growly "^1.3.0"
- is-wsl "^1.1.0"
- semver "^5.5.0"
- shellwords "^0.1.1"
- which "^1.3.0"
-
node-releases@^1.1.53:
version "1.1.53"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4"
@@ -6456,7 +5171,7 @@ npmlog@^4.1.2:
gauge "~2.7.3"
set-blocking "~2.0.0"
-nth-check@^1.0.2, nth-check@~1.0.1:
+nth-check@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==
@@ -6473,16 +5188,6 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-nwsapi@^2.0.7:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
- integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
-
-oauth-sign@~0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
- integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
object-assign@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
@@ -6512,7 +5217,7 @@ object-inspect@^1.7.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
-object-is@^1.0.1, object-is@^1.0.2:
+object-is@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4"
integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==
@@ -6539,17 +5244,7 @@ object.assign@^4.1.0:
has-symbols "^1.0.0"
object-keys "^1.0.11"
-object.entries@^1.1.0, object.entries@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b"
- integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- function-bind "^1.1.1"
- has "^1.0.3"
-
-object.fromentries@^2.0.0, object.fromentries@^2.0.2:
+object.fromentries@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9"
integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==
@@ -6574,7 +5269,7 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-object.values@^1.1.0, object.values@^1.1.1:
+object.values@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e"
integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==
@@ -6638,7 +5333,7 @@ opn@^5.5.0:
dependencies:
is-wsl "^1.1.0"
-optionator@^0.8.1, optionator@^0.8.2:
+optionator@^0.8.2:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@@ -6681,13 +5376,6 @@ p-defer@^1.0.0:
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
-p-each-series@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71"
- integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=
- dependencies:
- p-reduce "^1.0.0"
-
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
@@ -6731,11 +5419,6 @@ p-map@^2.0.0:
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
-p-reduce@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
- integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
-
p-retry@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328"
@@ -6836,18 +5519,6 @@ parse-passwd@^1.0.0:
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
-parse5@4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
- integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
-
-parse5@^3.0.1:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
- integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==
- dependencies:
- "@types/node" "*"
-
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -6917,13 +5588,6 @@ path-type@^2.0.0:
dependencies:
pify "^2.0.0"
-path-type@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
- integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
- dependencies:
- pify "^3.0.0"
-
path-type@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -7005,11 +5669,6 @@ pify@^2.0.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-pify@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
- integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
-
pify@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
@@ -7027,13 +5686,6 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-pirates@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
- integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==
- dependencies:
- node-modules-regexp "^1.0.0"
-
pkg-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
@@ -7055,11 +5707,6 @@ pkg-up@^2.0.0:
dependencies:
find-up "^2.1.0"
-pn@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
- integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
-
popper.js@^1.14.4:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
@@ -7464,16 +6111,6 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
-pretty-format@^24.9.0:
- version "24.9.0"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
- integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==
- dependencies:
- "@jest/types" "^24.9.0"
- ansi-regex "^4.0.0"
- ansi-styles "^3.2.0"
- react-is "^16.8.4"
-
private@^0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -7506,23 +6143,6 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
-prompts@^2.0.1:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068"
- integrity sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==
- dependencies:
- kleur "^3.0.3"
- sisteransi "^1.0.4"
-
-prop-types-exact@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869"
- integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==
- dependencies:
- has "^1.0.3"
- object.assign "^4.1.0"
- reflect.ownkeys "^0.2.0"
-
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
@@ -7545,11 +6165,6 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
-psl@^1.1.28:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
- integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
-
public-encrypt@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
@@ -7602,7 +6217,7 @@ punycode@^1.2.4:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
-punycode@^2.1.0, punycode@^2.1.1:
+punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
@@ -7617,11 +6232,6 @@ qs@6.7.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-qs@~6.5.2:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-
query-string@^6.12.1:
version "6.12.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.12.1.tgz#2ae4d272db4fba267141665374e49a1de09e8a7c"
@@ -7658,24 +6268,11 @@ raf@^3.0.0, raf@^3.1.0, raf@^3.4.1:
dependencies:
performance-now "^2.1.0"
-railroad-diagrams@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
- integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=
-
rails-ujs@^5.2.3:
version "5.2.4"
resolved "https://registry.yarnpkg.com/rails-ujs/-/rails-ujs-5.2.4.tgz#31056ccd62d868f7d044395f31d77a4440550ceb"
integrity sha512-Mzu6bnTBKn4IuJvP7BDJRy4lzvR1zMWVDeTdPwDubXBfxpFEKqwOi5Nb6tfE2SYtTd+bb3PRETf40I94jgKw3w==
-randexp@0.4.6:
- version "0.4.6"
- resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
- integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
- dependencies:
- discontinuous-range "1.0.0"
- ret "~0.1.10"
-
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@@ -7792,7 +6389,7 @@ react-intl@^2.9.0:
intl-relativeformat "^2.1.0"
invariant "^2.1.1"
-react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0:
+react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.6:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -7932,7 +6529,7 @@ react-swipeable-views@^0.13.9:
react-swipeable-views-utils "^0.13.9"
warning "^4.0.1"
-react-test-renderer@^16.0.0-0, react-test-renderer@^16.7.0:
+react-test-renderer@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1"
integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ==
@@ -7967,14 +6564,6 @@ read-pkg-up@^2.0.0:
find-up "^2.0.0"
read-pkg "^2.0.0"
-read-pkg-up@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
- integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==
- dependencies:
- find-up "^3.0.0"
- read-pkg "^3.0.0"
-
read-pkg@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
@@ -7984,15 +6573,6 @@ read-pkg@^2.0.0:
normalize-package-data "^2.3.2"
path-type "^2.0.0"
-read-pkg@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
- integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
- dependencies:
- load-json-file "^4.0.0"
- normalize-package-data "^2.3.2"
- path-type "^3.0.0"
-
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
@@ -8006,7 +6586,7 @@ read-pkg@^3.0.0:
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-readable-stream@^3.0.6, readable-stream@^3.1.1:
+readable-stream@^3.0.6:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -8024,13 +6604,6 @@ readdirp@^2.2.1:
micromatch "^3.1.10"
readable-stream "^2.0.2"
-realpath-native@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
- integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
- dependencies:
- util.promisify "^1.0.0"
-
redis-commands@^1.2.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785"
@@ -8068,11 +6641,6 @@ redux@^4.0.1:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
-reflect.ownkeys@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
- integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
-
regenerate-unicode-properties@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
@@ -8176,48 +6744,6 @@ repeat-string@^1.6.1:
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
-request-promise-core@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9"
- integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==
- dependencies:
- lodash "^4.17.15"
-
-request-promise-native@^1.0.5:
- version "1.0.8"
- resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36"
- integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==
- dependencies:
- request-promise-core "1.1.3"
- stealthy-require "^1.1.1"
- tough-cookie "^2.3.3"
-
-request@^2.87.0:
- version "2.88.2"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
- integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.8.0"
- caseless "~0.12.0"
- combined-stream "~1.0.6"
- extend "~3.0.2"
- forever-agent "~0.6.1"
- form-data "~2.3.2"
- har-validator "~5.1.3"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.19"
- oauth-sign "~0.9.0"
- performance-now "^2.1.0"
- qs "~6.5.2"
- safe-buffer "^5.1.2"
- tough-cookie "~2.5.0"
- tunnel-agent "^0.6.0"
- uuid "^3.3.2"
-
requestidlecallback@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/requestidlecallback/-/requestidlecallback-0.3.0.tgz#6fb74e0733f90df3faa4838f9f6a2a5f9b742ac5"
@@ -8293,11 +6819,6 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
-resolve@1.1.7:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
- integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
-
resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.6.0, resolve@^1.8.1, resolve@^1.9.0:
version "1.15.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
@@ -8355,19 +6876,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
-rst-selector-parser@^2.2.3:
- version "2.2.3"
- resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"
- integrity sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=
- dependencies:
- lodash.flattendeep "^4.4.0"
- nearley "^2.7.10"
-
-rsvp@^4.8.4:
- version "4.8.5"
- resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
- integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
-
run-async@^2.2.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8"
@@ -8406,26 +6914,11 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
-"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sane@^4.0.3:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded"
- integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==
- dependencies:
- "@cnakazawa/watch" "^1.0.3"
- anymatch "^2.0.0"
- capture-exit "^2.0.0"
- exec-sh "^0.3.2"
- execa "^1.0.0"
- fb-watchman "^2.0.0"
- micromatch "^3.1.4"
- minimist "^1.1.1"
- walker "~1.0.5"
-
sanitize-html@^1.22.0:
version "1.23.0"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.23.0.tgz#e7a5ce7427cd2844dae5b9961cd372e349f91fb5"
@@ -8442,7 +6935,7 @@ sanitize-html@^1.22.0:
srcset "^2.0.1"
xtend "^4.0.1"
-sax@^1.2.4, sax@~1.2.4:
+sax@~1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
@@ -8492,7 +6985,7 @@ selfsigned@^1.10.7:
dependencies:
node-forge "0.9.0"
-"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
+"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -8507,7 +7000,7 @@ semver@7.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
-semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
+semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@@ -8624,11 +7117,6 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-shellwords@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
- integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
-
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@@ -8641,21 +7129,11 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"
-sisteransi@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
- integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
-
slash@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
-slash@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
- integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
-
slice-ansi@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
@@ -8732,7 +7210,7 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0"
urix "^0.1.0"
-source-map-support@^0.5.6, source-map-support@~0.5.12:
+source-map-support@~0.5.12:
version "0.5.16"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
@@ -8833,21 +7311,6 @@ srcset@^2.0.1:
resolved "https://registry.yarnpkg.com/srcset/-/srcset-2.0.1.tgz#8f842d357487eb797f413d9c309de7a5149df5ac"
integrity sha512-00kZI87TdRKwt+P8jj8UZxbfp7mK2ufxcIMWvhAOZNJTRROimpHeruWrGvCZneiuVDLqdyHefVp748ECTnyUBQ==
-sshpk@^1.7.0:
- version "1.16.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
- integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
- dependencies:
- asn1 "~0.2.3"
- assert-plus "^1.0.0"
- bcrypt-pbkdf "^1.0.0"
- dashdash "^1.12.0"
- ecc-jsbn "~0.1.1"
- getpass "^0.1.1"
- jsbn "~0.1.0"
- safer-buffer "^2.0.2"
- tweetnacl "~0.14.0"
-
ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
@@ -8860,11 +7323,6 @@ stable@^0.1.8:
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
-stack-utils@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
- integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
-
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
@@ -8878,11 +7336,6 @@ static-extend@^0.1.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-stealthy-require@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
- integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
-
stream-browserify@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
@@ -8920,14 +7373,6 @@ strict-uri-encode@^2.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
-string-length@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
- integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=
- dependencies:
- astral-regex "^1.0.0"
- strip-ansi "^4.0.0"
-
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -8954,15 +7399,6 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
-string.prototype.trim@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782"
- integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==
- dependencies:
- define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- function-bind "^1.1.1"
-
string.prototype.trimend@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
@@ -9135,11 +7571,6 @@ symbol-observable@^1.2.0:
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
-symbol-tree@^3.2.2:
- version "3.2.4"
- resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
- integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
-
table@^5.2.3:
version "5.4.6"
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
@@ -9184,26 +7615,11 @@ terser@^4.1.2:
source-map "~0.6.1"
source-map-support "~0.5.12"
-test-exclude@^5.2.3:
- version "5.2.3"
- resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0"
- integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==
- dependencies:
- glob "^7.1.3"
- minimatch "^3.0.4"
- read-pkg-up "^4.0.0"
- require-main-filename "^2.0.0"
-
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
-throat@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
- integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
-
throng@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/throng/-/throng-4.0.0.tgz#983c6ba1993b58eae859998aa687ffe88df84c17"
@@ -9263,11 +7679,6 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
-tmpl@1.0.x:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
- integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
-
to-arraybuffer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@@ -9308,21 +7719,6 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
- integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
- dependencies:
- psl "^1.1.28"
- punycode "^2.1.1"
-
-tr46@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
- integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
- dependencies:
- punycode "^2.1.0"
-
tryer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
@@ -9343,18 +7739,6 @@ tty-browserify@0.0.0:
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
- dependencies:
- safe-buffer "^5.0.1"
-
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -9546,7 +7930,7 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-util.promisify@^1.0.0, util.promisify@~1.0.0:
+util.promisify@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee"
integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==
@@ -9608,34 +7992,11 @@ vendors@^1.0.0:
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e"
integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
vm-browserify@^1.0.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
-w3c-hr-time@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
- integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
- dependencies:
- browser-process-hrtime "^1.0.0"
-
-walker@^1.0.7, walker@~1.0.5:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
- integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
- dependencies:
- makeerror "1.0.x"
-
warning@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
@@ -9666,11 +8027,6 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
-webidl-conversions@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
- integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
-
webpack-assets-manifest@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz#39bbc3bf2ee57fcd8ba07cda51c9ba4a3c6ae1de"
@@ -9850,47 +8206,17 @@ websocket.js@^0.1.12:
dependencies:
backoff "^2.4.1"
-whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
- integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
- dependencies:
- iconv-lite "0.4.24"
-
whatwg-fetch@>=0.10.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
-whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
- integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
-
-whatwg-url@^6.4.1:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
- integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
- dependencies:
- lodash.sortby "^4.7.0"
- tr46 "^1.0.1"
- webidl-conversions "^4.0.2"
-
-whatwg-url@^7.0.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
- integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
- dependencies:
- lodash.sortby "^4.7.0"
- tr46 "^1.0.1"
- webidl-conversions "^4.0.2"
-
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+which@^1.2.14, which@^1.2.9, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
@@ -9938,15 +8264,6 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-write-file-atomic@2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529"
- integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==
- dependencies:
- graceful-fs "^4.1.11"
- imurmurhash "^0.1.4"
- signal-exit "^3.0.2"
-
write@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
@@ -9954,13 +8271,6 @@ write@1.0.3:
dependencies:
mkdirp "^0.5.1"
-ws@^5.2.0:
- version "5.2.2"
- resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
- integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
- dependencies:
- async-limiter "~1.0.0"
-
ws@^6.0.0, ws@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
@@ -9968,11 +8278,6 @@ ws@^6.0.0, ws@^6.2.1:
dependencies:
async-limiter "~1.0.0"
-xml-name-validator@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
- integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
-
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -10046,7 +8351,7 @@ yargs@^12.0.5:
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^11.1.1"
-yargs@^13.3.0, yargs@^13.3.2:
+yargs@^13.3.2:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==