Skip to content
Snippets Groups Projects
Commit 74ae158c authored by Eugen Rochko's avatar Eugen Rochko
Browse files

Add "direct" visibility level in the backend. Web UI is not yet

adjusted to allow choosing it, yet
parent c1124228
No related branches found
No related tags found
No related merge requests found
......@@ -88,7 +88,7 @@ const StatusActionBar = React.createClass({
return (
<div style={{ marginTop: '10px', overflow: 'hidden' }}>
<div style={{ float: 'left', marginRight: '18px'}}><IconButton title={intl.formatMessage(messages.reply)} icon='reply' onClick={this.handleReplyClick} /></div>
<div style={{ float: 'left', marginRight: '18px'}}><IconButton disabled={status.get('visibility') === 'private'} active={status.get('reblogged')} title={intl.formatMessage(messages.reblog)} icon={status.get('visibility') === 'private' ? 'lock' : 'retweet'} onClick={this.handleReblogClick} /></div>
<div style={{ float: 'left', marginRight: '18px'}}><IconButton disabled={status.get('visibility') === 'private' || status.get('visibility') === 'direct'} active={status.get('reblogged')} title={intl.formatMessage(messages.reblog)} icon={status.get('visibility') === 'direct' ? 'envelope' : (status.get('visibility') === 'private' ? 'lock' : 'retweet')} onClick={this.handleReblogClick} /></div>
<div style={{ float: 'left', marginRight: '18px'}}><IconButton animate={true} active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div>
<div style={{ width: '18px', height: '18px', float: 'left' }}>
......
......@@ -74,7 +74,7 @@ const ActionBar = React.createClass({
return (
<div className='detailed-status__action-bar'>
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton title={intl.formatMessage(messages.reply)} icon='reply' onClick={this.handleReplyClick} /></div>
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton disabled={status.get('visibility') === 'private'} active={status.get('reblogged')} title={intl.formatMessage(messages.reblog)} icon={status.get('visibility') === 'private' ? 'lock' : 'retweet'} onClick={this.handleReblogClick} /></div>
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton disabled={status.get('visibility') === 'direct' || status.get('visibility') === 'private'} active={status.get('reblogged')} title={intl.formatMessage(messages.reblog)} icon={status.get('visibility') === 'direct' ? 'envelope' : (status.get('visibility') === 'private' ? 'lock' : 'retweet')} onClick={this.handleReblogClick} /></div>
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton animate={true} active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div>
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><DropdownMenu size={18} icon='ellipsis-h' items={menu} direction="left" /></div>
</div>
......
......@@ -108,6 +108,7 @@ class FeedManager
elsif status.reblog? # Filter out a reblog
should_filter = receiver.blocking?(status.reblog.account) # if I'm blocking the reblogged person
should_filter ||= receiver.muting?(status.reblog.account) # or muting that person
should_filter ||= status.reblog.account.blocking?(receiver) # or if the author of the reblogged status is blocking me
end
should_filter ||= receiver.blocking?(status.mentions.map(&:account_id)) # or if it mentions someone I blocked
......
......@@ -6,7 +6,7 @@ class Status < ApplicationRecord
include Streamable
include Cacheable
enum visibility: [:public, :unlisted, :private], _suffix: :visibility
enum visibility: [:public, :unlisted, :private, :direct], _suffix: :visibility
belongs_to :application, class_name: 'Doorkeeper::Application'
......@@ -75,12 +75,14 @@ class Status < ApplicationRecord
end
def hidden?
private_visibility?
private_visibility? || direct_visibility?
end
def permitted?(other_account = nil)
if private_visibility?
(account.id == other_account&.id || other_account&.following?(account) || mentions.where(account: other_account).exists?)
if direct_visibility?
account.id == other_account&.id || mentions.where(account: other_account).exists?
elsif private_visibility?
account.id == other_account&.id || other_account&.following?(account) || mentions.where(account: other_account).exists?
else
other_account.nil? || !account.blocking?(other_account)
end
......@@ -156,15 +158,18 @@ class Status < ApplicationRecord
end
def permitted_for(target_account, account)
if account&.id == target_account.id || account&.following?(target_account)
where('1 = 1')
elsif !account.nil? && target_account.blocking?(account)
return where.not(visibility: [:private, :direct]) if account.nil?
if target_account.blocking?(account) # get rid of blocked peeps
where('1 = 0')
elsif !account.nil?
elsif account.id == target_account.id # author can see own stuff
where('1 = 1')
elsif account.following?(target_account) # followers can see followers-only stuff, but also things they are mentioned in
joins('LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = ' + account.id.to_s)
.where('statuses.visibility != ? OR mentions.id IS NOT NULL', Status.visibilities[:direct])
else # non-followers can see everything that isn't private/direct, but can see stuff they are mentioned in
joins('LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = ' + account.id.to_s)
.where('statuses.visibility != ? OR mentions.id IS NOT NULL', Status.visibilities[:private])
else
where.not(visibility: :private)
.where('statuses.visibility NOT IN (?) OR mentions.id IS NOT NULL', [Status.visibilities[:direct], Status.visibilities[:private]])
end
end
......
......@@ -5,7 +5,8 @@ class FanOutOnWriteService < BaseService
# @param [Status] status
def call(status)
deliver_to_self(status) if status.account.local?
deliver_to_followers(status)
status.direct_visibility? ? deliver_to_mentioned_followers(status) : deliver_to_followers(status)
return if status.account.silenced? || !status.public_visibility? || status.reblog?
......@@ -32,6 +33,16 @@ class FanOutOnWriteService < BaseService
end
end
def deliver_to_mentioned_followers(status)
Rails.logger.debug "Delivering status #{status.id} to mentioned followers"
status.mentions.includes(:account).each do |mention|
mentioned_account = mention.account
next if !mentioned_account.local? || !mentioned_account.following?(status.account) || FeedManager.instance.filter?(:home, status, mentioned_account)
FeedManager.instance.push(:home, mentioned_account, status)
end
end
def deliver_to_hashtags(status)
Rails.logger.debug "Delivering status #{status.id} to hashtags"
......
......@@ -10,7 +10,7 @@ class ReblogService < BaseService
def call(account, reblogged_status)
reblogged_status = reblogged_status.reblog if reblogged_status.reblog?
raise Mastodon::NotPermittedError if reblogged_status.private_visibility? || !reblogged_status.permitted?(account)
raise Mastodon::NotPermittedError if reblogged_status.direct_visibility? || reblogged_status.private_visibility? || !reblogged_status.permitted?(account)
reblog = account.statuses.create!(reblog: reblogged_status, text: '')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment