[前][次][番号順一覧][スレッド一覧]

ruby-changes:67479

From: Daniel <ko1@a...>
Date: Tue, 31 Aug 2021 19:07:59 +0900 (JST)
Subject: [ruby-changes:67479] b41802421a (master): [rubygems/rubygems] Introduce `Gem::PrintableUri` that would redact URIs to be used on outputs

https://git.ruby-lang.org/ruby.git/commit/?id=b41802421a

From b41802421ac7e790a98ed59be67631687fc5808f Mon Sep 17 00:00:00 2001
From: Daniel Niknam <mhmd.niknam@g...>
Date: Sun, 22 Aug 2021 01:31:03 +1000
Subject: [rubygems/rubygems] Introduce `Gem::PrintableUri` that would redact
 URIs to be used on outputs

We need to redact URI credential in several places and copy pasting the code into each part of it is not ideal. This class is responsible for parsing URI strings and redacting credential from it. Also, it will handle URI object in the same manner. We will be reusing this class whenever we need to print/display a URI to users.
URI with the following format will be redacted:
- Token: `http://my-secure-token@e...` => `http://REDACTED@e...`
- Username & Password: `http://my-username:my-secure-password@e...` => `http://my-username:REDACTED@e...`
- x-oauth-basic: `http://my-secure-token:x-oauth-basic@e...` => `http://REDACTED:x-oauth-basic@e...`

https://github.com/rubygems/rubygems/commit/f1e45d3a89
---
 lib/rubygems/printable_uri.rb           |  81 ++++++++++++++++++++++
 test/rubygems/test_gem_printable_uri.rb | 116 ++++++++++++++++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 lib/rubygems/printable_uri.rb
 create mode 100644 test/rubygems/test_gem_printable_uri.rb

