Merge remote-tracking branch 'parent/main' into upstream-20231116

This commit is contained in:
KMY 2023-11-15 13:01:29 +09:00
commit 24371d6b2a
87 changed files with 566 additions and 347 deletions

View file

@ -94,7 +94,7 @@ jobs:
DB_HOST: localhost
DB_USER: postgres
DB_PASS: postgres
DISABLE_SIMPLECOV: true
DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }}
RAILS_ENV: test
ALLOW_NOPAM: true
PAM_ENABLED: true
@ -138,6 +138,12 @@ jobs:
- run: bin/rspec
- name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version'
uses: codecov/codecov-action@v3
with:
files: coverage/lcov/mastodon.lcov
test-e2e:
name: End to End testing
runs-on: ubuntu-latest

View file

@ -41,23 +41,6 @@ Metrics/CyclomaticComplexity:
Metrics/PerceivedComplexity:
Max: 27
RSpec/AnyInstance:
Exclude:
- 'spec/controllers/activitypub/inboxes_controller_spec.rb'
- 'spec/controllers/admin/accounts_controller_spec.rb'
- 'spec/controllers/admin/resets_controller_spec.rb'
- 'spec/controllers/auth/sessions_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb'
- 'spec/lib/request_spec.rb'
- 'spec/lib/status_filter_spec.rb'
- 'spec/models/account_spec.rb'
- 'spec/models/setting_spec.rb'
- 'spec/services/activitypub/process_collection_service_spec.rb'
- 'spec/validators/follow_limit_validator_spec.rb'
- 'spec/workers/activitypub/delivery_worker_spec.rb'
- 'spec/workers/web/push_notification_worker_spec.rb'
# Configuration parameters: CountAsOne.
RSpec/ExampleLength:
Max: 22

View file

@ -139,6 +139,7 @@ group :test do
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
gem 'simplecov', '~> 0.22', require: false
gem 'simplecov-lcov', '~> 0.8', require: false
# Stub web requests for specs
gem 'webmock', '~> 3.18'

View file

@ -727,6 +727,7 @@ GEM
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov-lcov (0.8.0)
simplecov_json_formatter (0.1.4)
smart_properties (1.17.0)
sprockets (3.7.2)
@ -939,6 +940,7 @@ DEPENDENCIES
simple-navigation (~> 4.4)
simple_form (~> 5.2)
simplecov (~> 0.22)
simplecov-lcov (~> 0.8)
sprockets (~> 3.7.2)
sprockets-rails (~> 3.4)
stackprof

View file

@ -1,4 +1,4 @@
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
stream: env PORT=4000 yarn run start
stream: env PORT=4000 yarn workspace @mastodon/streaming start
webpack: bin/webpack-dev-server

View file

@ -7,6 +7,7 @@ class Api::BaseController < ApplicationController
include RateLimitHeaders
include AccessTokenTrackingConcern
include ApiCachingConcern
include Api::ContentSecurityPolicy
skip_before_action :require_functional!, unless: :limited_federation_mode?
@ -17,26 +18,6 @@ class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session
content_security_policy do |p|
# Set every directive that does not have a fallback
p.default_src :none
p.frame_ancestors :none
p.form_action :none
# Disable every directive with a fallback to cut on response size
p.base_uri false
p.font_src false
p.img_src false
p.style_src false
p.media_src false
p.frame_src false
p.manifest_src false
p.connect_src false
p.script_src false
p.child_src false
p.worker_src false
end
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422
end

View file

