Merge commit '092bb8a27af9ee87ff9ebabaf354477470ea3a94' into glitch-soc/merge-upstream
This commit is contained in:
		
						commit
						9d9008666b
					
				| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
        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?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,11 +78,11 @@
 | 
			
		|||
  "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.other_server_instructions": "மேச்டடான் இரு பரவலாக்கப்பட்ட மென்பொருள் என்பதால், நீங்கள் வேரு ஒரு வழங்கியில் கணக்கை உருவாக்கியிருந்தாலும் இந்த வழங்கியில் பயன்படுத்தலாம்.",
 | 
			
		||||
  "closed_registrations_modal.description": "{domain} இல் இப்பொழுது கணக்குகள் உருவாக்க முடியாது. நீங்கள் மேச்டடான் பயன்படுத்த, குறிப்பாக {domain} முகவரியில் கணக்கைத் துவங்க வேண்டும் என்ற அவசியமில்லை என்பதை மனதில் வைத்துக் கொள்ளவும்.",
 | 
			
		||||
  "closed_registrations_modal.find_another_server": "வேறொரு வழங்கியைக் கண்டுபிடி",
 | 
			
		||||
  "closed_registrations_modal.preamble": "மசுடோடன் ஒரு பரவலாக்கப்பட்ட மென்பொருள். ஆதனால் நீங்கள் எங்குக் கணக்கை உருவாக்கினாலும் இந்த வழங்கியில் உள்ள யாருடன் வேண்டும் என்றாலும் உரவாடலாம். நீங்களே கூட ஒரு வழங்கியை நிறுவலாம்!",
 | 
			
		||||
  "closed_registrations_modal.title": "மசுடோடன் கணக்கு துவங்கப்படுகிறது",
 | 
			
		||||
  "closed_registrations_modal.preamble": "மேச்டடான் ஒரு பரவலாக்கப்பட்ட மென்பொருள். ஆதனால் நீங்கள் எங்குக் கணக்கை உருவாக்கினாலும் இந்த வழங்கியில் உள்ள யாருடன் வேண்டும் என்றாலும் உரவாடலாம். நீங்களே கூட ஒரு வழங்கியை நிறுவலாம்!",
 | 
			
		||||
  "closed_registrations_modal.title": "மேச்டடான் கணக்கு துவங்கப்படுகிறது",
 | 
			
		||||
  "column.about": "பற்றி",
 | 
			
		||||
  "column.blocks": "தடுக்கப்பட்ட பயனர்கள்",
 | 
			
		||||
  "column.bookmarks": "அடையாளக்குறிகள்",
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +113,7 @@
 | 
			
		|||
  "compose.language.search": "தேடல் மொழிகள்...",
 | 
			
		||||
  "compose.published.body": "பதிவிடப்பட்டது.",
 | 
			
		||||
  "compose.published.open": "திற",
 | 
			
		||||
  "compose.saved.body": "பதிவி சேமிக்கப்பட்டது.",
 | 
			
		||||
  "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.",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,7 @@ ie:
 | 
			
		|||
      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.
 | 
			
		||||
| 
						 | 
				
			
			@ -110,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
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +245,7 @@ ie:
 | 
			
		|||
        url: URL de punctu terminal
 | 
			
		||||
    'no': 'No'
 | 
			
		||||
    not_recommended: Ne recomandat
 | 
			
		||||
    overridden: Substituet
 | 
			
		||||
    recommended: Recomandat
 | 
			
		||||
    required:
 | 
			
		||||
      mark: "*"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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": "^47.0.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,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: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								yarn.lock
								
								
								
								
							
							
						
						
									
										16
									
								
								yarn.lock
								
								
								
								
							| 
						 | 
				
			
			@ -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:^47.0.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"
 | 
			
		||||
| 
						 | 
				
			
			@ -7417,9 +7417,9 @@ __metadata:
 | 
			
		|||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
"eslint-plugin-jsdoc@npm:^47.0.0":
 | 
			
		||||
  version: 47.0.1
 | 
			
		||||
  resolution: "eslint-plugin-jsdoc@npm:47.0.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"
 | 
			
		||||
| 
						 | 
				
			
			@ -7432,7 +7432,7 @@ __metadata:
 | 
			
		|||
    spdx-expression-parse: "npm:^4.0.0"
 | 
			
		||||
  peerDependencies:
 | 
			
		||||
    eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
 | 
			
		||||
  checksum: f2657cfc1394af0fca2c9c079065ffbc4e5fd41678299afb9ae261aff246cbd861d0ff38b57258caf6c9e9c57eb9975c75cd47c9f8c92bfefdaa4924eef62c24
 | 
			
		||||
  checksum: 9b211cfb2e07e076dad12681cd2045c65766dd24fe9399fd0adeaf6f8785f9a4dd58608f1183195f63d3c6c91013aa1cf9edc9101580cff9cb60e1e688f456f9
 | 
			
		||||
  languageName: node
 | 
			
		||||
  linkType: hard
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14578,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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue