Merge branch 'glitch-soc' into develop

main
Jeremy Kescher 5 months ago
commit 3b9a52aab6
No known key found for this signature in database
GPG Key ID: 80A419A7A613DFA4

@ -74,14 +74,12 @@ Metrics/ModuleLength:
Metrics/AbcSize:
Exclude:
- 'lib/mastodon/cli/*.rb'
- db/*migrate/**/*
# Reason: Currently disabled in .rubocop_todo.yml
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricscyclomaticcomplexity
Metrics/CyclomaticComplexity:
Exclude:
- lib/mastodon/cli/*.rb
- db/*migrate/**/*
# Reason:
# https://docs.rubocop.org/rubocop/cops_metrics.html#metricsparameterlists

@ -103,6 +103,7 @@ RUN \
procps \
tini \
tzdata \
wget \
; \
# Patch Ruby to use jemalloc
patchelf --add-needed libjemalloc.so.2 /usr/local/bin/ruby; \

@ -457,9 +457,9 @@ GEM
azure-storage-blob (~> 2.0.1)
hashie (~> 5.0)
memory_profiler (1.0.1)
mime-types (3.5.1)
mime-types (3.5.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2023.1003)
mime-types-data (3.2023.1205)
mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.20.0)
@ -544,7 +544,7 @@ GEM
psych (5.1.2)
stringio
public_suffix (5.0.4)
puma (6.4.0)
puma (6.4.1)
nio4r (~> 2.0)
pundit (2.3.1)
activesupport (>= 3.0.0)

@ -13,10 +13,8 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
## Supported Versions
| Version | Supported |
| ------- | ---------------- |
| 4.2.x | Yes |
| 4.1.x | Yes |
| 4.0.x | No |
| 3.5.x | Until 2023-12-31 |
| < 3.5 | No |
| Version | Supported |
| ------- | --------- |
| 4.2.x | Yes |
| 4.1.x | Yes |
| < 4.1 | No |

@ -68,7 +68,7 @@ module Admin
def export_data
CSV.generate(headers: export_headers, write_headers: true) do |content|
DomainBlock.with_limitations.each do |instance|
DomainBlock.with_limitations.order(id: :asc).each do |instance|
content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate]
end
end

@ -13,7 +13,9 @@ class Api::V1::StreamingController < Api::BaseController
def streaming_api_url
Addressable::URI.parse(request.url).tap do |uri|
uri.host = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url).host
base_url = Addressable::URI.parse(Rails.configuration.x.streaming_api_base_url)
uri.host = base_url.host
uri.port = base_url.port
end.to_s
end
end

@ -91,14 +91,23 @@ module SignatureVerification
raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
signature = Base64.decode64(signature_params['signature'])
compare_signed_string = build_signed_string
compare_signed_string = build_signed_string(include_query_string: true)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
# Compatibility quirk with older Mastodon versions
compare_signed_string = build_signed_string(include_query_string: false)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
actor = stoplight_wrap_request { actor_refresh_key!(actor) }
raise SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil?
compare_signed_string = build_signed_string(include_query_string: true)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
# Compatibility quirk with older Mastodon versions
compare_signed_string = build_signed_string(include_query_string: false)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature']
@ -180,11 +189,18 @@ module SignatureVerification
nil
end
def build_signed_string
def build_signed_string(include_query_string: true)
signed_headers.map do |signed_header|
case signed_header
when Request::REQUEST_TARGET
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
if include_query_string
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}"
else
# Current versions of Mastodon incorrectly omit the query string from the (request-target) pseudo-header.
# Therefore, temporarily support such incorrect signatures for compatibility.
# TODO: remove eventually some time after release of the fixed version
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
end
when '(created)'
raise SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank?