@ -13,7 +13,7 @@ class Api::V1::Instances::DomainBlocksController < Api::V1::Instances::BaseContr
cache_if_unauthenticated!
end
render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?))
render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: show_rationale_in_response?
end
private
@ -26,4 +26,16 @@ class Api::V1::Instances::DomainBlocksController < Api::V1::Instances::BaseContr
@domain_blocks = DomainBlock.with_user_facing_limitations.by_severity
@domain_blocks = @domain_blocks.filter { |block| !block.hidden_anonymous } unless user_signed_in?
end
def show_rationale_in_response?
always_show_rationale? || show_rationale_for_user?
end
def always_show_rationale?
Setting.show_domain_blocks_rationale == 'all'
end
def show_rationale_for_user?
Setting.show_domain_blocks_rationale == 'users' && user_signed_in?
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
class Api::V1::Timelines::BaseController < Api::BaseController
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
private
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
def next_path_params
permitted_params.merge(max_id: pagination_max_id)
end
def prev_path_params
permitted_params.merge(min_id: pagination_since_id)
end
def permitted_params
params
.slice(*self.class::PERMITTED_PARAMS)
.permit(*self.class::PERMITTED_PARAMS)
end
end

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true
class Api::V1::Timelines::HomeController < Api::BaseController
class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show]
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(local limit).freeze
def show
with_read_replica do
@ -42,27 +43,11 @@ class Api::V1::Timelines::HomeController < Api::BaseController
HomeFeed.new(current_account)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:local, :limit).permit(:local, :limit).merge(core_params)
end
def next_path
api_v1_timelines_home_url pagination_params(max_id: pagination_max_id)
api_v1_timelines_home_url next_path_params
end
def prev_path
api_v1_timelines_home_url pagination_params(min_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
api_v1_timelines_home_url prev_path_params
end
end

View file

@ -1,12 +1,12 @@
# frozen_string_literal: true
class Api::V1::Timelines::ListController < Api::BaseController
class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:lists' }
before_action :require_user!
before_action :set_list
before_action :set_statuses
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(limit).freeze
def show
render json: @statuses,
@ -41,27 +41,11 @@ class Api::V1::Timelines::ListController < Api::BaseController
ListFeed.new(@list)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path
api_v1_timelines_list_url params[:id], pagination_params(max_id: pagination_max_id)
api_v1_timelines_list_url params[:id], next_path_params
end
def prev_path
api_v1_timelines_list_url params[:id], pagination_params(min_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
api_v1_timelines_list_url params[:id], prev_path_params
end
end

View file

@ -1,8 +1,9 @@
# frozen_string_literal: true
class Api::V1::Timelines::PublicController < Api::BaseController
class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
before_action :require_user!, only: [:show], if: :require_auth?
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(local remote limit only_media).freeze
def show
cache_if_unauthenticated!
@ -44,27 +45,11 @@ class Api::V1::Timelines::PublicController < Api::BaseController
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:local, :remote, :limit, :only_media).permit(:local, :remote, :limit, :only_media).merge(core_params)
end
def next_path
api_v1_timelines_public_url pagination_params(max_id: pagination_max_id)
api_v1_timelines_public_url next_path_params
end
def prev_path
api_v1_timelines_public_url pagination_params(min_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
api_v1_timelines_public_url prev_path_params
end
end

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true
class Api::V1::Timelines::TagController < Api::BaseController
class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth?
before_action :load_tag
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(local limit only_media).freeze
def show
cache_if_unauthenticated!
@ -53,27 +54,11 @@ class Api::V1::Timelines::TagController < Api::BaseController
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:local, :limit, :only_media).permit(:local, :limit, :only_media).merge(core_params)
end
def next_path
api_v1_timelines_tag_url params[:id], pagination_params(max_id: pagination_max_id)
api_v1_timelines_tag_url params[:id], next_path_params
end
def prev_path
api_v1_timelines_tag_url params[:id], pagination_params(min_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
api_v1_timelines_tag_url params[:id], prev_path_params
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
module Api::ContentSecurityPolicy
extend ActiveSupport::Concern
included do
content_security_policy do |policy|
# Set every directive that does not have a fallback
policy.default_src :none
policy.frame_ancestors :none
policy.form_action :none
# Disable every directive with a fallback to cut on response size
policy.base_uri false
policy.font_src false
policy.img_src false
policy.style_src false
policy.media_src false
policy.frame_src false
policy.manifest_src false
policy.connect_src false
policy.script_src false
policy.child_src false
policy.worker_src false
end
end
end

View file

@ -219,7 +219,7 @@ class ListTimeline extends PureComponent {
</div>
<div className='setting-toggle'>
<Toggle id={`list-${id}-exclusive`} defaultChecked={isExclusive} onChange={this.onExclusiveToggle} />
<Toggle id={`list-${id}-exclusive`} checked={isExclusive} onChange={this.onExclusiveToggle} />
<label htmlFor={`list-${id}-exclusive`} className='setting-toggle__label'>
<FormattedMessage id='lists.exclusive' defaultMessage='Hide these posts from home or STL' />
</label>

View file

@ -14,6 +14,7 @@
"account.badges.group": "Groep",
"account.block": "Blokkeer @{name}",
"account.block_domain": "Blokkeer domein {domain}",
"account.block_short": "Blokkeer",
"account.blocked": "Geblokkeer",
"account.browse_more_on_origin_server": "Verken die oorspronklike profiel",
"account.cancel_follow_request": "Herroep volgversoek",
@ -45,6 +46,7 @@
"account.posts_with_replies": "Plasings en antwoorde",
"account.report": "Rapporteer @{name}",
"account.requested": "Wag op goedkeuring. Klik om volgversoek te kanselleer",
"account.requested_follow": "{name} het versoek om jou te volg",
"account.share": "Deel @{name} se profiel",
"account.show_reblogs": "Wys aangestuurde plasings van @{name}",
"account.statuses_counter": "{count, plural, one {{counter} Plaas} other {{counter} Plasings}}",
@ -82,6 +84,7 @@
"column.community": "Plaaslike tydlyn",
"column.directory": "Blaai deur profiele",
"column.domain_blocks": "Geblokkeerde domeine",
"column.favourites": "Gunstelinge",
"column.follow_requests": "Volgversoeke",
"column.home": "Tuis",
"column.lists": "Lyste",
@ -271,6 +274,7 @@
"privacy.unlisted.short": "Ongelys",
"privacy_policy.last_updated": "Laaste bywerking op {date}",
"privacy_policy.title": "Privaatheidsbeleid",
"regeneration_indicator.sublabel": "Jou tuis-voer word voorberei!",
"reply_indicator.cancel": "Kanselleer",
"report.placeholder": "Type or paste additional comments",
"report.submit": "Submit report",

View file

@ -201,7 +201,7 @@
"disabled_account_banner.text": "Ваш уліковы запіс {disabledAccount} часова адключаны.",
"dismissable_banner.community_timeline": "Гэта самыя апошнія допісы ад людзей, уліковыя запісы якіх размяшчаюцца на {domain}.",
"dismissable_banner.dismiss": "Адхіліць",
"dismissable_banner.explore_links": "Гэтыя навіны абмяркоўваюцца прама зараз на гэтым і іншых серверах дэцэнтралізаванай сеткі.",
"dismissable_banner.explore_links": "Гэтыя навіны абмяркоўваюцца цяпер на гэтым і іншых серверах дэцэнтралізаванай сеткі.",
"dismissable_banner.explore_statuses": "Допісы з гэтага і іншых сервераў дэцэнтралізаванай сеткі, якія набіраюць папулярнасць прама зараз.",
"dismissable_banner.explore_tags": "Гэтыя хэштэгі зараз набіраюць папулярнасць сярод людзей на гэтым і іншых серверах дэцэнтралізаванай сеткі",
"dismissable_banner.public_timeline": "Гэта апошнія публічныя допісы людзей з усей сеткі, за якімі сочаць карыстальнікі {domain}.",
@ -482,7 +482,7 @@
"onboarding.share.lead": "Дайце людзям ведаць, як яны могуць знайсці вас на Mastodon!",
"onboarding.share.message": "Я {username} на #Mastodon! Сачыце за мной на {url}",
"onboarding.share.next_steps": "Магчымыя наступныя крокі:",
"onboarding.share.title": "Падзяліцеся сваім профілем",
"onboarding.share.title": "Абагульце свой профіль",
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
"onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Вы зрабілі гэта!",
@ -493,7 +493,7 @@
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
"onboarding.steps.share_profile.title": "Share your profile",
"onboarding.steps.share_profile.title": "Абагульць ваш профіль у Mastodon",
"onboarding.tips.2fa": "<strong>Ці вы ведаеце?</strong> Вы можаце абараніць свой уліковы запіс, усталяваўшы двухфактарную аўтэнтыфікацыю ў наладах уліковага запісу. Яна працуе з любой праграмай TOTP на ваш выбар, нумар тэлефона не патрэбны!",
"onboarding.tips.accounts_from_other_servers": "<strong>Ці вы ведаеце?</strong> Паколькі Mastodon дэцэнтралізаваны, некаторыя профілі, якія вам трапляюцца, будуць размяшчацца на іншых серверах, адрозных ад вашага. І ўсё ж вы можаце бесперашкодна ўзаемадзейнічаць з імі! Іх сервер пазначаны ў другой палове імя карыстальніка!",
"onboarding.tips.migration": "<strong>Ці вы ведаеце?</strong> Калі вы адчуваеце, што {domain} не з'яўляецца для вас лепшым выбарам у будучыні, вы можаце перайсці на іншы сервер Mastodon, не губляючы сваіх падпісчыкаў. Вы нават можаце стварыць свой уласны сервер!",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Resultats de la cerca",
"emoji_button.symbols": "Símbols",
"emoji_button.travel": "Viatges i llocs",
"empty_column.account_hides_collections": "Aquest usuari ha elegit no mostrar aquesta informació",
"empty_column.account_suspended": "Compte suspès",
"empty_column.account_timeline": "No hi ha tuts aquí!",
"empty_column.account_unavailable": "Perfil no disponible",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Sykresultaten",
"emoji_button.symbols": "Symboalen",
"emoji_button.travel": "Reizgje en lokaasjes",
"empty_column.account_hides_collections": "Dizze brûker hat derfoar keazen dizze ynformaasje net beskikber te meitsjen",
"empty_column.account_suspended": "Account beskoattele",
"empty_column.account_timeline": "Hjir binne gjin berjochten!",
"empty_column.account_unavailable": "Profyl net beskikber",

View file

@ -41,6 +41,8 @@
"account.languages": "Keisti prenumeruojamas kalbas",
"account.locked_info": "Šios paskyros privatumo būsena nustatyta kaip užrakinta. Savininkas (-ė) rankiniu būdu peržiūri, kas gali sekti.",
"account.media": "Medija",
"account.mention": "Paminėti @{name}",
"account.moved_to": "{name} nurodė, kad dabar jų nauja paskyra yra:",
"account.mute": "Užtildyti @{name}",
"account.muted": "Užtildytas",
"account.posts": "Toots",
@ -53,10 +55,15 @@
"account.unfollow": "Nebesekti",
"account.unmute_short": "Atitildyti",
"account_note.placeholder": "Click to add a note",
"alert.unexpected.title": "Oi!",
"alert.unexpected.message": "Įvyko netikėta klaida.",
"alert.unexpected.title": "Ups!",
"announcement.announcement": "Skelbimas",
"attachments_list.unprocessed": "(neapdorotas)",
"audio.hide": "Slėpti garsą",
"autosuggest_hashtag.per_week": "{count} per savaitę",
"boost_modal.combo": "Gali spausti {combo}, kad praleisti kitą kartą",
"bundle_column_error.copy_stacktrace": "Kopijuoti klaidos ataskaitą",
"bundle_column_error.error.body": "Užklausos puslapio nepavyko atvaizduoti. Tai gali būti dėl mūsų kodo klaidos arba naršyklės suderinamumo problemos.",
"bundle_column_error.error.title": "O, ne!",
"column.domain_blocks": "Hidden domains",
"column.lists": "Sąrašai",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Rezultati iskanja",
"emoji_button.symbols": "Simboli",
"emoji_button.travel": "Potovanja in kraji",
"empty_column.account_hides_collections": "Ta uporabnik se je odločil, da te informacije ne bo dal na voljo",
"empty_column.account_suspended": "Račun je suspendiran",
"empty_column.account_timeline": "Tukaj ni objav!",
"empty_column.account_unavailable": "Profil ni na voljo",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Rezultati pretrage",
"emoji_button.symbols": "Simboli",
"emoji_button.travel": "Putovanja i mesta",
"empty_column.account_hides_collections": "Ovaj korisnik je odlučio da ove informacije ne učini dostupnim",
"empty_column.account_suspended": "Nalog je suspendovan",
"empty_column.account_timeline": "Nema objava ovde!",
"empty_column.account_unavailable": "Profil je nedostupan",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Резултати претраге",
"emoji_button.symbols": "Симболи",
"emoji_button.travel": "Путовања и места",
"empty_column.account_hides_collections": "Овај корисник је одлучио да ове информације не учини доступним",
"empty_column.account_suspended": "Налог је суспендован",
"empty_column.account_timeline": "Нема објава овде!",
"empty_column.account_unavailable": "Профил је недоступан",

View file

@ -39,7 +39,7 @@ class Tag < ApplicationRecord
HASHTAG_RE = %r{(?<![=/)\w])#(#{HASHTAG_NAME_PAT})}i
HASHTAG_NAME_RE = /\A(#{HASHTAG_NAME_PAT})\z/i
HASHTAG_INVALID_CHARS_RE = /[^[:alnum:]#{HASHTAG_SEPARATORS}]/
HASHTAG_INVALID_CHARS_RE = /[^[:alnum:]\u0E47-\u0E4E#{HASHTAG_SEPARATORS}]/
validates :name, presence: true, format: { with: HASHTAG_NAME_RE }
validates :display_name, format: { with: HASHTAG_NAME_RE }

View file

@ -53,3 +53,7 @@ af:
position:
elevated: kan nie hoër as jou huidige rol wees nie
own_role: kan nie verander word met jou huidige rol nie
webhook:
attributes:
events:
invalid_permissions: geleenthede waartoe jy nie toegang het nie mag nie ingesluit word nie

View file

@ -5,7 +5,23 @@ af:
contact_unavailable: NVT
hosted_on: Mastodon gehuisves op %{domain}
title: Aangaande
accounts:
follow: Volg
followers:
one: Volgeling
other: Volgelinge
following: Volg
nothing_here: Daar is niks hier nie!
posts:
one: Plasing
other: Plasings
posts_tab_heading: Plasings
admin:
account_actions:
action: Voer aksie uit
title: Voer modereer aksie uit op %{acct}
account_moderation_notes:
create: Los nota
accounts:
location:
local: Plaaslik
@ -102,6 +118,7 @@ af:
types:
bookmarks: Boekmerke
invites:
invalid: Hierdie uitnodiging is nie geldig nie
title: Nooi ander
login_activities:
description_html: Indien jy onbekende aktiwiteite gewaar, oorweeg dit om jou wagwoord te verander en tweefaktorverifikasie te aktiveer.

View file

@ -1418,6 +1418,7 @@ be:
'86400': 1 дзень
expires_in_prompt: Ніколі
generate: Стварыць запрашальную спасылку
invalid: Гэта запрашэнне несапраўднае
invited_by: 'Вас запрасіў(-ла):'
max_uses:
few: "%{count} выкарыстанні"

View file

@ -1358,6 +1358,7 @@ ca:
'86400': 1 dia
expires_in_prompt: Mai
generate: Genera
invalid: Aquesta invitació no és vàlida
invited_by: 'Has estat invitat per:'
max_uses:
one: 1 ús

View file

@ -1468,6 +1468,7 @@ cy:
'86400': 1 diwrnod
expires_in_prompt: Byth
generate: Cynhyrchu dolen wahoddiad
invalid: Nid yw'r gwahoddiad hwn yn ddilys
invited_by: 'Cawsoch eich gwahodd gan:'
max_uses:
few: "%{count} defnydd"

View file

@ -1110,6 +1110,7 @@ da:
functional: Din konto er fuldt funktionel.
pending: Din ansøgning afventer gennemgang af vores medarbejdere. Dette kan tage noget tid. Du modtager en e-mail, hvis din ansøgning godkendes.
redirecting_to: Din konto er inaktiv, da den pt. er omdirigerer til %{acct}.
self_destruct: Da %{domain} er under nedlukning, vil kontoadgangen være begrænset.
view_strikes: Se tidligere anmeldelser af din konto
too_fast: Formularen indsendt for hurtigt, forsøg igen.
use_security_key: Brug sikkerhedsnøgle
@ -1367,6 +1368,7 @@ da:
'86400': 1 dag
expires_in_prompt: Aldrig
generate: Generér invitationslink
invalid: Denne invitation er ikke gyldig
invited_by: 'Du blev inviteret af:'
max_uses:
one: 1 benyttelse
@ -1579,6 +1581,9 @@ da:
over_daily_limit: Den daglige grænse på %{limit} planlagte indlæg er nået
over_total_limit: Grænsen på %{limit} planlagte indlæg er nået
too_soon: Den planlagte dato skal være i fremtiden
self_destruct:
lead_html: Desværre lukker <strong>%{domain}</strong> permanent. Har man en konto dér, vil fortsat brug heraf ikke være mulig. Man kan dog stadig anmode om en sikkerhedskopi af sine data.
title: Denne server er under nedlukning
sessions:
activity: Seneste aktivitet
browser: Browser

View file

@ -1368,6 +1368,7 @@ de:
'86400': 1 Tag
expires_in_prompt: Nie
generate: Einladungslink erstellen
invalid: Diese Einladung ist ungültig
invited_by: 'Du wurdest eingeladen von:'
max_uses:
one: Eine Verwendung

View file

@ -18,7 +18,7 @@ be:
unconfirmed: Вы павінны пацвердзіць свой адрас электроннай пошты, перш чым працягнуць
mailer:
confirmation_instructions:
action: Пацвердзіце адрас электроннай пошты
action: Пацвердзіць адрас электроннай пошты
action_with_app: Пацвердзіць і вярнуцца да %{app}
explanation: Вы стварылі ўліковы запіс на %{host} з гэтым адрасам электроннай пошты. Вам спатрэбіцца ўсяго адзін клік, каб пацвердзіць яго. Калі гэта былі не вы, то проста праігнаруйце гэты ліст.
explanation_when_pending: Вы падалі заяўку на запрашэнне на %{host} з гэтым адрасам электроннай пошты. Як толькі вы пацвердзіце свой адрас электроннай пошты, мы разгледзім вашу заяўку. Вы можаце ўвайсці, каб змяніць свае дадзеныя або выдаліць свой уліковы запіс, але вы не можаце атрымаць доступ да большасці функцый, пакуль ваш уліковы запіс не будзе зацверджаны. Калі ваша заяўка будзе адхілена, вашы даныя будуць выдалены, таму ад вас не спатрэбіцца ніякіх дадатковых дзеянняў. Калі гэта былі не вы, ігнаруйце гэты ліст

View file

@ -149,6 +149,7 @@ af:
write:blocks: blokkeer rekeninge en domeine
write:bookmarks: laat n boekmerk by plasings
write:conversations: doof en wis gesprekke uit
write:favourites: gunsteling plasings
write:filters: skep filters
write:follows: volg mense
write:lists: skep lyste

View file

@ -1368,6 +1368,7 @@ es-AR:
'86400': 1 día
expires_in_prompt: Nunca
generate: Generar enlace de invitación
invalid: Esta invitación no es válida
invited_by: 'Fuiste invitado por:'
max_uses:
one: 1 uso

View file

@ -1368,6 +1368,7 @@ es-MX:
'86400': 1 día
expires_in_prompt: Nunca
generate: Generar
invalid: Esta invitación no es válida
invited_by: 'Fuiste invitado por:'
max_uses:
one: 1 uso

View file

@ -1368,6 +1368,7 @@ es:
'86400': 1 día
expires_in_prompt: Nunca
generate: Generar
invalid: Esta invitación no es válida
invited_by: 'Fuiste invitado por:'
max_uses:
one: 1 uso

View file

@ -1363,6 +1363,7 @@ eu:
'86400': Egun 1
expires_in_prompt: Inoiz ez
generate: Sortu
invalid: Gonbidapen hau ez da baliozkoa
invited_by: 'Honek gonbidatu zaitu:'
max_uses:
one: Erabilera 1

View file

@ -1157,6 +1157,7 @@ fa:
'86400': ۱ روز
expires_in_prompt: هیچ وقت
generate: ساختن
invalid: این دعوت‌نامه معتبر نیست
invited_by: 'دعوت‌کنندهٔ شما:'
max_uses:
one: ۱ بار

View file

@ -1368,6 +1368,7 @@ fo:
'86400': 1 dag
expires_in_prompt: Ongantíð
generate: Ger innbjóðingarleinki
invalid: Henda innbjóðing er ikki gildug
invited_by: 'Tú var bjóðað/ur av:'
max_uses:
one: 1 brúk

View file

@ -1368,6 +1368,7 @@ fr-QC:
'86400': 1 jour
expires_in_prompt: Jamais
generate: Générer un lien d'invitation
invalid: Cette invitation nest pas valide
invited_by: 'Vous avez été invité·e par:'
max_uses:
one: 1 utilisation

View file

@ -1368,6 +1368,7 @@ fr:
'86400': 1 jour
expires_in_prompt: Jamais
generate: Générer un lien d'invitation
invalid: Cette invitation nest pas valide
invited_by: 'Vous avez été invité·e par:'
max_uses:
one: 1 utilisation

View file

@ -1368,6 +1368,7 @@ fy:
'86400': 1 dei
expires_in_prompt: Nea
generate: Utnûgingskeppeling generearje
invalid: Dizze útnûging is net jildich
invited_by: 'Jo binne útnûge troch:'
max_uses:
one: 1 kear

View file

@ -1368,6 +1368,7 @@ gl:
'86400': 1 día
expires_in_prompt: Nunca
generate: Xerar
invalid: Este convite non é válido
invited_by: 'Convidoute:'
max_uses:
one: 1 uso

View file

@ -113,8 +113,8 @@ he:
previous_strikes_description_html:
many: לחשבון הזה יש <strong>%{count}</strong> פסילות.
one: לחשבון הזה פסילה <strong>אחת</strong>.
other: לחשבון הזה <strong>%{count}</strong> פסילות.
two: לחשבון הזה <strong>%{count}</strong> פסילות.
other: לחשבון הזה יש <strong>%{count}</strong> פסילות.
two: לחשבון הזה יש <strong>שתי</strong> פסילות.
promote: להעלות בדרגה
protocol: פרטיכל
public: פומבי
@ -1418,6 +1418,7 @@ he:
'86400': יום אחד
expires_in_prompt: לעולם לא
generate: יצירת קישור להזמנה
invalid: הזמנה זו אינה תקפה
invited_by: הוזמנת ע"י
max_uses:
many: "%{count} שימושים"

View file

@ -1368,6 +1368,7 @@ hu:
'86400': 1 nap
expires_in_prompt: Soha
generate: Generálás
invalid: Ez a meghívó nem érvényes
invited_by: 'Téged meghívott:'
max_uses:
one: 1 használat

View file

@ -1372,6 +1372,7 @@ is:
'86400': 1 dagur
expires_in_prompt: Aldrei
generate: Útbúa boðstengil
invalid: Þetta boð er ekki gilt
invited_by: 'Þér var boðið af:'
max_uses:
one: 1 afnot

View file

@ -1370,6 +1370,7 @@ it:
'86400': 1 giorno
expires_in_prompt: Mai
generate: Genera
invalid: Questo invito non è valido
invited_by: 'Sei stato invitato da:'
max_uses:
one: un uso

View file

@ -1345,6 +1345,7 @@ ko:
'86400': 1
expires_in_prompt: 영원히
generate: 초대 링크 생성하기
invalid: 이 초대는 올바르지 않습니다
invited_by: '당신을 초대한 사람:'
max_uses:
other: "%{count}회"

View file

@ -383,6 +383,7 @@ lt:
'86400': 1 dienos
expires_in_prompt: Niekada
generate: Generuoti
invalid: Šis kvietimas negalioja.
invited_by: 'Jus pakvietė:'
max_uses:
few: "%{count} panaudojimai"

View file

@ -1368,6 +1368,7 @@ nl:
'86400': 1 dag
expires_in_prompt: Nooit
generate: Uitnodigingslink genereren
invalid: Deze uitnodiging is niet geldig
invited_by: 'Jij bent uitgenodigd door:'
max_uses:
one: 1 keer

View file

@ -1368,6 +1368,7 @@ nn:
'86400': 1 dag
expires_in_prompt: Aldri
generate: Lag innbydingslenkje
invalid: Denne invitasjonen er ikkje gyldig
invited_by: 'Du vart innboden av:'
max_uses:
one: 1 bruk

View file

@ -1368,6 +1368,7 @@
'86400': 1 dag
expires_in_prompt: Aldri
generate: Generer
invalid: Denne invitasjonen er ikke gyldig
invited_by: 'Du ble invitert av:'
max_uses:
one: 1 bruk

View file

@ -1418,6 +1418,7 @@ pl:
'86400': dobie
expires_in_prompt: Nigdy
generate: Wygeneruj
invalid: Niepoprawne zaproszenie
invited_by: 'Zostałeś(-aś) zaproszony(-a) przez:'
max_uses:
few: "%{count} użycia"

View file

@ -1368,6 +1368,7 @@ pt-BR:
'86400': 1 dia
expires_in_prompt: Nunca
generate: Gerar convite
invalid: Este convite não é válido
invited_by: 'Você recebeu convite de:'
max_uses:
one: 1 uso

View file

@ -1368,6 +1368,7 @@ pt-PT:
'86400': 1 dia
expires_in_prompt: Nunca
generate: Gerar hiperligação de convite
invalid: Este convite não é válido
invited_by: 'Foi convidado por:'
max_uses:
one: 1 uso

View file

@ -53,7 +53,7 @@ be:
password: Не менш за 8 сімвалаў
phrase: Параўнанне адбудзецца нягледзячы на рэгістр тэксту і папярэджанні аб змесціве допісу
scopes: Якімі API праграм будзе дазволена карыстацца. Калі вы абярэце найвышэйшы ўзровень, не трэба абіраць асобныя.
setting_aggregate_reblogs: Не паказваць новыя пашырэнні для допісаў, якія нядаўна пашырылі(уплывае выключна на будучыя пашырэнні)
setting_aggregate_reblogs: Не паказваць новыя пашырэнні для допісаў, якія пашырылі нядаўна (закранае толькі нядаўнія пашырэнні)
setting_always_send_emails: Звычайна лісты з апавяшчэннямі не будуць дасылацца, калі вы актыўна карыстаецеся Mastodon
setting_default_sensitive: Далікатныя медыя прадвызначана схаваныя. Іх можна адкрыць адзіным клікам
setting_display_media_default: Хаваць медыя пазначаныя як далікатныя

View file

@ -592,6 +592,8 @@ sk:
title: Ohľadom
appearance:
title: Vzhľad
content_retention:
title: Ponechanie obsahu
discovery:
follow_recommendations: Odporúčania pre nasledovanie
profile_directory: Katalóg profilov
@ -616,6 +618,7 @@ sk:
delete: Vymaž nahratý súbor
destroyed_msg: Nahratie bolo zo stránky úspešne vymazané!
software_updates:
critical_update: Kritické — prosím aktualizuj rýchlo
documentation_link: Zisti viac
title: Dostupné aktualizácie
types:
@ -646,6 +649,10 @@ sk:
appeal_approved: Namietnuté
appeal_rejected: Námietka zamietnutá
system_checks:
elasticsearch_preset:
action: Pozri dokumentáciu
elasticsearch_preset_single_node:
action: Pozri dokumentáciu
rules_check:
action: Spravuj serverové pravidlá
message_html: Neurčil/a si žiadne serverové pravidlá.
@ -925,6 +932,7 @@ sk:
'86400': 1 deň
expires_in_prompt: Nikdy
generate: Vygeneruj
invalid: Táto pozvánka je neplatná
invited_by: 'Bol/a si pozvaný/á užívateľom:'
max_uses:
few: "%{count} využití"

View file

@ -1418,6 +1418,7 @@ sl:
'86400': 1 dan
expires_in_prompt: Nikoli
generate: Ustvari
invalid: To povabilo ni veljavno
invited_by: 'Povabil/a vas je:'
max_uses:
few: "%{count} uporabe"

View file

@ -1362,6 +1362,7 @@ sq:
'86400': 1 ditë
expires_in_prompt: Kurrë
generate: Prodho lidhje ftese
invalid: Kjo ftesë sështë e vlefshme
invited_by: 'Qetë ftuar nga:'
max_uses:
one: 1 përdorim

View file

@ -1393,6 +1393,7 @@ sr-Latn:
'86400': 1 dan
expires_in_prompt: Nikad
generate: Generiši
invalid: Ova pozivnica nije važeća
invited_by: 'Pozvao Vas je:'
max_uses:
few: "%{count} korišćenja"

View file

@ -1393,6 +1393,7 @@ sr:
'86400': 1 дан
expires_in_prompt: Никад
generate: Генериши
invalid: Ова позивница није важећа
invited_by: 'Позвао Вас је:'
max_uses:
few: "%{count} коришћења"

View file

@ -1368,6 +1368,7 @@ sv:
'86400': 1 dag
expires_in_prompt: Aldrig
generate: Skapa
invalid: Ogiltig inbjudan
invited_by: 'Du blev inbjuden av:'
max_uses:
one: 1 användning

View file

@ -1343,6 +1343,7 @@ th:
'86400': 1 วัน
expires_in_prompt: ไม่เลย
generate: สร้างลิงก์เชิญ
invalid: คำเชิญนี้ไม่ถูกต้อง
invited_by: 'คุณได้รับเชิญโดย:'
max_uses:
other: "%{count} การใช้งาน"

View file

@ -1368,6 +1368,7 @@ tr:
'86400': 1 gün
expires_in_prompt: Asla
generate: Davet bağlantısı oluştur
invalid: Bu davet geçerli değil
invited_by: 'Davet edildiniz:'
max_uses:
one: 1 kullanım

View file

@ -1418,6 +1418,7 @@ uk:
'86400': 1 день
expires_in_prompt: Ніколи
generate: Згенерувати
invalid: Це запрошення не дійсне
invited_by: 'Вас запросив:'
max_uses:
few: "%{count} використання"

View file

@ -1343,6 +1343,7 @@ zh-CN:
'86400': 1 天后
expires_in_prompt: 永不过期
generate: 生成邀请链接
invalid: 此邀请无效
invited_by: 你的邀请人是:
max_uses:
other: "%{count} 次"

View file

@ -1343,6 +1343,7 @@ zh-HK:
'86400': 1 天後
expires_in_prompt: 永不過期
generate: 生成邀請連結
invalid: 此邀請無效
invited_by: 你的邀請人是:
max_uses:
other: "%{count} 次"

View file

@ -1345,6 +1345,7 @@ zh-TW:
'86400': 1 天後
expires_in_prompt: 永不過期
generate: 建立邀請連結
invalid: 此邀請是無效的
invited_by: 您的邀請人是:
max_uses:
other: "%{count} 則"

View file

@ -1,11 +1,13 @@
{
"name": "@mastodon/mastodon",
"license": "AGPL-3.0-or-later",
"packageManager": "yarn@4.0.2",
"engines": {
"node": ">=18"
},
"workspaces": [
"."
".",
"streaming"
],
"scripts": {
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/webpack",
@ -76,10 +78,8 @@
"css-loader": "^5.2.7",
"cssnano": "^6.0.1",
"detect-passive-events": "^2.0.3",
"dotenv": "^16.0.3",
"emoji-mart": "npm:emoji-mart-lazyload@latest",
"escape-html": "^1.0.3",
"express": "^4.18.2",
"file-loader": "^6.2.0",
"font-awesome": "^4.7.0",
"fuzzysort": "^2.0.4",
@ -90,21 +90,15 @@
"immutable": "^4.3.0",
"imports-loader": "^1.2.0",
"intl-messageformat": "^10.3.5",
"ioredis": "^5.3.2",
"js-yaml": "^4.1.0",
"jsdom": "^22.1.0",
"lodash": "^4.17.21",
"mark-loader": "^0.1.6",
"marky": "^1.2.5",
"mini-css-extract-plugin": "^1.6.2",
"mkdirp": "^3.0.1",
"npmlog": "^7.0.1",
"path-complete-extname": "^1.0.0",
"pg": "^8.5.0",
"pg-connection-string": "^2.6.0",
"postcss": "^8.4.24",
"postcss-loader": "^4.3.0",
"prom-client": "^15.0.0",
"prop-types": "^15.8.1",
"punycode": "^2.3.0",
"react": "^18.2.0",
@ -143,7 +137,6 @@
"tesseract.js": "^2.1.5",
"tiny-queue": "^0.2.1",
"twitter-text": "3.1.0",
"uuid": "^9.0.0",
"webpack": "^4.47.0",
"webpack-assets-manifest": "^4.0.6",
"webpack-bundle-analyzer": "^4.8.0",
@ -155,8 +148,7 @@
"workbox-routing": "^7.0.0",
"workbox-strategies": "^7.0.0",
"workbox-webpack-plugin": "^7.0.0",
"workbox-window": "^7.0.0",
"ws": "^8.12.1"
"workbox-window": "^7.0.0"
},
"devDependencies": {
"@formatjs/cli": "^6.1.1",
@ -165,16 +157,13 @@
"@types/babel__core": "^7.20.1",
"@types/emoji-mart": "^3.0.9",
"@types/escape-html": "^1.0.2",
"@types/express": "^4.17.17",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/http-link-header": "^1.0.3",
"@types/intl": "^1.2.0",
"@types/jest": "^29.5.2",
"@types/js-yaml": "^4.0.5",
"@types/lodash": "^4.14.195",
"@types/npmlog": "^4.1.4",
"@types/object-assign": "^4.0.30",
"@types/pg": "^8.6.6",
"@types/prop-types": "^15.7.5",
"@types/punycode": "^2.1.0",
"@types/react": "^18.2.7",
@ -193,7 +182,6 @@
"@types/react-toggle": "^4.0.3",
"@types/redux-immutable": "^4.0.3",
"@types/requestidlecallback": "^0.3.5",
"@types/uuid": "^9.0.0",
"@types/webpack": "^4.41.33",
"@types/yargs": "^17.0.24",
"@typescript-eslint/eslint-plugin": "^6.0.0",
@ -237,16 +225,11 @@
"optional": true
}
},
"optionalDependencies": {
"bufferutil": "^4.0.7",
"utf-8-validate": "^6.0.3"
},
"lint-staged": {
"*": "prettier --ignore-unknown --write",
"Capfile|Gemfile|*.{rb,ruby,ru,rake}": "bundle exec rubocop --force-exclusion -a",
"*.{haml}": "bundle exec haml-lint",
"*.{js,jsx,ts,tsx}": "eslint --fix",
"*.{css,scss}": "stylelint --fix"
},
"packageManager": "yarn@4.0.1"
}
}

View file

@ -58,7 +58,7 @@ RSpec.describe ActivityPub::InboxesController do
before do
allow(ActivityPub::FollowersSynchronizationWorker).to receive(:perform_async).and_return(nil)
allow_any_instance_of(Account).to receive(:local_followers_hash).and_return('somehash')
allow(remote_account).to receive(:local_followers_hash).and_return('somehash')
request.headers['Collection-Synchronization'] = synchronization_header
post :create, body: '{}'

View file

@ -227,7 +227,8 @@ RSpec.describe Admin::AccountsController do
let(:account) { Fabricate(:account, domain: 'example.com') }
before do
allow_any_instance_of(ResolveAccountService).to receive(:call)
service = instance_double(ResolveAccountService, call: nil)
allow(ResolveAccountService).to receive(:new).and_return(service)
end
context 'when user is admin' do

View file

@ -13,12 +13,20 @@ describe Admin::ResetsController do
describe 'POST #create' do
it 'redirects to admin accounts page' do
expect_any_instance_of(User).to receive(:send_reset_password_instructions) do |value|
expect(value.account_id).to eq account.id
end
expect do
post :create, params: { account_id: account.id }
end.to change(Devise.mailer.deliveries, :size).by(2)
expect(Devise.mailer.deliveries).to have_attributes(
first: have_attributes(
to: include(account.user.email),
subject: I18n.t('devise.mailer.password_change.subject')
),
last: have_attributes(
to: include(account.user.email),
subject: I18n.t('devise.mailer.reset_password_instructions.subject')
)
)
expect(response).to redirect_to(admin_account_path(account.id))
end
end

View file

@ -126,7 +126,7 @@ RSpec.describe Auth::SessionsController do
let!(:previous_login) { Fabricate(:login_activity, user: user, ip: previous_ip) }
before do
allow_any_instance_of(ActionDispatch::Request).to receive(:remote_ip).and_return(current_ip)
allow(controller.request).to receive(:remote_ip).and_return(current_ip)
user.update(current_sign_in_at: 1.month.ago)
post :create, params: { user: { email: user.email, password: user.password } }
end
@ -279,7 +279,9 @@ RSpec.describe Auth::SessionsController do
context 'when the server has an decryption error' do
before do
allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError)
allow(user).to receive(:validate_and_consume_otp!).with(user.current_otp).and_raise(OpenSSL::Cipher::CipherError)
allow(User).to receive(:find_by).with(id: user.id).and_return(user)
post :create, params: { user: { otp_attempt: user.current_otp } }, session: { attempt_user_id: user.id, attempt_user_updated_at: user.updated_at.to_s }
end

View file

@ -61,6 +61,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
it 'renders page with success' do
prepare_user_otp_generation
prepare_user_otp_consumption
allow(controller).to receive(:current_user).and_return(user)
expect do
post :create,
@ -75,30 +76,28 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
end
def prepare_user_otp_generation
expect_any_instance_of(User).to receive(:generate_otp_backup_codes!) do |value|
expect(value).to eq user
otp_backup_codes
end
allow(user)
.to receive(:generate_otp_backup_codes!)
.and_return(otp_backup_codes)
end
def prepare_user_otp_consumption
expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, code, options|
expect(value).to eq user
expect(code).to eq '123456'
expect(options).to eq({ otp_secret: 'thisisasecretforthespecofnewview' })
true
end
options = { otp_secret: 'thisisasecretforthespecofnewview' }
allow(user)
.to receive(:validate_and_consume_otp!)
.with('123456', options)
.and_return(true)
end
end
describe 'when creation fails' do
subject do
expect_any_instance_of(User).to receive(:validate_and_consume_otp!) do |value, code, options|
expect(value).to eq user
expect(code).to eq '123456'
expect(options).to eq({ otp_secret: 'thisisasecretforthespecofnewview' })
false
end
options = { otp_secret: 'thisisasecretforthespecofnewview' }
allow(user)
.to receive(:validate_and_consume_otp!)
.with('123456', options)
.and_return(false)
allow(controller).to receive(:current_user).and_return(user)
expect do
post :create,

View file

@ -9,10 +9,8 @@ describe Settings::TwoFactorAuthentication::RecoveryCodesController do
it 'updates the codes and shows them on a view when signed in' do
user = Fabricate(:user)
otp_backup_codes = user.generate_otp_backup_codes!
expect_any_instance_of(User).to receive(:generate_otp_backup_codes!) do |value|
expect(value).to eq user
otp_backup_codes
end
allow(user).to receive(:generate_otp_backup_codes!).and_return(otp_backup_codes)
allow(controller).to receive(:current_user).and_return(user)
sign_in user, scope: :user
post :create, session: { challenge_passed_at: Time.now.utc }

View file

@ -64,8 +64,11 @@ describe Request do
end
it 'closes underlying connection' do
expect_any_instance_of(HTTP::Client).to receive(:close)
allow(subject.send(:http_client)).to receive(:close)
expect { |block| subject.perform(&block) }.to yield_control
expect(subject.send(:http_client)).to have_received(:close)
end
it 'returns response which implements body_with_limit' do

View file

@ -23,7 +23,8 @@ describe StatusFilter do
context 'when status policy does not allow show' do
it 'filters the status' do
allow_any_instance_of(StatusPolicy).to receive(:show?).and_return(false)
policy = instance_double(StatusPolicy, show?: false)
allow(StatusPolicy).to receive(:new).and_return(policy)
expect(filter).to be_filtered
end
@ -74,7 +75,8 @@ describe StatusFilter do
context 'when status policy does not allow show' do
it 'filters the status' do
allow_any_instance_of(StatusPolicy).to receive(:show?).and_return(false)
policy = instance_double(StatusPolicy, show?: false)
allow(StatusPolicy).to receive(:new).and_return(policy)
expect(filter).to be_filtered
end

View file

@ -209,9 +209,13 @@ RSpec.describe Account do
expect(account.refresh!).to be_nil
end
it 'calls not ResolveAccountService#call' do
expect_any_instance_of(ResolveAccountService).to_not receive(:call).with(acct)
it 'does not call ResolveAccountService#call' do
service = instance_double(ResolveAccountService, call: nil)
allow(ResolveAccountService).to receive(:new).and_return(service)
account.refresh!
expect(service).to_not have_received(:call).with(acct)
end
end
@ -219,8 +223,12 @@ RSpec.describe Account do
let(:domain) { 'example.com' }
it 'calls ResolveAccountService#call' do
expect_any_instance_of(ResolveAccountService).to receive(:call).with(acct).once
service = instance_double(ResolveAccountService, call: nil)
allow(ResolveAccountService).to receive(:new).and_return(service)
account.refresh!
expect(service).to have_received(:call).with(acct).once
end
end
end

View file

@ -52,7 +52,8 @@ RSpec.describe Setting do
before do
allow(RailsSettings::Settings).to receive(:object).with(key).and_return(object)
allow(described_class).to receive(:default_settings).and_return(default_settings)
allow_any_instance_of(Settings::ScopedSettings).to receive(:thing_scoped).and_return(records)
settings_double = instance_double(Settings::ScopedSettings, thing_scoped: records)
allow(Settings::ScopedSettings).to receive(:new).and_return(settings_double)
Rails.cache.delete(cache_key)
end
@ -128,7 +129,8 @@ RSpec.describe Setting do
describe '.all_as_records' do
before do
allow_any_instance_of(Settings::ScopedSettings).to receive(:thing_scoped).and_return(records)
settings_double = instance_double(Settings::ScopedSettings, thing_scoped: records)
allow(Settings::ScopedSettings).to receive(:new).and_return(settings_double)
allow(described_class).to receive(:default_settings).and_return(default_settings)
end

View file

@ -102,17 +102,25 @@ describe 'GET /api/v1/accounts/relationships' do
end
end
it 'returns JSON with correct data on cached requests too' do
subject
subject
it 'returns JSON with correct data on previously cached requests' do
# Initial request including multiple accounts in params
get '/api/v1/accounts/relationships', headers: headers, params: { id: [simon.id, lewis.id] }
expect(body_as_json.size).to eq(2)
# Subsequent request with different id, should override cache from first request
get '/api/v1/accounts/relationships', headers: headers, params: { id: [simon.id] }
expect(response).to have_http_status(200)
json = body_as_json
expect(json).to be_a Enumerable
expect(json.first[:following]).to be true
expect(json.first[:showing_reblogs]).to be true
expect(body_as_json)
.to be_an(Enumerable)
.and have_attributes(
size: 1,
first: hash_including(
following: true,
showing_reblogs: true
)
)
end
it 'returns JSON with correct data after change too' do

View file

@ -0,0 +1,43 @@
# frozen_string_literal: true
require 'rails_helper'
describe 'API namespace minimal Content-Security-Policy' do
before { stub_tests_controller }
after { Rails.application.reload_routes! }
it 'returns the correct CSP headers' do
get '/api/v1/tests'
expect(response).to have_http_status(200)
expect(response.headers['Content-Security-Policy']).to eq(minimal_csp_headers)
end
private
def stub_tests_controller
stub_const('Api::V1::TestsController', api_tests_controller)
Rails.application.routes.draw do
get '/api/v1/tests', to: 'api/v1/tests#index'
end
end
def api_tests_controller
Class.new(Api::BaseController) do
def index
head 200
end
private
def user_signed_in? = false
def current_user = nil
end
end
def minimal_csp_headers
"default-src 'none'; frame-ancestors 'none'; form-action 'none'"
end
end

View file

@ -76,7 +76,8 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') }
it 'does not process payload if no signature exists' do
allow_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_actor!).and_return(nil)
signature_double = instance_double(ActivityPub::LinkedDataSignature, verify_actor!: nil)
allow(ActivityPub::LinkedDataSignature).to receive(:new).and_return(signature_double)
allow(ActivityPub::Activity).to receive(:factory)
subject.call(json, forwarder)
@ -87,7 +88,8 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
it 'processes payload with actor if valid signature exists' do
payload['signature'] = { 'type' => 'RsaSignature2017' }
allow_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_actor!).and_return(actor)
signature_double = instance_double(ActivityPub::LinkedDataSignature, verify_actor!: actor)
allow(ActivityPub::LinkedDataSignature).to receive(:new).and_return(signature_double)
allow(ActivityPub::Activity).to receive(:factory).with(instance_of(Hash), actor, instance_of(Hash))
subject.call(json, forwarder)
@ -98,7 +100,8 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do
it 'does not process payload if invalid signature exists' do
payload['signature'] = { 'type' => 'RsaSignature2017' }
allow_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_actor!).and_return(nil)
signature_double = instance_double(ActivityPub::LinkedDataSignature, verify_actor!: nil)
allow(ActivityPub::LinkedDataSignature).to receive(:new).and_return(signature_double)
allow(ActivityPub::Activity).to receive(:factory)
subject.call(json, forwarder)

