-
Notifications
You must be signed in to change notification settings - Fork 4
Add residential proxy data to anonymizer object #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| require 'date' | ||
| require 'maxmind/geoip2/record/abstract' | ||
|
|
||
| module MaxMind | ||
| module GeoIP2 | ||
| module Record | ||
| # Contains data for one type of anonymizer detection, currently | ||
| # residential proxies. Additional feeds may be added in the future. | ||
| # | ||
| # This record is returned by the anonymizer object of the Insights web | ||
| # service. | ||
| class AnonymizerFeed < Abstract | ||
| # A score ranging from 1 to 99 that represents our percent confidence | ||
| # that the network is currently part of this anonymizer feed. This | ||
| # property is only available from Insights. | ||
| # | ||
| # @return [Integer, nil] | ||
| def confidence | ||
| get('confidence') | ||
| end | ||
|
|
||
| # The last day that the network was sighted in our analysis of this | ||
| # anonymizer feed. This value is parsed lazily. This property is only | ||
| # available from Insights. | ||
| # | ||
| # @return [Date, nil] A Date object representing the last seen date, | ||
| # or nil if the date is not available. | ||
| def network_last_seen | ||
| return @network_last_seen if defined?(@network_last_seen) | ||
|
|
||
| date_string = get('network_last_seen') | ||
|
|
||
| if !date_string | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test gap (major): this nil-date branch is untested — Suggest asserting — Claude, on behalf of Will
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Claude, on behalf of Greg: Added coverage in commit f9d3fbc (test/test_record.rb): |
||
| @network_last_seen = nil | ||
| return nil | ||
| end | ||
|
|
||
| @network_last_seen = Date.parse(date_string) | ||
| end | ||
|
oschwald marked this conversation as resolved.
|
||
|
|
||
| # The name of the provider associated with the network in this | ||
| # anonymizer feed. This property is only available from Insights. | ||
| # | ||
| # @return [String, nil] | ||
| def provider_name | ||
| get('provider_name') | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| require 'date' | ||
| require 'maxmind/geoip2' | ||
| require 'minitest/autorun' | ||
|
|
||
| class RecordTest < Minitest::Test | ||
| # This covers the common case where a web service response has no | ||
| # "anonymizer" key at all. Insights#initialize always calls | ||
| # Anonymizer.new(record['anonymizer']), so this exercises | ||
| # Anonymizer.new(nil) and, in turn, AnonymizerFeed.new(nil). | ||
| def test_insights_no_anonymizer | ||
| model = MaxMind::GeoIP2::Model::Insights.new({}, ['en']) | ||
|
|
||
| assert_nil(model.anonymizer.confidence) | ||
| refute(model.anonymizer.anonymous?) | ||
| refute(model.anonymizer.anonymous_vpn?) | ||
| refute(model.anonymizer.hosting_provider?) | ||
| refute(model.anonymizer.public_proxy?) | ||
| refute(model.anonymizer.residential_proxy?) | ||
| refute(model.anonymizer.tor_exit_node?) | ||
| assert_nil(model.anonymizer.network_last_seen) | ||
| assert_nil(model.anonymizer.provider_name) | ||
|
|
||
| assert_nil(model.anonymizer.residential.confidence) | ||
| assert_nil(model.anonymizer.residential.network_last_seen) | ||
| assert_nil(model.anonymizer.residential.provider_name) | ||
| end | ||
|
|
||
| # This covers an "anonymizer" object being present without a nested | ||
| # "residential" key, which is the common case when the network is not | ||
| # part of the residential proxy feed. | ||
| def test_insights_anonymizer_without_residential | ||
| model = MaxMind::GeoIP2::Model::Insights.new( | ||
| { | ||
| 'anonymizer' => { | ||
| 'confidence' => 85, | ||
| }, | ||
| }, | ||
| ['en'], | ||
| ) | ||
|
|
||
| assert_equal(85, model.anonymizer.confidence) | ||
|
|
||
| assert_nil(model.anonymizer.residential.confidence) | ||
| assert_nil(model.anonymizer.residential.network_last_seen) | ||
| assert_nil(model.anonymizer.residential.provider_name) | ||
| end | ||
|
|
||
| # network_last_seen is parsed lazily and guards against a missing date | ||
| # string. This asserts the guard is in place rather than an unconditional | ||
| # Date.parse(nil), which would raise. | ||
| def test_anonymizer_feed_network_last_seen_absent | ||
| feed = MaxMind::GeoIP2::Record::AnonymizerFeed.new( | ||
| { 'confidence' => 82 }, | ||
| ) | ||
|
|
||
| assert_nil(feed.network_last_seen) | ||
| end | ||
|
|
||
| def test_anonymizer_network_last_seen_absent | ||
| anonymizer = MaxMind::GeoIP2::Record::Anonymizer.new( | ||
| { 'confidence' => 85 }, | ||
| ) | ||
|
|
||
| assert_nil(anonymizer.network_last_seen) | ||
| end | ||
|
|
||
| def test_anonymous_plus_network_last_seen_absent | ||
| model = MaxMind::GeoIP2::Model::AnonymousPlus.new( | ||
| { | ||
| 'ip_address' => '1.2.3.4', | ||
| 'prefix_length' => 24, | ||
| }, | ||
| ) | ||
|
|
||
| assert_nil(model.network_last_seen) | ||
| end | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test gap (major): the absent-
residentialand absent-anonymizerpaths are untested.Insights#initializealways callsAnonymizer.new(record['anonymizer']), and most Insights responses carry no residential data (and non-Insights responses have noanonymizerat all), soAnonymizer.new(nil)/AnonymizerFeed.new(nil)are the common paths. Thisrecord.nil? ? nil : record['residential']guard is the only thing preventing aNoMethodError, yet the sole fixture always fully populatesresidential.Suggest adding a test with (a) an anonymizer that has only
residential(the documented "may be populated even when no other anonymizer attributes are set" case) and (b) an anonymizer-less response, assertingresidentialis non-nil and its three fields return nil without raising. GeoIP2-php'sInsightsTest.phphas this exact case as a model.— Claude, on behalf of Will
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claude, on behalf of Greg: Added coverage in commit f9d3fbc (test/test_record.rb):
test_insights_no_anonymizerbuilds aModel::Insightsfrom a raw hash with noanonymizerkey at all and asserts everyanonymizer/anonymizer.residentialgetter returns nil with noNoMethodError, andtest_insights_anonymizer_without_residentialcovers ananonymizerpresent without a nestedresidentialkey, assertingresidential.confidence/.network_last_seen/.provider_nameare all nil.