Merge branch 'upstream' into main
This commit is contained in:
commit
451e6e9025
95
CHANGELOG.md
95
CHANGELOG.md
|
@ -2,6 +2,101 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [4.2.7] - 2024-02-16
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix OmniAuth tests and edge cases in error handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/29201), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/29207))
|
||||||
|
- Fix new installs by upgrading to the latest release of the `nsa` gem, instead of a no longer existing commit ([mjankowski](https://github.com/mastodon/mastodon/pull/29065))
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Fix insufficient checking of remote posts ([GHSA-jhrq-qvrm-qr36](https://github.com/mastodon/mastodon/security/advisories/GHSA-jhrq-qvrm-qr36))
|
||||||
|
|
||||||
|
## [4.2.6] - 2024-02-14
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Update the `sidekiq-unique-jobs` dependency (see [GHSA-cmh9-rx85-xj38](https://github.com/mhenrixon/sidekiq-unique-jobs/security/advisories/GHSA-cmh9-rx85-xj38))
|
||||||
|
In addition, we have disabled the web interface for `sidekiq-unique-jobs` out of caution.
|
||||||
|
If you need it, you can re-enable it by setting `ENABLE_SIDEKIQ_UNIQUE_JOBS_UI=true`.
|
||||||
|
If you only need to clear all locks, you can now use `bundle exec rake sidekiq_unique_jobs:delete_all_locks`.
|
||||||
|
- Update the `nokogiri` dependency (see [GHSA-xc9x-jj77-9p9j](https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j))
|
||||||
|
- Disable administrative Doorkeeper routes ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/29187))
|
||||||
|
- Fix ongoing streaming sessions not being invalidated when applications get deleted in some cases ([GHSA-7w3c-p9j8-mq3x](https://github.com/mastodon/mastodon/security/advisories/GHSA-7w3c-p9j8-mq3x))
|
||||||
|
In some rare cases, the streaming server was not notified of access tokens revocation on application deletion.
|
||||||
|
- Change external authentication behavior to never reattach a new identity to an existing user by default ([GHSA-vm39-j3vx-pch3](https://github.com/mastodon/mastodon/security/advisories/GHSA-vm39-j3vx-pch3))
|
||||||
|
Up until now, Mastodon has allowed new identities from external authentication providers to attach to an existing local user based on their verified e-mail address.
|
||||||
|
This allowed upgrading users from a database-stored password to an external authentication provider, or move from one authentication provider to another.
|
||||||
|
However, this behavior may be unexpected, and means that when multiple authentication providers are configured, the overall security would be that of the least secure authentication provider.
|
||||||
|
For these reasons, this behavior is now locked under the `ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH` environment variable.
|
||||||
|
In addition, regardless of this environment variable, Mastodon will refuse to attach two identities from the same authentication provider to the same account.
|
||||||
|
|
||||||
|
## [4.2.5] - 2024-02-01
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Fix insufficient origin validation (CVE-2024-23832, [GHSA-3fjr-858r-92rw](https://github.com/mastodon/mastodon/security/advisories/GHSA-3fjr-858r-92rw))
|
||||||
|
|
||||||
|
## [4.2.4] - 2024-01-24
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix error when processing remote files with unusually long names ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28823))
|
||||||
|
- Fix processing of compacted single-item JSON-LD collections ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28816))
|
||||||
|
- Retry 401 errors on replies fetching ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/28788))
|
||||||
|
- Fix `RecordNotUnique` errors in LinkCrawlWorker ([tribela](https://github.com/mastodon/mastodon/pull/28748))
|
||||||
|
- Fix Mastodon not correctly processing HTTP Signatures with query strings ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28443), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28476))
|
||||||
|
- Fix potential redirection loop of streaming endpoint ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28665))
|
||||||
|
- Fix streaming API redirection ignoring the port of `streaming_api_base_url` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28558))
|
||||||
|
- Fix error when processing link preview with an array as `inLanguage` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28252))
|
||||||
|
- Fix unsupported time zone or locale preventing sign-up ([Gargron](https://github.com/mastodon/mastodon/pull/28035))
|
||||||
|
- Fix "Hide these posts from home" list setting not refreshing when switching lists ([brianholley](https://github.com/mastodon/mastodon/pull/27763))
|
||||||
|
- Fix missing background behind dismissable banner in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/27479))
|
||||||
|
- Fix line wrapping of language selection button with long locale codes ([gunchleoc](https://github.com/mastodon/mastodon/pull/27100), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27127))
|
||||||
|
- Fix `Undo Announce` activity not being sent to non-follower authors ([MitarashiDango](https://github.com/mastodon/mastodon/pull/18482))
|
||||||
|
- Fix N+1s because of association preloaders not actually getting called ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28339))
|
||||||
|
- Fix empty column explainer getting cropped under certain conditions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28337))
|
||||||
|
- Fix `LinkCrawlWorker` error when encountering empty OEmbed response ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28268))
|
||||||
|
- Fix call to inefficient `delete_matched` cache method in domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28367))
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Add rate-limit of TOTP authentication attempts at controller level ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28801))
|
||||||
|
|
||||||
|
## [4.2.3] - 2023-12-05
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix dependency on `json-canonicalization` version that has been made unavailable since last release
|
||||||
|
|
||||||
|
## [4.2.2] - 2023-12-04
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Change dismissed banners to be stored server-side ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27055))
|
||||||
|
- Change GIF max matrix size error to explicitly mention GIF files ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27927))
|
||||||
|
- Change `Follow` activities delivery to bypass availability check ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/27586))
|
||||||
|
- Change single-column navigation notice to be displayed outside of the logo container ([renchap](https://github.com/mastodon/mastodon/pull/27462), [renchap](https://github.com/mastodon/mastodon/pull/27476))
|
||||||
|
- Change Content-Security-Policy to be tighter on media paths ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26889))
|
||||||
|
- Change post language code to include country code when relevant ([gunchleoc](https://github.com/mastodon/mastodon/pull/27099), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27207))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix upper border radius of onboarding columns ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27890))
|
||||||
|
- Fix incoming status creation date not being restricted to standard ISO8601 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27655), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28081))
|
||||||
|
- Fix some posts from threads received out-of-order sometimes not being inserted into timelines ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27653))
|
||||||
|
- Fix posts from force-sensitized accounts being able to trend ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27620))
|
||||||
|
- Fix error when trying to delete already-deleted file with OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27569))
|
||||||
|
- Fix batch attachment deletion when using OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27554))
|
||||||
|
- Fix processing LDSigned activities from actors with unknown public keys ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27474))
|
||||||
|
- Fix error and incorrect URLs in `/api/v1/accounts/:id/featured_tags` for remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27459))
|
||||||
|
- Fix report processing notice not mentioning the report number when performing a custom action ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27442))
|
||||||
|
- Fix handling of `inLanguage` attribute in preview card processing ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27423))
|
||||||
|
- Fix own posts being removed from home timeline when unfollowing a used hashtag ([kmycode](https://github.com/mastodon/mastodon/pull/27391))
|
||||||
|
- Fix some link anchors being recognized as hashtags ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27271), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27584))
|
||||||
|
- Fix format-dependent redirects being cached regardless of requested format ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27634))
|
||||||
|
|
||||||
## [4.2.1] - 2023-10-10
|
## [4.2.1] - 2023-10-10
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -505,7 +505,7 @@ GEM
|
||||||
parslet (2.0.0)
|
parslet (2.0.0)
|
||||||
pastel (0.8.0)
|
pastel (0.8.0)
|
||||||
tty-color (~> 0.5)
|
tty-color (~> 0.5)
|
||||||
pg (1.5.4)
|
pg (1.5.5)
|
||||||
pghero (3.4.1)
|
pghero (3.4.1)
|
||||||
activerecord (>= 6)
|
activerecord (>= 6)
|
||||||
posix-spawn (0.3.15)
|
posix-spawn (0.3.15)
|
||||||
|
|
|
@ -174,7 +174,19 @@ module JsonLdHelper
|
||||||
build_request(uri, on_behalf_of, options: request_options).perform do |response|
|
build_request(uri, on_behalf_of, options: request_options).perform do |response|
|
||||||
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error
|
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error
|
||||||
|
|
||||||
body_to_json(response.body_with_limit) if response.code == 200
|
body_to_json(response.body_with_limit) if response.code == 200 && valid_activitypub_content_type?(response)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_activitypub_content_type?(response)
|
||||||
|
return true if response.mime_type == 'application/activity+json'
|
||||||
|
|
||||||
|
# When the mime type is `application/ld+json`, we need to check the profile,
|
||||||
|
# but `http.rb` does not parse it for us.
|
||||||
|
return false unless response.mime_type == 'application/ld+json'
|
||||||
|
|
||||||
|
response.headers[HTTP::Headers::CONTENT_TYPE]&.split(';')&.map(&:strip)&.any? do |str|
|
||||||
|
str.start_with?('profile="') && str[9...-1].split.include?('https://www.w3.org/ns/activitystreams')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
|
|
||||||
|
|
||||||
export default class FollowRequestNote extends ImmutablePureComponent {
|
export default class FollowRequestNote extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { withRouter } from 'react-router-dom';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
|
|
||||||
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||||
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
||||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||||
|
@ -372,28 +371,29 @@ class Header extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{signedIn && <AccountNoteContainer account={account} />}
|
|
||||||
|
|
||||||
{!(suspended || hidden) && (
|
{!(suspended || hidden) && (
|
||||||
<div className='account__header__extra'>
|
<div className='account__header__extra'>
|
||||||
<div className='account__header__bio'>
|
<div className='account__header__bio'>
|
||||||
{ fields.size > 0 && (
|
{(account.get('id') !== me && signedIn) && <AccountNoteContainer account={account} />}
|
||||||
<div className='account__header__fields'>
|
|
||||||
{fields.map((pair, i) => (
|
|
||||||
<dl key={i}>
|
|
||||||
<dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} />
|
|
||||||
|
|
||||||
<dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}>
|
{account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />}
|
||||||
{pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' icon={CheckIcon} className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} className='translate' />
|
|
||||||
|
<div className='account__header__fields'>
|
||||||
|
<dl>
|
||||||
|
<dt><FormattedMessage id='account.joined_short' defaultMessage='Joined' /></dt>
|
||||||
|
<dd>{intl.formatDate(account.get('created_at'), { year: 'numeric', month: 'short', day: '2-digit' })}</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
{fields.map((pair, i) => (
|
||||||
|
<dl key={i} className={classNames({ verified: pair.get('verified_at') })}>
|
||||||
|
<dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} className='translate' />
|
||||||
|
|
||||||
|
<dd className='translate' title={pair.get('value_plain')}>
|
||||||
|
{pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><Icon id='check' icon={CheckIcon} className='verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />}
|
|
||||||
|
|
||||||
<div className='account__header__joined'><FormattedMessage id='account.joined' defaultMessage='Joined {date}' values={{ date: intl.formatDate(account.get('created_at'), { year: 'numeric', month: 'short', day: '2-digit' }) }} /></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
|
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
|
||||||
"account.follows": "Follows",
|
"account.follows": "Follows",
|
||||||
"account.follows_you": "Follows you",
|
"account.follows_you": "Follows you",
|
||||||
"account.joined": "Joined {date}",
|
|
||||||
"account.suspended_disclaimer_full": "This user has been suspended by a moderator.",
|
"account.suspended_disclaimer_full": "This user has been suspended by a moderator.",
|
||||||
"account.view_full_profile": "View full profile",
|
"account.view_full_profile": "View full profile",
|
||||||
"advanced_options.icon_title": "Advanced options",
|
"advanced_options.icon_title": "Advanced options",
|
||||||
|
|
|
@ -5317,7 +5317,7 @@ a.status-card.compact:hover {
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
padding: 10px 0;
|
padding: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.language-dropdown {
|
.language-dropdown {
|
||||||
|
@ -7986,6 +7986,7 @@ noscript {
|
||||||
height: 145px;
|
height: 145px;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: darken($ui-base-color, 4%);
|
background: darken($ui-base-color, 4%);
|
||||||
|
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||||
|
|
||||||
img {
|
img {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
@ -7998,9 +7999,9 @@ noscript {
|
||||||
|
|
||||||
&__bar {
|
&__bar {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: lighten($ui-base-color, 4%);
|
padding: 0 20px;
|
||||||
padding: 5px;
|
padding-bottom: 16px; // glitch-soc addition for the different tabs design
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 12%);
|
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -8009,7 +8010,7 @@ noscript {
|
||||||
|
|
||||||
.account__avatar {
|
.account__avatar {
|
||||||
background: darken($ui-base-color, 8%);
|
background: darken($ui-base-color, 8%);
|
||||||
border: 2px solid lighten($ui-base-color, 4%);
|
border: 2px solid $ui-base-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8028,8 +8029,8 @@ noscript {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 7px 10px;
|
|
||||||
margin-top: -55px;
|
margin-top: -55px;
|
||||||
|
padding-top: 10px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-inline-start: -2px; // aligns the pfp with content below
|
margin-inline-start: -2px; // aligns the pfp with content below
|
||||||
|
@ -8064,7 +8065,8 @@ noscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
&__name {
|
&__name {
|
||||||
padding: 5px 10px;
|
margin-top: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
.emojione {
|
.emojione {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
|
@ -8072,17 +8074,17 @@ noscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 16px;
|
font-size: 17px;
|
||||||
line-height: 24px;
|
line-height: 22px;
|
||||||
color: $primary-text-color;
|
color: $primary-text-color;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
small {
|
small {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 14px;
|
font-size: 15px;
|
||||||
color: $darker-text-color;
|
color: $darker-text-color;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -8108,63 +8110,97 @@ noscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
&__bio {
|
&__bio {
|
||||||
overflow: hidden;
|
|
||||||
margin: 0 -5px;
|
|
||||||
|
|
||||||
.account__header__content {
|
.account__header__content {
|
||||||
padding: 20px 15px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
color: $primary-text-color;
|
color: $primary-text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.account__header__joined {
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 5px 15px;
|
|
||||||
color: $darker-text-color;
|
|
||||||
|
|
||||||
.columns-area--mobile & {
|
|
||||||
padding-inline-start: 20px;
|
|
||||||
padding-inline-end: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.account__header__fields {
|
.account__header__fields {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
margin-top: 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: darken($ui-base-color, 4%);
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
dl {
|
||||||
|
display: block;
|
||||||
|
padding: 8px 16px; // glitch-soc: padding purposefuly reduced
|
||||||
|
border-bottom-color: lighten($ui-base-color, 4%);
|
||||||
|
}
|
||||||
|
|
||||||
|
dd,
|
||||||
|
dt {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 0;
|
||||||
|
text-align: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
width: auto;
|
||||||
|
background: transparent;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: $dark-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
color: $darker-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: lighten($ui-highlight-color, 8%);
|
color: lighten($ui-highlight-color, 8%);
|
||||||
}
|
}
|
||||||
|
|
||||||
dl:first-child .verified {
|
|
||||||
border-radius: 0 4px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
vertical-align: middle;
|
}
|
||||||
|
|
||||||
|
.verified {
|
||||||
|
border: 1px solid rgba($valid-value-color, 0.5);
|
||||||
|
margin-top: -1px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt,
|
||||||
|
dd {
|
||||||
|
color: $valid-value-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
dd {
|
dd {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.verified a {
|
a {
|
||||||
color: $valid-value-color;
|
color: $valid-value-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__extra {
|
&__extra {
|
||||||
margin-top: 4px;
|
margin-top: 16px;
|
||||||
|
|
||||||
&__links {
|
&__links {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: $darker-text-color;
|
color: $darker-text-color;
|
||||||
padding: 10px 0;
|
margin: 0 -10px;
|
||||||
|
padding-top: 16px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -8182,14 +8218,10 @@ noscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
&__account-note {
|
&__account-note {
|
||||||
margin: 0 -5px;
|
color: $primary-text-color;
|
||||||
padding: 10px 15px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
border-top: 1px solid lighten($ui-base-color, 12%);
|
margin-bottom: 10px;
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 12%);
|
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -8200,23 +8232,12 @@ noscript {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
display: block;
|
display: block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: calc(100% + 20px);
|
width: calc(100% + 20px);
|
||||||
color: $secondary-text-color;
|
color: $secondary-text-color;
|
||||||
background: $ui-base-color;
|
background: transparent;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin: 0 -10px;
|
margin: 0 -10px;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
|
@ -8230,6 +8251,10 @@ noscript {
|
||||||
color: $dark-text-color;
|
color: $dark-text-color;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background: $ui-base-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ class FetchResourceService < BaseService
|
||||||
@response_code = response.code
|
@response_code = response.code
|
||||||
return nil if response.code != 200
|
return nil if response.code != 200
|
||||||
|
|
||||||
if ['application/activity+json', 'application/ld+json'].include?(response.mime_type)
|
if valid_activitypub_content_type?(response)
|
||||||
body = response.body_with_limit
|
body = response.body_with_limit
|
||||||
json = body_to_json(body)
|
json = body_to_json(body)
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ services:
|
||||||
|
|
||||||
web:
|
web:
|
||||||
build: .
|
build: .
|
||||||
image: ghcr.io/mastodon/mastodon:v4.2.0
|
image: ghcr.io/mastodon/mastodon:v4.2.7
|
||||||
restart: always
|
restart: always
|
||||||
env_file: .env.production
|
env_file: .env.production
|
||||||
command: bundle exec puma -C config/puma.rb
|
command: bundle exec puma -C config/puma.rb
|
||||||
|
@ -77,7 +77,7 @@ services:
|
||||||
|
|
||||||
streaming:
|
streaming:
|
||||||
build: .
|
build: .
|
||||||
image: ghcr.io/mastodon/mastodon:v4.2.0
|
image: ghcr.io/mastodon/mastodon:v4.2.7
|
||||||
restart: always
|
restart: always
|
||||||
env_file: .env.production
|
env_file: .env.production
|
||||||
command: node ./streaming
|
command: node ./streaming
|
||||||
|
@ -95,7 +95,7 @@ services:
|
||||||
|
|
||||||
sidekiq:
|
sidekiq:
|
||||||
build: .
|
build: .
|
||||||
image: ghcr.io/mastodon/mastodon:v4.2.0
|
image: ghcr.io/mastodon/mastodon:v4.2.7
|
||||||
restart: always
|
restart: always
|
||||||
env_file: .env.production
|
env_file: .env.production
|
||||||
command: bundle exec sidekiq
|
command: bundle exec sidekiq
|
||||||
|
|
|
@ -17,7 +17,7 @@ module Mastodon
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_prerelease
|
def default_prerelease
|
||||||
'alpha.2'
|
'alpha.3'
|
||||||
end
|
end
|
||||||
|
|
||||||
def prerelease
|
def prerelease
|
||||||
|
|
|
@ -56,15 +56,15 @@ describe JsonLdHelper do
|
||||||
describe '#fetch_resource' do
|
describe '#fetch_resource' do
|
||||||
context 'when the second argument is false' do
|
context 'when the second argument is false' do
|
||||||
it 'returns resource even if the retrieved ID and the given URI does not match' do
|
it 'returns resource even if the retrieved ID and the given URI does not match' do
|
||||||
stub_request(:get, 'https://bob.test/').to_return body: '{"id": "https://alice.test/"}'
|
stub_request(:get, 'https://bob.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://alice.test/').to_return body: '{"id": "https://alice.test/"}'
|
stub_request(:get, 'https://alice.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
|
|
||||||
expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' })
|
expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do
|
it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do
|
||||||
stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://marvin.test/"}'
|
stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://marvin.test/"}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://marvin.test/').to_return body: '{"id": "https://alice.test/"}'
|
stub_request(:get, 'https://marvin.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
|
|
||||||
expect(fetch_resource('https://mallory.test/', false)).to be_nil
|
expect(fetch_resource('https://mallory.test/', false)).to be_nil
|
||||||
end
|
end
|
||||||
|
@ -72,7 +72,7 @@ describe JsonLdHelper do
|
||||||
|
|
||||||
context 'when the second argument is true' do
|
context 'when the second argument is true' do
|
||||||
it 'returns nil if the retrieved ID and the given URI does not match' do
|
it 'returns nil if the retrieved ID and the given URI does not match' do
|
||||||
stub_request(:get, 'https://mallory.test/').to_return body: '{"id": "https://alice.test/"}'
|
stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
expect(fetch_resource('https://mallory.test/', true)).to be_nil
|
expect(fetch_resource('https://mallory.test/', true)).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -80,12 +80,12 @@ describe JsonLdHelper do
|
||||||
|
|
||||||
describe '#fetch_resource_without_id_validation' do
|
describe '#fetch_resource_without_id_validation' do
|
||||||
it 'returns nil if the status code is not 200' do
|
it 'returns nil if the status code is not 200' do
|
||||||
stub_request(:get, 'https://host.test/').to_return status: 400, body: '{}'
|
stub_request(:get, 'https://host.test/').to_return(status: 400, body: '{}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil
|
expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns hash' do
|
it 'returns hash' do
|
||||||
stub_request(:get, 'https://host.test/').to_return status: 200, body: '{}'
|
stub_request(:get, 'https://host.test/').to_return(status: 200, body: '{}', headers: { 'Content-Type': 'application/activity+json' })
|
||||||
expect(fetch_resource_without_id_validation('https://host.test/')).to eq({})
|
expect(fetch_resource_without_id_validation('https://host.test/')).to eq({})
|
||||||
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: Oj.dump(unknown_object_json))
|
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_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: Oj.dump(unknown_object_json))
|
stub_request(:get, 'https://example.com/actor/hello-world').to_return(body: Oj.dump(unknown_object_json), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the relay is enabled' do
|
context 'when the relay is enabled' do
|
||||||
|
|
|
@ -72,11 +72,11 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service 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: Oj.dump(status_json_pinned_known))
|
stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined))
|
stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined), 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: Oj.dump(status_json_pinned_unknown_reachable))
|
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null))
|
stub_request(:get, 'https://example.com/account/collections/featured').to_return(status: 200, body: Oj.dump(featured_with_null), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
|
|
||||||
subject.call(actor, note: true, hashtag: false)
|
subject.call(actor, note: true, hashtag: false)
|
||||||
end
|
end
|
||||||
|
@ -94,7 +94,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service 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, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
|
@ -111,7 +111,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
|
@ -120,7 +120,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service 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: Oj.dump(status_json_pinned_unknown_reachable))
|
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
subject.call(actor, note: true, hashtag: false)
|
subject.call(actor, note: true, hashtag: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, actor.featured_collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets pinned posts'
|
it_behaves_like 'sets pinned posts'
|
||||||
|
@ -156,7 +156,7 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service 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: Oj.dump(status_json_pinned_unknown_reachable))
|
stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_reachable), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
subject.call(actor, note: true, hashtag: false)
|
subject.call(actor, note: true, hashtag: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ RSpec.describe ActivityPub::FetchFeaturedTagsCollectionService, type: :service d
|
||||||
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: Oj.dump(payload))
|
stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), 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, type: :service d
|
||||||
|
|
||||||
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: Oj.dump(payload))
|
stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), 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, type: :service d
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), 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, type: :service d
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, collection_url).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'sets featured tags'
|
it_behaves_like 'sets featured tags'
|
||||||
|
|
|
@ -44,7 +44,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
|
||||||
before do
|
before do
|
||||||
actor[:inbox] = nil
|
actor[:inbox] = nil
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
@ -125,7 +125,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ RSpec.describe ActivityPub::FetchRemoteAccountService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,7 +44,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do
|
||||||
before do
|
before do
|
||||||
actor[:inbox] = nil
|
actor[:inbox] = nil
|
||||||
|
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/alice' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
@ -125,7 +125,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@example.com', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ RSpec.describe ActivityPub::FetchRemoteActorService, type: :service do
|
||||||
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
let!(:webfinger) { { subject: 'acct:alice@iscool.af', links: [{ rel: 'self', href: 'https://example.com/bob' }] } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://iscool.af/.well-known/webfinger?resource=acct:alice@iscool.af').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
|
@ -50,7 +50,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service do
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor))
|
stub_request(:get, 'https://example.com/alice').to_return(body: Oj.dump(actor), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
stub_request(:get, 'https://example.com/.well-known/webfinger?resource=acct:alice@example.com').to_return(body: Oj.dump(webfinger), headers: { 'Content-Type': 'application/jrd+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ RSpec.describe ActivityPub::FetchRemoteKeyService, type: :service 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: Oj.dump(actor))
|
stub_request(:get, public_key_id).to_return(body: Oj.dump(actor), 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, type: :service 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: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })))
|
stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), 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, type: :service 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: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })))
|
stub_request(:get, public_key_id).to_return(body: Oj.dump(key_json.merge({ '@context': ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] })), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the nil' do
|
it 'returns the nil' do
|
||||||
|
|
|
@ -58,7 +58,7 @@ RSpec.describe ActivityPub::FetchRepliesService, type: :service 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: Oj.dump(payload))
|
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), 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, type: :service 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: Oj.dump(payload))
|
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), 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, type: :service 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: Oj.dump(payload))
|
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), 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
|
||||||
|
|
|
@ -60,7 +60,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do
|
||||||
describe '#call' do
|
describe '#call' 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: Oj.dump(payload))
|
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
|
@ -77,7 +77,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
|
@ -98,7 +98,7 @@ RSpec.describe ActivityPub::SynchronizeFollowersService, type: :service do
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload))
|
stub_request(:get, collection_uri).to_return(status: 200, body: Oj.dump(payload), headers: { 'Content-Type': 'application/activity+json' })
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like 'synchronizes followers'
|
it_behaves_like 'synchronizes followers'
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe ActivityPub::FetchRepliesWorker do
|
||||||
|
|
||||||
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
|
||||||
stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json)
|
stub_request(:get, 'https://example.com/statuses_replies/1').to_return(status: 200, body: json, headers: { 'Content-Type': 'application/activity+json' })
|
||||||
subject.perform(status.id, 'https://example.com/statuses_replies/1')
|
subject.perform(status.id, 'https://example.com/statuses_replies/1')
|
||||||
expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once
|
expect(a_request(:get, 'https://example.com/statuses_replies/1')).to have_been_made.once
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue