Private visibility on statuses prevents non-followers from seeing those
Filters out hidden stream entries from Atom feed Blocks now generate hidden stream entries, can be used to federate blocks Private statuses cannot be reblogged (generates generic 422 error for now) POST /api/v1/statuses now takes visibility=(public|unlisted|private) param instead of unlisted boolean Statuses JSON now contains visibility=(public|unlisted|private) field
This commit is contained in:
parent
6d71044c85
commit
80e02b90e4
|
@ -67,7 +67,7 @@ export function submitCompose() {
|
||||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||||
media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
|
media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
|
||||||
sensitive: getState().getIn(['compose', 'sensitive']),
|
sensitive: getState().getIn(['compose', 'sensitive']),
|
||||||
unlisted: getState().getIn(['compose', 'unlisted'])
|
visibility: getState().getIn(['compose', 'unlisted']) ? 'unlisted' : 'public'
|
||||||
}).then(function (response) {
|
}).then(function (response) {
|
||||||
dispatch(submitComposeSuccess({ ...response.data }));
|
dispatch(submitComposeSuccess({ ...response.data }));
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@ class AccountsController < ApplicationController
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html do
|
format.html do
|
||||||
@statuses = @account.statuses.order('id desc').paginate_by_max_id(20, params[:max_id], params[:since_id])
|
@statuses = @account.statuses.permitted_for(@account, current_account).order('id desc').paginate_by_max_id(20, params[:max_id], params[:since_id])
|
||||||
@statuses = cache_collection(@statuses, Status)
|
@statuses = cache_collection(@statuses, Status)
|
||||||
end
|
end
|
||||||
|
|
||||||
format.atom do
|
format.atom do
|
||||||
@entries = @account.stream_entries.order('id desc').with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
@entries = @account.stream_entries.order('id desc').where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,7 @@ class Api::V1::AccountsController < ApiController
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
def show
|
def show; end
|
||||||
end
|
|
||||||
|
|
||||||
def verify_credentials
|
def verify_credentials
|
||||||
@account = current_user.account
|
@account = current_user.account
|
||||||
|
@ -47,7 +46,7 @@ class Api::V1::AccountsController < ApiController
|
||||||
end
|
end
|
||||||
|
|
||||||
def statuses
|
def statuses
|
||||||
@statuses = @account.statuses.paginate_by_max_id(DEFAULT_STATUSES_LIMIT, params[:max_id], params[:since_id])
|
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(DEFAULT_STATUSES_LIMIT, params[:max_id], params[:since_id])
|
||||||
@statuses = cache_collection(@statuses, Status)
|
@statuses = cache_collection(@statuses, Status)
|
||||||
|
|
||||||
set_maps(@statuses)
|
set_maps(@statuses)
|
||||||
|
|
|
@ -52,7 +52,7 @@ class Api::V1::StatusesController < ApiController
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), media_ids: params[:media_ids], sensitive: params[:sensitive], unlisted: params[:unlisted])
|
@status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), media_ids: params[:media_ids], sensitive: params[:sensitive], visibility: params[:visibility])
|
||||||
render action: :show
|
render action: :show
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -95,5 +95,6 @@ class Api::V1::StatusesController < ApiController
|
||||||
|
|
||||||
def set_status
|
def set_status
|
||||||
@status = Status.find(params[:id])
|
@status = Status.find(params[:id])
|
||||||
|
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,8 +14,8 @@ class StreamEntriesController < ApplicationController
|
||||||
return gone if @stream_entry.activity.nil?
|
return gone if @stream_entry.activity.nil?
|
||||||
|
|
||||||
if @stream_entry.activity_type == 'Status'
|
if @stream_entry.activity_type == 'Status'
|
||||||
@ancestors = @stream_entry.activity.ancestors
|
@ancestors = @stream_entry.activity.ancestors(current_account)
|
||||||
@descendants = @stream_entry.activity.descendants
|
@descendants = @stream_entry.activity.descendants(current_account)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class StreamEntriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_stream_entry
|
def set_stream_entry
|
||||||
@stream_entry = @account.stream_entries.find(params[:id])
|
@stream_entry = @account.stream_entries.where(hidden: false).find(params[:id])
|
||||||
@type = @stream_entry.activity_type.downcase
|
@type = @stream_entry.activity_type.downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,31 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Block < ApplicationRecord
|
class Block < ApplicationRecord
|
||||||
|
include Streamable
|
||||||
|
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
belongs_to :target_account, class_name: 'Account'
|
belongs_to :target_account, class_name: 'Account'
|
||||||
|
|
||||||
validates :account, :target_account, presence: true
|
validates :account, :target_account, presence: true
|
||||||
validates :account_id, uniqueness: { scope: :target_account_id }
|
validates :account_id, uniqueness: { scope: :target_account_id }
|
||||||
|
|
||||||
|
def verb
|
||||||
|
destroyed? ? :unblock : :block
|
||||||
|
end
|
||||||
|
|
||||||
|
def target
|
||||||
|
target_account
|
||||||
|
end
|
||||||
|
|
||||||
|
def object_type
|
||||||
|
:person
|
||||||
|
end
|
||||||
|
|
||||||
|
def hidden?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def title
|
||||||
|
destroyed? ? "#{account.acct} is no longer blocking #{target_account.acct}" : "#{account.acct} blocked #{target_account.acct}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,8 +26,12 @@ module Streamable
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def hidden?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
after_create do
|
after_create do
|
||||||
account.stream_entries.create!(activity: self) if account.local?
|
account.stream_entries.create!(activity: self, hidden: hidden?) if account.local?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class Status < ApplicationRecord
|
||||||
include Streamable
|
include Streamable
|
||||||
include Cacheable
|
include Cacheable
|
||||||
|
|
||||||
enum visibility: [:public, :unlisted], _suffix: :visibility
|
enum visibility: [:public, :unlisted, :private], _suffix: :visibility
|
||||||
|
|
||||||
belongs_to :account, inverse_of: :statuses
|
belongs_to :account, inverse_of: :statuses
|
||||||
|
|
||||||
|
@ -66,19 +66,19 @@ class Status < ApplicationRecord
|
||||||
content
|
content
|
||||||
end
|
end
|
||||||
|
|
||||||
def reblogs_count
|
def hidden?
|
||||||
attributes['reblogs_count'] || reblogs.count
|
private_visibility?
|
||||||
end
|
end
|
||||||
|
|
||||||
def favourites_count
|
def permitted?(other_account = nil)
|
||||||
attributes['favourites_count'] || favourites.count
|
private_visibility? ? (account.id == other_account&.id || other_account&.following?(account)) : true
|
||||||
end
|
end
|
||||||
|
|
||||||
def ancestors(account = nil)
|
def ancestors(account = nil)
|
||||||
ids = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, in_reply_to_id, path) AS (SELECT id, in_reply_to_id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, statuses.in_reply_to_id, path || statuses.id FROM search_tree JOIN statuses ON statuses.id = search_tree.in_reply_to_id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path DESC', id]) - [self]).pluck(:id)
|
ids = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, in_reply_to_id, path) AS (SELECT id, in_reply_to_id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, statuses.in_reply_to_id, path || statuses.id FROM search_tree JOIN statuses ON statuses.id = search_tree.in_reply_to_id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path DESC', id]) - [self]).pluck(:id)
|
||||||
statuses = Status.where(id: ids).with_includes.group_by(&:id)
|
statuses = Status.where(id: ids).with_includes.group_by(&:id)
|
||||||
results = ids.map { |id| statuses[id].first }
|
results = ids.map { |id| statuses[id].first }
|
||||||
results = results.reject { |status| account.blocking?(status.account) } unless account.nil?
|
results = results.reject { |status| filter_from_context?(status, account) }
|
||||||
|
|
||||||
results
|
results
|
||||||
end
|
end
|
||||||
|
@ -87,7 +87,7 @@ class Status < ApplicationRecord
|
||||||
ids = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, path) AS (SELECT id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, path || statuses.id FROM search_tree JOIN statuses ON statuses.in_reply_to_id = search_tree.id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path', id]) - [self]).pluck(:id)
|
ids = (Status.find_by_sql(['WITH RECURSIVE search_tree(id, path) AS (SELECT id, ARRAY[id] FROM statuses WHERE id = ? UNION ALL SELECT statuses.id, path || statuses.id FROM search_tree JOIN statuses ON statuses.in_reply_to_id = search_tree.id WHERE NOT statuses.id = ANY(path)) SELECT id FROM search_tree ORDER BY path', id]) - [self]).pluck(:id)
|
||||||
statuses = Status.where(id: ids).with_includes.group_by(&:id)
|
statuses = Status.where(id: ids).with_includes.group_by(&:id)
|
||||||
results = ids.map { |id| statuses[id].first }
|
results = ids.map { |id| statuses[id].first }
|
||||||
results = results.reject { |status| account.blocking?(status.account) } unless account.nil?
|
results = results.reject { |status| filter_from_context?(status, account) }
|
||||||
|
|
||||||
results
|
results
|
||||||
end
|
end
|
||||||
|
@ -128,6 +128,14 @@ class Status < ApplicationRecord
|
||||||
select('reblog_of_id').where(reblog_of_id: status_ids).where(account_id: account_id).map { |s| [s.reblog_of_id, true] }.to_h
|
select('reblog_of_id').where(reblog_of_id: status_ids).where(account_id: account_id).map { |s| [s.reblog_of_id, true] }.to_h
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def permitted_for(target_account, account)
|
||||||
|
if account&.id == target_account.id || account&.following?(target_account)
|
||||||
|
self
|
||||||
|
else
|
||||||
|
where.not(visibility: :private)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def reload_stale_associations!(cached_items)
|
def reload_stale_associations!(cached_items)
|
||||||
account_ids = []
|
account_ids = []
|
||||||
|
|
||||||
|
@ -161,5 +169,12 @@ class Status < ApplicationRecord
|
||||||
before_validation do
|
before_validation do
|
||||||
text.strip!
|
text.strip!
|
||||||
self.in_reply_to_account_id = thread.account_id if reply?
|
self.in_reply_to_account_id = thread.account_id if reply?
|
||||||
|
self.visibility = :public if visibility.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def filter_from_context?(status, account)
|
||||||
|
account&.blocking?(status.account) || !status.permitted?(account)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,7 @@ class StreamEntry < ApplicationRecord
|
||||||
belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id'
|
belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id'
|
||||||
belongs_to :follow, foreign_type: 'Follow', foreign_key: 'activity_id'
|
belongs_to :follow, foreign_type: 'Follow', foreign_key: 'activity_id'
|
||||||
belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id'
|
belongs_to :favourite, foreign_type: 'Favourite', foreign_key: 'activity_id'
|
||||||
|
belongs_to :block, foreign_type: 'Block', foreign_key: 'activity_id'
|
||||||
|
|
||||||
validates :account, :activity, presence: true
|
validates :account, :activity, presence: true
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ class StreamEntry < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def targeted?
|
def targeted?
|
||||||
[:follow, :share, :favorite].include? verb
|
[:follow, :unfollow, :block, :unblock, :share, :favorite].include? verb
|
||||||
end
|
end
|
||||||
|
|
||||||
def target
|
def target
|
||||||
|
@ -57,7 +58,7 @@ class StreamEntry < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def activity
|
def activity
|
||||||
send(activity_type.downcase.to_sym)
|
!new_record? ? send(activity_type.downcase) : super
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -10,7 +10,7 @@ class PostStatusService < BaseService
|
||||||
# @option [Enumerable] :media_ids Optional array of media IDs to attach
|
# @option [Enumerable] :media_ids Optional array of media IDs to attach
|
||||||
# @return [Status]
|
# @return [Status]
|
||||||
def call(account, text, in_reply_to = nil, options = {})
|
def call(account, text, in_reply_to = nil, options = {})
|
||||||
status = account.statuses.create!(text: text, thread: in_reply_to, sensitive: options[:sensitive], visibility: options[:unlisted] ? :unlisted : :public)
|
status = account.statuses.create!(text: text, thread: in_reply_to, sensitive: options[:sensitive], visibility: options[:visibility])
|
||||||
attach_media(status, options[:media_ids])
|
attach_media(status, options[:media_ids])
|
||||||
process_mentions_service.call(status)
|
process_mentions_service.call(status)
|
||||||
process_hashtags_service.call(status)
|
process_hashtags_service.call(status)
|
||||||
|
|
|
@ -6,6 +6,8 @@ class ReblogService < BaseService
|
||||||
# @param [Status] reblogged_status Status to be reblogged
|
# @param [Status] reblogged_status Status to be reblogged
|
||||||
# @return [Status]
|
# @return [Status]
|
||||||
def call(account, reblogged_status)
|
def call(account, reblogged_status)
|
||||||
|
raise ActiveRecord::RecordInvalid if reblogged_status.private_visibility?
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
attributes :id, :created_at, :in_reply_to_id, :sensitive
|
attributes :id, :created_at, :in_reply_to_id, :sensitive, :visibility
|
||||||
|
|
||||||
node(:uri) { |status| TagManager.instance.uri_for(status) }
|
node(:uri) { |status| TagManager.instance.uri_for(status) }
|
||||||
node(:content) { |status| Formatter.instance.format(status) }
|
node(:content) { |status| Formatter.instance.format(status) }
|
||||||
node(:url) { |status| TagManager.instance.url_for(status) }
|
node(:url) { |status| TagManager.instance.url_for(status) }
|
||||||
node(:reblogs_count) { |status| defined?(@reblogs_counts_map) ? (@reblogs_counts_map[status.id] || 0) : status.reblogs_count }
|
node(:reblogs_count) { |status| defined?(@reblogs_counts_map) ? (@reblogs_counts_map[status.id] || 0) : status.reblogs.count }
|
||||||
node(:favourites_count) { |status| defined?(@favourites_counts_map) ? (@favourites_counts_map[status.id] || 0) : status.favourites_count }
|
node(:favourites_count) { |status| defined?(@favourites_counts_map) ? (@favourites_counts_map[status.id] || 0) : status.favourites.count }
|
||||||
|
|
||||||
child :account do
|
child :account do
|
||||||
extends 'api/v1/accounts/show'
|
extends 'api/v1/accounts/show'
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddHiddenToStreamEntries < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
add_column :stream_entries, :hidden, :boolean, null: false, default: false
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20161205214545) do
|
ActiveRecord::Schema.define(version: 20161221152630) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -198,6 +198,7 @@ ActiveRecord::Schema.define(version: 20161205214545) do
|
||||||
t.string "activity_type"
|
t.string "activity_type"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.boolean "hidden", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_stream_entries_on_account_id", using: :btree
|
t.index ["account_id"], name: "index_stream_entries_on_account_id", using: :btree
|
||||||
t.index ["activity_id", "activity_type"], name: "index_stream_entries_on_activity_id_and_activity_type", using: :btree
|
t.index ["activity_id", "activity_type"], name: "index_stream_entries_on_activity_id_and_activity_type", using: :btree
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,67 +2,42 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>The page you were looking for doesn't exist (404)</title>
|
<title>The page you were looking for doesn't exist</title>
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Roboto:400" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #EFEFEF;
|
font-family: 'Roboto', sans-serif;
|
||||||
color: #2E2F30;
|
background: #282c37;
|
||||||
|
color: #9baec8;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: arial, sans-serif;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.dialog {
|
.dialog img {
|
||||||
width: 95%;
|
display: block;
|
||||||
max-width: 33em;
|
margin: 20px auto;
|
||||||
margin: 4em auto 0;
|
margin-top: 50px;
|
||||||
|
max-width: 600px;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.dialog > div {
|
.dialog h1 {
|
||||||
border: 1px solid #CCC;
|
font: 20px/28px 'Roboto', sans-serif;
|
||||||
border-right-color: #999;
|
font-weight: 400;
|
||||||
border-left-color: #999;
|
|
||||||
border-bottom-color: #BBB;
|
|
||||||
border-top: #B00100 solid 4px;
|
|
||||||
border-top-left-radius: 9px;
|
|
||||||
border-top-right-radius: 9px;
|
|
||||||
background-color: white;
|
|
||||||
padding: 7px 12% 0;
|
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 100%;
|
|
||||||
color: #730E15;
|
|
||||||
line-height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dialog > p {
|
|
||||||
margin: 0 0 1em;
|
|
||||||
padding: 1em;
|
|
||||||
background-color: #F7F7F7;
|
|
||||||
border: 1px solid #CCC;
|
|
||||||
border-right-color: #999;
|
|
||||||
border-left-color: #999;
|
|
||||||
border-bottom-color: #999;
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
border-top-color: #DADADA;
|
|
||||||
color: #666;
|
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- This file lives in public/404.html -->
|
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
|
<img src="/oops.png" alt="Mastodon" />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h1>The page you were looking for doesn't exist.</h1>
|
<h1>The page you were looking for doesn't exist</h1>
|
||||||
<p>You may have mistyped the address or the page may have moved.</p>
|
|
||||||
</div>
|
</div>
|
||||||
<p>If you are the application owner check the logs for more information.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>The change you wanted was rejected (422)</title>
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background-color: #EFEFEF;
|
|
||||||
color: #2E2F30;
|
|
||||||
text-align: center;
|
|
||||||
font-family: arial, sans-serif;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dialog {
|
|
||||||
width: 95%;
|
|
||||||
max-width: 33em;
|
|
||||||
margin: 4em auto 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dialog > div {
|
|
||||||
border: 1px solid #CCC;
|
|
||||||
border-right-color: #999;
|
|
||||||
border-left-color: #999;
|
|
||||||
border-bottom-color: #BBB;
|
|
||||||
border-top: #B00100 solid 4px;
|
|
||||||
border-top-left-radius: 9px;
|
|
||||||
border-top-right-radius: 9px;
|
|
||||||
background-color: white;
|
|
||||||
padding: 7px 12% 0;
|
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 100%;
|
|
||||||
color: #730E15;
|
|
||||||
line-height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dialog > p {
|
|
||||||
margin: 0 0 1em;
|
|
||||||
padding: 1em;
|
|
||||||
background-color: #F7F7F7;
|
|
||||||
border: 1px solid #CCC;
|
|
||||||
border-right-color: #999;
|
|
||||||
border-left-color: #999;
|
|
||||||
border-bottom-color: #999;
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
border-top-color: #DADADA;
|
|
||||||
color: #666;
|
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- This file lives in public/422.html -->
|
|
||||||
<div class="dialog">
|
|
||||||
<div>
|
|
||||||
<h1>The change you wanted was rejected.</h1>
|
|
||||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
|
||||||
</div>
|
|
||||||
<p>If you are the application owner check the logs for more information.</p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -97,7 +97,7 @@ RSpec.describe Api::V1::StatusesController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the reblogs count' do
|
it 'updates the reblogs count' do
|
||||||
expect(status.reblogs_count).to eq 1
|
expect(status.reblogs.count).to eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the reblogged attribute' do
|
it 'updates the reblogged attribute' do
|
||||||
|
@ -126,7 +126,7 @@ RSpec.describe Api::V1::StatusesController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the reblogs count' do
|
it 'updates the reblogs count' do
|
||||||
expect(status.reblogs_count).to eq 0
|
expect(status.reblogs.count).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the reblogged attribute' do
|
it 'updates the reblogged attribute' do
|
||||||
|
@ -146,7 +146,7 @@ RSpec.describe Api::V1::StatusesController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the favourites count' do
|
it 'updates the favourites count' do
|
||||||
expect(status.favourites_count).to eq 1
|
expect(status.favourites.count).to eq 1
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the favourited attribute' do
|
it 'updates the favourited attribute' do
|
||||||
|
@ -175,7 +175,7 @@ RSpec.describe Api::V1::StatusesController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the favourites count' do
|
it 'updates the favourites count' do
|
||||||
expect(status.favourites_count).to eq 0
|
expect(status.favourites.count).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the favourited attribute' do
|
it 'updates the favourited attribute' do
|
||||||
|
|
Loading…
Reference in New Issue