View file

@ -4,13 +4,21 @@ require 'rspec/retry'
if ENV['DISABLE_SIMPLECOV'] != 'true'
require 'simplecov'
require 'simplecov-lcov'
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
SimpleCov.start 'rails' do
enable_coverage :branch
enable_coverage_for_eval
add_filter 'lib/linter'
add_group 'Policies', 'app/policies'
add_group 'Presenters', 'app/presenters'
add_group 'Serializers', 'app/serializers'
add_group 'Services', 'app/services'
add_group 'Validators', 'app/validators'
add_group 'Libraries', 'lib'
end
end

View file

@ -11,7 +11,8 @@ describe ActivityPub::DeliveryWorker do
let(:payload) { 'test' }
before do
allow_any_instance_of(Account).to receive(:remote_followers_hash).with('https://example.com/api').and_return('somehash')
allow(sender).to receive(:remote_followers_hash).with('https://example.com/api').and_return('somehash')
allow(Account).to receive(:find).with(sender.id).and_return(sender)
end
describe 'perform' do

View file

@ -23,8 +23,8 @@ describe Web::PushNotificationWorker do
describe 'perform' do
before do
allow_any_instance_of(subscription.class).to receive(:contact_email).and_return(contact_email)
allow_any_instance_of(subscription.class).to receive(:vapid_key).and_return(vapid_key)
allow(subscription).to receive_messages(contact_email: contact_email, vapid_key: vapid_key)
allow(Web::PushSubscription).to receive(:find).with(subscription.id).and_return(subscription)
allow(Webpush::Encryption).to receive(:encrypt).and_return(payload)
allow(JWT).to receive(:encode).and_return('jwt.encoded.payload')