diff --git a/lib/rubygems/printable_uri.rb b/lib/rubygems/printable_uri.rb
new file mode 100644
index 0000000..90b05dd
--- /dev/null
+++ b/lib/rubygems/printable_uri.rb
@@ -0,0 +1,81 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/printable_uri.rb#L1
+# frozen_string_literal: true
+
+require 'uri'
+require_relative 'uri_parser'
+
+class Gem::PrintableUri
+  def self.parse_uri(uri)
+    new(uri).parse_uri
+  end
+
+  def initialize(original_uri)
+    @credential_redacted = false
+    @original_uri = original_uri
+  end
+
+  def parse_uri
+    @original_uri = Gem::UriParser.parse_uri(@original_uri)
+    @uri = @original_uri.clone
+    redact_credential
+
+    self
+  end
+
+  def parsed_uri?
+    @uri.is_a? URI::Generic
+  end
+
+  def credential_redacted?
+    @credential_redacted
+  end
+
+  def original_password
+    return unless parsed_uri?
+
+    @original_uri.password
+  end
+
+  def to_s
+    @uri.to_s
+  end
+
+  private
+
+  def redact_credential
+    return unless redactable_credential?
+
+    if token?
+      @uri.user = 'REDACTED'
+    elsif oauth_basic?
+      @uri.user = 'REDACTED'
+    elsif password?
+      @uri.password = 'REDACTED' if password?
+    end
+
+    @credential_redacted = true
+  end
+
+  def redactable_credential?
+    return false unless parsed_uri?
+
+    password? || oauth_basic? || token?
+  end
+
+  def password?
+    return false unless parsed_uri?
+
+    !!@uri.password
+  end
+
+  def oauth_basic?
+    return false unless parsed_uri?
+
+    @uri.password == 'x-oauth-basic'
+  end
+
+  def token?
+    return false unless parsed_uri?
+
+    !@uri.user.nil? && @uri.password.nil?
+  end
+end
diff --git a/test/rubygems/test_gem_printable_uri.rb b/test/rubygems/test_gem_printable_uri.rb
new file mode 100644
index 0000000..5939454
--- /dev/null
+++ b/test/rubygems/test_gem_printable_uri.rb
@@ -0,0 +1,116 @@ https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_printable_uri.rb#L1
+require_relative 'helper'
+require 'uri'
+require 'rubygems/printable_uri'
+
+class TestPrintableUri < Gem::TestCase
+  def test_parsed_uri
+    assert_equal true, Gem::PrintableUri.parse_uri("https://www.example.com").parsed_uri?
+  end
+
+  def test_parsed_uri_with_empty_uri_object
+    assert_equal true, Gem::PrintableUri.parse_uri(URI("")).parsed_uri?
+  end
+
+  def test_parsed_uri_with_valid_uri_object
+    assert_equal true, Gem::PrintableUri.parse_uri(URI("https://www.example.com")).parsed_uri?
+  end
+
+  def test_parsed_uri_with_other_objects
+    assert_equal false, Gem::PrintableUri.parse_uri(Object.new).parsed_uri?
+  end
+
+  def test_parsed_uri_with_invalid_uri
+    assert_equal false, Gem::PrintableUri.parse_uri("https://www.example.com:80index").parsed_uri?
+  end
+
+  def test_credential_redacted_with_user_pass
+    assert_equal true, Gem::PrintableUri.parse_uri("https://user:pass@e...").credential_redacted?
+  end
+
+  def test_credential_redacted_with_token
+    assert_equal true, Gem::PrintableUri.parse_uri("https://token@e...").credential_redacted?
+  end
+
+  def test_credential_redacted_with_user_x_oauth_basic
+    assert_equal true, Gem::PrintableUri.parse_uri("https://token:x-oauth-basic@e...").credential_redacted?
+  end
+
+  def test_credential_redacted_without_credential
+    assert_equal false, Gem::PrintableUri.parse_uri("https://www.example.com").credential_redacted?
+  end
+
+  def test_credential_redacted_with_empty_uri_object
+    assert_equal false, Gem::PrintableUri.parse_uri(URI("")).credential_redacted?
+  end
+
+  def test_credential_redacted_with_valid_uri_object
+    assert_equal true, Gem::PrintableUri.parse_uri(URI("https://user:pass@e...")).credential_redacted?
+  end
+
+  def test_credential_redacted_with_other_objects
+    assert_equal false, Gem::PrintableUri.parse_uri(Object.new).credential_redacted?
+  end
+
+  def test_original_password_user_pass
+    assert_equal "pass", Gem::PrintableUri.parse_uri("https://user:pass@e...").original_password
+  end
+
+  def test_original_password_with_token
+    assert_equal nil, Gem::PrintableUri.parse_uri("https://token@e...").original_password
+  end
+
+  def test_original_password_without_credential
+    assert_equal nil, Gem::PrintableUri.parse_uri("https://www.example.com").original_password
+  end
+
+  def test_original_password_with_invalid_uri
+    assert_equal nil, Gem::PrintableUri.parse_uri("https://www.example.com:80index").original_password
+  end
+
+  def test_original_password_with_empty_uri_object
+    assert_equal nil, Gem::PrintableUri.parse_uri(URI("")).original_password
+  end
+
+  def test_original_password_with_valid_uri_object
+    assert_equal "pass", Gem::PrintableUri.parse_uri(URI("https://user:pass@e...")).original_password
+  end
+
+  def test_original_password_with_other_objects
+    assert_equal nil, Gem::PrintableUri.parse_uri(Object.new).original_password
+  end
+
+  def test_to_s_with_user_pass
+    assert_equal "https://user:REDACTED@e...", Gem::PrintableUri.parse_uri("https://user:pass@e...").to_s
+  end
+
+  def test_to_s_with_token
+    assert_equal "https://REDACTED@e...", Gem::PrintableUri.parse_uri("https://token@e...").to_s
+  end
+
+  def test_to_s_with_user_x_oauth_basic
+    assert_equal "https://REDACTED:x-oauth-basic@e...", Gem::PrintableUri.parse_uri("https://token:x-oauth-basic@e...").to_s
+  end
+
+  def test_to_s_without_credential
+    assert_equal "https://www.example.com", Gem::PrintableUri.parse_uri("https://www.example.com").to_s
+  end
+
+  def test_to_s_with_invalid_uri
+    assert_equal "https://www.example.com:80index", Gem::PrintableUri.parse_uri("https://www.example.com:80index").to_s
+  end
+
+  def test_to_s_with_empty_uri_object
+    assert_equal "", Gem::PrintableUri.parse_uri(URI("")).to_s
+  end
+
+  def test_to_s_with_valid_uri_object
+    assert_equal "https://user:REDACTED@e...", Gem::PrintableUri.parse_uri(URI("https://user:pass@e...")).to_s
+  end
+
+  def test_to_s_with_other_objects
+    obj = Object.new
+    obj.stub(:to_s, "my-to-s") do
+      assert_equal "my-to-s", Gem::PrintableUri.parse_uri(obj).to_s
+    end
+  end
+end
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]