@ -221,7 +221,7 @@ class FocalPointModal extends ImmutablePureComponent {
const worker = createWorker({
workerPath: tesseractWorkerPath,
corePath: tesseractCorePath,
langPath: `${assetHost}/ocr/lang-data/`,
langPath: `${assetHost}/ocr/lang-data`,
logger: ({ status, progress }) => {
if (status === 'recognizing text') {
this.setState({ ocrStatus: 'detecting', progress });

@ -2,8 +2,13 @@ import { Map as ImmutableMap } from 'immutable';
import { ACCOUNT_LOOKUP_FAIL } from '../actions/accounts';
import { importAccounts } from '../actions/accounts_typed';
import { domain } from '../initial_state';
export const normalizeForLookup = str => str.toLowerCase();
export const normalizeForLookup = str => {
str = str.toLowerCase();
const trailingIndex = str.indexOf(`@${domain.toLowerCase()}`);
return (trailingIndex > 0) ? str.slice(0, trailingIndex) : str;
};
const initialState = ImmutableMap();

@ -222,7 +222,7 @@ class FocalPointModal extends ImmutablePureComponent {
const worker = createWorker({
workerPath: tesseractWorkerPath,
corePath: tesseractCorePath,
langPath: `${assetHost}/ocr/lang-data/`,
langPath: `${assetHost}/ocr/lang-data`,
logger: ({ status, progress }) => {
if (status === 'recognizing text') {
this.setState({ ocrStatus: 'detecting', progress });

@ -21,6 +21,7 @@
"account.blocked": "Blociwyd",
"account.browse_more_on_origin_server": "Pori mwy ar y proffil gwreiddiol",
"account.cancel_follow_request": "Tynnu cais i ddilyn",
"account.copy": "Copïo dolen i'r proffil",
"account.direct": "Crybwyll yn breifat @{name}",
"account.disable_notifications": "Stopiwch fy hysbysu pan fydd @{name} yn postio",
"account.domain_blocked": "Parth wedi ei flocio",
@ -31,6 +32,7 @@
"account.featured_tags.last_status_never": "Dim postiadau",
"account.featured_tags.title": "Prif hashnodau {name}",
"account.follow": "Dilyn",
"account.follow_back": "Dilyn yn ôl",
"account.followers": "Dilynwyr",
"account.followers.empty": "Does neb yn dilyn y defnyddiwr hwn eto.",
"account.followers_counter": "{count, plural, one {Dilynwr: {counter}} other {Dilynwyr: {counter}}}",
@ -51,6 +53,7 @@
"account.mute_notifications_short": "Distewi hysbysiadau",
"account.mute_short": "Tewi",
"account.muted": "Wedi anwybyddu",
"account.mutual": "Cydgydnabod",
"account.no_bio": "Dim disgrifiad wedi'i gynnig.",
"account.open_original_page": "Agor y dudalen wreiddiol",
"account.posts": "Postiadau",
@ -168,9 +171,9 @@
"confirmations.delete.confirm": "Dileu",
"confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y post hwn?",
"confirmations.delete_list.confirm": "Dileu",
"confirmations.delete_list.message": "Ydych chi'n siŵr eich bod eisiau dileu y rhestr hwn am byth?",
"confirmations.delete_list.message": "Ydych chi'n siŵr eich bod eisiau dileu'r rhestr hwn am byth?",
"confirmations.discard_edit_media.confirm": "Dileu",
"confirmations.discard_edit_media.message": "Mae gennych newidiadau heb eu cadw i'r disgrifiad cyfryngau neu'r rhagolwg, eu taflu beth bynnag?",
"confirmations.discard_edit_media.message": "Mae gennych newidiadau heb eu cadw i'r disgrifiad cyfryngau neu'r rhagolwg - eu dileu beth bynnag?",
"confirmations.domain_block.confirm": "Blocio parth cyfan",
"confirmations.domain_block.message": "Ydych chi wir, wir eisiau blocio'r holl {domain}? Fel arfer, mae blocio neu dewi pobl penodol yn broses mwy effeithiol. Fyddwch chi ddim yn gweld cynnwys o'r parth hwnnw mewn ffrydiau cyhoeddus neu yn eich hysbysiadau. Bydd eich dilynwyr o'r parth hwnnw yn cael eu ddileu.",
"confirmations.edit.confirm": "Golygu",
@ -481,12 +484,15 @@
"onboarding.follows.title": "Yn boblogaidd ar Mastodon",
"onboarding.profile.discoverable": "Gwnewch fy mhroffil yn un y gellir ei ddarganfod",
"onboarding.profile.discoverable_hint": "Pan fyddwch yn optio i mewn i ddarganfodadwyedd ar Mastodon, gall eich postiadau ymddangos mewn canlyniadau chwilio a thueddiadau, ac efallai y bydd eich proffil yn cael ei awgrymu i bobl sydd â diddordebau tebyg i chi.",
"onboarding.profile.display_name": "Enw dangos",
"onboarding.profile.display_name_hint": "Eich enw llawn neu'ch enw hwyl…",
"onboarding.profile.lead": "Gallwch chi bob amser gwblhau hyn yn ddiweddarach yn y gosodiadau, lle mae hyd yn oed mwy o ddewisiadau cyfaddasu ar gael.",
"onboarding.profile.note": "Bywgraffiad",
"onboarding.profile.note_hint": "Gallwch @grybwyll pobl eraill neu #hashnodau…",
"onboarding.profile.save_and_continue": "Cadw a pharhau",
"onboarding.profile.title": "Gosodiad proffil",
"onboarding.profile.upload_avatar": "Llwytho llun proffil",
"onboarding.profile.upload_header": "Llwytho pennyn proffil",
"onboarding.share.lead": "Cofiwch ddweud wrth bobl sut y gallan nhw ddod o hyd i chi ar Mastodon!",
"onboarding.share.message": "Fi yw {username} ar #Mastodon! Dewch i'm dilyn i yn {url}",
"onboarding.share.next_steps": "Camau nesaf posib:",
@ -601,6 +607,7 @@
"search.quick_action.status_search": "Postiadau sy'n cyfateb i {x}",
"search.search_or_paste": "Chwilio neu gludo URL",
"search_popout.full_text_search_disabled_message": "Ddim ar gael ar {domain}.",
"search_popout.full_text_search_logged_out_message": "Dim ond ar gael pan wedi mewngofnodi.",
"search_popout.language_code": "Cod iaith ISO",
"search_popout.options": "Dewisiadau chwilio",
"search_popout.quick_actions": "Gweithredoedd cyflym",

@ -1,8 +1,15 @@
{
"about.blocks": "Moderirani poslužitelji",
"about.contact": "Kontakt:",
"about.disclaimer": "Mastodon je besplatan softver otvorenog koda i zaštitni znak tvrtke Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Razlog nije dostupan",
"about.domain_blocks.preamble": "Mastodon vam općenito omogućuje pregled sadržaja i interakciju s korisnicima s bilo kojeg drugog poslužitelja u fediverse. Ovo su iznimke napravljene na ovom poslužitelju.",
"about.domain_blocks.silenced.explanation": "Obično nećete vidjeti profile i sadržaj s ovog poslužitelja, osim ako ga izričito ne potražite ili uključite u njega slijedeći ga.",
"about.domain_blocks.silenced.title": "Ograničen",
"about.domain_blocks.suspended.explanation": "Podatci s ovog poslužitelja neće se obrađivati, pohranjivati ili razmjenjivati, što onemogućuje bilo kakvu interakciju ili komunikaciju s korisnicima s ovog poslužitelja.",
"about.domain_blocks.suspended.title": "Suspendiran",
"about.not_available": "Te informacije nisu dostupne na ovom poslužitelju.",
"about.powered_by": "Decentralizirani društveni mediji koje pokreće {mastodon}",
"about.rules": "Pravila servera",
"account.account_note_header": "Bilješka",
"account.add_or_remove_from_list": "Dodaj ili ukloni s liste",
@ -14,6 +21,8 @@
"account.blocked": "Blokirano",
"account.browse_more_on_origin_server": "Pogledajte više na izvornom profilu",
"account.cancel_follow_request": "Withdraw follow request",
"account.copy": "Kopiraj vezu u profil",
"account.direct": "Privatno spomeni @{name}",
"account.disable_notifications": "Nemoj me obavjestiti kada @{name} napravi objavu",
"account.domain_blocked": "Domena je blokirana",
"account.edit_profile": "Uredi profil",
@ -21,7 +30,9 @@
"account.endorse": "Istakni na profilu",
"account.featured_tags.last_status_at": "Zadnji post {date}",
"account.featured_tags.last_status_never": "Nema postova",
"account.featured_tags.title": "Istaknuti hashtagovi {name}",
"account.follow": "Prati",
"account.follow_back": "Slijedi natrag",
"account.followers": "Pratitelji",
"account.followers.empty": "Nitko još ne prati korisnika/cu.",
"account.followers_counter": "{count, plural, one {{counter} pratitelj} other {{counter} pratitelja}}",
@ -32,6 +43,7 @@
"account.hide_reblogs": "Sakrij boostove od @{name}",
"account.in_memoriam": "U sjećanje.",
"account.joined_short": "Pridružen",
"account.languages": "Promjeni pretplaćene jezike",
"account.link_verified_on": "Vlasništvo ove poveznice provjereno je {date}",
"account.locked_info": "Status privatnosti ovog računa postavljen je na zaključano. Vlasnik ručno pregledava tko ih može pratiti.",
"account.media": "Medijski sadržaj",
@ -40,11 +52,14 @@
"account.mute_notifications_short": "Utišaj obavijesti",
"account.mute_short": "Utišaj",
"account.muted": "Utišano",
"account.mutual": "Uzajamno",
"account.no_bio": "Nije dan opis.",
"account.open_original_page": "Otvori originalnu stranicu",
"account.posts": "Objave",
"account.posts_with_replies": "Objave i odgovori",
"account.report": "Prijavi @{name}",
"account.requested": "Čekanje na potvrdu. Kliknite za poništavanje zahtjeva za praćenje",
"account.requested_follow": "{name} zatražio/la je praćenje",
"account.share": "Podijeli profil @{name}",
"account.show_reblogs": "Prikaži boostove od @{name}",
"account.statuses_counter": "{count, plural, one {{counter} toot} other {{counter} toota}}",
@ -54,11 +69,18 @@
"account.unendorse": "Ne ističi na profilu",
"account.unfollow": "Prestani pratiti",
"account.unmute": "Poništi utišavanje @{name}",
"account.unmute_notifications_short": "Uključi utišane obavijesti",
"account.unmute_short": "Poništi utišavanje",
"account_note.placeholder": "Kliknite za dodavanje bilješke",
"admin.dashboard.daily_retention": "Stopa zadržavanja korisnika po danu nakon prijave",
"admin.dashboard.monthly_retention": "Stopa zadržavanja korisnika po mjesecu nakon prijave",
"admin.dashboard.retention.average": "Prosječno",
"admin.dashboard.retention.cohort": "Mjesec prijave",
"admin.dashboard.retention.cohort_size": "Novi korisnici",
"admin.impact_report.instance_accounts": "Profili računa koji bi ovo izbrisali",
"admin.impact_report.instance_followers": "Sljedbenici koje bi izgubili naši korisnici",
"admin.impact_report.instance_follows": "Sljedbenici koje bi izgubili njihovi korisnici",
"admin.impact_report.title": "Sažetak učinka",
"alert.rate_limited.message": "Molimo pokušajte nakon {retry_time, time, medium}.",
"alert.rate_limited.title": "Ograničenje učestalosti",
"alert.unexpected.message": "Dogodila se neočekivana greška.",
@ -68,10 +90,14 @@
"audio.hide": "Sakrij audio",
"autosuggest_hashtag.per_week": "{count} tjedno",
"boost_modal.combo": "Možete pritisnuti {combo} kako biste preskočili ovo sljedeći put",
"bundle_column_error.copy_stacktrace": "Kopiraj izvješće o pogrešci",
"bundle_column_error.error.body": "Zaraženu stranicu nije moguće prikazati. To bi moglo biti zbog pogreške u našem kodu ili problema s kompatibilnošću preglednika.",
"bundle_column_error.error.title": "Oh, ne!",
"bundle_column_error.network.body": "Došlo je do pogreške prilikom pokušaja učitavanja ove stranice. Razlog može biti privremeni problem s internetskom vezom ili ovim poslužiteljem.",
"bundle_column_error.network.title": "Greška mreže",
"bundle_column_error.retry": "Pokušajte ponovno",
"bundle_column_error.return": "Na glavnu",
"bundle_column_error.routing.body": "Traženu stranicu nije moguće pronaći. Jeste li sigurni da je URL u adresnoj traci točan?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Zatvori",
"bundle_modal_error.message": "Nešto je pošlo po zlu tijekom učitavanja ove komponente.",
@ -171,6 +197,7 @@
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Evo kako će izgledati:",
"emoji_button.activity": "Aktivnost",
"emoji_button.clear": "Obriši",
"emoji_button.custom": "Prilagođeno",
"emoji_button.flags": "Zastave",
"emoji_button.food": "Hrana i piće",
@ -211,6 +238,7 @@
"explore.trending_links": "Novosti",
"explore.trending_statuses": "Objave",
"explore.trending_tags": "Hashtagovi",
"filter_modal.added.context_mismatch_title": "Nepodudaranje konteksta!",
"filter_modal.added.review_and_configure_title": "Postavke filtara",
"filter_modal.added.title": "Filtar dodan!",
"filter_modal.select_filter.prompt_new": "Nova kategorija: {name}",

@ -1,23 +1,84 @@
{
"account.add_or_remove_from_list": "Adder o remover ab listas",
"account.badges.group": "Gruppo",
"account.block": "Blocar @{name}",
"account.block_short": "Blocar",
"account.blocked": "Blocate",
"account.copy": "Copiar ligamine a profilo",
"account.edit_profile": "Modificar profilo",
"account.go_to_profile": "Vader al profilo",
"account.moved_to": "{name} indicava que lor nove conto ora es:",
"account.share": "Compartir profilo de @{name}",
"account.unblock": "Disblocar @{name}",
"account.unblock_short": "Disblocar",
"account.unendorse": "Non evidentiar sur le profilo",
"account_note.placeholder": "Clicca pro adder un nota",
"admin.dashboard.retention.cohort_size": "Nove usatores",
"audio.hide": "Celar audio",
"autosuggest_hashtag.per_week": "{count} per septimana",
"bundle_column_error.network.title": "Error de rete",
"bundle_column_error.retry": "Tentar novemente",
"bundle_column_error.return": "Retornar al initio",
"bundle_modal_error.close": "Clauder",
"bundle_modal_error.retry": "Tentar novemente",
"column.blocks": "Usatores blocate",
"column.directory": "Navigar profilos",
"column.favourites": "Favoritos",
"column.home": "Initio",
"column.lists": "Listas",
"column.notifications": "Notificationes",
"column_header.hide_settings": "Celar le parametros",
"column_header.show_settings": "Monstrar le parametros",
"column_subheading.settings": "Parametros",
"compose.language.change": "Cambiar le lingua",
"compose.language.search": "Cercar linguas...",
"compose.published.open": "Aperir",
"compose_form.poll.add_option": "Adder un option",
"compose_form.poll.remove_option": "Remover iste option",
"confirmation_modal.cancel": "Cancellar",
"confirmations.delete.confirm": "Deler",
"confirmations.delete_list.confirm": "Deler",
"confirmations.logout.confirm": "Clauder le session",
"copy_icon_button.copied": "Copiate al area de transferentia",
"copypaste.copy_to_clipboard": "Copiar al area de transferentia",
"disabled_account_banner.account_settings": "Parametros de conto",
"dismissable_banner.dismiss": "Dimitter",
"emoji_button.activity": "Activitate",
"emoji_button.custom": "Personalisate",
"emoji_button.search_results": "Resultatos de recerca",
"empty_column.account_unavailable": "Profilo non disponibile",
"errors.unexpected_crash.report_issue": "Signalar un defecto",
"explore.search_results": "Resultatos de recerca",
"explore.trending_links": "Novas",
"firehose.all": "Toto",
"firehose.local": "Iste servitor",
"firehose.remote": "Altere servitores",
"footer.about": "A proposito de",
"footer.directory": "Directorio de profilos",
"footer.privacy_policy": "Politica de confidentialitate",
"footer.source_code": "Vider le codice fonte",
"footer.status": "Stato",
"home.pending_critical_update.link": "Vider actualisationes",
"keyboard_shortcuts.my_profile": "Aperir tu profilo",
"lightbox.close": "Clauder",
"lightbox.next": "Sequente",
"link_preview.author": "Per {name}",
"lists.account.add": "Adder al lista",
"navigation_bar.about": "A proposito de"
"mute_modal.duration": "Duration",
"mute_modal.hide_notifications": "Celar notificationes de iste usator?",
"navigation_bar.about": "A proposito de",
"navigation_bar.advanced_interface": "Aperir in un interfacie web avantiate",
"navigation_bar.blocks": "Usatores blocate",
"navigation_bar.favourites": "Favoritos",
"navigation_bar.lists": "Listas",
"navigation_bar.logout": "Clauder le session",
"navigation_bar.preferences": "Preferentias",
"navigation_bar.security": "Securitate",
"notifications.column_settings.alert": "Notificationes de scriptorio",
"notifications.column_settings.filter_bar.advanced": "Monstrar tote le categorias",
"notifications.column_settings.sound": "Reproducer sono",
"notifications.filter.all": "Toto",
"onboarding.compose.template": "Salute #Mastodon!",
"onboarding.profile.save_and_continue": "Salvar e continuar",
"onboarding.share.title": "Compartir tu profilo"
}

@ -250,6 +250,7 @@
"error.unexpected_crash.explanation_addons": "Ti-ci págine ne posset esser monstrat correctmen. Li error es probabilmen causat de un extension al navigator o instrumentes por automatic traduction.",
"error.unexpected_crash.next_steps": "Prova recargar li págine. Si to ne auxilia, tu fórsan posse usar Mastodon per un diferent navigator o aplication.",
"error.unexpected_crash.next_steps_addons": "Prova desactivisar les e recargar li págine. Si to ne auxilia, tu fórsan posse usar Mastodon per un diferent navigator o aplication.",
"errors.unexpected_crash.copy_stacktrace": "Copiar cumul-tracie a paperiere",
"errors.unexpected_crash.report_issue": "Raportar un problema",
"explore.search_results": "Resultates de sercha",
"explore.suggested_follows": "Gente",
@ -350,6 +351,7 @@
"keyboard_shortcuts.heading": "Rapid-tastes",
"keyboard_shortcuts.home": "Aperter li hemal témpor-linea",
"keyboard_shortcuts.hotkey": "Rapid clave",
"keyboard_shortcuts.legend": "Monstrar ti-ci legende",
"keyboard_shortcuts.local": "Aperter li local témpor-linea",
"keyboard_shortcuts.mention": "Mentionar li autor",
"keyboard_shortcuts.muted": "Aperter li lista de silentiat usatores",

@ -2,7 +2,7 @@
"about.blocks": "Prižiūrimi serveriai",
"about.contact": "Kontaktuoti:",
"about.disclaimer": "Mastodon nemokama atvirojo kodo programa ir Mastodon gGmbH prekės ženklas.",
"about.domain_blocks.no_reason_available": "Priežastis nežinoma",
"about.domain_blocks.no_reason_available": "Priežastis nepateikta",
"about.domain_blocks.preamble": "Mastodon paprastai leidžia peržiūrėti turinį ir bendrauti su naudotojais iš bet kurio kito fediverse esančio serverio. Šios yra išimtys, kurios buvo padarytos šiame konkrečiame serveryje.",
"about.domain_blocks.silenced.explanation": "Paprastai nematysi profilių ir turinio iš šio serverio, nebent jį aiškiai ieškosi arba pasirinksi jį sekdamas (-a).",
"about.domain_blocks.silenced.title": "Ribota",
@ -35,7 +35,7 @@
"account.follow_back": "Sekti atgal",
"account.followers": "Sekėjai",
"account.followers.empty": "Šio naudotojo dar niekas neseka.",
"account.followers_counter": "{count, plural, one {{counter} sekėjas (-a)} few {{counter} sekėjai} many {{counter} sekėjo} other {{counter} sekėjų}}",
"account.followers_counter": "{count, plural, one {{counter} sekėjas} few {{counter} sekėjai} many {{counter} sekėjo} other {{counter} sekėjų}}",
"account.following": "Seka",
"account.following_counter": "{count, plural, one {{counter} Seka} few {{counter} Seka} many {{counter} Seka} other {{counter} Seka}}",
"account.follows.empty": "Šis (-i) naudotojas (-a) dar nieko neseka.",

@ -10,6 +10,7 @@
"account.badges.group": "குழு",
"account.block": "@{name} -ஐத் தடு",
"account.block_domain": "{domain} யில் இருந்து வரும் எல்லாவற்றையும் மறை",
"account.block_short": "தடு",
"account.blocked": "முடக்கப்பட்டது",
"account.browse_more_on_origin_server": "மேலும் உலாவ சுயவிவரத்திற்குச் செல்க",
"account.cancel_follow_request": "Withdraw follow request",
@ -18,20 +19,26 @@
"account.edit_profile": "சுயவிவரத்தை மாற்று",
"account.enable_notifications": "@{name} பதிவிட்டல் எனக்குத் தெரியப்படுத்தவும்",
"account.endorse": "சுயவிவரத்தில் வெளிப்படுத்து",
"account.featured_tags.last_status_never": "இடுகைகள் இல்லை",
"account.follow": "பின்தொடர்",
"account.follow_back": "பின்தொடரு",
"account.followers": "பின்தொடர்பவர்கள்",
"account.followers.empty": "இதுவரை யாரும் இந்த பயனரைப் பின்தொடரவில்லை.",
"account.followers_counter": "{count, plural, one {{counter} வாசகர்} other {{counter} வாசகர்கள்}}",
"account.following": "பின்தொடரும்",
"account.following_counter": "{count, plural,one {{counter} சந்தா} other {{counter} சந்தாக்கள்}}",
"account.follows.empty": "இந்த பயனர் இதுவரை யாரையும் பின்தொடரவில்லை.",
"account.go_to_profile": "சுயவிவரத்திற்குச் செல்லவும்",
"account.hide_reblogs": "இருந்து ஊக்கியாக மறை @{name}",
"account.link_verified_on": "இந்த இணைப்பை உரிமையாளர் சரிபார்க்கப்பட்டது {date}",
"account.locked_info": "இந்தக் கணக்கு தனியுரிமை நிலை பூட்டப்பட்டுள்ளது. அவர்களைப் பின்தொடர்பவர் யார் என்பதை உரிமையாளர் கைமுறையாக மதிப்பாய்வு செய்கிறார்.",
"account.media": "ஊடகங்கள்",
"account.mention": "குறிப்பிடு @{name}",
"account.mute": "ஊமையான @{name}",
"account.mute_notifications_short": "அறிவிப்புகளை ஒலியடக்கு",
"account.mute_short": "அமைதியாக்கு",
"account.muted": "முடக்கியது",
"account.no_bio": "விளக்கம் எதுவும் வழங்கப்படவில்லை.",
"account.posts": "டூட்டுகள்",
"account.posts_with_replies": "Toots மற்றும் பதில்கள்",
"account.report": "@{name} -ஐப் புகாரளி",
@ -61,15 +68,29 @@
"audio.hide": "ஆடியோவை மறை",
"autosuggest_hashtag.per_week": "ஒவ்வொரு வாரம் {count}",
"boost_modal.combo": "நீங்கள் இதை அடுத்தமுறை தவிர்க்க {combo} வை அழுத்தவும்",
"bundle_column_error.error.title": "அடடே!",
"bundle_column_error.network.body": "இந்தப் பக்கத்தைத் திறக்கும்பொழுது ஒரு பிழை ஏற்பட்டுவிட்டது. இது உங்கள் இணைய தொடர்பில் அல்லது இப்பத்தின் வழங்க்கியில் ஏற்பட்டுள்ள ஒரு தற்காலிக பிரச்சணையாக இருக்கலாம்.",
"bundle_column_error.network.title": "பிணையப் பிழை",
"bundle_column_error.retry": "மீண்டும் முயற்சிக்கவும்",
"bundle_column_error.return": "முகப்பிற்கு செல்லவும்",
"bundle_column_error.routing.body": "கேட்கப்பட்ட பக்கத்தைக் காணவில்லை. நீங்கள் உள்ளிட்ட முகவரி சரியனதா?",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "மூடுக",
"bundle_modal_error.message": "இக்கூற்றை ஏற்றம் செய்யும்பொழுது ஏதோ தவறு ஏற்பட்டுள்ளது.",
"bundle_modal_error.retry": "மீண்டும் முயற்சி செய்",
"closed_registrations.other_server_instructions": "மேச்டடான் இரு பரவலாக்கப்பட்ட மென்பொருள் என்பதால், நீங்கள் வேரு ஒரு வழங்கியில் கணக்கை உருவாக்கியிருந்தாலும் இந்த வழங்கியில் பயன்படுத்தலாம்.",
"closed_registrations_modal.description": "{domain} இல் இப்பொழுது கணக்குகள் உருவாக்க முடியாது. நீங்கள் மேச்டடான் பயன்படுத்த, குறிப்பாக {domain} முகவரியில் கணக்கைத் துவங்க வேண்டும் என்ற அவசியமில்லை என்பதை மனதில் வைத்துக் கொள்ளவும்.",
"closed_registrations_modal.find_another_server": "வேறொரு வழங்கியைக் கண்டுபிடி",
"closed_registrations_modal.preamble": "மேச்டடான் ஒரு பரவலாக்கப்பட்ட மென்பொருள். ஆதனால் நீங்கள் எங்குக் கணக்கை உருவாக்கினாலும் இந்த வழங்கியில் உள்ள யாருடன் வேண்டும் என்றாலும் உரவாடலாம். நீங்களே கூட ஒரு வழங்கியை நிறுவலாம்!",
"closed_registrations_modal.title": "மேச்டடான் கணக்கு துவங்கப்படுகிறது",
"column.about": "பற்றி",
"column.blocks": "தடுக்கப்பட்ட பயனர்கள்",
"column.bookmarks": "அடையாளக்குறிகள்",
"column.community": "சுய நிகழ்வு காலவரிசை",
"column.direct": "தனிப்பட்ட குறிப்புகள்",
"column.directory": "சுயவிவரங்களை உலாவு",
"column.domain_blocks": "மறைந்திருக்கும் திரளங்கள்",
"column.favourites": "பிடித்தவை",
"column.follow_requests": "பின்தொடர அனுமதிகள்",
"column.home": "முகப்பு",
"column.lists": "பட்டியல்கள்",
@ -90,6 +111,9 @@
"community.column_settings.remote_only": "தொலைவிலிருந்து மட்டுமே",
"compose.language.change": "மொழியை மாற்று",
"compose.language.search": "தேடல் மொழிகள்...",
"compose.published.body": "பதிவிடப்பட்டது.",
"compose.published.open": "திற",
"compose.saved.body": "பதிவு சேமிக்கப்பட்டது.",
"compose_form.direct_message_warning_learn_more": "மேலும் அறிய",
"compose_form.encryption_warning": "Mastodonல் உள்ள பதிவுகள் முறையாக என்க்ரிப்ட்(encrypt) செய்யபடவில்லை. அதனால் முக்கிய தகவல்களை இங்கே பகிர வேண்டாம்.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
@ -180,6 +204,10 @@
"error.unexpected_crash.next_steps": "பக்கத்தைப் புதுப்பித்துப் பார்க்கவும். அப்படியும் வேலை செய்யவில்லை எனில், மாஸ்டடானை வேறு ஒரு உலாவியின் மூலமோ, அல்லது பொருத்தமான செயலியின் மூலமோ பயன்படுத்திப் பார்க்கவும்.",
"errors.unexpected_crash.copy_stacktrace": "Stacktrace-ஐ clipboard-ல் நகலெடு",
"errors.unexpected_crash.report_issue": "புகாரளி",
"explore.title": "உலாவு",
"explore.trending_links": "செய்திகள்",
"explore.trending_statuses": "பதிவுகள்",
"explore.trending_tags": "ஹேஷ்டேக்குகள்",
"follow_request.authorize": "அனுமதியளி",
"follow_request.reject": "நிராகரி",
"follow_requests.unlocked_explanation": "உங்கள் கணக்கு பூட்டப்படவில்லை என்றாலும், இந்தக் கணக்குகளிலிருந்து உங்களைப் பின்தொடர விரும்பும் கோரிக்கைகளை நீங்கள் பரீசீலிப்பது நலம் என்று {domain} ஊழியர் எண்ணுகிறார்.",

@ -2,8 +2,13 @@ import { Map as ImmutableMap } from 'immutable';
import { ACCOUNT_LOOKUP_FAIL } from '../actions/accounts';
import { importAccounts } from '../actions/accounts_typed';
import { domain } from '../initial_state';
export const normalizeForLookup = str => str.toLowerCase();
export const normalizeForLookup = str => {
str = str.toLowerCase();
const trailingIndex = str.indexOf(`@${domain.toLowerCase()}`);
return (trailingIndex > 0) ? str.slice(0, trailingIndex) : str;
};
const initialState = ImmutableMap();

@ -77,6 +77,7 @@ class Request
@url = Addressable::URI.parse(url).normalize
@http_client = options.delete(:http_client)
@allow_local = options.delete(:allow_local)
@full_path = options.delete(:with_query_string)
@options = options.merge(socket_class: use_proxy? || @allow_local ? ProxySocket : Socket)
@options = @options.merge(timeout_class: PerOperationWithDeadline, timeout_options: TIMEOUT)
@options = @options.merge(proxy_url) if use_proxy?
@ -146,7 +147,7 @@ class Request
private
def set_common_headers!
@headers[REQUEST_TARGET] = "#{@verb} #{@url.path}"
@headers[REQUEST_TARGET] = request_target
@headers['User-Agent'] = Mastodon::Version.user_agent
@headers['Host'] = @url.host
@headers['Date'] = Time.now.utc.httpdate
@ -157,6 +158,14 @@ class Request
@headers['Digest'] = "SHA-256=#{Digest::SHA256.base64digest(@options[:body])}"
end
def request_target
if @url.query.nil? || !@full_path
"#{@verb} #{@url.path}"
else
"#{@verb} #{@url.path}?#{@url.query}"
end
end
def signature
algorithm = 'rsa-sha256'
signature = Base64.strict_encode64(@keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))

@ -23,7 +23,7 @@ Rails.application.configure do
if Rails.env.production?
"ws#{https ? 's' : ''}://#{web_host}"
else
"ws://#{ENV['REMOTE_DEV'] == 'true' ? host.split(':').first : 'localhost'}:4000"
"ws://#{host.split(':').first}:4000"
end
end

@ -659,6 +659,7 @@ cy:
created_at: Adroddwyd
delete_and_resolve: Dileu postiadau
forwarded: Wedi'i anfon ymlaen
forwarded_replies_explanation: Mae'r adroddiad hwn gan ddefnyddiwr o weinydd arall ac am gynnwys pell. Mae wedi ei anfon ymlaen atoch chi oherwydd bod y cynnwys sy'n cael ei adrodd yn ateb i un o'ch defnyddwyr.
forwarded_to: Wedi'i anfon ymlaen i %{domain}
mark_as_resolved: Nodi fel wedi'i ddatrys
mark_as_sensitive: Marcio fel sensitif

@ -18,6 +18,8 @@ ie:
confirmation_instructions:
action: Verificar e-posta
action_with_app: Confirma e retorna a%{app}
explanation: Tu ha creat un conto sur %{host} con ti-ci e-posta, quel tu posse activar per un sol clicc. Si it ne esset tu qui creat li conto, ples ignorar ti-ci missage.
explanation_when_pending: Tu ha demandat un invitation a %{host} con ti-ci e-posta. Pos confirmation de tui adresse, noi va inspecter tui aplication. Tu posse inloggar por changear detallies o deleter li conto, ma li pluparte del functiones va restar ínusabil til quande tui conto es aprobat. Tui data va esser deletet si tui conto es rejectet, e in ti casu tu ne besona far quelcunc cose. Si it ne esset tu qui creat li conto, ples ignorar ti-ci missage.
title: Verificar e-posta
email_changed:
explanation: 'Li e-mail adresse de tui es changeat a:'

@ -70,6 +70,10 @@ ie:
invalid_redirect_uri: Li uri de redirection includet ne es valid.
invalid_request:
unknown: Li petition manca un postulat parametre, include un ne apoyat parametre-valore, o es altrimen mal format.
invalid_token:
expired: Li access-clave expirat
revoked: Li access-clave esset revocat
unknown: Li accesse-clave es ínvalid
unsupported_grant_type: Li tip de autorisation concedet ne es subtenet per li autorisant servitor.
unsupported_response_type: Li autorisant servitor ne subtene ti-ci tip de response.
flash:
@ -151,6 +155,7 @@ ie:
write:filters: crea filtres
write:follows: sequer homes
write:lists: crear listes
write:media: adcargar files de medie
write:mutes: silentiar persones e conversationes
write:notifications: aclarar tui notificationes
write:reports: raportar altri persones

@ -1559,7 +1559,7 @@ fi:
last_active: Viimeksi aktiivinen
most_recent: Viimeisimmät
moved: Muuttaneet
mutual: Molemmat
mutual: Seuraatte toisianne
primary: Ensisijaiset
relationship: Suhde
remove_selected_domains: Poista kaikki seuraajat valituista verkkotunnuksista

@ -112,6 +112,7 @@ ie:
promote: Promoer
protocol: Protocol
public: Public
push_subscription_expires: Subscrition a PuSH expira
redownload: Recargar li profil
redownloaded_msg: Successosimen recargat li profil de %{username} del original fonte
reject: Rejecter
@ -465,6 +466,7 @@ ie:
unsuppress: Restaurar seque-recomandation
instances:
availability:
failure_threshold_reached: Límite de falliment atinget ye %{date}.
failures_recorded:
one: Fallit prova por %{count} die.
other: Fallit provas por %{count} dies.
@ -478,6 +480,8 @@ ie:
confirm_purge: Vole tu vermen permanentmen deleter data de ti dominia?
content_policies:
comment: Internal nota
description_html: Tu posse definar planes de contenete a aplicar sur omni contos de ti-ci dominia e omni su subdominias.
limited_federation_mode_description_html: Tu posse selecter ca permisser federation a ti-ci dominia.
policies:
reject_media: Rejecter medie
reject_reports: Rejecter raportes
@ -704,6 +708,7 @@ ie:
manage_users: Gerer usatores
manage_users_description: Permisse que usatores vide detallies de altri usatores e fa actiones de moderation contra les
manage_webhooks: Gerer Webcrocs
manage_webhooks_description: Permisse que usatores configura webcrocs por evenimentes administrativ
view_audit_log: Vider li Jurnale de Audit
view_audit_log_description: Permisse que usatores vide li historie de administrativ actiones sur li servitor
view_dashboard: Vider Panel de Control
@ -714,6 +719,7 @@ ie:
rules:
add_new: Adjunter un regule
delete: Deleter
description_html: Benque li pluparte di que ili ha leet e acorda con li termines de servicie, presc nequi perlee les til quande un problema eveni. <strong>Tu posse facilitar li perletura del regules de tui servitor per dar les sur un liste de plat balle-punctus.</strong> Li índividual regules posse esser curt e simplic, ma mem un liste de micri punctus posse esser tro exigent por li letor si it es tro grand.
edit: Redacter regul
empty: Ancor null regules de servitor ha esset definit.
title: Regules del servitor
@ -724,6 +730,11 @@ ie:
appearance:
preamble: Customisar li interfacie web de Mastodon.
title: Aspecte
branding:
title: Marca
captcha_enabled:
desc_html: To ci usa extern scrites de hCaptcha, quel posse esser ínquietant pro rasones de securitá e privatie. In plu, <strong>it posse far li processu de registration mult plu desfacil (particularimen por tis con deshabilitás)</strong>. Pro ti rasones, ples considerar alternativ mesuras, tales quam registration per aprobation o invitation.
title: Exige que nov usatores solue un CAPTCHA por confirmar lor conto
content_retention:
title: Retention de contenete
discovery:
@ -1374,6 +1385,7 @@ ie:
media_attachments:
validations:
images_and_video: On ne posse atachar un video a un posta quel ja contene images
too_many: Ne posse atachar plu quam 4 files
migrations:
acct: Translocat a
cancel: Anullar redirection
@ -1401,6 +1413,8 @@ ie:
carry_blocks_over_text: Ti usator translocat se de %{acct}, quel tu hat bloccat.
carry_mutes_over_text: Ti-ci usator movet se de %{acct}, quel tu hat silentiat.
copy_account_note_text: 'Vi tui notas pri ti usator qui translocat se de %{acct}:'
navigation:
toggle_menu: Changear menú
notification_mailer:
admin:
report:
@ -1443,6 +1457,7 @@ ie:
number:
human:
decimal_units:
format: "%n%u"
units:
billion: B
million: M
@ -1800,6 +1815,8 @@ ie:
success: Tui clave de securitá esset adjuntet con successe.
delete: Deleter
delete_confirmation: Vole tu vermen deleter ti-ci clave de securitá?
destroy:
success: Tui clave de securitá esset successosimen deletet.
invalid_credential: Ínvalid clave de securitá
not_enabled: Tu ancor ne ha possibilisat WebAuthn
not_supported: Ti-ci navigator ne subtene claves de securitá

@ -6,6 +6,7 @@ ie:
discoverable: Tui public postas e profil posse esser recomandat in multiplic areas de Mastodon e tui profil posse esser suggestat a altri usatores.
display_name: Tui complet nómine o tui amusant nómine.
fields: Tui websitu, pronómines, etá, quocunc quel tu vole.
indexable: Tui public postas posse aparir in sercha-resultates sur Mastodon. E in omni casu, tis qui ha interactet con tui postas va posser serchar e trovar les.
note: 'Tu posse @mentionar altri persones o #hashtags.'
unlocked: Persones va posser sequer te sin petir aprobation. Desselecte si tu vole manualmen tractar petitiones de sequer e decider ca acceptar o rejecter nov sequitores.
account_alias:
@ -65,20 +66,28 @@ ie:
hide: Celar completmen li contenete filtrat, quam si it ne existe
warn: Celar li contenete filtrat detra un avise mentionant li titul del filtre
form_admin_settings:
backups_retention_period: Mantener usator-generat archives por li specificat quantitá de dies.
bootstrap_timeline_accounts: Ti-ci contos va esser pinglat al parte superiori del recomandationes por nov usatores.
mascot: Substitue li ilustration in li avansat interfacie web.
peers_api_enabled: Un liste de nómines de dominia queles ti-ci servitor ha incontrat in li fediverse. Ci null data es includet pri ca tu confedera con un cert servitor o ne; it indica solmen que tui servitor conosse it. Usat per servicies colectent general statisticas pri federation.
profile_directory: Li profilarium monstra omni usatores volent esser decovribil.
site_contact_email: Qualmen on posse contacter te por inquestes legal o de apoy.
site_contact_username: Qualmen li gente posse atinger te sur Mastodon.
site_short_description: Un curt descrition por auxiliar identificar tui servitor. Qui gere it, por qual persones it es?
site_title: Quant persones posse aluder a tui servitor ultra su nómine de dominia.
status_page_url: URL de un págine monstrant li statu de ti-ci servitor durant un ruptura de servicie
theme: Li dessine quel ínregistrat visitantes e nov usatores vide.
thumbnail: Un image de dimensiones circa 2:1 monstrat along tui servitor-information.
timeline_preview: Ínregistrat visitantes va posser vider li max recent public postas disponibil che li servitor.
trends: Tendenties monstra quel postas, hashtags e novas es ganiant atention sur tui servitor.
trends_as_landing_page: Monstrar populari contenete a ínregistrat visitantes vice un description del servitor. Besona que tendenties es activisat.
form_challenge:
current_password: Tu nu intra un area secur
ip_block:
comment: Facultativ. Ne obliviar pro quo tu adjuntet ti-ci regul.
expires_in: IP-adresses es un ressurse finit, quelcvez partit e transferet de manu a manu. Pro to, un índefinit bloccada de IP ne es recomandat.
severities:
no_access: Bloccar accesse a omni ressurses
sign_up_block: Nov registrationes ne va esser possibil
sign_up_requires_approval: Nov registrationes va besonar tui aprobation
severity: Selecter quo va evenir con demandes ex ti-ci IP
@ -102,6 +111,10 @@ ie:
name: Etiquette
value: Contenete
indexable: Includer public postas in resultates de sercha
account_alias:
acct: Usator-nómine del anteyan conto
account_migration:
acct: Usator-nómine del nov conto
account_warning_preset:
text: Textu prefigurat
title: Titul
@ -142,11 +155,13 @@ ie:
honeypot: "%{label} (ne plenar)"
irreversible: Lassar cader vice celar
locale: Lingue del interfacie
max_uses: Max grand númere de usas
new_password: Nov passa-parol
note: Biografie
password: Passa-parol
phrase: Clave-parol o frase
setting_advanced_layout: Possibilisar web-interfacie avansat
setting_always_send_emails: Sempre misser notificationes de e-posta
setting_default_language: Lingue in quel postar
setting_default_privacy: Privatie de postada
setting_default_sensitive: Sempre marcar medie quam sensitiv
@ -162,18 +177,27 @@ ie:
severity: Severitá
sign_in_token_attempt: Code de securitá
title: Titul
type: Specie de importation
username: Nómine de usator
whole_word: Plen parol
featured_tag:
name: Hashtag
filters:
actions:
hide: Celar completmen
warn: Celar con un admonition
form_admin_settings:
backups_retention_period: Periode de retener archives de usator
bootstrap_timeline_accounts: Sempre recomandar ti-ci contos a nov usatores
closed_registrations_message: Customisat missage quande registration ne disponibil
custom_css: Custom CSS
profile_directory: Possibilisar profilarium
registrations_mode: Qui posse registrar se
show_domain_blocks: Vider bloccas de dominia
show_domain_blocks_rationale: Monstrar pro quo cert dominias esset bloccat
site_contact_email: Contact e-mail adresse
site_contact_username: Usator-nómine de contact
site_extended_description: Extendet descrition
site_title: Nómine de servitor
theme: Predefenit tema
trendable_by_default: Possibilisar tendenties sin priori inspection
@ -220,6 +244,8 @@ ie:
events: Evenimentes activisat
url: URL de punctu terminal
'no': 'No'
not_recommended: Ne recomandat
overridden: Substituet
recommended: Recomandat
required:
mark: "*"

@ -574,6 +574,7 @@ sk:
manage_announcements: Spravuj oboznámenia
manage_appeals: Spravuj námietky
manage_blocks: Spravuj blokovania
manage_custom_emojis: Spravuj vlastné emotikony
manage_federation: Spravuj federáciu
manage_invites: Spravuj pozvánky
manage_reports: Spravuj hlásenia
@ -696,6 +697,7 @@ sk:
title: Populárne príspevky
tags:
dashboard:
tag_accounts_measure: unikátnych použití
tag_servers_measure: iné servery
tag_uses_measure: užívateľov celkovo
not_usable: Nemôže byť použitý

@ -77,90 +77,135 @@ class BackfillAdminActionLogs < ActiveRecord::Migration[6.1]
def up
safety_assured do
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
next if log.account.nil?
process_logs_for_account
process_logs_for_user
process_logs_for_report
process_logs_for_domain_block
process_logs_for_domain_allow
process_logs_for_email_domain_block
process_logs_for_unavailable_domain
process_logs_for_status
process_logs_for_account_warning
process_logs_for_announcement
process_logs_for_ip_block
process_logs_for_custom_emoji
process_logs_for_canonical_email_block
process_logs_for_appeal
end
end
log.update_attribute('human_identifier', log.account.acct)
end
def down; end
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
next if log.user.nil?
private
log.update_attribute('human_identifier', log.user.account.acct)
log.update_attribute('route_param', log.user.account_id)
end
def process_logs_for_account
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
next if log.account.nil?
AdminActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
log.update_attribute('human_identifier', log.account.acct)
end
end
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
next if log.domain_block.nil?
def process_logs_for_user
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
next if log.user.nil?
log.update_attribute('human_identifier', log.domain_block.domain)
end
log.update_attribute('human_identifier', log.user.account.acct)
log.update_attribute('route_param', log.user.account_id)
end
end
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
next if log.domain_allow.nil?
def process_logs_for_report
AdminActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
end
log.update_attribute('human_identifier', log.domain_allow.domain)
end
def process_logs_for_domain_block
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
next if log.domain_block.nil?
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
next if log.email_domain_block.nil?
log.update_attribute('human_identifier', log.domain_block.domain)
end
end
log.update_attribute('human_identifier', log.email_domain_block.domain)
end
def process_logs_for_domain_allow
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
next if log.domain_allow.nil?
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
next if log.unavailable_domain.nil?
log.update_attribute('human_identifier', log.domain_allow.domain)
end
end
log.update_attribute('human_identifier', log.unavailable_domain.domain)
end
def process_logs_for_email_domain_block
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
next if log.email_domain_block.nil?
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
next if log.status.nil?
log.update_attribute('human_identifier', log.email_domain_block.domain)
end
end
log.update_attribute('human_identifier', log.status.account.acct)
log.update_attribute('permalink', log.status.uri)
end
def process_logs_for_unavailable_domain
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
next if log.unavailable_domain.nil?
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
next if log.account_warning.nil?
log.update_attribute('human_identifier', log.unavailable_domain.domain)
end
end
log.update_attribute('human_identifier', log.account_warning.account.acct)
end
def process_logs_for_status
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
next if log.status.nil?
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
next if log.announcement.nil?
log.update_attribute('human_identifier', log.status.account.acct)
log.update_attribute('permalink', log.status.uri)
end
end
log.update_attribute('human_identifier', log.announcement.text)
end
def process_logs_for_account_warning
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
next if log.account_warning.nil?
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
next if log.ip_block.nil?
log.update_attribute('human_identifier', log.account_warning.account.acct)
end
end
log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
end
def process_logs_for_announcement
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
next if log.announcement.nil?
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
next if log.custom_emoji.nil?
log.update_attribute('human_identifier', log.announcement.text)
end
end
log.update_attribute('human_identifier', log.custom_emoji.shortcode)
end
def process_logs_for_ip_block
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
next if log.ip_block.nil?
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
next if log.canonical_email_block.nil?
log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
end
end
log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash)
end
def process_logs_for_custom_emoji
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
next if log.custom_emoji.nil?
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
next if log.appeal.nil?
log.update_attribute('human_identifier', log.custom_emoji.shortcode)
end
end
log.update_attribute('human_identifier', log.appeal.account.acct)
log.update_attribute('route_param', log.appeal.account_warning_id)
end
def process_logs_for_canonical_email_block
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
next if log.canonical_email_block.nil?
log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash)
end
end
def down; end
def process_logs_for_appeal
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
next if log.appeal.nil?
log.update_attribute('human_identifier', log.appeal.account.acct)
log.update_attribute('route_param', log.appeal.account_warning_id)
end
end
end

@ -77,90 +77,135 @@ class BackfillAdminActionLogsAgain < ActiveRecord::Migration[6.1]
def up
safety_assured do
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
next if log.account.nil?
process_logs_for_account
process_logs_for_user
process_logs_for_report
process_logs_for_domain_block
process_logs_for_domain_allow
process_logs_for_email_domain_block
process_logs_for_unavailable_domain
process_logs_for_status
process_logs_for_account_warning
process_logs_for_announcement
process_logs_for_ip_block
process_logs_for_custom_emoji
process_logs_for_canonical_email_block
process_logs_for_appeal
end
end
log.update_attribute('human_identifier', log.account.acct)
end
def down; end
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
next if log.user.nil?
private
log.update_attribute('human_identifier', log.user.account.acct)
log.update_attribute('route_param', log.user.account_id)
end
def process_logs_for_account
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
next if log.account.nil?
AdminActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
log.update_attribute('human_identifier', log.account.acct)
end
end
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
next if log.domain_block.nil?
def process_logs_for_user
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
next if log.user.nil?
log.update_attribute('human_identifier', log.domain_block.domain)
end
log.update_attribute('human_identifier', log.user.account.acct)
log.update_attribute('route_param', log.user.account_id)
end
end
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
next if log.domain_allow.nil?
def process_logs_for_report
AdminActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
end
log.update_attribute('human_identifier', log.domain_allow.domain)
end
def process_logs_for_domain_block
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
next if log.domain_block.nil?
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
next if log.email_domain_block.nil?
log.update_attribute('human_identifier', log.domain_block.domain)
end
end
log.update_attribute('human_identifier', log.email_domain_block.domain)
end
def process_logs_for_domain_allow
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
next if log.domain_allow.nil?
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
next if log.unavailable_domain.nil?
log.update_attribute('human_identifier', log.domain_allow.domain)
end
end
log.update_attribute('human_identifier', log.unavailable_domain.domain)
end
def process_logs_for_email_domain_block
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
next if log.email_domain_block.nil?
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
next if log.status.nil?
log.update_attribute('human_identifier', log.email_domain_block.domain)
end
end
log.update_attribute('human_identifier', log.status.account.acct)
log.update_attribute('permalink', log.status.uri)
end
def process_logs_for_unavailable_domain
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
next if log.unavailable_domain.nil?
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
next if log.account_warning.nil?
log.update_attribute('human_identifier', log.unavailable_domain.domain)
end
end
log.update_attribute('human_identifier', log.account_warning.account.acct)
end
def process_logs_for_status
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
next if log.status.nil?
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
next if log.announcement.nil?
log.update_attribute('human_identifier', log.status.account.acct)
log.update_attribute('permalink', log.status.uri)
end
end
log.update_attribute('human_identifier', log.announcement.text)
end
def process_logs_for_account_warning
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
next if log.account_warning.nil?
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
next if log.ip_block.nil?
log.update_attribute('human_identifier', log.account_warning.account.acct)
end
end
log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
end
def process_logs_for_announcement
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
next if log.announcement.nil?
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
next if log.custom_emoji.nil?
log.update_attribute('human_identifier', log.announcement.text)
end
end
log.update_attribute('human_identifier', log.custom_emoji.shortcode)
end
def process_logs_for_ip_block
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
next if log.ip_block.nil?
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
next if log.canonical_email_block.nil?
log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
end
end
log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash)
end
def process_logs_for_custom_emoji
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
next if log.custom_emoji.nil?
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
next if log.appeal.nil?
log.update_attribute('human_identifier', log.custom_emoji.shortcode)
end
end
log.update_attribute('human_identifier', log.appeal.account.acct)
log.update_attribute('route_param', log.appeal.account_warning_id)
end
def process_logs_for_canonical_email_block
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
next if log.canonical_email_block.nil?
log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash)
end
end
def down; end
def process_logs_for_appeal
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
next if log.appeal.nil?
log.update_attribute('human_identifier', log.appeal.account.acct)
log.update_attribute('route_param', log.appeal.account_warning_id)
end
end
end

@ -4,6 +4,7 @@ require_relative '../../../config/boot'
require_relative '../../../config/environment'
require 'thor'
require 'pastel'
require_relative 'progress_helper'
module Mastodon

@ -1,7 +1,5 @@
# frozen_string_literal: true
require 'tty-prompt'
module Mastodon::CLI
module Federation
extend ActiveSupport::Concern
@ -30,45 +28,39 @@ module Mastodon::CLI
LONG_DESC
def self_destruct
if SelfDestructHelper.self_destruct?
prompt.ok('Self-destruct mode is already enabled for this Mastodon server')
say('Self-destruct mode is already enabled for this Mastodon server', :green)
pending_accounts = Account.local.without_suspended.count + Account.local.suspended.joins(:deletion_request).count
sidekiq_stats = Sidekiq::Stats.new
if pending_accounts.positive?
prompt.warn("#{pending_accounts} accounts are still pending deletion.")
say("#{pending_accounts} accounts are still pending deletion.", :yellow)
elsif sidekiq_stats.enqueued.positive?
prompt.warn('Deletion notices are still being processed')
say('Deletion notices are still being processed', :yellow)
elsif sidekiq_stats.retry_size.positive?
prompt.warn('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry')
say('At least one delivery attempt for each deletion notice has been made, but some have failed and are scheduled for retry', :yellow)
else
prompt.ok('Every deletion notice has been sent! You can safely delete all data and decomission your servers!')
say('Every deletion notice has been sent! You can safely delete all data and decomission your servers!', :green)
end
exit(0)
end
exit(1) unless prompt.ask('Type in the domain of the server to confirm:', required: true) == Rails.configuration.x.local_domain
exit(1) unless ask('Type in the domain of the server to confirm:') == Rails.configuration.x.local_domain
prompt.warn('This operation WILL NOT be reversible.')
prompt.warn('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.')
prompt.warn('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).')
say('This operation WILL NOT be reversible.', :yellow)
say('While the data won\'t be erased locally, the server will be in a BROKEN STATE afterwards.', :yellow)
say('The deletion process itself may take a long time, and will be handled by Sidekiq, so do not shut it down until it has finished (you will be able to re-run this command to see the state of the self-destruct process).', :yellow)
exit(1) if prompt.no?('Are you sure you want to proceed?')
exit(1) if no?('Are you sure you want to proceed?')
self_destruct_value = Rails.application.message_verifier('self-destruct').generate(Rails.configuration.x.local_domain)
prompt.ok('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:')
prompt.ok(" SELF_DESTRUCT=#{self_destruct_value}")
prompt.ok("\nYou can re-run this command to see the state of the self-destruct process.")
rescue TTY::Reader::InputInterrupt
say('To switch Mastodon to self-destruct mode, add the following variable to your evironment (e.g. by adding a line to your `.env.production`) and restart all Mastodon processes:', :green)
say(" SELF_DESTRUCT=#{self_destruct_value}", :green)
say("\nYou can re-run this command to see the state of the self-destruct process.", :green)
rescue Interrupt
exit(1)
end
private
def prompt
@prompt ||= TTY::Prompt.new
end
end
end
end

@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'tty-prompt'
require_relative 'base'
module Mastodon::CLI

@ -25,7 +25,7 @@ module Mastodon
end
def catstodon_revision
'1.0.2'
'1.0.3'
end
def build_metadata

@ -169,7 +169,7 @@
"@types/react-dom": "^18.2.4",
"@types/react-helmet": "^6.1.6",
"@types/react-immutable-proptypes": "^2.1.0",
"@types/react-motion": "^0.0.39",
"@types/react-motion": "^0.0.40",
"@types/react-overlays": "^3.1.0",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
@ -184,7 +184,7 @@
"@types/webpack": "^4.41.33",
"@types/yargs": "^17.0.24",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@typescript-eslint/parser": "^6.17.0",
"babel-jest": "^29.5.0",
"eslint": "^8.41.0",
"eslint-config-prettier": "^9.0.0",
@ -192,7 +192,7 @@
"eslint-import-resolver-typescript": "^3.5.5",
"eslint-plugin-formatjs": "^4.10.1",
"eslint-plugin-import": "~2.29.0",
"eslint-plugin-jsdoc": "^46.1.0",
"eslint-plugin-jsdoc": "^48.0.0",
"eslint-plugin-jsx-a11y": "~6.8.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-promise": "~6.1.1",

@ -20,4 +20,157 @@ describe Mastodon::CLI::Main do
.to output_results(Mastodon::Version.to_s)
end
end
describe '#self_destruct' do
let(:action) { :self_destruct }
context 'with self destruct mode enabled' do
before do
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(true)
end
context 'with pending accounts' do
before { Fabricate(:account) }
it 'reports about pending accounts' do
expect { subject }
.to output_results(
'already enabled',
'still pending deletion'
)
.and raise_error(SystemExit)
end
end
context 'with sidekiq notices being processed' do
before do
Account.delete_all
stats_double = instance_double(Sidekiq::Stats, enqueued: 5)
allow(Sidekiq::Stats).to receive(:new).and_return(stats_double)
end
it 'reports about notices' do
expect { subject }
.to output_results(
'already enabled',
'notices are still being'
)
.and raise_error(SystemExit)
end
end
context 'with sidekiq failed deliveries' do
before do
Account.delete_all
stats_double = instance_double(Sidekiq::Stats, enqueued: 0, retry_size: 10)
allow(Sidekiq::Stats).to receive(:new).and_return(stats_double)
end
it 'reports about notices' do
expect { subject }
.to output_results(
'already enabled',
'some have failed and are scheduled'
)
.and raise_error(SystemExit)
end
end
context 'with self descruct mode ready' do
before do
Account.delete_all
stats_double = instance_double(Sidekiq::Stats, enqueued: 0, retry_size: 0)
allow(Sidekiq::Stats).to receive(:new).and_return(stats_double)
end
it 'reports about notices' do
expect { subject }
.to output_results(
'already enabled',
'can safely delete all data'
)
.and raise_error(SystemExit)
end
end
end
context 'with self destruct mode disabled' do
before do
allow(SelfDestructHelper).to receive(:self_destruct?).and_return(false)
end
context 'with an incorrect response to hostname' do
before do
answer_hostname_incorrectly
end
it 'exits silently' do
expect { subject }
.to raise_error(SystemExit)
end
end
context 'with a correct response to hostname but no to proceed' do
before do
answer_hostname_correctly
decline_proceed
end
it 'passes first step but stops before instructions' do
expect { subject }
.to output_results('operation WILL NOT')
.and raise_error(SystemExit)
end
end
context 'with a correct response to hostname and yes to proceed' do
before do
answer_hostname_correctly
accept_proceed
end
it 'instructs to set the appropriate environment variable' do
expect { subject }
.to output_results(
'operation WILL NOT',
'the following variable'
)
end
end
private
def answer_hostname_incorrectly
allow(cli.shell)
.to receive(:ask)
.with('Type in the domain of the server to confirm:')
.and_return('wrong.host')
.once
end
def answer_hostname_correctly
allow(cli.shell)
.to receive(:ask)
.with('Type in the domain of the server to confirm:')
.and_return(Rails.configuration.x.local_domain)
.once
end
def decline_proceed
allow(cli.shell)
.to receive(:no?)
.with('Are you sure you want to proceed?')
.and_return(true)
.once
end
def accept_proceed
allow(cli.shell)
.to receive(:no?)
.with('Are you sure you want to proceed?')
.and_return(false)
.once
end
end
end
end

@ -184,4 +184,58 @@ describe Mastodon::CLI::Media do
end
end
end
describe '#remove_orphans' do
let(:action) { :remove_orphans }
before do
FileUtils.mkdir_p Rails.public_path.join('system')
end
context 'without any options' do
it 'runs without error' do
expect { subject }
.to output_results('Removed', 'orphans (approx')
end
end
context 'when in azure mode' do
before do
allow(Paperclip::Attachment).to receive(:default_options).and_return(storage: :azure)
end
it 'warns about usage and exits' do
expect { subject }
.to output_results('azure storage driver is not supported')
.and raise_error(SystemExit)
end
end
context 'when in fog mode' do
before do
allow(Paperclip::Attachment).to receive(:default_options).and_return(storage: :fog)
end
it 'warns about usage and exits' do
expect { subject }
.to output_results('fog storage driver is not supported')
.and raise_error(SystemExit)
end
end
context 'when in filesystem mode' do
before do
allow(File).to receive(:delete).and_return(true)
media_attachment.delete
end
let(:media_attachment) { Fabricate(:media_attachment) }
it 'removes the unlinked files' do
expect { subject }
.to output_results('Removed', 'orphans (approx')
expect(File).to have_received(:delete).with(media_attachment.file.path)
end
end
end
end

@ -20,7 +20,7 @@ describe 'Content-Security-Policy' do
"form-action 'self'",
"child-src 'self' blob: https://cb6e6126.ngrok.io",
"worker-src 'self' blob: https://cb6e6126.ngrok.io",
"connect-src 'self' data: blob: https://cb6e6126.ngrok.io ws://localhost:4000",
"connect-src 'self' data: blob: https://cb6e6126.ngrok.io ws://cb6e6126.ngrok.io:4000",
"script-src 'self' https://cb6e6126.ngrok.io 'wasm-unsafe-eval'"
)
end

@ -94,6 +94,72 @@ describe 'signature verification concern' do
end
end
context 'with a valid signature on a GET request that has a query string' do
let(:signature_header) do
'keyId="https://remote.domain/users/bob#main-key",algorithm="rsa-sha256",headers="date host (request-target)",signature="SDMa4r/DQYMXYxVgYO2yEqGWWUXugKjVuz0I8dniQAk+aunzBaF2aPu+4grBfawAshlx1Xytl8lhb0H2MllEz16/tKY7rUrb70MK0w8ohXgpb0qs3YvQgdj4X24L1x2MnkFfKHR/J+7TBlnivq0HZqXm8EIkPWLv+eQxu8fbowLwHIVvRd/3t6FzvcfsE0UZKkoMEX02542MhwSif6cu7Ec/clsY9qgKahb9JVGOGS1op9Lvg/9y1mc8KCgD83U5IxVygYeYXaVQ6gixA9NgZiTCwEWzHM5ELm7w5hpdLFYxYOHg/3G3fiqJzpzNQAcCD4S4JxfE7hMI0IzVlNLT6A=="' # rubocop:disable Layout/LineLength
end
it 'successfuly verifies signature', :aggregate_failures do
expect(signature_header).to eq build_signature_string(actor_keypair, 'https://remote.domain/users/bob#main-key', 'get /activitypub/success?foo=42', { 'Date' => 'Wed, 20 Dec 2023 10:00:00 GMT', 'Host' => 'www.example.com' })
get '/activitypub/success?foo=42', headers: {
'Host' => 'www.example.com',
'Date' => 'Wed, 20 Dec 2023 10:00:00 GMT',
'Signature' => signature_header,
}
expect(response).to have_http_status(200)
expect(body_as_json).to match(
signed_request: true,
signature_actor_id: actor.id.to_s
)
end
end
context 'when the query string is missing from the signature verification (compatibility quirk)' do
let(:signature_header) do
'keyId="https://remote.domain/users/bob#main-key",algorithm="rsa-sha256",headers="date host (request-target)",signature="Z8ilar3J7bOwqZkMp7sL8sRs4B1FT+UorbmvWoE+A5UeoOJ3KBcUmbsh+k3wQwbP5gMNUrra9rEWabpasZGphLsbDxfbsWL3Cf0PllAc7c1c7AFEwnewtExI83/qqgEkfWc2z7UDutXc2NfgAx89Ox8DXU/fA2GG0jILjB6UpFyNugkY9rg6oI31UnvfVi3R7sr3/x8Ea3I9thPvqI2byF6cojknSpDAwYzeKdngX3TAQEGzFHz3SDWwyp3jeMWfwvVVbM38FxhvAnSumw7YwWW4L7M7h4M68isLimoT3yfCn2ucBVL5Dz8koBpYf/40w7QidClAwCafZQFC29yDOg=="' # rubocop:disable Layout/LineLength
end
it 'successfuly verifies signature', :aggregate_failures do
expect(signature_header).to eq build_signature_string(actor_keypair, 'https://remote.domain/users/bob#main-key', 'get /activitypub/success', { 'Date' => 'Wed, 20 Dec 2023 10:00:00 GMT', 'Host' => 'www.example.com' })
get '/activitypub/success?foo=42', headers: {
'Host' => 'www.example.com',
'Date' => 'Wed, 20 Dec 2023 10:00:00 GMT',
'Signature' => signature_header,
}
expect(response).to have_http_status(200)
expect(body_as_json).to match(
signed_request: true,
signature_actor_id: actor.id.to_s
)
end
end
context 'with mismatching query string' do
let(:signature_header) do
'keyId="https://remote.domain/users/bob#main-key",algorithm="rsa-sha256",headers="date host (request-target)",signature="SDMa4r/DQYMXYxVgYO2yEqGWWUXugKjVuz0I8dniQAk+aunzBaF2aPu+4grBfawAshlx1Xytl8lhb0H2MllEz16/tKY7rUrb70MK0w8ohXgpb0qs3YvQgdj4X24L1x2MnkFfKHR/J+7TBlnivq0HZqXm8EIkPWLv+eQxu8fbowLwHIVvRd/3t6FzvcfsE0UZKkoMEX02542MhwSif6cu7Ec/clsY9qgKahb9JVGOGS1op9Lvg/9y1mc8KCgD83U5IxVygYeYXaVQ6gixA9NgZiTCwEWzHM5ELm7w5hpdLFYxYOHg/3G3fiqJzpzNQAcCD4S4JxfE7hMI0IzVlNLT6A=="' # rubocop:disable Layout/LineLength
end
it 'fails to verify signature', :aggregate_failures do
expect(signature_header).to eq build_signature_string(actor_keypair, 'https://remote.domain/users/bob#main-key', 'get /activitypub/success?foo=42', { 'Date' => 'Wed, 20 Dec 2023 10:00:00 GMT', 'Host' => 'www.example.com' })
get '/activitypub/success?foo=43', headers: {
'Host' => 'www.example.com',
'Date' => 'Wed, 20 Dec 2023 10:00:00 GMT',
'Signature' => signature_header,
}
expect(body_as_json).to match(
signed_request: true,
signature_actor_id: nil,
error: anything
)
end
end
context 'with a mismatching path' do
it 'fails to verify signature', :aggregate_failures do
get '/activitypub/alternative-path', headers: {

@ -12,10 +12,10 @@ __metadata:
languageName: node
linkType: hard
"@adobe/css-tools@npm:^4.3.1":
version: 4.3.1
resolution: "@adobe/css-tools@npm:4.3.1"
checksum: 05672719b544cc0c21ae3ed0eb6349bf458e9d09457578eeeb07cf0f696469ac6417e9c9be1b129e5d6a18098a061c1db55b2275591760ef30a79822436fcbfa
"@adobe/css-tools@npm:^4.3.2":
version: 4.3.2
resolution: "@adobe/css-tools@npm:4.3.2"
checksum: 296a03dd29f227c60500d2da8c7f64991fecf1d8b456ce2b4adb8cec7363d9c08b5b03f1463673fc8cbfe54b538745588e7a13c736d2dd14a80c01a20f127f39
languageName: node
linkType: hard
@ -60,25 +60,25 @@ __metadata:
linkType: hard
"@babel/core@npm:^7.10.4, @babel/core@npm:^7.11.1, @babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.22.1":
version: 7.23.6
resolution: "@babel/core@npm:7.23.6"
version: 7.23.7
resolution: "@babel/core@npm:7.23.7"
dependencies:
"@ampproject/remapping": "npm:^2.2.0"
"@babel/code-frame": "npm:^7.23.5"
"@babel/generator": "npm:^7.23.6"
"@babel/helper-compilation-targets": "npm:^7.23.6"
"@babel/helper-module-transforms": "npm:^7.23.3"
"@babel/helpers": "npm:^7.23.6"
"@babel/helpers": "npm:^7.23.7"
"@babel/parser": "npm:^7.23.6"
"@babel/template": "npm:^7.22.15"
"@babel/traverse": "npm:^7.23.6"
"@babel/traverse": "npm:^7.23.7"
"@babel/types": "npm:^7.23.6"
convert-source-map: "npm:^2.0.0"
debug: "npm:^4.1.0"
gensync: "npm:^1.0.0-beta.2"
json5: "npm:^2.2.3"
semver: "npm:^6.3.1"
checksum: a02bae7d916029b70706dc301535e1b31e5d216f55d4ee6f64a15825c6b69ee2c14c52a213d1497ec414e925ed4e9d897d41fb0d75df9fea28ed2c0008790e31
checksum: 38c9934973d384ed83369712978453eac91dc3f22167404dbdb272b64f602e74728a6f37012c53ee57e521b8ae2da60097f050497d9b6a212d28b59cdfb2cd1d
languageName: node
linkType: hard
@ -167,9 +167,9 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-define-polyfill-provider@npm:^0.4.3":
version: 0.4.3
resolution: "@babel/helper-define-polyfill-provider@npm:0.4.3"
"@babel/helper-define-polyfill-provider@npm:^0.4.4":
version: 0.4.4
resolution: "@babel/helper-define-polyfill-provider@npm:0.4.4"
dependencies:
"@babel/helper-compilation-targets": "npm:^7.22.6"
"@babel/helper-plugin-utils": "npm:^7.22.5"
@ -178,7 +178,7 @@ __metadata:
resolve: "npm:^1.14.2"
peerDependencies:
"@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0
checksum: 0007035157e0d32ee9cb4ca319b89d6f3705523383efe52a59eb3d4dfa2ed08c5147e49c10a6e6d69c15221d89c76c8e5875475d6710fb44a5c37b8e69388e40
checksum: 60126f5f719b9e2114df62e3bf3ac0797b71d8dc733db60192eb169b004fde72ee309fa5848c5fdfe98b8e8863c46f55e16da5aa8a4e420b4d2670cd0c5dd708
languageName: node
linkType: hard
@ -342,14 +342,14 @@ __metadata:
languageName: node
linkType: hard
"@babel/helpers@npm:^7.23.6":
version: 7.23.6
resolution: "@babel/helpers@npm:7.23.6"
"@babel/helpers@npm:^7.23.7":
version: 7.23.7
resolution: "@babel/helpers@npm:7.23.7"
dependencies:
"@babel/template": "npm:^7.22.15"
"@babel/traverse": "npm:^7.23.6"
"@babel/traverse": "npm:^7.23.7"
"@babel/types": "npm:^7.23.6"
checksum: df1cf6607676ad36f52f652ec03536f2732d70aef5e76dba5c964e34d49f3c2d3dcf9fb3740db359f53071d74b64606a833d5ba156f79f437f71bfe06e2e7e19
checksum: f74a61ad28a1bc1fdd9133ad571c07787b66d6db017c707b87c203b0cd06879cea8b33e9c6a8585765a4949efa5df3cc9e19b710fe867f11be38ee29fd4a0488
languageName: node
linkType: hard
@ -397,15 +397,15 @@ __metadata:
languageName: node
linkType: hard
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.3":
version: 7.23.3
resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.3"
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.7":
version: 7.23.7
resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.7"
dependencies:
"@babel/helper-environment-visitor": "npm:^7.22.20"
"@babel/helper-plugin-utils": "npm:^7.22.5"
peerDependencies:
"@babel/core": ^7.0.0
checksum: 0f43b74741d50e637ba4dcef2786621126fe4da6ccf4ee2e94423ee23f6a04ecd91d458e59764c43e4968be139e5197ee43be8a2fea2c09f0b202a3391e548cc
checksum: 355746e21ad7f43e4f4daef54cfe2ef461ecd19446b2afedd53c39df1bf9aa2eeeeaabee2279b1321de89a97c9360e4f76e9ba950fee50ff1676c25f6929d625
languageName: node
linkType: hard
@ -661,9 +661,9 @@ __metadata:
languageName: node
linkType: hard
"@babel/plugin-transform-async-generator-functions@npm:^7.23.4":
version: 7.23.4
resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.4"
"@babel/plugin-transform-async-generator-functions@npm:^7.23.7":
version: 7.23.7
resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.7"
dependencies:
"@babel/helper-environment-visitor": "npm:^7.22.20"
"@babel/helper-plugin-utils": "npm:^7.22.5"
@ -671,7 +671,7 @@ __metadata:
"@babel/plugin-syntax-async-generators": "npm:^7.8.4"
peerDependencies:
"@babel/core": ^7.0.0-0
checksum: f2eef4de609975a3f7da7832576b5ffc93e43c80f87e1a99e886b0f8591096cfc4c37e2d5f52fdeaa2a9c09a25a59f3e621159abaca75d3193922a5c0e4cbe0c
checksum: 63d314edc9fbeaf2700745ca0e19bf9840e87f2d7d1f6c5638e06d2aec3e7418d0d7493ed09087e2fe369cc15e9d96c113fb2cd367cb5e3ff922e3712c27b7d4
languageName: node
linkType: hard
@ -1201,18 +1201,18 @@ __metadata:
linkType: hard
"@babel/plugin-transform-runtime@npm:^7.22.4":
version: 7.23.6
resolution: "@babel/plugin-transform-runtime@npm:7.23.6"
version: 7.23.7
resolution: "@babel/plugin-transform-runtime@npm:7.23.7"
dependencies:
"@babel/helper-module-imports": "npm:^7.22.15"
"@babel/helper-plugin-utils": "npm:^7.22.5"
babel-plugin-polyfill-corejs2: "npm:^0.4.6"
babel-plugin-polyfill-corejs3: "npm:^0.8.5"
babel-plugin-polyfill-regenerator: "npm:^0.5.3"
babel-plugin-polyfill-corejs2: "npm:^0.4.7"
babel-plugin-polyfill-corejs3: "npm:^0.8.7"
babel-plugin-polyfill-regenerator: "npm:^0.5.4"
semver: "npm:^6.3.1"
peerDependencies:
"@babel/core": ^7.0.0-0
checksum: 94a7ee92f073df53fd8bebf9ed391a95553716077da1c6c3a57f10f042358c938495d55e6b09b4b50544c01f03560c4770c17698e1c24817a15d3668e8231249
checksum: 0d5038462a5762c3a88d820785f685ce1b659075527a3ad538647fd9ce486052777d5aea3d62e626639d60441a04dd0ded2ed32c86b92cf8afbdbd3d54460c13
languageName: node
linkType: hard
@ -1334,8 +1334,8 @@ __metadata:
linkType: hard
"@babel/preset-env@npm:^7.11.0, @babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.22.4":
version: 7.23.6
resolution: "@babel/preset-env@npm:7.23.6"
version: 7.23.7
resolution: "@babel/preset-env@npm:7.23.7"
dependencies:
"@babel/compat-data": "npm:^7.23.5"
"@babel/helper-compilation-targets": "npm:^7.23.6"
@ -1343,7 +1343,7 @@ __metadata:
"@babel/helper-validator-option": "npm:^7.23.5"
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.23.3"
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.23.3"
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.3"
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.23.7"
"@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2"
"@babel/plugin-syntax-async-generators": "npm:^7.8.4"
"@babel/plugin-syntax-class-properties": "npm:^7.12.13"
@ -1364,7 +1364,7 @@ __metadata:
"@babel/plugin-syntax-top-level-await": "npm:^7.14.5"
"@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6"
"@babel/plugin-transform-arrow-functions": "npm:^7.23.3"
"@babel/plugin-transform-async-generator-functions": "npm:^7.23.4"
"@babel/plugin-transform-async-generator-functions": "npm:^7.23.7"
"@babel/plugin-transform-async-to-generator": "npm:^7.23.3"
"@babel/plugin-transform-block-scoped-functions": "npm:^7.23.3"
"@babel/plugin-transform-block-scoping": "npm:^7.23.4"
@ -1412,14 +1412,14 @@ __metadata:
"@babel/plugin-transform-unicode-regex": "npm:^7.23.3"
"@babel/plugin-transform-unicode-sets-regex": "npm:^7.23.3"
"@babel/preset-modules": "npm:0.1.6-no-external-plugins"
babel-plugin-polyfill-corejs2: "npm:^0.4.6"
babel-plugin-polyfill-corejs3: "npm:^0.8.5"
babel-plugin-polyfill-regenerator: "npm:^0.5.3"
babel-plugin-polyfill-corejs2: "npm:^0.4.7"
babel-plugin-polyfill-corejs3: "npm:^0.8.7"
babel-plugin-polyfill-regenerator: "npm:^0.5.4"
core-js-compat: "npm:^3.31.0"
semver: "npm:^6.3.1"
peerDependencies:
"@babel/core": ^7.0.0-0
checksum: 5b24d179af52f082d04b9b98cc4777e37bf31a97cef5a91d8917e996dbd75f2f743c88c40f80744cb8529355bb674619d150c0260c32d834aa4067e21d0c8962
checksum: ac9def873cec52ee02a550bde6e22eced16d1ae331bb8ebc82c03e4c91c12ac17e3e4027647e61612937bcc25ac46e71370aaf99dc2e85dbd11f7777ffeed54e
languageName: node
linkType: hard
@ -1484,11 +1484,11 @@ __metadata:
linkType: hard
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
version: 7.23.6
resolution: "@babel/runtime@npm:7.23.6"
version: 7.23.7
resolution: "@babel/runtime@npm:7.23.7"
dependencies:
regenerator-runtime: "npm:^0.14.0"
checksum: d886954e985ef8e421222f7a2848884d96a752e0020d3078b920dd104e672fdf23bcc6f51a44313a048796319f1ac9d09c2c88ec8cbb4e1f09174bcd3335b9ff
checksum: 3e304133ee55b0750e03e53cb4efb47fb2bdcdb5795f85bbffa10595196c34b9be60eb65bd6d833c87f49fc827f0365f86f95f51d85b188004d3128bb5129c93
languageName: node
linkType: hard
@ -1503,9 +1503,9 @@ __metadata:
languageName: node
linkType: hard
"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.6":
version: 7.23.6
resolution: "@babel/traverse@npm:7.23.6"
"@babel/traverse@npm:7, @babel/traverse@npm:^7.23.7":
version: 7.23.7
resolution: "@babel/traverse@npm:7.23.7"
dependencies:
"@babel/code-frame": "npm:^7.23.5"
"@babel/generator": "npm:^7.23.6"
@ -1517,7 +1517,7 @@ __metadata:
"@babel/types": "npm:^7.23.6"
debug: "npm:^4.3.1"
globals: "npm:^11.1.0"
checksum: 5b4ebb94a00a7e1daf111e4b0b45a7998d5b7598637a14e75e855e88cc1b702789e09a958726b5d599a003be1e9032dbdfde4b88ea6061332228738950d5582d
checksum: e32fceb4249beec2bde83968ddffe17444221c1ee5cd18c543a2feaf94e3ca83f2a4dfbc2dcca87cf226e0105973e0fe3717063a21e982a9de9945615ab3f3f5
languageName: node
linkType: hard
@ -1539,38 +1539,38 @@ __metadata:
languageName: node
linkType: hard
"@csstools/css-parser-algorithms@npm:^2.3.2":
version: 2.3.2
resolution: "@csstools/css-parser-algorithms@npm:2.3.2"
"@csstools/css-parser-algorithms@npm:^2.4.0":
version: 2.5.0
resolution: "@csstools/css-parser-algorithms@npm:2.5.0"
peerDependencies:
"@csstools/css-tokenizer": ^2.2.1
checksum: ccae373a3ab5c10716418b69ce1f6db10a26d3a2d60b65df5fe69099afe4fb1d3192925f3c0f93c3b17c3ab1964b0f39ad2b0e97312ec4a51caa55d6b6a31672
"@csstools/css-tokenizer": ^2.2.3
checksum: 31b4a523d956e204af9842183678cca5a88ad76551d54dcb6083f8a6f2dfd8fdec6c09bca5410842af54b90997308bebee7593c17dbc1a4e951453b54bd3f024
languageName: node
linkType: hard
"@csstools/css-tokenizer@npm:^2.2.1":
version: 2.2.1
resolution: "@csstools/css-tokenizer@npm:2.2.1"
checksum: 0c6901d291e99c567893846a47068057c2a28b3edc4219b6da589a530f55f51ddd4675f906f707b393bfe7a508ab2604bf3f75708f064db857bb277636bd5a44
"@csstools/css-tokenizer@npm:^2.2.2":
version: 2.2.3
resolution: "@csstools/css-tokenizer@npm:2.2.3"
checksum: 557266ec52e8b36c19008a5bbd7151effba085cdd6d68270c01afebf914981caac698eda754b2a530a8a9947a3dd70e3f3a39a5e037c4170bb2a055a92754acb
languageName: node
linkType: hard
"@csstools/media-query-list-parser@npm:^2.1.5":
version: 2.1.5
resolution: "@csstools/media-query-list-parser@npm:2.1.5"
"@csstools/media-query-list-parser@npm:^2.1.6":
version: 2.1.7
resolution: "@csstools/media-query-list-parser@npm:2.1.7"
peerDependencies:
"@csstools/css-parser-algorithms": ^2.3.2
"@csstools/css-tokenizer": ^2.2.1
checksum: ae0692c6f92cdc82053291c7a50028b692094dfed795f0259571c5eb40f4b3fa580182ac3701e56c2834e40a62a122ea6639299e43ae88b3a835ae4c869a1a12
"@csstools/css-parser-algorithms": ^2.5.0
"@csstools/css-tokenizer": ^2.2.3
checksum: 433aef06b00f1d402fd24074a1919b8e2de94245a3b780da6466c8cc9e0f3cc93d2db930f0fce36c7d6908cd50b626cd61e803d3f62dddad79eeb742858028ef
languageName: node
linkType: hard
"@csstools/selector-specificity@npm:^3.0.0":
version: 3.0.0
resolution: "@csstools/selector-specificity@npm:3.0.0"
"@csstools/selector-specificity@npm:^3.0.1":
version: 3.0.1
resolution: "@csstools/selector-specificity@npm:3.0.1"
peerDependencies:
postcss-selector-parser: ^6.0.13
checksum: 6f0e2fa9a3c5dcbc7a446fd827d3eb85ca775cc884f73f0bbb119ab49b4f5f0af8763dd23a37d423f4e7989069c09bb977e7e5f017db296e1417abb1fba75c30
checksum: 4280f494726d5e38de74e28dee2ff74ec86244560dff4edeec3ddff3ac73c774c19535bd1bb70cad77949bfb359cf87e977d0ec3264591e3b7260342a20dd84f
languageName: node
linkType: hard
@ -2323,7 +2323,7 @@ __metadata:
"@types/react-dom": "npm:^18.2.4"
"@types/react-helmet": "npm:^6.1.6"
"@types/react-immutable-proptypes": "npm:^2.1.0"
"@types/react-motion": "npm:^0.0.39"
"@types/react-motion": "npm:^0.0.40"
"@types/react-overlays": "npm:^3.1.0"
"@types/react-router": "npm:^5.1.20"
"@types/react-router-dom": "npm:^5.3.3"
@ -2338,7 +2338,7 @@ __metadata:
"@types/webpack": "npm:^4.41.33"
"@types/yargs": "npm:^17.0.24"
"@typescript-eslint/eslint-plugin": "npm:^6.0.0"
"@typescript-eslint/parser": "npm:^6.0.0"
"@typescript-eslint/parser": "npm:^6.17.0"
arrow-key-navigation: "npm:^1.2.0"
async-mutex: "npm:^0.4.0"
atrament: "npm:0.2.4"
@ -2369,7 +2369,7 @@ __metadata:
eslint-import-resolver-typescript: "npm:^3.5.5"
eslint-plugin-formatjs: "npm:^4.10.1"
eslint-plugin-import: "npm:~2.29.0"
eslint-plugin-jsdoc: "npm:^46.1.0"
eslint-plugin-jsdoc: "npm:^48.0.0"
eslint-plugin-jsx-a11y: "npm:~6.8.0"
eslint-plugin-prettier: "npm:^5.0.0"
eslint-plugin-promise: "npm:~6.1.1"
@ -2897,10 +2897,10 @@ __metadata:
linkType: hard
"@testing-library/jest-dom@npm:^6.0.0":
version: 6.1.5
resolution: "@testing-library/jest-dom@npm:6.1.5"
version: 6.1.6
resolution: "@testing-library/jest-dom@npm:6.1.6"
dependencies:
"@adobe/css-tools": "npm:^4.3.1"
"@adobe/css-tools": "npm:^4.3.2"
"@babel/runtime": "npm:^7.9.2"
aria-query: "npm:^5.0.0"
chalk: "npm:^3.0.0"
@ -2922,7 +2922,7 @@ __metadata:
optional: true
vitest:
optional: true
checksum: f3643a56fcd970b5c7e8fd10faf3c4817d8ab0e74fb1198d726643bdc5ac675ceaac3b0068c5b4fbad254470e8f98ed50028741de875a29ceaa2f854570979c9
checksum: f98f79f3e470517469c86947d0ff1bb83ac2e59fd2a29728ab306eca5fba63c948084ec06b7b531642e6002d1f0211d918c298c628f0d386c0ef63ba881c47ba
languageName: node
linkType: hard
@ -3382,12 +3382,12 @@ __metadata:
languageName: node
linkType: hard
"@types/react-motion@npm:^0.0.39":
version: 0.0.39
resolution: "@types/react-motion@npm:0.0.39"
"@types/react-motion@npm:^0.0.40":
version: 0.0.40
resolution: "@types/react-motion@npm:0.0.40"
dependencies:
"@types/react": "npm:*"
checksum: 0dfcde777576b3c3289b4dbf2a5085decf71aba6d543697f4c1069d02ed3b543792a253692bd98870af04112c92469328a4fdb93988f93af2e099de8f2c9bc2e
checksum: 8a560051be917833fdbe051185b53aeafbe8657968ac8e073ac874b9a55c6f16e3793748b13cfb9bd6d9a3d27aba116d6f8f296ec1950f4175dc94d17c5e8470
languageName: node
linkType: hard
@ -3485,13 +3485,13 @@ __metadata:
linkType: hard
"@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7":
version: 18.2.45
resolution: "@types/react@npm:18.2.45"
version: 18.2.46
resolution: "@types/react@npm:18.2.46"
dependencies:
"@types/prop-types": "npm:*"
"@types/scheduler": "npm:*"
csstype: "npm:^3.0.2"
checksum: 4cc650c47ffb88baac29fb7a74e842e4af4a55f437086ef70250fdc75f0a5f2fcf8adc272d05ab2e00b1de6e14613296881271caee037dadf9130fdeb498c59e
checksum: 814cc67107e5e69501d65bfc371cc2c716665d2a3608d395a2f81e24c3a2875db28e2cad717dfb17017eabcffd1d68ee2c9e09ecaba3f7108d5b7fbb9888ebab
languageName: node
linkType: hard
@ -3696,21 +3696,21 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:^6.0.0":
version: 6.16.0
resolution: "@typescript-eslint/parser@npm:6.16.0"
"@typescript-eslint/parser@npm:^6.17.0":
version: 6.17.0
resolution: "@typescript-eslint/parser@npm:6.17.0"
dependencies:
"@typescript-eslint/scope-manager": "npm:6.16.0"
"@typescript-eslint/types": "npm:6.16.0"
"@typescript-eslint/typescript-estree": "npm:6.16.0"
"@typescript-eslint/visitor-keys": "npm:6.16.0"
"@typescript-eslint/scope-manager": "npm:6.17.0"
"@typescript-eslint/types": "npm:6.17.0"
"@typescript-eslint/typescript-estree": "npm:6.17.0"
"@typescript-eslint/visitor-keys": "npm:6.17.0"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 9d573d14df4ec661dccaca785223a8a330d64f50a9279ff9170b1da22198ff91b9afa3ee7d3d7127c0cbc148c86831e76b33fc5b47d630799e98940ef666bfe0
checksum: 66b53159688083eb48259de5b4daf076f3de284ac3b4d2618bda3f7ab2d8ee27b01ae851b08e8487047e33ff3668424f17d677d66413164cb231f1519dcff82f
languageName: node
linkType: hard
@ -3724,6 +3724,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:6.17.0":
version: 6.17.0
resolution: "@typescript-eslint/scope-manager@npm:6.17.0"
dependencies:
"@typescript-eslint/types": "npm:6.17.0"
"@typescript-eslint/visitor-keys": "npm:6.17.0"
checksum: b7ac7d9c39515c2a1b3844577fab967bf126ec25ccf28076240748b3f42d60ab3e64131bfffee61f66251bdf2d59e50e39f5cb0bee7987c85c49140c75d26b5f
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:6.16.0":
version: 6.16.0
resolution: "@typescript-eslint/type-utils@npm:6.16.0"
@ -3748,6 +3758,13 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/types@npm:6.17.0":
version: 6.17.0
resolution: "@typescript-eslint/types@npm:6.17.0"
checksum: c458d985b9ab4f369018536bcb88f0aedafb0c8c4b22ffd376e0c0c768a44e3956475c85ebeef40ae44238841c8df268893477b85873aa2621995c37e738e37e
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:6.16.0":
version: 6.16.0
resolution: "@typescript-eslint/typescript-estree@npm:6.16.0"
@ -3767,6 +3784,25 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:6.17.0":
version: 6.17.0
resolution: "@typescript-eslint/typescript-estree@npm:6.17.0"
dependencies:
"@typescript-eslint/types": "npm:6.17.0"
"@typescript-eslint/visitor-keys": "npm:6.17.0"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
minimatch: "npm:9.0.3"
semver: "npm:^7.5.4"
ts-api-utils: "npm:^1.0.1"
peerDependenciesMeta:
typescript:
optional: true
checksum: 5a858288bb05f45a2a45b04394115826ff19f85555144bfb67dc281d4e75fc3a1e1aceb3dee68022e86b91f199d1310c15bda3100a4890004b8e474d86afad51
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:6.16.0, @typescript-eslint/utils@npm:^6.5.0":
version: 6.16.0
resolution: "@typescript-eslint/utils@npm:6.16.0"
@ -3794,6 +3830,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:6.17.0":
version: 6.17.0
resolution: "@typescript-eslint/visitor-keys@npm:6.17.0"
dependencies:
"@typescript-eslint/types": "npm:6.17.0"
eslint-visitor-keys: "npm:^3.4.1"
checksum: 75a48f5810c6a69bc1c082b07d2b840c40895807b1b4ecf9d3ab9eb783176eeb3e7b11eb89d652e8331da79d604f82300f315ffc21cd937819197a8601b48d1d
languageName: node
linkType: hard
"@ungap/structured-clone@npm:^1.2.0":
version: 1.2.0
resolution: "@ungap/structured-clone@npm:1.2.0"
@ -4774,39 +4820,39 @@ __metadata:
languageName: node
linkType: hard
"babel-plugin-polyfill-corejs2@npm:^0.4.6":
version: 0.4.6
resolution: "babel-plugin-polyfill-corejs2@npm:0.4.6"
"babel-plugin-polyfill-corejs2@npm:^0.4.7":
version: 0.4.7
resolution: "babel-plugin-polyfill-corejs2@npm:0.4.7"
dependencies:
"@babel/compat-data": "npm:^7.22.6"
"@babel/helper-define-polyfill-provider": "npm:^0.4.3"
"@babel/helper-define-polyfill-provider": "npm:^0.4.4"
semver: "npm:^6.3.1"
peerDependencies:
"@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0
checksum: 64a98811f343492aa6970ab253760194e389c0417e5b830522f944009c1f0c78e1251975fd1b9869cd48cc4623111b20a3389cf6732a1d10ba0d19de6fa5114f
checksum: f80f7284ec72c63e7dd751e0bdf25e9978df195a79e0887470603bfdea13ee518d62573cf360bb1bc01b80819e54915dd5edce9cff14c52d0af5f984aa3d36a3
languageName: node
linkType: hard
"babel-plugin-polyfill-corejs3@npm:^0.8.5":
version: 0.8.5
resolution: "babel-plugin-polyfill-corejs3@npm:0.8.5"
"babel-plugin-polyfill-corejs3@npm:^0.8.7":
version: 0.8.7
resolution: "babel-plugin-polyfill-corejs3@npm:0.8.7"
dependencies:
"@babel/helper-define-polyfill-provider": "npm:^0.4.3"
core-js-compat: "npm:^3.32.2"
"@babel/helper-define-polyfill-provider": "npm:^0.4.4"
core-js-compat: "npm:^3.33.1"
peerDependencies:
"@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0
checksum: 577a072971bda2929a87655c816ad14b6a8f7276e6914851b98a6465bdb56f7f2e3db6136c8b8607bd6ba4cde3cd9cbde21f0078250cd93aee3df977c0a731d0
checksum: 094e40f4ab9f131408202063964d63740609fd4fdb70a5b6332b371761921b540ffbcee7a434c0199b8317dfb2ba4675eef674867215fd3b85e24054607c1501
languageName: node
linkType: hard
"babel-plugin-polyfill-regenerator@npm:^0.5.3":
version: 0.5.3
resolution: "babel-plugin-polyfill-regenerator@npm:0.5.3"
"babel-plugin-polyfill-regenerator@npm:^0.5.4":
version: 0.5.4
resolution: "babel-plugin-polyfill-regenerator@npm:0.5.4"
dependencies:
"@babel/helper-define-polyfill-provider": "npm:^0.4.3"
"@babel/helper-define-polyfill-provider": "npm:^0.4.4"
peerDependencies:
"@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0
checksum: cc32313b9ebbf1d7bedc33524a861136b9e5d3b6e9be317ac360a1c2a59ae5ed1b465a6c68b2715cdefb089780ddfb0c11f4a148e49827a947beee76e43da598
checksum: 0b903f5fe2f8c487b4260935dfe60bd9a95bcaee7ae63958f063045093b16d4e8288c232199d411261300aa21f6b106a3cb83c42cc996de013b337f5825a79fe
languageName: node
linkType: hard
@ -5161,7 +5207,7 @@ __metadata:
languageName: node
linkType: hard
"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.1, browserslist@npm:^4.22.2":
"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.2":
version: 4.22.2
resolution: "browserslist@npm:4.22.2"
dependencies:
@ -5541,9 +5587,9 @@ __metadata:
linkType: hard
"classnames@npm:^2.2.5, classnames@npm:^2.3.2":
version: 2.5.0
resolution: "classnames@npm:2.5.0"
checksum: f10a5b07db7fda8eb77f701f795b7006f3de86a723ec62cc10f4d82b4195fc65a578bbf91c47675b8c6fcb2921b903bfea5c670bdb43513e454daa6c2e9738b3
version: 2.5.1
resolution: "classnames@npm:2.5.1"
checksum: afff4f77e62cea2d79c39962980bf316bacb0d7c49e13a21adaadb9221e1c6b9d3cdb829d8bb1b23c406f4e740507f37e1dcf506f7e3b7113d17c5bab787aa69
languageName: node
linkType: hard
@ -5907,12 +5953,12 @@ __metadata:
languageName: node
linkType: hard
"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.32.2":
version: 3.33.1
resolution: "core-js-compat@npm:3.33.1"
"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1":
version: 3.35.0
resolution: "core-js-compat@npm:3.35.0"
dependencies:
browserslist: "npm:^4.22.1"
checksum: 9c7361b370eac30756e6ec52469988d62c6110759efa1c85edd15e6b30f05ace8319a9cc0671bf596a98e7e81c67ad693ceaab2691b85cb62c636da1afe8feb9
browserslist: "npm:^4.22.2"
checksum: 8c4379240b8decb94b21e81d5ba6f768418721061923b28c9dfc97574680c35d778d39c010207402fc7c8308a68a4cf6d5e02bcbcb96e931c52e6e0dce29a68c
languageName: node
linkType: hard
@ -7371,9 +7417,9 @@ __metadata:
languageName: node
linkType: hard
"eslint-plugin-jsdoc@npm:^46.1.0":
version: 46.9.1
resolution: "eslint-plugin-jsdoc@npm:46.9.1"
"eslint-plugin-jsdoc@npm:^48.0.0":
version: 48.0.1
resolution: "eslint-plugin-jsdoc@npm:48.0.1"
dependencies:
"@es-joy/jsdoccomment": "npm:~0.41.0"
are-docs-informative: "npm:^0.0.2"
@ -7385,8 +7431,8 @@ __metadata:
semver: "npm:^7.5.4"
spdx-expression-parse: "npm:^4.0.0"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
checksum: d15d68797e85bb7b6fdcfc1170653683c16ab1d62c2e9c537101e774cb3231913e2bc4781f2bb808d074adce5699e5b545e450c6801b637c6434587d226ad6ac
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
checksum: 9b211cfb2e07e076dad12681cd2045c65766dd24fe9399fd0adeaf6f8785f9a4dd58608f1183195f63d3c6c91013aa1cf9edc9101580cff9cb60e1e688f456f9
languageName: node
linkType: hard
@ -7964,12 +8010,12 @@ __metadata:
languageName: node
linkType: hard
"file-entry-cache@npm:^7.0.2":
version: 7.0.2
resolution: "file-entry-cache@npm:7.0.2"
"file-entry-cache@npm:^8.0.0":
version: 8.0.0
resolution: "file-entry-cache@npm:8.0.0"
dependencies:
flat-cache: "npm:^3.2.0"
checksum: 822664e35c3e295e6a8ca7ec490d8d8077017607f41f94b29922f1f49c6dd07025048e3ed528e2909a1439eba66d60f802c0774aa612cf6ee053ee4ecc16c8c5
flat-cache: "npm:^4.0.0"
checksum: 9e2b5938b1cd9b6d7e3612bdc533afd4ac17b2fc646569e9a8abbf2eb48e5eb8e316bc38815a3ef6a1b456f4107f0d0f055a614ca613e75db6bf9ff4d72c1638
languageName: node
linkType: hard
@ -8103,7 +8149,7 @@ __metadata:
languageName: node
linkType: hard
"flat-cache@npm:^3.0.4, flat-cache@npm:^3.2.0":
"flat-cache@npm:^3.0.4":
version: 3.2.0
resolution: "flat-cache@npm:3.2.0"
dependencies:
@ -8114,6 +8160,17 @@ __metadata:
languageName: node
linkType: hard
"flat-cache@npm:^4.0.0":
version: 4.0.0
resolution: "flat-cache@npm:4.0.0"
dependencies:
flatted: "npm:^3.2.9"
keyv: "npm:^4.5.4"
rimraf: "npm:^5.0.5"
checksum: 8f99e27bb3de94e91e7b4ca5120488cdc2b7f8cd952a538f1a566101963057eb42ca318e9fac0d36987dcca34316ff04b61c1dc3dcc8084f6f5e801a52a8e547
languageName: node
linkType: hard
"flat@npm:^5.0.2":
version: 5.0.2
resolution: "flat@npm:5.0.2"
@ -10761,7 +10818,7 @@ __metadata:
languageName: node
linkType: hard
"keyv@npm:^4.5.3":
"keyv@npm:^4.5.3, keyv@npm:^4.5.4":
version: 4.5.4
resolution: "keyv@npm:4.5.4"
dependencies:
@ -11289,10 +11346,10 @@ __metadata:
languageName: node
linkType: hard
"meow@npm:^12.1.1":
version: 12.1.1
resolution: "meow@npm:12.1.1"
checksum: a125ca99a32e2306e2f4cbe651a0d27f6eb67918d43a075f6e80b35e9bf372ebf0fc3a9fbc201cbbc9516444b6265fb3c9f80c5b7ebd32f548aa93eb7c28e088
"meow@npm:^13.0.0":
version: 13.0.0
resolution: "meow@npm:13.0.0"
checksum: fab0f91578154c048e792a81704f3f28099ffff900f364df8a85f6e770a57e1c124859a25e186186e149dad30692c7893af0dfd71517bea343bfe5d749b1fa04
languageName: node
linkType: hard
@ -14368,7 +14425,7 @@ __metadata:
languageName: node
linkType: hard
"rimraf@npm:^5.0.1":
"rimraf@npm:^5.0.1, rimraf@npm:^5.0.5":
version: 5.0.5
resolution: "rimraf@npm:5.0.5"
dependencies:
@ -14521,15 +14578,15 @@ __metadata:
linkType: hard
"sass@npm:^1.62.1":
version: 1.69.6
resolution: "sass@npm:1.69.6"
version: 1.69.7
resolution: "sass@npm:1.69.7"
dependencies:
chokidar: "npm:>=3.0.0 <4.0.0"
immutable: "npm:^4.0.0"
source-map-js: "npm:>=0.6.2 <2.0.0"
bin:
sass: sass.js
checksum: 8153db8e51e74a9007bb54332e14d122c34288c7d21a5f2eaefef753a1b7bb13f35e042dc6247253dab5b1550b05cea27970371e7548286b4f50f23dd1147d89
checksum: 773d0938e7d4ff3972d3fda3132f34fe98a2f712e028a58e28fecd615434795eff3266eddc38d5e13f03b90c0d6360d0e737b30bff2949a47280c64a18e0fb18
languageName: node
linkType: hard
@ -15633,13 +15690,13 @@ __metadata:
linkType: hard
"stylelint@npm:^16.0.2":
version: 16.0.2
resolution: "stylelint@npm:16.0.2"
version: 16.1.0
resolution: "stylelint@npm:16.1.0"
dependencies:
"@csstools/css-parser-algorithms": "npm:^2.3.2"
"@csstools/css-tokenizer": "npm:^2.2.1"
"@csstools/media-query-list-parser": "npm:^2.1.5"
"@csstools/selector-specificity": "npm:^3.0.0"
"@csstools/css-parser-algorithms": "npm:^2.4.0"
"@csstools/css-tokenizer": "npm:^2.2.2"
"@csstools/media-query-list-parser": "npm:^2.1.6"
"@csstools/selector-specificity": "npm:^3.0.1"
balanced-match: "npm:^2.0.0"
colord: "npm:^2.9.3"
cosmiconfig: "npm:^9.0.0"
@ -15648,7 +15705,7 @@ __metadata:
debug: "npm:^4.3.4"
fast-glob: "npm:^3.3.2"
fastest-levenshtein: "npm:^1.0.16"
file-entry-cache: "npm:^7.0.2"
file-entry-cache: "npm:^8.0.0"
global-modules: "npm:^2.0.0"
globby: "npm:^11.1.0"
globjoin: "npm:^0.1.4"
@ -15658,7 +15715,7 @@ __metadata:
is-plain-object: "npm:^5.0.0"
known-css-properties: "npm:^0.29.0"
mathml-tag-names: "npm:^2.1.3"
meow: "npm:^12.1.1"
meow: "npm:^13.0.0"
micromatch: "npm:^4.0.5"
normalize-path: "npm:^3.0.0"
picocolors: "npm:^1.0.0"
@ -15676,7 +15733,7 @@ __metadata:
write-file-atomic: "npm:^5.0.1"
bin:
stylelint: bin/stylelint.mjs
checksum: 5ec755e209beb1877ff40d50f18c1ebb05bf251925da1f98f28fb3911e4031195eb86adaf641ac5cdb01ba973f4c999bc0c6b0270d08c1d5c070adbdd9e734cf
checksum: 765eea0b07319d1e7989502c07b8b5794938e5a8542bec00990b09ec10c3f7006891689930099e948d06c9ef9982066edb98b1ea64a435138a6b0f0905eb2b87
languageName: node
linkType: hard

Loading…
Cancel
Save