View file

@ -2,6 +2,7 @@
const fs = require('fs');
const http = require('http');
const path = require('path');
const url = require('url');
const dotenv = require('dotenv');
@ -17,8 +18,11 @@ const WebSocket = require('ws');
const environment = process.env.NODE_ENV || 'development';
// Correctly detect and load .env or .env.production file based on environment:
const dotenvFile = environment === 'production' ? '.env.production' : '.env';
dotenv.config({
path: environment === 'production' ? '.env.production' : '.env',
path: path.resolve(__dirname, path.join('..', dotenvFile))
});
log.level = process.env.LOG_LEVEL || 'verbose';

39
streaming/package.json Normal file
View file

@ -0,0 +1,39 @@
{
"name": "@mastodon/streaming",
"license": "AGPL-3.0-or-later",
"packageManager": "yarn@4.0.2",
"engines": {
"node": ">=18"
},
"description": "Mastodon's Streaming Server",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/mastodon/mastodon.git"
},
"scripts": {
"start": "node ./index.js"
},
"dependencies": {
"dotenv": "^16.0.3",
"express": "^4.18.2",
"ioredis": "^5.3.2",
"jsdom": "^22.1.0",
"npmlog": "^7.0.1",
"pg": "^8.5.0",
"pg-connection-string": "^2.6.0",
"prom-client": "^15.0.0",
"uuid": "^9.0.0",
"ws": "^8.12.1"
},
"devDependencies": {
"@types/express": "^4.17.17",
"@types/npmlog": "^4.1.4",
"@types/pg": "^8.6.6",
"@types/uuid": "^9.0.0"
},
"optionalDependencies": {
"bufferutil": "^4.0.7",
"utf-8-validate": "^6.0.3"
}
}

