Commiting

This commit is contained in:
mgabdev 2020-11-15 12:48:32 -06:00
parent 62515bbaee
commit fb612f60c8
1011 changed files with 3507 additions and 49604 deletions

@ -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

@ -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__/**',
],
},
],

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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)

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -1,7 +1,6 @@
# frozen_string_literal: true
class Api::OEmbedController < Api::BaseController
respond_to :json
def show
@status = status_finder.status

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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)

@ -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

@ -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

@ -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

@ -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?

@ -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?

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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,

@ -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)

@ -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

@ -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

@ -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

@ -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

@ -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)

@ -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

@ -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

@ -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: [],
],

@ -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)

@ -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'

@ -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

@ -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

@ -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

@ -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,

@ -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

@ -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)

@ -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

@ -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

@ -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

@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::PushSubscriptionsController < Api::Web::BaseController
respond_to :json
before_action :require_user!
def create

@ -1,8 +1,6 @@
# frozen_string_literal: true
class Api::Web::SettingsController < Api::Web::BaseController
respond_to :json
before_action :require_user!
def update

@ -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

@ -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)

@ -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

@ -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!

@ -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

@ -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

@ -1,8 +0,0 @@
# frozen_string_literal: true
class DownloadsController < ApplicationController
layout 'public'
before_action :check_enabled
end

@ -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

@ -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

@ -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

@ -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

@ -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

@ -5,4 +5,5 @@ class ManifestsController < EmptyController
def show
render json: InstancePresenter.new, serializer: ManifestSerializer
end
end

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

Some files were not shown because too many files have changed in this diff Show More