Use backend from glitch-soc for instance-only toots
This commit is contained in:
parent
ccc2f608c5
commit
ffaa814bbe
@ -35,7 +35,7 @@ class AccountsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
format.rss do
|
format.rss do
|
||||||
@statuses = cache_collection(default_statuses.without_reblogs.without_replies.limit(PAGE_SIZE), Status)
|
@statuses = cache_collection(default_statuses.without_local_only.without_reblogs.without_replies.limit(PAGE_SIZE), Status)
|
||||||
render xml: RSS::AccountSerializer.render(@account, @statuses)
|
render xml: RSS::AccountSerializer.render(@account, @statuses)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class StreamEntriesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
unless @stream_entry.hidden?
|
unless @stream_entry.hidden? || @stream_entry.local_only?
|
||||||
skip_session!
|
skip_session!
|
||||||
expires_in 3.minutes, public: true
|
expires_in 3.minutes, public: true
|
||||||
end
|
end
|
||||||
@ -53,7 +53,7 @@ class StreamEntriesController < ApplicationController
|
|||||||
@type = @stream_entry.activity_type.downcase
|
@type = @stream_entry.activity_type.downcase
|
||||||
|
|
||||||
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
|
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
|
||||||
authorize @stream_entry.activity, :show? if @stream_entry.hidden?
|
authorize @stream_entry.activity, :show? if @stream_entry.hidden? || @stream_entry.local_only?
|
||||||
rescue Mastodon::NotPermittedError
|
rescue Mastodon::NotPermittedError
|
||||||
# Reraise in order to get a 404
|
# Reraise in order to get a 404
|
||||||
raise ActiveRecord::RecordNotFound
|
raise ActiveRecord::RecordNotFound
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
# account_id :bigint(8) not null
|
# account_id :bigint(8) not null
|
||||||
# application_id :bigint(8)
|
# application_id :bigint(8)
|
||||||
# in_reply_to_account_id :bigint(8)
|
# in_reply_to_account_id :bigint(8)
|
||||||
|
# local_only :boolean
|
||||||
#
|
#
|
||||||
|
|
||||||
class Status < ApplicationRecord
|
class Status < ApplicationRecord
|
||||||
@ -73,6 +74,7 @@ class Status < ApplicationRecord
|
|||||||
|
|
||||||
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
|
scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') }
|
||||||
scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') }
|
scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') }
|
||||||
|
scope :without_local_only, -> { where(local_only: [false, nil]) }
|
||||||
scope :with_public_visibility, -> { where(visibility: :public) }
|
scope :with_public_visibility, -> { where(visibility: :public) }
|
||||||
scope :tagged_with, ->(tag) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag }) }
|
scope :tagged_with, ->(tag) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag }) }
|
||||||
scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced: false }) }
|
scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced: false }) }
|
||||||
@ -336,7 +338,7 @@ class Status < ApplicationRecord
|
|||||||
visibility = [:public, :unlisted]
|
visibility = [:public, :unlisted]
|
||||||
|
|
||||||
if account.nil?
|
if account.nil?
|
||||||
where(visibility: visibility)
|
where(visibility: visibility).without_local_only
|
||||||
elsif target_account.blocking?(account) # get rid of blocked peeps
|
elsif target_account.blocking?(account) # get rid of blocked peeps
|
||||||
none
|
none
|
||||||
elsif account.id == target_account.id # author can see own stuff
|
elsif account.id == target_account.id # author can see own stuff
|
||||||
@ -379,7 +381,7 @@ class Status < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def filter_timeline_default(query)
|
def filter_timeline_default(query)
|
||||||
query.excluding_silenced_accounts
|
query.without_local_only.excluding_silenced_accounts
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_silencing_filter(account)
|
def account_silencing_filter(account)
|
||||||
|
@ -27,7 +27,7 @@ class StreamEntry < ApplicationRecord
|
|||||||
scope :recent, -> { reorder(id: :desc) }
|
scope :recent, -> { reorder(id: :desc) }
|
||||||
scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) }
|
scope :with_includes, -> { includes(:account, status: STATUS_INCLUDES) }
|
||||||
|
|
||||||
delegate :target, :title, :content, :thread,
|
delegate :target, :title, :content, :thread, :local_only?,
|
||||||
to: :status,
|
to: :status,
|
||||||
allow_nil: true
|
allow_nil: true
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ class StatusPolicy < ApplicationPolicy
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show?
|
def show?
|
||||||
|
return false if local_only? && (current_account.nil? || !current_account.local?)
|
||||||
|
|
||||||
if direct?
|
if direct?
|
||||||
owned? || mention_exists?
|
owned? || mention_exists?
|
||||||
elsif private?
|
elsif private?
|
||||||
@ -84,4 +86,8 @@ class StatusPolicy < ApplicationPolicy
|
|||||||
def author
|
def author
|
||||||
record.account
|
record.account
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def local_only?
|
||||||
|
record.local_only?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -39,9 +39,12 @@ class PostStatusService < BaseService
|
|||||||
|
|
||||||
LinkCrawlWorker.perform_async(status.id) unless status.spoiler_text?
|
LinkCrawlWorker.perform_async(status.id) unless status.spoiler_text?
|
||||||
DistributionWorker.perform_async(status.id)
|
DistributionWorker.perform_async(status.id)
|
||||||
|
|
||||||
|
unless status.local_only?
|
||||||
Pubsubhubbub::DistributionWorker.perform_async(status.stream_entry.id)
|
Pubsubhubbub::DistributionWorker.perform_async(status.stream_entry.id)
|
||||||
ActivityPub::DistributionWorker.perform_async(status.id)
|
ActivityPub::DistributionWorker.perform_async(status.id)
|
||||||
ActivityPub::ReplyDistributionWorker.perform_async(status.id) if status.reply? && status.thread.account.local?
|
ActivityPub::ReplyDistributionWorker.perform_async(status.id) if status.reply? && status.thread.account.local?
|
||||||
|
end
|
||||||
|
|
||||||
if options[:idempotency].present?
|
if options[:idempotency].present?
|
||||||
redis.setex("idempotency:status:#{account.id}:#{options[:idempotency]}", 3_600, status.id)
|
redis.setex("idempotency:status:#{account.id}:#{options[:idempotency]}", 3_600, status.id)
|
||||||
|
@ -20,8 +20,11 @@ class ReblogService < BaseService
|
|||||||
reblog = account.statuses.create!(reblog: reblogged_status, text: '')
|
reblog = account.statuses.create!(reblog: reblogged_status, text: '')
|
||||||
|
|
||||||
DistributionWorker.perform_async(reblog.id)
|
DistributionWorker.perform_async(reblog.id)
|
||||||
|
|
||||||
|
unless reblogged_status.local_only?
|
||||||
Pubsubhubbub::DistributionWorker.perform_async(reblog.stream_entry.id)
|
Pubsubhubbub::DistributionWorker.perform_async(reblog.stream_entry.id)
|
||||||
ActivityPub::DistributionWorker.perform_async(reblog.id)
|
ActivityPub::DistributionWorker.perform_async(reblog.id)
|
||||||
|
end
|
||||||
|
|
||||||
create_notification(reblog)
|
create_notification(reblog)
|
||||||
bump_potential_friendship(account, reblog)
|
bump_potential_friendship(account, reblog)
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
class AddLocalOnlyFlagToStatuses < ActiveRecord::Migration[5.1]
|
||||||
|
def change
|
||||||
|
add_column :statuses, :local_only, :boolean
|
||||||
|
end
|
||||||
|
end
|
@ -492,6 +492,7 @@ ActiveRecord::Schema.define(version: 2018_08_20_232245) do
|
|||||||
t.bigint "account_id", null: false
|
t.bigint "account_id", null: false
|
||||||
t.bigint "application_id"
|
t.bigint "application_id"
|
||||||
t.bigint "in_reply_to_account_id"
|
t.bigint "in_reply_to_account_id"
|
||||||
|
t.boolean "local_only"
|
||||||
t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20180106", order: { id: :desc }
|
t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20180106", order: { id: :desc }
|
||||||
t.index ["in_reply_to_account_id"], name: "index_statuses_on_in_reply_to_account_id"
|
t.index ["in_reply_to_account_id"], name: "index_statuses_on_in_reply_to_account_id"
|
||||||
t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id"
|
t.index ["in_reply_to_id"], name: "index_statuses_on_in_reply_to_id"
|
||||||
|
@ -574,6 +574,32 @@ RSpec.describe Status, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with local-only statuses' do
|
||||||
|
let(:status) { Fabricate(:status, local_only: true) }
|
||||||
|
|
||||||
|
subject { Status.as_public_timeline(viewer) }
|
||||||
|
|
||||||
|
context 'without a viewer' do
|
||||||
|
let(:viewer) { nil }
|
||||||
|
|
||||||
|
it 'excludes local-only statuses' do
|
||||||
|
expect(subject).to_not include(status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a viewer' do
|
||||||
|
let(:viewer) { Fabricate(:account, username: 'viewer') }
|
||||||
|
|
||||||
|
it 'includes local-only statuses' do
|
||||||
|
expect(subject).to include(status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: What happens if the viewer is remote?
|
||||||
|
# Can the viewer be remote?
|
||||||
|
# What prevents the viewer from being remote?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.as_tag_timeline' do
|
describe '.as_tag_timeline' do
|
||||||
@ -595,6 +621,27 @@ RSpec.describe Status, type: :model do
|
|||||||
results = Status.as_tag_timeline(tag)
|
results = Status.as_tag_timeline(tag)
|
||||||
expect(results).to include(status)
|
expect(results).to include(status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'on a local-only status' do
|
||||||
|
let(:tag) { Fabricate(:tag) }
|
||||||
|
let(:status) { Fabricate(:status, local_only: true, tags: [tag]) }
|
||||||
|
|
||||||
|
context 'without a viewer' do
|
||||||
|
let(:viewer) { nil }
|
||||||
|
|
||||||
|
it 'filters the local-only status out of the result set' do
|
||||||
|
expect(Status.as_tag_timeline(tag, viewer)).not_to include(status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a viewer' do
|
||||||
|
let(:viewer) { Fabricate(:account, username: 'viewer', domain: nil) }
|
||||||
|
|
||||||
|
it 'keeps the local-only status in the result set' do
|
||||||
|
expect(Status.as_tag_timeline(tag, viewer)).to include(status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.permitted_for' do
|
describe '.permitted_for' do
|
||||||
|
@ -71,6 +71,18 @@ RSpec.describe StatusPolicy, type: :model do
|
|||||||
|
|
||||||
expect(subject).to_not permit(viewer, status)
|
expect(subject).to_not permit(viewer, status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'denies access when local-only and the viewer is not logged in' do
|
||||||
|
allow(status).to receive(:local_only?) { true }
|
||||||
|
|
||||||
|
expect(subject).to_not permit(nil, status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'denies access when local-only and the viewer is from another domain' do
|
||||||
|
viewer = Fabricate(:account, domain: 'remote-domain')
|
||||||
|
allow(status).to receive(:local_only?) { true }
|
||||||
|
expect(subject).to_not permit(viewer, status)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
permissions :reblog? do
|
permissions :reblog? do
|
||||||
|
Loading…
Reference in New Issue
Block a user