Merge commit 'b320c9e4c901bf99ccbca321bad2ceb2f51de140' into glitch-soc/merge-upstream
This commit is contained in:
2
Gemfile
2
Gemfile
@@ -27,7 +27,7 @@ gem 'addressable', '~> 2.8'
|
|||||||
gem 'bootsnap', require: false
|
gem 'bootsnap', require: false
|
||||||
gem 'browser'
|
gem 'browser'
|
||||||
gem 'charlock_holmes', '~> 0.7.7'
|
gem 'charlock_holmes', '~> 0.7.7'
|
||||||
gem 'chewy', '~> 7.3'
|
gem 'chewy'
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'devise-two-factor'
|
gem 'devise-two-factor'
|
||||||
|
|
||||||
|
|||||||
24
Gemfile.lock
24
Gemfile.lock
@@ -159,9 +159,9 @@ GEM
|
|||||||
cbor (0.5.10.1)
|
cbor (0.5.10.1)
|
||||||
cgi (0.5.1)
|
cgi (0.5.1)
|
||||||
charlock_holmes (0.7.9)
|
charlock_holmes (0.7.9)
|
||||||
chewy (7.6.0)
|
chewy (8.0.1)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 7.2)
|
||||||
elasticsearch (>= 7.14.0, < 8)
|
elasticsearch (>= 8.14, < 9.0)
|
||||||
elasticsearch-dsl
|
elasticsearch-dsl
|
||||||
childprocess (5.1.0)
|
childprocess (5.1.0)
|
||||||
logger (~> 1.5)
|
logger (~> 1.5)
|
||||||
@@ -214,16 +214,16 @@ GEM
|
|||||||
dotenv (3.2.0)
|
dotenv (3.2.0)
|
||||||
drb (2.2.3)
|
drb (2.2.3)
|
||||||
dry-cli (1.4.1)
|
dry-cli (1.4.1)
|
||||||
elasticsearch (7.17.11)
|
elastic-transport (8.4.1)
|
||||||
elasticsearch-api (= 7.17.11)
|
faraday (< 3)
|
||||||
elasticsearch-transport (= 7.17.11)
|
multi_json
|
||||||
elasticsearch-api (7.17.11)
|
elasticsearch (8.19.3)
|
||||||
|
elastic-transport (~> 8.3)
|
||||||
|
elasticsearch-api (= 8.19.3)
|
||||||
|
ostruct
|
||||||
|
elasticsearch-api (8.19.3)
|
||||||
multi_json
|
multi_json
|
||||||
elasticsearch-dsl (0.1.10)
|
elasticsearch-dsl (0.1.10)
|
||||||
elasticsearch-transport (7.17.11)
|
|
||||||
base64
|
|
||||||
faraday (>= 1, < 3)
|
|
||||||
multi_json
|
|
||||||
email_validator (2.2.4)
|
email_validator (2.2.4)
|
||||||
activemodel
|
activemodel
|
||||||
erb (6.0.2)
|
erb (6.0.2)
|
||||||
@@ -959,7 +959,7 @@ DEPENDENCIES
|
|||||||
capybara (~> 3.39)
|
capybara (~> 3.39)
|
||||||
capybara-playwright-driver
|
capybara-playwright-driver
|
||||||
charlock_holmes (~> 0.7.7)
|
charlock_holmes (~> 0.7.7)
|
||||||
chewy (~> 7.3)
|
chewy
|
||||||
climate_control
|
climate_control
|
||||||
cocoon (~> 1.2)
|
cocoon (~> 1.2)
|
||||||
color_diff (~> 0.1)
|
color_diff (~> 0.1)
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ Mastodon is a **free, open-source social network server** based on [ActivityPub]
|
|||||||
- **PostgreSQL** 14+
|
- **PostgreSQL** 14+
|
||||||
- **Redis** 7.0+
|
- **Redis** 7.0+
|
||||||
- **Node.js** 20+
|
- **Node.js** 20+
|
||||||
|
- **FFmpeg** 5.1+
|
||||||
|
|
||||||
This repository includes deployment configurations for **Docker and docker-compose**, as well as for other environments like Heroku and Scalingo. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). A [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the main documentation.
|
This repository includes deployment configurations for **Docker and docker-compose**, as well as for other environments like Heroku and Scalingo. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). A [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the main documentation.
|
||||||
|
|
||||||
|
|||||||
@@ -1366,6 +1366,9 @@ body > [data-popper-placement] {
|
|||||||
.autosuggest-textarea > .autosuggest-textarea__textarea:lang(#{$lang}) {
|
.autosuggest-textarea > .autosuggest-textarea__textarea:lang(#{$lang}) {
|
||||||
writing-mode: vertical-lr;
|
writing-mode: vertical-lr;
|
||||||
min-height: 209px; // writable
|
min-height: 209px; // writable
|
||||||
|
max-height: 209px; // suppress autosizing by react-textarea-autosize
|
||||||
|
overflow-x: auto;
|
||||||
|
scrollbar-color: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailed-status > .status__content > .status__content__text:lang(#{$lang}) {
|
.detailed-status > .status__content > .status__content__text:lang(#{$lang}) {
|
||||||
|
|||||||
@@ -1257,31 +1257,44 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.progress-tracker {
|
.progress-tracker {
|
||||||
|
--circle-size: 30px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
flex: 0 0 auto;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
--connector-color: var(--color-border-primary);
|
||||||
height: 2px;
|
--connector-thickness: 2px;
|
||||||
background: var(--color-border-primary);
|
|
||||||
flex: 1 1 auto;
|
|
||||||
|
|
||||||
&.completed {
|
&.completed {
|
||||||
background: var(--color-text-brand);
|
--connector-color: var(--color-bg-brand-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
// Connector line between circles
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
inset-inline: var(--circle-size) 0;
|
||||||
|
background-color: var(--connector-color);
|
||||||
|
height: 2px;
|
||||||
|
top: calc((var(--circle-size) - var(--connector-thickness)) / 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.circle {
|
.circle {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 30px;
|
width: var(--circle-size);
|
||||||
height: 30px;
|
height: var(--circle-size);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 2px solid var(--color-border-primary);
|
border: 2px solid var(--color-border-primary);
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
@@ -1302,8 +1315,9 @@ code {
|
|||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
// Center-align the label with the circle
|
||||||
|
transform: translateX(-33.3333%);
|
||||||
}
|
}
|
||||||
|
|
||||||
li:first-child .label {
|
li:first-child .label {
|
||||||
@@ -1320,15 +1334,15 @@ code {
|
|||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.active .circle {
|
[aria-current='step'] .circle {
|
||||||
border-color: var(--color-text-brand);
|
border-color: var(--color-bg-brand-base);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--color-text-brand);
|
background: var(--color-bg-brand-base);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@@ -1337,8 +1351,9 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.completed .circle {
|
.completed .circle {
|
||||||
border-color: var(--color-text-brand);
|
color: var(--color-text-on-brand-base);
|
||||||
background: var(--color-text-brand);
|
background: var(--color-bg-brand-base);
|
||||||
|
border-color: var(--color-bg-brand-base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,12 @@ class ActivityPub::Activity
|
|||||||
@follow_from_object ||= ::Follow.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
|
@follow_from_object ||= ::Follow.find_by(target_account: @account, uri: object_uri) unless object_uri.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def feature_request_from_object
|
||||||
|
return @collection_item if instance_variable_defined?(:@collection_item)
|
||||||
|
|
||||||
|
@collection_item = CollectionItem.local.find_by(activity_uri: value_or_id(@object), account_id: @account.id)
|
||||||
|
end
|
||||||
|
|
||||||
def fetch_remote_original_status
|
def fetch_remote_original_status
|
||||||
if object_uri.start_with?('http')
|
if object_uri.start_with?('http')
|
||||||
return if ActivityPub::TagManager.instance.local_uri?(object_uri)
|
return if ActivityPub::TagManager.instance.local_uri?(object_uri)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity
|
|||||||
return accept_follow_for_relay if relay_follow?
|
return accept_follow_for_relay if relay_follow?
|
||||||
return accept_follow!(follow_request_from_object) unless follow_request_from_object.nil?
|
return accept_follow!(follow_request_from_object) unless follow_request_from_object.nil?
|
||||||
return accept_quote!(quote_request_from_object) unless quote_request_from_object.nil?
|
return accept_quote!(quote_request_from_object) unless quote_request_from_object.nil?
|
||||||
|
return accept_feature_request! if Mastodon::Feature.collections_federation_enabled? && feature_request_from_object.present?
|
||||||
|
|
||||||
case @object['type']
|
case @object['type']
|
||||||
when 'Follow'
|
when 'Follow'
|
||||||
@@ -44,6 +45,17 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity
|
|||||||
accept_quote!(quote)
|
accept_quote!(quote)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def accept_feature_request!
|
||||||
|
approval_uri = value_or_id(first_of_value(@json['result']))
|
||||||
|
return if approval_uri.nil? || unsupported_uri_scheme?(approval_uri) || non_matching_uri_hosts?(approval_uri, @account.uri)
|
||||||
|
|
||||||
|
collection_item = feature_request_from_object
|
||||||
|
collection_item.update!(approval_uri:, state: :accepted)
|
||||||
|
|
||||||
|
activity_json = ActiveModelSerializers::SerializableResource.new(collection_item, serializer: ActivityPub::AddFeaturedItemSerializer, adapter: ActivityPub::Adapter).to_json
|
||||||
|
ActivityPub::AccountRawDistributionWorker.perform_async(activity_json, collection_item.collection.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
def accept_quote!(quote)
|
def accept_quote!(quote)
|
||||||
approval_uri = value_or_id(first_of_value(@json['result']))
|
approval_uri = value_or_id(first_of_value(@json['result']))
|
||||||
return if unsupported_uri_scheme?(approval_uri) || quote.quoted_account != @account || !quote.status.local? || !quote.pending?
|
return if unsupported_uri_scheme?(approval_uri) || quote.quoted_account != @account || !quote.status.local? || !quote.pending?
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity
|
|||||||
return follow_request_from_object.reject! unless follow_request_from_object.nil?
|
return follow_request_from_object.reject! unless follow_request_from_object.nil?
|
||||||
return UnfollowService.new.call(follow_from_object.account, @account) unless follow_from_object.nil?
|
return UnfollowService.new.call(follow_from_object.account, @account) unless follow_from_object.nil?
|
||||||
return reject_quote!(quote_request_from_object) unless quote_request_from_object.nil?
|
return reject_quote!(quote_request_from_object) unless quote_request_from_object.nil?
|
||||||
|
return reject_feature_request! unless feature_request_from_object.nil?
|
||||||
|
|
||||||
case @object['type']
|
case @object['type']
|
||||||
when 'Follow'
|
when 'Follow'
|
||||||
@@ -46,6 +47,13 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity
|
|||||||
quote.reject!
|
quote.reject!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reject_feature_request!
|
||||||
|
collection_item = feature_request_from_object
|
||||||
|
return unless collection_item.account == @account && collection_item.local?
|
||||||
|
|
||||||
|
collection_item.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
def relay
|
def relay
|
||||||
@relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
|
@relay ||= Relay.find_by(follow_activity_id: object_uri) unless object_uri.nil?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class Admin::Metrics::Dimension::SoftwareVersionsDimension < Admin::Metrics::Dim
|
|||||||
value: version,
|
value: version,
|
||||||
human_value: version,
|
human_value: version,
|
||||||
}
|
}
|
||||||
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
|
rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class Admin::Metrics::Dimension::SpaceUsageDimension < Admin::Metrics::Dimension
|
|||||||
unit: 'bytes',
|
unit: 'bytes',
|
||||||
human_value: number_to_human_size(value),
|
human_value: number_to_human_size(value),
|
||||||
}
|
}
|
||||||
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
|
rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
|||||||
return true unless Chewy.enabled?
|
return true unless Chewy.enabled?
|
||||||
|
|
||||||
running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && specifications_match? && preset_matches?
|
running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && specifications_match? && preset_matches?
|
||||||
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected
|
rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
|||||||
else
|
else
|
||||||
Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/elasticsearch/#scaling')
|
Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/elasticsearch/#scaling')
|
||||||
end
|
end
|
||||||
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected
|
rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error, HTTPClient::KeepAliveDisconnected
|
||||||
Admin::SystemCheck::Message.new(:elasticsearch_running_check)
|
Admin::SystemCheck::Message.new(:elasticsearch_running_check)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
|
|||||||
def running_version
|
def running_version
|
||||||
@running_version ||= begin
|
@running_version ||= begin
|
||||||
Chewy.client.info['version']['number']
|
Chewy.client.info['version']['number']
|
||||||
rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
|
rescue Faraday::ConnectionFailed, Elastic::Transport::Transport::Error
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class CollectionItem < ApplicationRecord
|
|||||||
|
|
||||||
validates :position, numericality: { only_integer: true, greater_than: 0 }
|
validates :position, numericality: { only_integer: true, greater_than: 0 }
|
||||||
validates :activity_uri, presence: true, if: :local_item_with_remote_account?
|
validates :activity_uri, presence: true, if: :local_item_with_remote_account?
|
||||||
validates :approval_uri, presence: true, unless: -> { local? || account&.local? }
|
validates :approval_uri, presence: true, unless: -> { local? || account&.local? || !accepted? }
|
||||||
validates :account, presence: true, if: :accepted?
|
validates :account, presence: true, if: :accepted?
|
||||||
validates :object_uri, presence: true, if: -> { account.nil? }
|
validates :object_uri, presence: true, if: -> { account.nil? }
|
||||||
validates :uri, presence: true, if: :remote_item_with_remote_account?
|
validates :uri, presence: true, if: :remote_item_with_remote_account?
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ class ActivityPub::ProcessFeaturedItemService
|
|||||||
else
|
else
|
||||||
@collection_item = collection.collection_items.create!(
|
@collection_item = collection.collection_items.create!(
|
||||||
uri: item_json['id'],
|
uri: item_json['id'],
|
||||||
object_uri: item_json['featuredObject'],
|
object_uri: item_json['featuredObject']
|
||||||
approval_uri: item_json['featureAuthorization']
|
|
||||||
)
|
)
|
||||||
|
@approval_uri = item_json['featureAuthorization']
|
||||||
|
|
||||||
verify_authorization!
|
verify_authorization!
|
||||||
end
|
end
|
||||||
@@ -35,8 +35,8 @@ class ActivityPub::ProcessFeaturedItemService
|
|||||||
private
|
private
|
||||||
|
|
||||||
def verify_authorization!
|
def verify_authorization!
|
||||||
ActivityPub::VerifyFeaturedItemService.new.call(@collection_item)
|
ActivityPub::VerifyFeaturedItemService.new.call(@collection_item, @approval_uri)
|
||||||
rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
|
rescue Mastodon::RecursionLimitExceededError, Mastodon::UnexpectedResponseError, *Mastodon::HTTP_CONNECTION_ERRORS
|
||||||
ActivityPub::VerifyFeaturedItemWorker.perform_in(rand(30..600).seconds, @collection_item.id)
|
ActivityPub::VerifyFeaturedItemWorker.perform_in(rand(30..600).seconds, @collection_item.id, @approval_uri)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,23 +3,23 @@
|
|||||||
class ActivityPub::VerifyFeaturedItemService
|
class ActivityPub::VerifyFeaturedItemService
|
||||||
include JsonLdHelper
|
include JsonLdHelper
|
||||||
|
|
||||||
def call(collection_item)
|
def call(collection_item, approval_uri)
|
||||||
@collection_item = collection_item
|
@collection_item = collection_item
|
||||||
@authorization = fetch_resource(@collection_item.approval_uri, true, raise_on_error: :temporary)
|
@authorization = fetch_resource(approval_uri, true, raise_on_error: :temporary)
|
||||||
|
|
||||||
if @authorization.nil?
|
if @authorization.nil?
|
||||||
@collection_item.update!(state: :rejected)
|
@collection_item.update!(state: :rejected)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
return if non_matching_uri_hosts?(@collection_item.approval_uri, @authorization['interactionTarget'])
|
return if non_matching_uri_hosts?(approval_uri, @authorization['interactionTarget'])
|
||||||
return unless matching_type? && matching_collection_uri?
|
return unless matching_type? && matching_collection_uri?
|
||||||
|
|
||||||
account = Account.where(uri: @collection_item.object_uri).first
|
account = Account.where(uri: @collection_item.object_uri).first
|
||||||
account ||= ActivityPub::FetchRemoteAccountService.new.call(@collection_item.object_uri)
|
account ||= ActivityPub::FetchRemoteAccountService.new.call(@collection_item.object_uri)
|
||||||
return if account.blank?
|
return if account.blank?
|
||||||
|
|
||||||
@collection_item.update!(account:, state: :accepted)
|
@collection_item.update!(account:, approval_uri:, state: :accepted)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -86,14 +86,14 @@ class FetchOEmbedService
|
|||||||
end
|
end
|
||||||
|
|
||||||
validate(parse_for_format(body)) if body.present?
|
validate(parse_for_format(body)) if body.present?
|
||||||
rescue Oj::ParseError, Ox::ParseError
|
rescue JSON::ParserError, Ox::ParseError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_for_format(body)
|
def parse_for_format(body)
|
||||||
case @format
|
case @format
|
||||||
when :json
|
when :json
|
||||||
Oj.load(body, mode: :strict)&.with_indifferent_access
|
JSON.parse(body)&.with_indifferent_access
|
||||||
when :xml
|
when :xml
|
||||||
Ox.load(body, mode: :hash_no_attrs)&.with_indifferent_access&.dig(:oembed)
|
Ox.load(body, mode: :hash_no_attrs)&.with_indifferent_access&.dig(:oembed)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,26 +1,35 @@
|
|||||||
- progress_index = { rules: 0, details: 1, confirm: 2, confirmed: 3, completed: 4 }[stage.to_sym]
|
- progress_index = { rules: 0, details: 1, confirm: 2, confirmed: 3, completed: 4 }[stage.to_sym]
|
||||||
|
|
||||||
%ol.progress-tracker
|
%ol.progress-tracker{ role: 'list', 'aria-label': t('auth.progress.list') }
|
||||||
%li{ class: progress_index.positive? ? 'completed' : 'active' }
|
%li{
|
||||||
|
class: progress_index.positive? ? 'completed' : nil,
|
||||||
|
'aria-current': progress_index.zero? ? 'step' : nil
|
||||||
|
}
|
||||||
.circle
|
.circle
|
||||||
- if progress_index.positive?
|
- if progress_index.positive?
|
||||||
= check_icon
|
= check_icon
|
||||||
.label= t('auth.progress.rules')
|
.label= t('auth.progress.rules')
|
||||||
%li.separator{ class: progress_index.positive? ? 'completed' : nil }
|
%li{
|
||||||
%li{ class: [progress_index > 1 && 'completed', progress_index == 1 && 'active'] }
|
class: progress_index > 1 && 'completed',
|
||||||
|
'aria-current': progress_index == 1 ? 'step' : nil
|
||||||
|
}
|
||||||
.circle
|
.circle
|
||||||
- if progress_index > 1
|
- if progress_index > 1
|
||||||
= check_icon
|
= check_icon
|
||||||
.label= t('auth.progress.details')
|
.label= t('auth.progress.details')
|
||||||
%li.separator{ class: progress_index > 1 ? 'completed' : nil }
|
%li{
|
||||||
%li{ class: [progress_index > 2 && 'completed', progress_index == 2 && 'active'] }
|
class: progress_index > 2 && 'completed',
|
||||||
|
'aria-current': progress_index == 2 ? 'step' : nil
|
||||||
|
}
|
||||||
.circle
|
.circle
|
||||||
- if progress_index > 2
|
- if progress_index > 2
|
||||||
= check_icon
|
= check_icon
|
||||||
.label= t('auth.progress.confirm')
|
.label= t('auth.progress.confirm')
|
||||||
- if approved_registrations?
|
- if approved_registrations?
|
||||||
%li.separator{ class: progress_index > 2 ? 'completed' : nil }
|
%li{
|
||||||
%li{ class: [progress_index > 3 && 'completed', progress_index == 3 && 'active'] }
|
class: progress_index > 3 && 'completed',
|
||||||
|
'aria-current': progress_index == 3 ? 'step' : nil
|
||||||
|
}
|
||||||
.circle
|
.circle
|
||||||
- if progress_index > 3
|
- if progress_index > 3
|
||||||
= check_icon
|
= check_icon
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ class ActivityPub::VerifyFeaturedItemWorker
|
|||||||
|
|
||||||
sidekiq_options queue: 'pull', retry: 5
|
sidekiq_options queue: 'pull', retry: 5
|
||||||
|
|
||||||
def perform(collection_item_id)
|
def perform(collection_item_id, approval_uri)
|
||||||
collection_item = CollectionItem.find(collection_item_id)
|
collection_item = CollectionItem.find(collection_item_id)
|
||||||
|
|
||||||
ActivityPub::VerifyFeaturedItemService.new.call(collection_item)
|
ActivityPub::VerifyFeaturedItemService.new.call(collection_item, approval_uri)
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
# Do nothing
|
# Do nothing
|
||||||
nil
|
nil
|
||||||
|
|||||||
@@ -1279,6 +1279,7 @@ en-GB:
|
|||||||
progress:
|
progress:
|
||||||
confirm: Confirm email
|
confirm: Confirm email
|
||||||
details: Your details
|
details: Your details
|
||||||
|
list: Sign up progress
|
||||||
review: Our review
|
review: Our review
|
||||||
rules: Accept rules
|
rules: Accept rules
|
||||||
providers:
|
providers:
|
||||||
|
|||||||
@@ -1279,6 +1279,7 @@ en:
|
|||||||
progress:
|
progress:
|
||||||
confirm: Confirm email
|
confirm: Confirm email
|
||||||
details: Your details
|
details: Your details
|
||||||
|
list: Sign up progress
|
||||||
review: Our review
|
review: Our review
|
||||||
rules: Accept rules
|
rules: Accept rules
|
||||||
providers:
|
providers:
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
module Elasticsearch
|
module Elasticsearch
|
||||||
module ClientExtensions
|
module ClientExtensions
|
||||||
def verify_elasticsearch
|
def initialize(arguments = {}, &block)
|
||||||
|
super
|
||||||
|
|
||||||
@verified = true
|
@verified = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -140,13 +140,13 @@ module Mastodon::CLI
|
|||||||
Request.new(:get, "https://#{domain}/api/v1/instance").perform do |res|
|
Request.new(:get, "https://#{domain}/api/v1/instance").perform do |res|
|
||||||
next unless res.code == 200
|
next unless res.code == 200
|
||||||
|
|
||||||
stats[domain] = Oj.load(res.to_s)
|
stats[domain] = JSON.parse(res.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
Request.new(:get, "https://#{domain}/api/v1/instance/peers").perform do |res|
|
Request.new(:get, "https://#{domain}/api/v1/instance/peers").perform do |res|
|
||||||
next unless res.code == 200
|
next unless res.code == 200
|
||||||
|
|
||||||
Oj.load(res.to_s).reject { |peer| stats.key?(peer) }.each do |peer|
|
JSON.parse(res.to_s).reject { |peer| stats.key?(peer) }.each do |peer|
|
||||||
pool.post(peer, &work_unit)
|
pool.post(peer, &work_unit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -154,7 +154,7 @@ module Mastodon::CLI
|
|||||||
Request.new(:get, "https://#{domain}/api/v1/instance/activity").perform do |res|
|
Request.new(:get, "https://#{domain}/api/v1/instance/activity").perform do |res|
|
||||||
next unless res.code == 200
|
next unless res.code == 200
|
||||||
|
|
||||||
stats[domain]['activity'] = Oj.load(res.to_s)
|
stats[domain]['activity'] = JSON.parse(res.to_s)
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
failed.increment
|
failed.increment
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ module Mastodon::CLI
|
|||||||
progress.finish
|
progress.finish
|
||||||
|
|
||||||
say("Indexed #{added} records, de-indexed #{removed}", :green, true)
|
say("Indexed #{added} records, de-indexed #{removed}", :green, true)
|
||||||
rescue Elasticsearch::Transport::Transport::ServerError => e
|
rescue Elastic::Transport::Transport::ServerError => e
|
||||||
fail_with_message <<~ERROR
|
fail_with_message <<~ERROR
|
||||||
There was an issue connecting to the search server. Make sure the
|
There was an issue connecting to the search server. Make sure the
|
||||||
server is configured and running correctly, and that the environment
|
server is configured and running correctly, and that the environment
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ module Paperclip
|
|||||||
@output_options['maxrate'] = bitrate + 192_000
|
@output_options['maxrate'] = bitrate + 192_000
|
||||||
@output_options['bufsize'] = bitrate * 5
|
@output_options['bufsize'] = bitrate * 5
|
||||||
|
|
||||||
if high_vfr?(metadata)
|
@output_options['fps_mode'] = 'vfr' if high_vfr?(metadata)
|
||||||
# TODO: change to `fps_mode` in the future, as `vsync` is being deprecated
|
|
||||||
@output_options['vsync'] = 'vfr'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ namespace :emojis do
|
|||||||
emojis_light = '👽⚾🐔☁️💨🕊️👀🍥👻🐐❕❔⛸️🌩️🔊🔇📃🌧️🐏🍚🍙🐓🐑💀☠️🌨️🔉🔈💬💭🏐🏳️⚪⬜◽◻️▫️🪽🪿'
|
emojis_light = '👽⚾🐔☁️💨🕊️👀🍥👻🐐❕❔⛸️🌩️🔊🔇📃🌧️🐏🍚🍙🐓🐑💀☠️🌨️🔉🔈💬💭🏐🏳️⚪⬜◽◻️▫️🪽🪿'
|
||||||
emojis_dark = '🎱🐜⚫🖤⬛◼️◾◼️✒️▪️💣🎳📷📸♣️🕶️✴️🔌💂♀️📽️🍳🦍💂🔪🕳️🕹️🕋🖊️🖋️💂♂️🎤🎓🎥🎼♠️🎩🦃📼📹🎮🐃🏴🐞🕺📱📲🚲🪮🐦⬛'
|
emojis_dark = '🎱🐜⚫🖤⬛◼️◾◼️✒️▪️💣🎳📷📸♣️🕶️✴️🔌💂♀️📽️🍳🦍💂🔪🕳️🕹️🕋🖊️🖋️💂♂️🎤🎓🎥🎼♠️🎩🦃📼📹🎮🐃🏴🐞🕺📱📲🚲🪮🐦⬛'
|
||||||
|
|
||||||
map = Oj.load(File.read(src))
|
map = JSON.parse(File.read(src))
|
||||||
|
|
||||||
emojis_light.each_grapheme_cluster do |emoji|
|
emojis_light.each_grapheme_cluster do |emoji|
|
||||||
gen_border map[emoji], 'black'
|
gen_border map[emoji], 'black'
|
||||||
@@ -193,7 +193,7 @@ namespace :emojis do
|
|||||||
require 'vips'
|
require 'vips'
|
||||||
|
|
||||||
src = Rails.root.join('app', 'javascript', 'mastodon', 'features', 'emoji', 'emoji_data.json')
|
src = Rails.root.join('app', 'javascript', 'mastodon', 'features', 'emoji', 'emoji_data.json')
|
||||||
sheet = Oj.load(File.read(src))
|
sheet = JSON.load_file(src)
|
||||||
|
|
||||||
max = 0
|
max = 0
|
||||||
sheet['emojis'].each_value do |row|
|
sheet['emojis'].each_value do |row|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace :repo do
|
|||||||
|
|
||||||
while url.present?
|
while url.present?
|
||||||
response = HTTP.get(url)
|
response = HTTP.get(url)
|
||||||
contributors = Oj.load(response.body)
|
contributors = JSON.parse(response.body)
|
||||||
|
|
||||||
contributors.each do |c|
|
contributors.each do |c|
|
||||||
file << "* [#{c['login']}](#{c['html_url']})\n" if c['login']
|
file << "* [#{c['login']}](#{c['html_url']})\n" if c['login']
|
||||||
@@ -68,7 +68,7 @@ namespace :repo do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
pull_request = Oj.load(response.to_s)
|
pull_request = JSON.parse(response.to_s)
|
||||||
pull_request['user']['login']
|
pull_request['user']['login']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module ViteRuby::ManifestIntegrityExtension
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_name_lookup_cache
|
def load_name_lookup_cache
|
||||||
Oj.load(config.build_output_dir.join('.vite/manifest-lookup.json').read)
|
JSON.load_file(config.build_output_dir.join('.vite/manifest-lookup.json'))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Upstream's `virtual` type is a hack, re-implement it with efficient exact name lookup
|
# Upstream's `virtual` type is a hack, re-implement it with efficient exact name lookup
|
||||||
|
|||||||
@@ -11,6 +11,5 @@ Fabricator(:unverified_remote_collection_item, from: :collection_item) do
|
|||||||
account nil
|
account nil
|
||||||
state :pending
|
state :pending
|
||||||
object_uri { Fabricate.build(:remote_account).uri }
|
object_uri { Fabricate.build(:remote_account).uri }
|
||||||
approval_uri { sequence(:uri) { |i| "https://example.com/authorizations/#{i}" } }
|
|
||||||
uri { sequence(:uri) { |i| "https://example.com/collection_items/#{i}" } }
|
uri { sequence(:uri) { |i| "https://example.com/collection_items/#{i}" } }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -171,5 +171,71 @@ RSpec.describe ActivityPub::Activity::Accept do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a FeatureRequest', feature: :collections_federation do
|
||||||
|
let(:collection) { Fabricate(:collection, account: recipient) }
|
||||||
|
let(:collection_item) { Fabricate(:collection_item, collection:, account: sender, state: :pending) }
|
||||||
|
let(:object) { collection_item.activity_uri }
|
||||||
|
let(:approval_uri) { 'https://example.com/stamps/1' }
|
||||||
|
let(:json) do
|
||||||
|
{
|
||||||
|
'id' => 'https://example.com/accepts/1',
|
||||||
|
'type' => 'Accept',
|
||||||
|
'actor' => sender.uri,
|
||||||
|
'to' => ActivityPub::TagManager.instance.uri_for(recipient),
|
||||||
|
'object' => object,
|
||||||
|
'result' => approval_uri,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when activity is valid' do
|
||||||
|
it 'accepts the collection item, stores the authorization uri and federates an `Add` activity' do
|
||||||
|
subject.perform
|
||||||
|
|
||||||
|
expect(collection_item.reload).to be_accepted
|
||||||
|
expect(collection_item.approval_uri).to eq 'https://example.com/stamps/1'
|
||||||
|
expect(ActivityPub::AccountRawDistributionWorker)
|
||||||
|
.to have_enqueued_sidekiq_job
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when activity is invalid' do
|
||||||
|
shared_examples 'ignoring activity' do
|
||||||
|
it 'does not accept the item and does not send out an activity' do
|
||||||
|
subject.perform
|
||||||
|
|
||||||
|
expect(collection_item.reload).to_not be_accepted
|
||||||
|
expect(collection_item.approval_uri).to be_nil
|
||||||
|
expect(ActivityPub::AccountRawDistributionWorker)
|
||||||
|
.to_not have_enqueued_sidekiq_job
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when matching collection item cannot be found' do
|
||||||
|
let(:object) { 'https://localhost/feature_requests/1' }
|
||||||
|
|
||||||
|
it_behaves_like 'ignoring activity'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the sender is not the featured account' do
|
||||||
|
let(:other_account) { Fabricate(:remote_account) }
|
||||||
|
let(:collection_item) { Fabricate(:collection_item, collection:, account: other_account, state: :pending) }
|
||||||
|
|
||||||
|
it_behaves_like 'ignoring activity'
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when approval_uri does not match the sender's uri" do
|
||||||
|
let(:approval_uri) { 'https://other.localhost/authorizations/1' }
|
||||||
|
|
||||||
|
it_behaves_like 'ignoring activity'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when approval_uri is missing' do
|
||||||
|
let(:approval_uri) { nil }
|
||||||
|
|
||||||
|
it_behaves_like 'ignoring activity'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ RSpec.describe ActivityPub::Activity::Announce do
|
|||||||
context 'when sender is followed by a local account' do
|
context 'when sender is followed by a local account' do
|
||||||
before do
|
before do
|
||||||
Fabricate(:account).follow!(sender)
|
Fabricate(:account).follow!(sender)
|
||||||
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: JSON.generate(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: unknown_object_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
subject.perform
|
subject.perform
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ RSpec.describe ActivityPub::Activity::Announce do
|
|||||||
let(:object_json) { 'https://example.com/actor/hello-world' }
|
let(:object_json) { 'https://example.com/actor/hello-world' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: JSON.generate(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: unknown_object_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the relay is enabled' do
|
context 'when the relay is enabled' do
|
||||||
|
|||||||
@@ -1078,8 +1078,8 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -1104,7 +1104,11 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: object_json[:id],
|
interactingObject: object_json[:id],
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates a status with a verified quote' do
|
it 'creates a status with a verified quote' do
|
||||||
@@ -1134,8 +1138,8 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -1160,7 +1164,11 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: object_json[:id],
|
interactingObject: object_json[:id],
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates a status without the verified quote' do
|
it 'creates a status without the verified quote' do
|
||||||
@@ -1267,7 +1275,7 @@ RSpec.describe ActivityPub::Activity::Create do
|
|||||||
before do
|
before do
|
||||||
stub_request(:get, object_json[:id])
|
stub_request(:get, object_json[:id])
|
||||||
.with(headers: { Authorization: "Bearer #{token}" })
|
.with(headers: { Authorization: "Bearer #{token}" })
|
||||||
.to_return(body: JSON.generate(object_json), headers: { 'Content-Type': 'application/activity+json' })
|
.to_return(body: object_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
|
|
||||||
subject.perform
|
subject.perform
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
|
|||||||
expect { subject.perform }
|
expect { subject.perform }
|
||||||
.to enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
.to enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
||||||
.with(satisfying do |body|
|
.with(satisfying do |body|
|
||||||
outgoing_json = Oj.load(body)
|
outgoing_json = JSON.parse(body)
|
||||||
outgoing_json['type'] == 'Reject' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] }
|
outgoing_json['type'] == 'Reject' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] }
|
||||||
end, recipient.id, sender.inbox_url)
|
end, recipient.id, sender.inbox_url)
|
||||||
end
|
end
|
||||||
@@ -78,7 +78,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
|
|||||||
expect { subject.perform }
|
expect { subject.perform }
|
||||||
.to enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
.to enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
||||||
.with(satisfying do |body|
|
.with(satisfying do |body|
|
||||||
outgoing_json = Oj.load(body)
|
outgoing_json = JSON.parse(body)
|
||||||
outgoing_json['type'] == 'Reject' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] }
|
outgoing_json['type'] == 'Reject' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] }
|
||||||
end, recipient.id, sender.inbox_url)
|
end, recipient.id, sender.inbox_url)
|
||||||
end
|
end
|
||||||
@@ -86,7 +86,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
|
|||||||
|
|
||||||
context 'when trying to quote a quotable local status' do
|
context 'when trying to quote a quotable local status' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/unknown-status').to_return(status: 200, body: JSON.generate(status_json), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/unknown-status').to_return(status: 200, body: status_json.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
quoted_post.update(quote_approval_policy: InteractionPolicy::POLICY_FLAGS[:public] << 16)
|
quoted_post.update(quote_approval_policy: InteractionPolicy::POLICY_FLAGS[:public] << 16)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
|
|||||||
.to change { quoted_post.reload.quotes.accepted.count }.by(1)
|
.to change { quoted_post.reload.quotes.accepted.count }.by(1)
|
||||||
.and enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
.and enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
||||||
.with(satisfying do |body|
|
.with(satisfying do |body|
|
||||||
outgoing_json = Oj.load(body)
|
outgoing_json = JSON.parse(body)
|
||||||
outgoing_json['type'] == 'Accept' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] }
|
outgoing_json['type'] == 'Accept' && %w(type id actor object instrument).all? { |key| json[key] == outgoing_json['object'][key] }
|
||||||
end, recipient.id, sender.inbox_url)
|
end, recipient.id, sender.inbox_url)
|
||||||
end
|
end
|
||||||
@@ -113,7 +113,7 @@ RSpec.describe ActivityPub::Activity::QuoteRequest do
|
|||||||
.to change { quoted_post.reload.quotes.accepted.count }.by(1)
|
.to change { quoted_post.reload.quotes.accepted.count }.by(1)
|
||||||
.and enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
.and enqueue_sidekiq_job(ActivityPub::DeliveryWorker)
|
||||||
.with(satisfying do |body|
|
.with(satisfying do |body|
|
||||||
outgoing_json = Oj.load(body)
|
outgoing_json = JSON.parse(body)
|
||||||
outgoing_json['type'] == 'Accept' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] }
|
outgoing_json['type'] == 'Accept' && json['instrument']['id'] == outgoing_json['object']['instrument'] && %w(type id actor object).all? { |key| json[key] == outgoing_json['object'][key] }
|
||||||
end, recipient.id, sender.inbox_url)
|
end, recipient.id, sender.inbox_url)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe ActivityPub::Activity::Reject do
|
RSpec.describe ActivityPub::Activity::Reject do
|
||||||
let(:sender) { Fabricate(:account) }
|
let(:sender) { Fabricate(:remote_account) }
|
||||||
let(:recipient) { Fabricate(:account) }
|
let(:recipient) { Fabricate(:account) }
|
||||||
|
|
||||||
let(:json) do
|
let(:json) do
|
||||||
@@ -129,12 +129,12 @@ RSpec.describe ActivityPub::Activity::Reject do
|
|||||||
context 'with a QuoteRequest' do
|
context 'with a QuoteRequest' do
|
||||||
let(:status) { Fabricate(:status, account: recipient) }
|
let(:status) { Fabricate(:status, account: recipient) }
|
||||||
let(:quoted_status) { Fabricate(:status, account: sender) }
|
let(:quoted_status) { Fabricate(:status, account: sender) }
|
||||||
let(:quote) { Fabricate(:quote, status: status, quoted_status: quoted_status, activity_uri: 'https://abc-123/456') }
|
let!(:quote) { Fabricate(:quote, status: status, quoted_status: quoted_status) }
|
||||||
let(:approval_uri) { "https://#{sender.domain}/approvals/1" }
|
let(:approval_uri) { "https://#{sender.domain}/approvals/1" }
|
||||||
|
|
||||||
let(:object_json) do
|
let(:object_json) do
|
||||||
{
|
{
|
||||||
id: 'https://abc-123/456',
|
id: quote.activity_uri,
|
||||||
type: 'QuoteRequest',
|
type: 'QuoteRequest',
|
||||||
actor: ActivityPub::TagManager.instance.uri_for(recipient),
|
actor: ActivityPub::TagManager.instance.uri_for(recipient),
|
||||||
object: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
object: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
@@ -147,5 +147,23 @@ RSpec.describe ActivityPub::Activity::Reject do
|
|||||||
.to change { quote.reload.rejected? }.from(false).to(true)
|
.to change { quote.reload.rejected? }.from(false).to(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a FeatureRequest' do
|
||||||
|
let(:collection) { Fabricate(:collection, account: recipient) }
|
||||||
|
let!(:collection_item) { Fabricate(:collection_item, collection:, account: sender, state: :pending) }
|
||||||
|
let(:json) do
|
||||||
|
{
|
||||||
|
'id' => 'https://example.com/accepts/1',
|
||||||
|
'type' => 'Accept',
|
||||||
|
'actor' => sender.uri,
|
||||||
|
'to' => ActivityPub::TagManager.instance.uri_for(recipient),
|
||||||
|
'object' => collection_item.activity_uri,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'deletes the collection item' do
|
||||||
|
expect { subject.perform }.to change(collection.collection_items, :count).by(-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ RSpec.describe ActivityPub::Activity do
|
|||||||
before do
|
before do
|
||||||
sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender))
|
sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender))
|
||||||
|
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate(approval_payload))
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: approval_payload.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when getting them in order' do
|
context 'when getting them in order' do
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ RSpec.describe ActivityPub::Dereferencer do
|
|||||||
let(:uri) { nil }
|
let(:uri) { nil }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/foo').to_return(body: JSON.generate(object), headers: { 'Content-Type' => 'application/activity+json' })
|
stub_request(:get, 'https://example.com/foo').to_return(body: object.to_json, headers: { 'Content-Type' => 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a URI' do
|
context 'with a URI' do
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ RSpec.describe ActivityPub::Forwarder do
|
|||||||
|
|
||||||
it 'correctly forwards to expected remote followers' do
|
it 'correctly forwards to expected remote followers' do
|
||||||
expect { subject.forward! }
|
expect { subject.forward! }
|
||||||
.to enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(JSON.generate(payload), anything, eve.preferred_inbox_url)
|
.to enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(payload.to_json, anything, eve.preferred_inbox_url)
|
||||||
.and enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(JSON.generate(payload), anything, mallory.preferred_inbox_url)
|
.and enqueue_sidekiq_job(ActivityPub::LowPriorityDeliveryWorker).with(payload.to_json, anything, mallory.preferred_inbox_url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ RSpec.describe Admin::SystemCheck::ElasticsearchCheck do
|
|||||||
|
|
||||||
def stub_elasticsearch_error
|
def stub_elasticsearch_error
|
||||||
client = instance_double(Elasticsearch::Client)
|
client = instance_double(Elasticsearch::Client)
|
||||||
allow(client).to receive(:info).and_raise(Elasticsearch::Transport::Transport::Error)
|
allow(client).to receive(:info).and_raise(Elastic::Transport::Transport::Error)
|
||||||
allow(Chewy).to receive(:client).and_return(client)
|
allow(Chewy).to receive(:client).and_return(client)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
14
spec/lib/elasticsearch/client_extensions_spec.rb
Normal file
14
spec/lib/elasticsearch/client_extensions_spec.rb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Elasticsearch::ClientExtensions do
|
||||||
|
describe '#initialize' do
|
||||||
|
it 'marks the connection as verified on initialization' do
|
||||||
|
client = Elasticsearch::Client.new
|
||||||
|
|
||||||
|
expect(client.instance_variable_get(:@verified))
|
||||||
|
.to be(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -87,7 +87,7 @@ RSpec.describe Mastodon::CLI::Domains do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def json_summary
|
def json_summary
|
||||||
JSON.generate('host.example': { activity: {} })
|
{ 'host.example': { activity: {} } }.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ RSpec.describe Mastodon::CLI::Search do
|
|||||||
context 'when server communication raises an error' do
|
context 'when server communication raises an error' do
|
||||||
let(:options) { { reset_chewy: true } }
|
let(:options) { { reset_chewy: true } }
|
||||||
|
|
||||||
before { allow(Chewy::Stash::Specification).to receive(:reset!).and_raise(Elasticsearch::Transport::Transport::Errors::InternalServerError) }
|
before { allow(Chewy::Stash::Specification).to receive(:reset!).and_raise(Elastic::Transport::Transport::Errors::InternalServerError) }
|
||||||
|
|
||||||
it 'Exits with error message' do
|
it 'Exits with error message' do
|
||||||
expect { subject }
|
expect { subject }
|
||||||
|
|||||||
@@ -3,27 +3,34 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Webhooks::PayloadRenderer do
|
RSpec.describe Webhooks::PayloadRenderer do
|
||||||
subject(:renderer) { described_class.new(json) }
|
subject(:renderer) { described_class.new(payload.to_json) }
|
||||||
|
|
||||||
let(:event) { Webhooks::EventPresenter.new(type, object) }
|
let(:event) { Webhooks::EventPresenter.new(type, object) }
|
||||||
let(:payload) { ActiveModelSerializers::SerializableResource.new(event, serializer: REST::Admin::WebhookEventSerializer, scope: nil, scope_name: :current_user).as_json }
|
let(:payload) { ActiveModelSerializers::SerializableResource.new(event, serializer: REST::Admin::WebhookEventSerializer, scope: nil, scope_name: :current_user).as_json }
|
||||||
let(:json) { JSON.generate(payload) }
|
|
||||||
|
|
||||||
describe '#render' do
|
describe '#render' do
|
||||||
|
subject { renderer.render(template) }
|
||||||
|
|
||||||
context 'when event is account.approved' do
|
context 'when event is account.approved' do
|
||||||
let(:type) { 'account.approved' }
|
let(:type) { 'account.approved' }
|
||||||
let(:object) { Fabricate(:account, display_name: 'Foo"') }
|
let(:object) { Fabricate(:account, display_name: 'Foo"', username: 'foofoobarbar') }
|
||||||
|
|
||||||
it 'renders event-related variables into template' do
|
context 'with event-related variables' do
|
||||||
expect(renderer.render('foo={{event}}')).to eq 'foo=account.approved'
|
let(:template) { 'foo={{event}}' }
|
||||||
|
|
||||||
|
it { is_expected.to eq('foo=account.approved') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'renders event-specific variables into template' do
|
context 'with event-specific variables' do
|
||||||
expect(renderer.render('foo={{object.username}}')).to eq "foo=#{object.username}"
|
let(:template) { 'foo={{object.username}}' }
|
||||||
|
|
||||||
|
it { is_expected.to eq('foo=foofoobarbar') }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'escapes values for use in JSON' do
|
context 'with values needing JSON escape' do
|
||||||
expect(renderer.render('foo={{object.account.display_name}}')).to eq 'foo=Foo\\"'
|
let(:template) { 'foo={{object.account.display_name}}' }
|
||||||
|
|
||||||
|
it { is_expected.to eq('foo=Foo\\"') }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Account::Avatar do
|
RSpec.describe Account::Avatar do
|
||||||
describe 'static avatars', :attachment_processing do
|
describe 'static avatars', :attachment_processing do
|
||||||
describe 'with a square GIF' do
|
describe 'with a square GIF' do
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Account::Header do
|
RSpec.describe Account::Header do
|
||||||
describe 'base64-encoded files', :attachment_processing do
|
describe 'base64-encoded files', :attachment_processing do
|
||||||
let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" }
|
let(:base64_attachment) { "data:image/jpeg;base64,#{Base64.encode64(attachment_fixture('attachment.jpg').read)}" }
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Account::Search do
|
RSpec.describe Account::Search do
|
||||||
describe '.search_for' do
|
describe '.search_for' do
|
||||||
before do
|
before do
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ RSpec.describe 'Donation campaigns' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, "#{api_url}?platform=web&seed=#{seed}&locale=en").to_return(body: JSON.generate(campaign_json), status: 200)
|
stub_request(:get, "#{api_url}?platform=web&seed=#{seed}&locale=en").to_return(body: campaign_json.to_json, status: 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the expected campaign' do
|
it 'returns the expected campaign' do
|
||||||
@@ -109,7 +109,7 @@ RSpec.describe 'Donation campaigns' do
|
|||||||
expect(Rails.cache.read("donation_campaign_request:#{seed}:en", raw: true))
|
expect(Rails.cache.read("donation_campaign_request:#{seed}:en", raw: true))
|
||||||
.to eq 'campaign-1:en'
|
.to eq 'campaign-1:en'
|
||||||
|
|
||||||
expect(Oj.load(Rails.cache.read('donation_campaign:campaign-1:en', raw: true)))
|
expect(JSON.parse(Rails.cache.read('donation_campaign:campaign-1:en', raw: true)))
|
||||||
.to match(campaign_json)
|
.to match(campaign_json)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -75,11 +75,11 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
|
|
||||||
shared_examples 'sets pinned posts' do
|
shared_examples 'sets pinned posts' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: JSON.generate(status_json_pinned_known), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: status_json_pinned_known.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_inlined), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: status_json_pinned_unknown_inlined.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404)
|
stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404)
|
||||||
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: status_json_pinned_unknown_reachable.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: JSON.generate(featured_with_null), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: featured_with_null.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
@@ -101,7 +101,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
let(:collection_or_uri) { actor.featured_collection_url }
|
let(:collection_or_uri) { actor.featured_collection_url }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
@@ -122,7 +122,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
|
|
||||||
context 'when the endpoint is a Collection' do
|
context 'when the endpoint is a Collection' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
@@ -139,7 +139,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
@@ -148,11 +148,12 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
let(:items) { 'https://example.com/account/pinned/unknown-reachable' }
|
let(:items) { 'https://example.com/account/pinned/unknown-reachable' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: status_json_pinned_unknown_reachable.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
subject
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets expected posts as pinned posts' do
|
it 'sets expected posts as pinned posts' do
|
||||||
|
subject
|
||||||
|
|
||||||
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
|
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
|
||||||
'https://example.com/account/pinned/unknown-reachable'
|
'https://example.com/account/pinned/unknown-reachable'
|
||||||
)
|
)
|
||||||
@@ -175,7 +176,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
@@ -184,11 +185,12 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService do
|
|||||||
let(:items) { 'https://example.com/account/pinned/unknown-reachable' }
|
let(:items) { 'https://example.com/account/pinned/unknown-reachable' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: JSON.generate(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: status_json_pinned_unknown_reachable.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
subject
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sets expected posts as pinned posts' do
|
it 'sets expected posts as pinned posts' do
|
||||||
|
subject
|
||||||
|
|
||||||
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
|
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
|
||||||
'https://example.com/account/pinned/unknown-reachable'
|
'https://example.com/account/pinned/unknown-reachable'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
|
|||||||
describe '#call' do
|
describe '#call' do
|
||||||
context 'when the endpoint is a Collection' do
|
context 'when the endpoint is a Collection' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets featured tags'
|
it_behaves_like 'sets featured tags'
|
||||||
@@ -46,7 +46,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
|
|||||||
|
|
||||||
context 'when the account already has featured tags' do
|
context 'when the account already has featured tags' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
|
|
||||||
actor.featured_tags.create!(name: 'FoO')
|
actor.featured_tags.create!(name: 'FoO')
|
||||||
actor.featured_tags.create!(name: 'baz')
|
actor.featured_tags.create!(name: 'baz')
|
||||||
@@ -67,7 +67,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets featured tags'
|
it_behaves_like 'sets featured tags'
|
||||||
@@ -88,7 +88,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_url).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_url).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets featured tags'
|
it_behaves_like 'sets featured tags'
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
|
|||||||
before do
|
before do
|
||||||
actor[:inbox] = nil
|
actor[:inbox] = nil
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and returns nil' do
|
it 'fetches resource and looks up webfinger and returns nil' do
|
||||||
@@ -54,8 +54,8 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and sets attributes' do
|
it 'fetches resource and looks up webfinger and sets attributes' do
|
||||||
@@ -75,9 +75,9 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and follows redirection and sets attributes' do
|
it 'fetches resource and looks up webfinger and follows redirection and sets attributes' do
|
||||||
@@ -98,8 +98,8 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and does not create account' do
|
it 'fetches resource and looks up webfinger and does not create account' do
|
||||||
@@ -114,9 +114,9 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and follows redirect and does not create account' do
|
it 'fetches resource and looks up webfinger and follows redirect and does not create account' do
|
||||||
@@ -130,7 +130,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService do
|
|||||||
|
|
||||||
context 'with wrong id' do
|
context 'with wrong id' do
|
||||||
it 'does not create account' do
|
it 'does not create account' do
|
||||||
expect(subject.call('https://fake.address/@foo', prefetched_body: JSON.generate(actor))).to be_nil
|
expect(subject.call('https://fake.address/@foo', prefetched_body: actor.to_json)).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
|
|||||||
before do
|
before do
|
||||||
actor[:inbox] = nil
|
actor[:inbox] = nil
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and returns nil' do
|
it 'fetches resource and looks up webfinger and returns nil' do
|
||||||
@@ -54,8 +54,8 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and sets values' do
|
it 'fetches resource and looks up webfinger and sets values' do
|
||||||
@@ -75,9 +75,9 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and follows redirect and sets values' do
|
it 'fetches resource and looks up webfinger and follows redirect and sets values' do
|
||||||
@@ -98,8 +98,8 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and does not create account' do
|
it 'fetches resource and looks up webfinger and does not create account' do
|
||||||
@@ -114,9 +114,9 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
|
|||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob', type: 'application/activity+json' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches resource and looks up webfinger and follows redirect and does not create account' do
|
it 'fetches resource and looks up webfinger and follows redirect and does not create account' do
|
||||||
@@ -130,7 +130,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService do
|
|||||||
|
|
||||||
context 'with wrong id' do
|
context 'with wrong id' do
|
||||||
it 'does not create account' do
|
it 'does not create account' do
|
||||||
expect(subject.call('https://fake.address/@foo', prefetched_body: JSON.generate(actor))).to be_nil
|
expect(subject.call('https://fake.address/@foo', prefetched_body: actor.to_json)).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, 'https://example.com/alice').to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: JSON.generate(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: webfinger.to_json, headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#call' do
|
describe '#call' do
|
||||||
@@ -59,7 +59,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
|
|||||||
|
|
||||||
context 'when the key is a sub-object from the actor' do
|
context 'when the key is a sub-object from the actor' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, public_key_id).to_return(body: JSON.generate(actor), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, public_key_id).to_return(body: actor.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the expected account' do
|
it 'returns the expected account' do
|
||||||
@@ -71,7 +71,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
|
|||||||
let(:public_key_id) { 'https://example.com/alice-public-key.json' }
|
let(:public_key_id) { 'https://example.com/alice-public-key.json' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, public_key_id).to_return(body: JSON.generate(key_json.merge({ '@context': ['https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, public_key_id).to_return(body: key_json.merge({ '@context': ['https://w3id.org/security/v1'] }).to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the expected account' do
|
it 'returns the expected account' do
|
||||||
@@ -84,7 +84,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService do
|
|||||||
let(:actor_public_key) { 'https://example.com/alice-public-key.json' }
|
let(:actor_public_key) { 'https://example.com/alice-public-key.json' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, public_key_id).to_return(body: JSON.generate(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, public_key_id).to_return(body: key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }).to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the nil' do
|
it 'returns the nil' do
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
|
|||||||
|
|
||||||
let(:follower) { Fabricate(:account, username: 'alice') }
|
let(:follower) { Fabricate(:account, username: 'alice') }
|
||||||
let(:follow) { nil }
|
let(:follow) { nil }
|
||||||
let(:response) { { body: JSON.generate(object), headers: { 'content-type': 'application/activity+json' } } }
|
let(:response) { { body: object.to_json, headers: { 'content-type': 'application/activity+json' } } }
|
||||||
let(:existing_status) { nil }
|
let(:existing_status) { nil }
|
||||||
|
|
||||||
let(:note) do
|
let(:note) do
|
||||||
@@ -369,7 +369,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'creates statuses but not more than limit allows' do
|
it 'creates statuses but not more than limit allows' do
|
||||||
expect { subject.call(object[:id], prefetched_body: JSON.generate(object)) }
|
expect { subject.call(object[:id], prefetched_body: object.to_json) }
|
||||||
.to change { sender.statuses.count }.by_at_least(2)
|
.to change { sender.statuses.count }.by_at_least(2)
|
||||||
.and change { sender.statuses.count }.by_at_most(3)
|
.and change { sender.statuses.count }.by_at_most(3)
|
||||||
end
|
end
|
||||||
@@ -419,7 +419,7 @@ RSpec.describe ActivityPub::FetchRemoteStatusService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'creates statuses but not more than limit allows' do
|
it 'creates statuses but not more than limit allows' do
|
||||||
expect { subject.call(object[:id], prefetched_body: JSON.generate(object)) }
|
expect { subject.call(object[:id], prefetched_body: object.to_json) }
|
||||||
.to change { sender.statuses.count }.by_at_least(2)
|
.to change { sender.statuses.count }.by_at_least(2)
|
||||||
.and change { sender.statuses.count }.by_at_most(3)
|
.and change { sender.statuses.count }.by_at_most(3)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ RSpec.describe ActivityPub::FetchRepliesService do
|
|||||||
|
|
||||||
context 'when passing the URL to the collection' do
|
context 'when passing the URL to the collection' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'spawns workers for up to 5 replies on the same server' do
|
it 'spawns workers for up to 5 replies on the same server' do
|
||||||
@@ -93,7 +93,7 @@ RSpec.describe ActivityPub::FetchRepliesService do
|
|||||||
|
|
||||||
context 'when passing the URL to the collection' do
|
context 'when passing the URL to the collection' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'spawns workers for up to 5 replies on the same server' do
|
it 'spawns workers for up to 5 replies on the same server' do
|
||||||
@@ -132,7 +132,7 @@ RSpec.describe ActivityPub::FetchRepliesService do
|
|||||||
|
|
||||||
context 'when passing the URL to the collection' do
|
context 'when passing the URL to the collection' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'spawns workers for up to 5 replies on the same server' do
|
it 'spawns workers for up to 5 replies on the same server' do
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ RSpec.describe ActivityPub::ProcessCollectionService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:json) { JSON.generate(payload) }
|
let(:json) { payload.to_json }
|
||||||
|
|
||||||
describe '#call' do
|
describe '#call' do
|
||||||
context 'when actor is suspended' do
|
context 'when actor is suspended' do
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do
|
|||||||
|
|
||||||
new_item = collection.collection_items.last
|
new_item = collection.collection_items.last
|
||||||
expect(new_item.object_uri).to eq 'https://example.com/actor/1'
|
expect(new_item.object_uri).to eq 'https://example.com/actor/1'
|
||||||
expect(new_item.approval_uri).to eq 'https://example.com/auth/1'
|
expect(new_item.approval_uri).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when an item exists for a local featured account' do
|
context 'when an item exists for a local featured account' do
|
||||||
@@ -93,7 +93,7 @@ RSpec.describe ActivityPub::ProcessFeaturedItemService do
|
|||||||
|
|
||||||
new_item = collection.collection_items.last
|
new_item = collection.collection_items.last
|
||||||
expect(new_item.object_uri).to eq 'https://example.com/actor/1'
|
expect(new_item.object_uri).to eq 'https://example.com/actor/1'
|
||||||
expect(new_item.approval_uri).to eq 'https://example.com/auth/1'
|
expect(new_item.approval_uri).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
let(:json) { Oj.load(JSON.generate(payload)) }
|
let(:json) { JSON.parse(payload.to_json) }
|
||||||
|
|
||||||
let(:alice) { Fabricate(:account) }
|
let(:alice) { Fabricate(:account) }
|
||||||
let(:bob) { Fabricate(:account) }
|
let(:bob) { Fabricate(:account) }
|
||||||
@@ -544,8 +544,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -570,7 +570,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the approval URI and verifies the quote' do
|
it 'updates the approval URI and verifies the quote' do
|
||||||
@@ -609,8 +613,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -635,7 +639,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the approval URI and verifies the quote' do
|
it 'updates the approval URI and verifies the quote' do
|
||||||
@@ -818,8 +826,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -844,7 +852,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the approval URI and verifies the quote' do
|
it 'updates the approval URI and verifies the quote' do
|
||||||
@@ -883,8 +895,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -909,7 +921,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the approval URI but does not verify the quote' do
|
it 'updates the approval URI but does not verify the quote' do
|
||||||
@@ -1126,8 +1142,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -1152,7 +1168,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(quoted_status.account),
|
||||||
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the URI and unverifies the quote' do
|
it 'updates the URI and unverifies the quote' do
|
||||||
@@ -1234,8 +1254,8 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
let(:quote_authorization_json) do
|
||||||
stub_request(:get, second_approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
{
|
||||||
'@context': [
|
'@context': [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
{
|
{
|
||||||
@@ -1260,7 +1280,11 @@ RSpec.describe ActivityPub::ProcessStatusUpdateService do
|
|||||||
attributedTo: ActivityPub::TagManager.instance.uri_for(second_quoted_status.account),
|
attributedTo: ActivityPub::TagManager.instance.uri_for(second_quoted_status.account),
|
||||||
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
interactingObject: ActivityPub::TagManager.instance.uri_for(status),
|
||||||
interactionTarget: ActivityPub::TagManager.instance.uri_for(second_quoted_status),
|
interactionTarget: ActivityPub::TagManager.instance.uri_for(second_quoted_status),
|
||||||
}))
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, second_approval_uri).to_return(headers: { 'Content-Type': 'application/activity+json' }, body: quote_authorization_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the URI and unverifies the quote' do
|
it 'updates the URI and unverifies the quote' do
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
|
|
||||||
context 'when the endpoint is a Collection of actor URIs' do
|
context 'when the endpoint is a Collection of actor URIs' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -72,7 +72,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -93,7 +93,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -102,31 +102,31 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
context 'when the endpoint is a paginated Collection of actor URIs split across multiple pages' do
|
context 'when the endpoint is a paginated Collection of actor URIs split across multiple pages' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/partial-followers')
|
stub_request(:get, 'https://example.com/partial-followers')
|
||||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
type: 'Collection',
|
type: 'Collection',
|
||||||
id: 'https://example.com/partial-followers',
|
id: 'https://example.com/partial-followers',
|
||||||
first: 'https://example.com/partial-followers/1',
|
first: 'https://example.com/partial-followers/1',
|
||||||
}))
|
}.to_json)
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/partial-followers/1')
|
stub_request(:get, 'https://example.com/partial-followers/1')
|
||||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
type: 'CollectionPage',
|
type: 'CollectionPage',
|
||||||
id: 'https://example.com/partial-followers/1',
|
id: 'https://example.com/partial-followers/1',
|
||||||
partOf: 'https://example.com/partial-followers',
|
partOf: 'https://example.com/partial-followers',
|
||||||
next: 'https://example.com/partial-followers/2',
|
next: 'https://example.com/partial-followers/2',
|
||||||
items: [alice, eve].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
|
items: [alice, eve].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
|
||||||
}))
|
}.to_json)
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/partial-followers/2')
|
stub_request(:get, 'https://example.com/partial-followers/2')
|
||||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
type: 'CollectionPage',
|
type: 'CollectionPage',
|
||||||
id: 'https://example.com/partial-followers/2',
|
id: 'https://example.com/partial-followers/2',
|
||||||
partOf: 'https://example.com/partial-followers',
|
partOf: 'https://example.com/partial-followers',
|
||||||
items: ActivityPub::TagManager.instance.uri_for(mallory),
|
items: ActivityPub::TagManager.instance.uri_for(mallory),
|
||||||
}))
|
}.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -135,22 +135,22 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
context 'when the endpoint is a paginated Collection of actor URIs split across, but one page errors out' do
|
context 'when the endpoint is a paginated Collection of actor URIs split across, but one page errors out' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/partial-followers')
|
stub_request(:get, 'https://example.com/partial-followers')
|
||||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
type: 'Collection',
|
type: 'Collection',
|
||||||
id: 'https://example.com/partial-followers',
|
id: 'https://example.com/partial-followers',
|
||||||
first: 'https://example.com/partial-followers/1',
|
first: 'https://example.com/partial-followers/1',
|
||||||
}))
|
}.to_json)
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/partial-followers/1')
|
stub_request(:get, 'https://example.com/partial-followers/1')
|
||||||
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: JSON.generate({
|
.to_return(status: 200, headers: { 'Content-Type': 'application/activity+json' }, body: {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
type: 'CollectionPage',
|
type: 'CollectionPage',
|
||||||
id: 'https://example.com/partial-followers/1',
|
id: 'https://example.com/partial-followers/1',
|
||||||
partOf: 'https://example.com/partial-followers',
|
partOf: 'https://example.com/partial-followers',
|
||||||
next: 'https://example.com/partial-followers/2',
|
next: 'https://example.com/partial-followers/2',
|
||||||
items: [mallory].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
|
items: [mallory].map { |account| ActivityPub::TagManager.instance.uri_for(account) },
|
||||||
}))
|
}.to_json)
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/partial-followers/2')
|
stub_request(:get, 'https://example.com/partial-followers/2')
|
||||||
.to_return(status: 404)
|
.to_return(status: 404)
|
||||||
@@ -185,7 +185,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
|
|
||||||
before do
|
before do
|
||||||
stub_const('ActivityPub::SynchronizeFollowersService::MAX_COLLECTION_PAGES', 1)
|
stub_const('ActivityPub::SynchronizeFollowersService::MAX_COLLECTION_PAGES', 1)
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'confirms pending follow request but does not remove extra followers' do
|
it 'confirms pending follow request but does not remove extra followers' do
|
||||||
@@ -213,7 +213,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
|
|
||||||
context 'when the endpoint is a Collection of actor URIs' do
|
context 'when the endpoint is a Collection of actor URIs' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -230,7 +230,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -251,7 +251,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
@@ -263,7 +263,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
|
|
||||||
context 'when the endpoint is a Collection of actor URIs' do
|
context 'when the endpoint is a Collection of actor URIs' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not remove followers' do
|
it 'does not remove followers' do
|
||||||
@@ -286,7 +286,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not remove followers' do
|
it 'does not remove followers' do
|
||||||
@@ -313,7 +313,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: JSON.generate(payload), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, collection_uri).to_return(status: 200, body: payload.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not remove followers' do
|
it 'does not remove followers' do
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
|
|||||||
account: nil,
|
account: nil,
|
||||||
state: :pending,
|
state: :pending,
|
||||||
uri: 'https://other.example.com/items/1',
|
uri: 'https://other.example.com/items/1',
|
||||||
object_uri: 'https://example.com/actor/1',
|
object_uri: 'https://example.com/actor/1')
|
||||||
approval_uri: verification_json['id'])
|
|
||||||
end
|
end
|
||||||
|
let(:approval_uri) { 'https://example.com/auth/1' }
|
||||||
let(:verification_json) do
|
let(:verification_json) do
|
||||||
{
|
{
|
||||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||||
'type' => 'FeatureAuthorization',
|
'type' => 'FeatureAuthorization',
|
||||||
'id' => 'https://example.com/auth/1',
|
'id' => approval_uri,
|
||||||
'interactionTarget' => 'https://example.com/actor/1',
|
'interactionTarget' => 'https://example.com/actor/1',
|
||||||
'interactingObject' => collection.uri,
|
'interactingObject' => collection.uri,
|
||||||
}
|
}
|
||||||
@@ -41,12 +41,13 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
|
|||||||
before { featured_account }
|
before { featured_account }
|
||||||
|
|
||||||
it 'verifies and creates the item' do
|
it 'verifies and creates the item' do
|
||||||
subject.call(collection_item)
|
subject.call(collection_item, approval_uri)
|
||||||
|
|
||||||
expect(verification_request).to have_been_requested
|
expect(verification_request).to have_been_requested
|
||||||
|
|
||||||
expect(collection_item.account_id).to eq featured_account.id
|
expect(collection_item.account_id).to eq featured_account.id
|
||||||
expect(collection_item).to be_accepted
|
expect(collection_item).to be_accepted
|
||||||
|
expect(collection_item.approval_uri).to eq approval_uri
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -59,13 +60,14 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'fetches the actor and creates the item' do
|
it 'fetches the actor and creates the item' do
|
||||||
subject.call(collection_item)
|
subject.call(collection_item, approval_uri)
|
||||||
|
|
||||||
expect(stubbed_service).to have_received(:call)
|
expect(stubbed_service).to have_received(:call)
|
||||||
expect(verification_request).to have_been_requested
|
expect(verification_request).to have_been_requested
|
||||||
|
|
||||||
expect(collection_item.account_id).to eq featured_account.id
|
expect(collection_item.account_id).to eq featured_account.id
|
||||||
expect(collection_item).to be_accepted
|
expect(collection_item).to be_accepted
|
||||||
|
expect(collection_item.approval_uri).to eq approval_uri
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -77,7 +79,7 @@ RSpec.describe ActivityPub::VerifyFeaturedItemService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'creates item without attached account and in proper state' do
|
it 'creates item without attached account and in proper state' do
|
||||||
subject.call(collection_item)
|
subject.call(collection_item, approval_uri)
|
||||||
|
|
||||||
expect(collection_item.account_id).to be_nil
|
expect(collection_item.account_id).to be_nil
|
||||||
expect(collection_item).to be_rejected
|
expect(collection_item).to be_rejected
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ RSpec.describe ActivityPub::VerifyQuoteService do
|
|||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, approval_uri)
|
stub_request(:get, approval_uri)
|
||||||
.to_return(status: 200, body: JSON.generate(json), headers: { 'Content-Type': 'application/activity+json' })
|
.to_return(status: 200, body: json.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a valid activity for already-fetched posts' do
|
context 'with a valid activity for already-fetched posts' do
|
||||||
@@ -179,7 +179,7 @@ RSpec.describe ActivityPub::VerifyQuoteService do
|
|||||||
|
|
||||||
context 'with a valid activity for already-fetched posts, with a pre-fetched approval' do
|
context 'with a valid activity for already-fetched posts, with a pre-fetched approval' do
|
||||||
it 'updates the status without fetching the activity' do
|
it 'updates the status without fetching the activity' do
|
||||||
expect { subject.call(quote, prefetched_approval: JSON.generate(json)) }
|
expect { subject.call(quote, prefetched_approval: json.to_json) }
|
||||||
.to change(quote, :state).to('accepted')
|
.to change(quote, :state).to('accepted')
|
||||||
|
|
||||||
expect(a_request(:get, approval_uri))
|
expect(a_request(:get, approval_uri))
|
||||||
|
|||||||
@@ -19,17 +19,15 @@ RSpec.describe FetchRemoteStatusService do
|
|||||||
context 'when protocol is :activitypub' do
|
context 'when protocol is :activitypub' do
|
||||||
subject { described_class.new.call(note[:id], prefetched_body: prefetched_body) }
|
subject { described_class.new.call(note[:id], prefetched_body: prefetched_body) }
|
||||||
|
|
||||||
let(:prefetched_body) { JSON.generate(note) }
|
let(:prefetched_body) { note.to_json }
|
||||||
|
|
||||||
before do
|
|
||||||
subject
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'creates status' do
|
it 'creates status' do
|
||||||
status = account.statuses.first
|
expect { subject }
|
||||||
|
.to change(Status, :count).by(1)
|
||||||
|
|
||||||
expect(status).to_not be_nil
|
expect(account.statuses.first)
|
||||||
expect(status.text).to eq 'Lorem ipsum'
|
.to be_present
|
||||||
|
.and have_attributes(text: 'Lorem ipsum')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ RSpec.describe ResolveAccountService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'with webfinger response subject missing a host value' do
|
context 'with webfinger response subject missing a host value' do
|
||||||
let(:body) { JSON.generate({ subject: 'user@' }) }
|
let(:body) { { subject: 'user@' }.to_json }
|
||||||
let(:url) { 'https://host.example/.well-known/webfinger?resource=acct:user@host.example' }
|
let(:url) { 'https://host.example/.well-known/webfinger?resource=acct:user@host.example' }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ RSpec.describe SoftwareUpdateCheckService do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, full_update_check_url).to_return(body: JSON.generate(server_json))
|
stub_request(:get, full_update_check_url).to_return(body: server_json.to_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates the list of known updates' do
|
it 'updates the list of known updates' do
|
||||||
|
|||||||
@@ -161,8 +161,8 @@ class StreamingClient
|
|||||||
|
|
||||||
def wait_for_message
|
def wait_for_message
|
||||||
message = @connection.wait_for_event(:message)
|
message = @connection.wait_for_event(:message)
|
||||||
event = Oj.load(message)
|
event = JSON.parse(message)
|
||||||
event['payload'] = Oj.load(event['payload']) if event['payload']
|
event['payload'] = JSON.parse(event['payload']) if event['payload']
|
||||||
|
|
||||||
event.deep_symbolize_keys
|
event.deep_symbolize_keys
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -126,11 +126,11 @@ RSpec.describe ActivityPub::FetchAllRepliesWorker do
|
|||||||
all_items.each do |item|
|
all_items.each do |item|
|
||||||
next if [top_note_uri, reply_note_uri].include? item
|
next if [top_note_uri, reply_note_uri].include? item
|
||||||
|
|
||||||
stub_request(:get, item).to_return(status: 200, body: JSON.generate(empty_object), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, item).to_return(status: 200, body: empty_object.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
stub_request(:get, top_note_uri).to_return(status: 200, body: JSON.generate(top_object), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, top_note_uri).to_return(status: 200, body: top_object.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, reply_note_uri).to_return(status: 200, body: JSON.generate(reply_object), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, reply_note_uri).to_return(status: 200, body: reply_object.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples 'fetches all replies' do
|
shared_examples 'fetches all replies' do
|
||||||
@@ -180,8 +180,8 @@ RSpec.describe ActivityPub::FetchAllRepliesWorker do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, top_collection_uri).to_return(status: 200, body: JSON.generate(replies_top), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, top_collection_uri).to_return(status: 200, body: replies_top.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, reply_collection_uri).to_return(status: 200, body: JSON.generate(replies_nested), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, reply_collection_uri).to_return(status: 200, body: replies_nested.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'fetches all replies'
|
it_behaves_like 'fetches all replies'
|
||||||
@@ -254,8 +254,8 @@ RSpec.describe ActivityPub::FetchAllRepliesWorker do
|
|||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, top_page_2_uri).to_return(status: 200, body: JSON.generate(top_page_two), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, top_page_2_uri).to_return(status: 200, body: top_page_two.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, reply_page_2_uri).to_return(status: 200, body: JSON.generate(reply_page_two), headers: { 'Content-Type': 'application/activity+json' })
|
stub_request(:get, reply_page_2_uri).to_return(status: 200, body: reply_page_two.to_json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'fetches all replies'
|
it_behaves_like 'fetches all replies'
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ RSpec.describe ActivityPub::FetchRepliesWorker do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:json) { JSON.generate(payload) }
|
let(:json) { payload.to_json }
|
||||||
|
|
||||||
describe 'perform' do
|
describe 'perform' do
|
||||||
it 'performs a request if the collection URI is from the same host' do
|
it 'performs a request if the collection URI is from the same host' do
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ RSpec.describe ActivityPub::VerifyFeaturedItemWorker do
|
|||||||
before { stub_service }
|
before { stub_service }
|
||||||
|
|
||||||
it 'sends the status to the service' do
|
it 'sends the status to the service' do
|
||||||
worker.perform(collection_item.id)
|
worker.perform(collection_item.id, 'https://example.com/authorizations/1')
|
||||||
|
|
||||||
expect(service).to have_received(:call).with(collection_item)
|
expect(service).to have_received(:call).with(collection_item, 'https://example.com/authorizations/1')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns nil for non-existent record' do
|
it 'returns nil for non-existent record' do
|
||||||
result = worker.perform(123_123_123)
|
result = worker.perform(123_123_123, 'https://example.com/authorizations/1')
|
||||||
|
|
||||||
expect(result).to be_nil
|
expect(result).to be_nil
|
||||||
end
|
end
|
||||||
|
|||||||
36
yarn.lock
36
yarn.lock
@@ -10715,10 +10715,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"pg-connection-string@npm:^2.11.0, pg-connection-string@npm:^2.6.0":
|
"pg-connection-string@npm:^2.12.0, pg-connection-string@npm:^2.6.0":
|
||||||
version: 2.11.0
|
version: 2.12.0
|
||||||
resolution: "pg-connection-string@npm:2.11.0"
|
resolution: "pg-connection-string@npm:2.12.0"
|
||||||
checksum: 10c0/7a4bcf9b4f1e1fee6482e2bd814f544d451240059be6b8a186f24f73f163f1c599bb8c4984c398254869f744f6c3659b83e285c3d525fc640e99c60c453bd0df
|
checksum: 10c0/3a26c62884a9f0464718f652bd5d6bce276ebda830c0fef4de4f88ae73c2507d70cae1d45c2f5b49bebd76187fb4c94f889d07c53fca6acd06b2eecbebcdc336
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -10729,19 +10729,19 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"pg-pool@npm:^3.12.0":
|
"pg-pool@npm:^3.13.0":
|
||||||
version: 3.12.0
|
version: 3.13.0
|
||||||
resolution: "pg-pool@npm:3.12.0"
|
resolution: "pg-pool@npm:3.13.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
pg: ">=8.0"
|
pg: ">=8.0"
|
||||||
checksum: 10c0/b09da392ae2d0dae7bdf62b8557d3643bb7d84335894bc536f16ddd0da116b44c2f2770c88ff71a80252988ca115ec95a480cc047a75df34fbbbb2432b3a75da
|
checksum: 10c0/2756f79cda14e3834356f2ca035deab806bca2172a38a488b62ada54bd3e65d33f583661bbe96da0c0e75e6bc59807ada733c37efca6e24ae2893429936a1549
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"pg-protocol@npm:*, pg-protocol@npm:^1.12.0":
|
"pg-protocol@npm:*, pg-protocol@npm:^1.13.0":
|
||||||
version: 1.12.0
|
version: 1.13.0
|
||||||
resolution: "pg-protocol@npm:1.12.0"
|
resolution: "pg-protocol@npm:1.13.0"
|
||||||
checksum: 10c0/577f33c756f6503682d9ac17fd813f9edbe4a1716e497f17d36b6edaf9bf8383accaf8cd7422c49e2fbe4eb28ef275bc52fbd8287e154d4510f50b9ccefe4165
|
checksum: 10c0/a4e851e6bb8ff404ca19d561cf49b6b0caf45163bd3f289889edaf6c4e9fb25b08fb57f50d37a8cc86007efcf2cbb3dd2372c97a353a546f45eb49ddebc84fa9
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -10759,13 +10759,13 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"pg@npm:^8.5.0":
|
"pg@npm:^8.5.0":
|
||||||
version: 8.19.0
|
version: 8.20.0
|
||||||
resolution: "pg@npm:8.19.0"
|
resolution: "pg@npm:8.20.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
pg-cloudflare: "npm:^1.3.0"
|
pg-cloudflare: "npm:^1.3.0"
|
||||||
pg-connection-string: "npm:^2.11.0"
|
pg-connection-string: "npm:^2.12.0"
|
||||||
pg-pool: "npm:^3.12.0"
|
pg-pool: "npm:^3.13.0"
|
||||||
pg-protocol: "npm:^1.12.0"
|
pg-protocol: "npm:^1.13.0"
|
||||||
pg-types: "npm:2.2.0"
|
pg-types: "npm:2.2.0"
|
||||||
pgpass: "npm:1.0.5"
|
pgpass: "npm:1.0.5"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -10776,7 +10776,7 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
pg-native:
|
pg-native:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/7713d6ef9f32746370f2bd599ebfa54d22bbdbb3a256a64b76997dd8a7279a5734dde260d6a1da22047171604fba88bd273d570c77b16f08ebe32a47ffbe2aba
|
checksum: 10c0/e21d44b9fb3ec188e67778d7abd32d945a546f2da5128b6c8c16da8ae1e42fdc953c0d6f0a2ee65d11f31808c1dffaf908cb9c880cd2e8f0ae05525e4b8bc832
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user