321
yarn.lock
View file

@ -1800,6 +1800,16 @@ __metadata:
languageName: node
linkType: hard
"@formatjs/ecma402-abstract@npm:1.18.0":
version: 1.18.0
resolution: "@formatjs/ecma402-abstract@npm:1.18.0"
dependencies:
"@formatjs/intl-localematcher": "npm:0.5.2"
tslib: "npm:^2.4.0"
checksum: bbdad0aee8e48baad6bfe6b2c27caf3befe35e658b922ee2f84417a819f0bdc7e849a8c0c782db8b53f5666bf19669d2b10a1104257c08796d198c87766bfc92
languageName: node
linkType: hard
"@formatjs/fast-memoize@npm:2.2.0":
version: 2.2.0
resolution: "@formatjs/fast-memoize@npm:2.2.0"
@ -1820,6 +1830,17 @@ __metadata:
languageName: node
linkType: hard
"@formatjs/icu-messageformat-parser@npm:2.7.3":
version: 2.7.3
resolution: "@formatjs/icu-messageformat-parser@npm:2.7.3"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/icu-skeleton-parser": "npm:1.7.0"
tslib: "npm:^2.4.0"
checksum: 2a51038813e5cff7e2df767e1227373d228e907adb7268fc3744b3d82c4fa69d4aa9f6020a62de2c468cf724600e9372ac07ae43a4480ed066fe34e224e80e4a
languageName: node
linkType: hard
"@formatjs/icu-skeleton-parser@npm:1.6.4":
version: 1.6.4
resolution: "@formatjs/icu-skeleton-parser@npm:1.6.4"
@ -1830,25 +1851,35 @@ __metadata:
languageName: node
linkType: hard
"@formatjs/intl-displaynames@npm:6.6.3":
version: 6.6.3
resolution: "@formatjs/intl-displaynames@npm:6.6.3"
"@formatjs/icu-skeleton-parser@npm:1.7.0":
version: 1.7.0
resolution: "@formatjs/icu-skeleton-parser@npm:1.7.0"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.17.4"
"@formatjs/intl-localematcher": "npm:0.5.1"
"@formatjs/ecma402-abstract": "npm:1.18.0"
tslib: "npm:^2.4.0"
checksum: b0520cb744a51290fbcde80860f39ed9c9df9b81beae98986e1fc089ef635f7699c750631fa42a559f3678d1dd02b14904614e70360477d18e68d3eba6592390
checksum: 2e4db815247ddb10f7990bbb501c85b854ee951ee45143673eb91b4392b11d0a8312327adb8b624c6a2fdafab12083904630d6d22475503d025f1612da4dcaee
languageName: node
linkType: hard
"@formatjs/intl-listformat@npm:7.5.2":
version: 7.5.2
resolution: "@formatjs/intl-listformat@npm:7.5.2"
"@formatjs/intl-displaynames@npm:6.6.4":
version: 6.6.4
resolution: "@formatjs/intl-displaynames@npm:6.6.4"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.17.4"
"@formatjs/intl-localematcher": "npm:0.5.1"
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/intl-localematcher": "npm:0.5.2"
tslib: "npm:^2.4.0"
checksum: 54fa03da4ea45504681d6d87d72d1cac574809ce43f965fa4b845e83be3072d92324c58cec57ad386827087fb1d6ecae438d29576f30176bf52eb212e454bce2
checksum: 009e443dd0d10776b8573d0181407d4c0d6c7a2ff537a5ea1e36413d1b08db9c21dfef272eabab8efabd01a58b64f663a30e4d584fd761df3fd68a5d23fe444b
languageName: node
linkType: hard
"@formatjs/intl-listformat@npm:7.5.3":
version: 7.5.3
resolution: "@formatjs/intl-listformat@npm:7.5.3"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/intl-localematcher": "npm:0.5.2"
tslib: "npm:^2.4.0"
checksum: de741ce84b16fed57016afbfe446ebd57cd23a046859a9353f5d455f8bc9114493bf83b9e18429268c7ce8f77bc54516a9b8190baf09fbb25c9b06cfc80101d4
languageName: node
linkType: hard
@ -1861,34 +1892,43 @@ __metadata:
languageName: node
linkType: hard
"@formatjs/intl-pluralrules@npm:^5.2.2":
version: 5.2.9
resolution: "@formatjs/intl-pluralrules@npm:5.2.9"
"@formatjs/intl-localematcher@npm:0.5.2":
version: 0.5.2
resolution: "@formatjs/intl-localematcher@npm:0.5.2"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.17.4"
"@formatjs/intl-localematcher": "npm:0.5.1"
tslib: "npm:^2.4.0"
checksum: a6ca5c498ce542facacf8ce8640d4ba068f9119b758547a23614b50611eb385a46abd386ff88fa423211355ec463cf102c2c908b74f6e23a5bc9e2a23873dc29
checksum: 4b3ae75470e3e53ffa39b2d46e65a2a4c9c4becbc0aac989b0694370e10c6687643660a045512d676509bc29b257fe5726fbb028de12f889be02c2d20b6527e6
languageName: node
linkType: hard
"@formatjs/intl@npm:2.9.8":
version: 2.9.8
resolution: "@formatjs/intl@npm:2.9.8"
"@formatjs/intl-pluralrules@npm:^5.2.2":
version: 5.2.10
resolution: "@formatjs/intl-pluralrules@npm:5.2.10"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.17.4"
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/intl-localematcher": "npm:0.5.2"
tslib: "npm:^2.4.0"
checksum: 1050416613e80bff2c58546c80c8d52ed97847d13c90535a53d058e44969369b50e1cfdb464e9e9ef4802c934c84ea0e656c3f4e3b4d5ac7496b722c759da4cf
languageName: node
linkType: hard
"@formatjs/intl@npm:2.9.9":
version: 2.9.9
resolution: "@formatjs/intl@npm:2.9.9"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/fast-memoize": "npm:2.2.0"
"@formatjs/icu-messageformat-parser": "npm:2.7.2"
"@formatjs/intl-displaynames": "npm:6.6.3"
"@formatjs/intl-listformat": "npm:7.5.2"
intl-messageformat: "npm:10.5.7"
"@formatjs/icu-messageformat-parser": "npm:2.7.3"
"@formatjs/intl-displaynames": "npm:6.6.4"
"@formatjs/intl-listformat": "npm:7.5.3"
intl-messageformat: "npm:10.5.8"
tslib: "npm:^2.4.0"
peerDependencies:
typescript: 5
peerDependenciesMeta:
typescript:
optional: true
checksum: 6341f4bfb56a0e14373395b1232e1eeb8e64588a8c3d4614cd2b06f71d4e65dbd4a79e3a1c07e1b6c20c48e399ac2385977b01a559e1d2bd1a1d226e0eae3058
checksum: b26904da605ab309535dfbbfbd403a3bb33d51d3c969c548b88fa04755be3aff60b1bddd1c453514a84048c7432271cef507ac66de32dcfa66b3f842a1ddb977
languageName: node
linkType: hard
@ -1912,6 +1952,26 @@ __metadata:
languageName: node
linkType: hard
"@formatjs/ts-transformer@npm:3.13.9":
version: 3.13.9
resolution: "@formatjs/ts-transformer@npm:3.13.9"
dependencies:
"@formatjs/icu-messageformat-parser": "npm:2.7.3"
"@types/json-stable-stringify": "npm:^1.0.32"
"@types/node": "npm:14 || 16 || 17"
chalk: "npm:^4.0.0"
json-stable-stringify: "npm:^1.0.1"
tslib: "npm:^2.4.0"
typescript: "npm:5"
peerDependencies:
ts-jest: ">=27"
peerDependenciesMeta:
ts-jest:
optional: true
checksum: 4e313b967e45aae79246174c3181d31cc7cd297380d3a880a98fc0be16d76b783868712151e840ea16d22e2fbec0388b1005f688b6d4cb74ee4411b43f6d33f4
languageName: node
linkType: hard
"@gamestdio/websocket@npm:^0.3.2":
version: 0.3.2
resolution: "@gamestdio/websocket@npm:0.3.2"
@ -2327,16 +2387,13 @@ __metadata:
"@types/babel__core": "npm:^7.20.1"
"@types/emoji-mart": "npm:^3.0.9"
"@types/escape-html": "npm:^1.0.2"
"@types/express": "npm:^4.17.17"
"@types/hoist-non-react-statics": "npm:^3.3.1"
"@types/http-link-header": "npm:^1.0.3"
"@types/intl": "npm:^1.2.0"
"@types/jest": "npm:^29.5.2"
"@types/js-yaml": "npm:^4.0.5"
"@types/lodash": "npm:^4.14.195"
"@types/npmlog": "npm:^4.1.4"
"@types/object-assign": "npm:^4.0.30"
"@types/pg": "npm:^8.6.6"
"@types/prop-types": "npm:^15.7.5"
"@types/punycode": "npm:^2.1.0"
"@types/react": "npm:^18.2.7"
@ -2355,7 +2412,6 @@ __metadata:
"@types/react-toggle": "npm:^4.0.3"
"@types/redux-immutable": "npm:^4.0.3"
"@types/requestidlecallback": "npm:^0.3.5"
"@types/uuid": "npm:^9.0.0"
"@types/webpack": "npm:^4.41.33"
"@types/yargs": "npm:^17.0.24"
"@typescript-eslint/eslint-plugin": "npm:^6.0.0"
@ -2371,7 +2427,6 @@ __metadata:
babel-plugin-preval: "npm:^5.1.0"
babel-plugin-transform-react-remove-prop-types: "npm:^0.4.24"
blurhash: "npm:^2.0.5"
bufferutil: "npm:^4.0.7"
circular-dependency-plugin: "npm:^5.2.2"
classnames: "npm:^2.3.2"
cocoon-js-vanilla: "npm:^1.3.0"
@ -2382,7 +2437,6 @@ __metadata:
css-loader: "npm:^5.2.7"
cssnano: "npm:^6.0.1"
detect-passive-events: "npm:^2.0.3"
dotenv: "npm:^16.0.3"
emoji-mart: "npm:emoji-mart-lazyload@latest"
escape-html: "npm:^1.0.3"
eslint: "npm:^8.41.0"
@ -2396,7 +2450,6 @@ __metadata:
eslint-plugin-promise: "npm:~6.1.1"
eslint-plugin-react: "npm:~7.33.0"
eslint-plugin-react-hooks: "npm:^4.6.0"
express: "npm:^4.18.2"
file-loader: "npm:^6.2.0"
font-awesome: "npm:^4.7.0"
fuzzysort: "npm:^2.0.4"
@ -2408,25 +2461,19 @@ __metadata:
immutable: "npm:^4.3.0"
imports-loader: "npm:^1.2.0"
intl-messageformat: "npm:^10.3.5"
ioredis: "npm:^5.3.2"
jest: "npm:^29.5.0"
jest-environment-jsdom: "npm:^29.5.0"
js-yaml: "npm:^4.1.0"
jsdom: "npm:^22.1.0"
lint-staged: "npm:^15.0.0"
lodash: "npm:^4.17.21"
mark-loader: "npm:^0.1.6"
marky: "npm:^1.2.5"
mini-css-extract-plugin: "npm:^1.6.2"
mkdirp: "npm:^3.0.1"
npmlog: "npm:^7.0.1"
path-complete-extname: "npm:^1.0.0"
pg: "npm:^8.5.0"
pg-connection-string: "npm:^2.6.0"
postcss: "npm:^8.4.24"
postcss-loader: "npm:^4.3.0"
prettier: "npm:^3.0.0"
prom-client: "npm:^15.0.0"
prop-types: "npm:^15.8.1"
punycode: "npm:^2.3.0"
react: "npm:^18.2.0"
@ -2469,8 +2516,6 @@ __metadata:
tiny-queue: "npm:^0.2.1"
twitter-text: "npm:3.1.0"
typescript: "npm:^5.0.4"
utf-8-validate: "npm:^6.0.3"
uuid: "npm:^9.0.0"
webpack: "npm:^4.47.0"
webpack-assets-manifest: "npm:^4.0.6"
webpack-bundle-analyzer: "npm:^4.8.0"
@ -2484,13 +2529,7 @@ __metadata:
workbox-strategies: "npm:^7.0.0"
workbox-webpack-plugin: "npm:^7.0.0"
workbox-window: "npm:^7.0.0"
ws: "npm:^8.12.1"
yargs: "npm:^17.7.2"
dependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
peerDependenciesMeta:
react:
optional: true
@ -2501,6 +2540,34 @@ __metadata:
languageName: unknown
linkType: soft
"@mastodon/streaming@workspace:streaming":
version: 0.0.0-use.local
resolution: "@mastodon/streaming@workspace:streaming"
dependencies:
"@types/express": "npm:^4.17.17"
"@types/npmlog": "npm:^4.1.4"
"@types/pg": "npm:^8.6.6"
"@types/uuid": "npm:^9.0.0"
bufferutil: "npm:^4.0.7"
dotenv: "npm:^16.0.3"
express: "npm:^4.18.2"
ioredis: "npm:^5.3.2"
jsdom: "npm:^22.1.0"
npmlog: "npm:^7.0.1"
pg: "npm:^8.5.0"
pg-connection-string: "npm:^2.6.0"
prom-client: "npm:^15.0.0"
utf-8-validate: "npm:^6.0.3"
uuid: "npm:^9.0.0"
ws: "npm:^8.12.1"
dependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
languageName: unknown
linkType: soft
"@material-symbols/svg-600@npm:^0.14.0":
version: 0.14.0
resolution: "@material-symbols/svg-600@npm:0.14.0"
@ -3015,21 +3082,21 @@ __metadata:
linkType: hard
"@types/body-parser@npm:*":
version: 1.19.4
resolution: "@types/body-parser@npm:1.19.4"
version: 1.19.5
resolution: "@types/body-parser@npm:1.19.5"
dependencies:
"@types/connect": "npm:*"
"@types/node": "npm:*"
checksum: bec2b8a97861a960ee415f7ab3c2aeb7f4d779fd364d27ddee46057897ea571735f1f854f5ee41682964315d4e3699f62427998b9c21851d773398ef535f0612
checksum: aebeb200f25e8818d8cf39cd0209026750d77c9b85381cdd8deeb50913e4d18a1ebe4b74ca9b0b4d21952511eeaba5e9fbbf739b52731a2061e206ec60d568df
languageName: node
linkType: hard
"@types/connect@npm:*":
version: 3.4.37
resolution: "@types/connect@npm:3.4.37"
version: 3.4.38
resolution: "@types/connect@npm:3.4.38"
dependencies:
"@types/node": "npm:*"
checksum: 79fd5c32a8bb5c9548369e6da3221b6a820f3a8c5396d50f6f642712b9f4c1c881ef86bdf48994a4a279e81998563410b8843c5a10dde5521d5ef6a8ae944c3b
checksum: 2e1cdba2c410f25649e77856505cd60223250fa12dff7a503e492208dbfdd25f62859918f28aba95315251fd1f5e1ffbfca1e25e73037189ab85dd3f8d0a148c
languageName: node
linkType: hard
@ -3074,14 +3141,14 @@ __metadata:
linkType: hard
"@types/express-serve-static-core@npm:^4.17.33":
version: 4.17.39
resolution: "@types/express-serve-static-core@npm:4.17.39"
version: 4.17.41
resolution: "@types/express-serve-static-core@npm:4.17.41"
dependencies:
"@types/node": "npm:*"
"@types/qs": "npm:*"
"@types/range-parser": "npm:*"
"@types/send": "npm:*"
checksum: b23b005fddd2ba3f7142ec9713f06b5582c7712cdf99c3419d3972364903b348a103c3264d9a761d6497140e3b89bd416454684c4bdeff206b4c59b86e96428a
checksum: dc166cbf4475c00a81fbcab120bf7477c527184be11ae149df7f26d9c1082114c68f8d387a2926fe80291b06477c8bbd9231ff4f5775de328e887695aefce269
languageName: node
linkType: hard
@ -3134,9 +3201,9 @@ __metadata:
linkType: hard
"@types/http-errors@npm:*":
version: 2.0.3
resolution: "@types/http-errors@npm:2.0.3"
checksum: 717ce3e8f49a1facb7130fed934108fa8a51ab02089a1049c782e353e0e08e79bdfaac054c2a94db14ea400302e523276387363aa820eaf0031af8ba5d2941dc
version: 2.0.4
resolution: "@types/http-errors@npm:2.0.4"
checksum: 494670a57ad4062fee6c575047ad5782506dd35a6b9ed3894cea65830a94367bd84ba302eb3dde331871f6d70ca287bfedb1b2cf658e6132cd2cbd427ab56836
languageName: node
linkType: hard
@ -3238,16 +3305,16 @@ __metadata:
linkType: hard
"@types/mime@npm:*":
version: 3.0.3
resolution: "@types/mime@npm:3.0.3"
checksum: cef99f8cdc42af9de698027c2a20ba5df12bc9a89dcf5513e70103ebb55e00c5f5c585d02411f4b42fde0e78488342f1b1d3e3546a59a3da42e95fdc616e01eb
version: 3.0.4
resolution: "@types/mime@npm:3.0.4"
checksum: db478bc0f99e40f7b3e01d356a9bdf7817060808a294978111340317bcd80ca35382855578c5b60fbc84ae449674bd9bb38427b18417e1f8f19e4f72f8b242cd
languageName: node
linkType: hard
"@types/mime@npm:^1":
version: 1.3.4
resolution: "@types/mime@npm:1.3.4"
checksum: a0a16d26c0e70a1b133e26e7c46b70b3136b7e894396bdb7de1c642f4ac87fdbbba26bf56cf73f001312289d89de4f1c06ab745d9445850df45a5a802564c4d6
version: 1.3.5
resolution: "@types/mime@npm:1.3.5"
checksum: c2ee31cd9b993804df33a694d5aa3fa536511a49f2e06eeab0b484fef59b4483777dbb9e42a4198a0809ffbf698081fdbca1e5c2218b82b91603dfab10a10fbc
languageName: node
linkType: hard
@ -3351,16 +3418,16 @@ __metadata:
linkType: hard
"@types/qs@npm:*":
version: 6.9.9
resolution: "@types/qs@npm:6.9.9"
checksum: aede2a4181a49ae8548a1354bac3f8235cb0c5aab066b10875a3e68e88a199e220f4284e7e2bb75a3c18e5d4ff6abe1a6ce0389ef31b63952cc45e0f4d885ba0
version: 6.9.10
resolution: "@types/qs@npm:6.9.10"
checksum: 6be12e5f062d1b41eb037d59bf9cb65bc9410cedd5e6da832dfd7c8e2b3f4c91e81c9b90b51811140770e5052c6c4e8361181bd9437ddcd4515dc128b7c00353
languageName: node
linkType: hard
"@types/range-parser@npm:*":
version: 1.2.6
resolution: "@types/range-parser@npm:1.2.6"
checksum: 46e7fffc54cdacc8fb0cd576f8f9a6436453f0176205d6ec55434a460c7677e78e688673426d5db5e480501b2943ba08a16ececa3a354c222093551c7217fb8f
version: 1.2.7
resolution: "@types/range-parser@npm:1.2.7"
checksum: 361bb3e964ec5133fa40644a0b942279ed5df1949f21321d77de79f48b728d39253e5ce0408c9c17e4e0fd95ca7899da36841686393b9f7a1e209916e9381a3c
languageName: node
linkType: hard
@ -3546,23 +3613,23 @@ __metadata:
linkType: hard
"@types/send@npm:*":
version: 0.17.3
resolution: "@types/send@npm:0.17.3"
version: 0.17.4
resolution: "@types/send@npm:0.17.4"
dependencies:
"@types/mime": "npm:^1"
"@types/node": "npm:*"
checksum: 773a0cb55ea03eefbe9a0e6d42114e0f84968db30954a131aae9ba7e9ab984a4776915447ebdeab4412d7f11750126614b0b75e99413f75810045bdb3196554a
checksum: 7f17fa696cb83be0a104b04b424fdedc7eaba1c9a34b06027239aba513b398a0e2b7279778af521f516a397ced417c96960e5f50fcfce40c4bc4509fb1a5883c
languageName: node
linkType: hard
"@types/serve-static@npm:*":
version: 1.15.4
resolution: "@types/serve-static@npm:1.15.4"
version: 1.15.5
resolution: "@types/serve-static@npm:1.15.5"
dependencies:
"@types/http-errors": "npm:*"
"@types/mime": "npm:*"
"@types/node": "npm:*"
checksum: 061b38993bf8f2b5033f57147c8ec90e1d1a0d6f734958ceb531ba7cc31192fd272c999cdbc57ede8672787e3aa171ec142dc65a467c04078e43823e7476eb49
checksum: 811d1a2f7e74a872195e7a013bcd87a2fb1edf07eaedcb9dcfd20c1eb4bc56ad4ea0d52141c13192c91ccda7c8aeb8a530d8a7e60b9c27f5990d7e62e0fecb03
languageName: node
linkType: hard
@ -4694,21 +4761,21 @@ __metadata:
linkType: hard
"babel-plugin-formatjs@npm:^10.5.1":
version: 10.5.9
resolution: "babel-plugin-formatjs@npm:10.5.9"
version: 10.5.10
resolution: "babel-plugin-formatjs@npm:10.5.10"
dependencies:
"@babel/core": "npm:^7.10.4"
"@babel/helper-plugin-utils": "npm:^7.10.4"
"@babel/plugin-syntax-jsx": "npm:7"
"@babel/traverse": "npm:7"
"@babel/types": "npm:^7.12.11"
"@formatjs/icu-messageformat-parser": "npm:2.7.2"
"@formatjs/ts-transformer": "npm:3.13.8"
"@formatjs/icu-messageformat-parser": "npm:2.7.3"
"@formatjs/ts-transformer": "npm:3.13.9"
"@types/babel__core": "npm:^7.1.7"
"@types/babel__helper-plugin-utils": "npm:^7.10.0"
"@types/babel__traverse": "npm:^7.1.7"
tslib: "npm:^2.4.0"
checksum: 5e4127cf7b4b9b3306a9d0ab5b029831712d22db5e2117225ce706b55d222d09a7eba1f3720fdad7a99f61843b5cba107296fc11ae00a6f0941217d9322aa02e
checksum: bff65cd2a88a0ae00eabab1d022ffc44c4385b7e529cac42375bb1828c678c7a71a78f644512e5d1dd8cd532d418c16acdbabcef2bf6670e24404f4f164a74ce
languageName: node
linkType: hard
@ -6398,6 +6465,13 @@ __metadata:
languageName: node
linkType: hard
"debounce@npm:^1.2.1":
version: 1.2.1
resolution: "debounce@npm:1.2.1"
checksum: 6c9320aa0973fc42050814621a7a8a78146c1975799b5b3cc1becf1f77ba9a5aa583987884230da0842a03f385def452fad5d60db97c3d1c8b824e38a8edf500
languageName: node
linkType: hard
"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3":
version: 2.6.9
resolution: "debug@npm:2.6.9"
@ -8871,7 +8945,7 @@ __metadata:
languageName: node
linkType: hard
"html-escaper@npm:^2.0.0":
"html-escaper@npm:^2.0.0, html-escaper@npm:^2.0.2":
version: 2.0.2
resolution: "html-escaper@npm:2.0.2"
checksum: 208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0
@ -9271,15 +9345,15 @@ __metadata:
languageName: node
linkType: hard
"intl-messageformat@npm:10.5.7, intl-messageformat@npm:^10.3.5":
version: 10.5.7
resolution: "intl-messageformat@npm:10.5.7"
"intl-messageformat@npm:10.5.8, intl-messageformat@npm:^10.3.5":
version: 10.5.8
resolution: "intl-messageformat@npm:10.5.8"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.17.4"
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/fast-memoize": "npm:2.2.0"
"@formatjs/icu-messageformat-parser": "npm:2.7.2"
"@formatjs/icu-messageformat-parser": "npm:2.7.3"
tslib: "npm:^2.4.0"
checksum: 7f341b3eb5b3d402167c99ca7fb98720c7ad553bed8a490b2210bd90ea9009a09f9030939307fecb111fce1454f31b4298b4f0a346999af627c86f8164a5c547
checksum: 1d2854aae8471ec48165ca265760d6c5b1814eca831c88db698eb29b5ed20bee21ca8533090c9d28d9c6f1d844dda210b0bc58a2e036446158fae0845e5eed4f
languageName: node
linkType: hard
@ -11000,20 +11074,6 @@ __metadata:
languageName: node
linkType: hard
"lodash.escape@npm:^4.0.1":
version: 4.0.1
resolution: "lodash.escape@npm:4.0.1"
checksum: 90ade409cec05b6869090476952fdfb84d4d87b1ff4a0e03ebd590f980d9a1248d93ba14579f10d80c6429e4d6af13ba137c28db64cae6dadb71442e54a3ad2b
languageName: node
linkType: hard
"lodash.flatten@npm:^4.4.0":
version: 4.4.0
resolution: "lodash.flatten@npm:4.4.0"
checksum: 97e8f0d6b61fe4723c02ad0c6e67e51784c4a2c48f56ef283483e556ad01594cf9cec9c773e177bbbdbdb5d19e99b09d2487cb6b6e5dc405c2693e93b125bd3a
languageName: node
linkType: hard
"lodash.get@npm:^4.0":
version: 4.4.2
resolution: "lodash.get@npm:4.4.2"
@ -11028,13 +11088,6 @@ __metadata:
languageName: node
linkType: hard
"lodash.invokemap@npm:^4.6.0":
version: 4.6.0
resolution: "lodash.invokemap@npm:4.6.0"
checksum: 2bcc5f4b8782a316d55ff139215eb797f576f0f6d3db2755ebba7b35fd6061f8cbe81702a72a30bc6d70073a5dcc461f7570eaddcc9184c2e42ec3023645c6a1
languageName: node
linkType: hard
"lodash.isarguments@npm:^3.1.0":
version: 3.1.0
resolution: "lodash.isarguments@npm:3.1.0"
@ -11077,13 +11130,6 @@ __metadata:
languageName: node
linkType: hard
"lodash.pullall@npm:^4.2.0":
version: 4.2.0
resolution: "lodash.pullall@npm:4.2.0"
checksum: b129e8d879258c7db04a7dc1c23dd9e37c52f63a04e105faa8d2ab55e97b5a170d5e15cffbb732a36e7f48c4345c07b6fbddfe50e1f5ec301492b6f64a92040c
languageName: node
linkType: hard
"lodash.sortby@npm:^4.7.0":
version: 4.7.0
resolution: "lodash.sortby@npm:4.7.0"
@ -11105,13 +11151,6 @@ __metadata:
languageName: node
linkType: hard
"lodash.uniqby@npm:^4.7.0":
version: 4.7.0
resolution: "lodash.uniqby@npm:4.7.0"
checksum: c505c0de20ca759599a2ba38710e8fb95ff2d2028e24d86c901ef2c74be8056518571b9b754bfb75053b2818d30dd02243e4a4621a6940c206bbb3f7626db656
languageName: node
linkType: hard
"lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.20, lodash@npm:^4.17.21":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
@ -13678,18 +13717,18 @@ __metadata:
linkType: hard
"react-intl@npm:^6.4.2":
version: 6.5.4
resolution: "react-intl@npm:6.5.4"
version: 6.5.5
resolution: "react-intl@npm:6.5.5"
dependencies:
"@formatjs/ecma402-abstract": "npm:1.17.4"
"@formatjs/icu-messageformat-parser": "npm:2.7.2"
"@formatjs/intl": "npm:2.9.8"
"@formatjs/intl-displaynames": "npm:6.6.3"
"@formatjs/intl-listformat": "npm:7.5.2"
"@formatjs/ecma402-abstract": "npm:1.18.0"
"@formatjs/icu-messageformat-parser": "npm:2.7.3"
"@formatjs/intl": "npm:2.9.9"
"@formatjs/intl-displaynames": "npm:6.6.4"
"@formatjs/intl-listformat": "npm:7.5.3"
"@types/hoist-non-react-statics": "npm:^3.3.1"
"@types/react": "npm:16 || 17 || 18"
hoist-non-react-statics: "npm:^3.3.2"
intl-messageformat: "npm:10.5.7"
intl-messageformat: "npm:10.5.8"
tslib: "npm:^2.4.0"
peerDependencies:
react: ^16.6.0 || 17 || 18
@ -13697,7 +13736,7 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 1117a7f866b103abf88a4087f5fe8b854d9c069c69444c592f8431e7d28c9b90423f7b50e550be0f2f173b7563e943bcc9238e80f6747181f81861275f6e2ce7
checksum: 9ff6200f195557804b735d618ee593aed7848e84213ac4eb9c57708f55c0d93232e0dd338c990348ba3b1d73dca071502a2051d4a2790838d962c3ccde87fa6c
languageName: node
linkType: hard
@ -17019,29 +17058,25 @@ __metadata:
linkType: hard
"webpack-bundle-analyzer@npm:^4.8.0":
version: 4.9.1
resolution: "webpack-bundle-analyzer@npm:4.9.1"
version: 4.10.0
resolution: "webpack-bundle-analyzer@npm:4.10.0"
dependencies:
"@discoveryjs/json-ext": "npm:0.5.7"
acorn: "npm:^8.0.4"
acorn-walk: "npm:^8.0.0"
commander: "npm:^7.2.0"
debounce: "npm:^1.2.1"
escape-string-regexp: "npm:^4.0.0"
gzip-size: "npm:^6.0.0"
html-escaper: "npm:^2.0.2"
is-plain-object: "npm:^5.0.0"
lodash.debounce: "npm:^4.0.8"
lodash.escape: "npm:^4.0.1"
lodash.flatten: "npm:^4.4.0"
lodash.invokemap: "npm:^4.6.0"
lodash.pullall: "npm:^4.2.0"
lodash.uniqby: "npm:^4.7.0"
opener: "npm:^1.5.2"
picocolors: "npm:^1.0.0"
sirv: "npm:^2.0.3"
ws: "npm:^7.3.1"
bin:
webpack-bundle-analyzer: lib/bin/analyzer.js
checksum: dd047c306471e6c389d6d4156ff22402e587140310a065a6191ee380f8251063f73a8ec6ac6d977c1cd634dbb717e2522b5d0b6cc9b0e847d4f15737fd9c65c9
checksum: f812a8d3c0198ce518baf742bff656526f3eae69fb7a64c7f0c9cff202f6fb3380cabf3baaae965b8d6ffbbb6fb802eacb373fca03a596a38b01b84cfb2e8329
languageName: node
linkType: hard