xposedornot 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f9cdb8cf4574407c468bb74827549048bf41754f4278c8987546b374b3a708c
4
- data.tar.gz: fe1dd67cd895457cb38191ecde0c7a4c6eb350598137ef3c69c1aaca44304472
3
+ metadata.gz: d5e29be49035702970f6e4420c5461f54fd862530298e3e1ab99d77cdfaccc86
4
+ data.tar.gz: 315dcc82cbcc4de0f3e9ad8715f960fe5f4eadcee8a0df1050b7058036f90164
5
5
  SHA512:
6
- metadata.gz: ed2b79e6fb0b032718c143c988ecb788c3718f1ce0f6b60f5fb9a38635ec3f019cb0d78e898f5020b9d8b18db3c64a4cf0ef874e82c3aae475ab1aa36d42ed02
7
- data.tar.gz: 589c001faa755f628a0c02c4b47120ec33eb7fa1082a7d69c63f42f23c57c51fbb25f012fb994e49a96cded660a955da678d789d17ca72cefb3834c306ee915d
6
+ metadata.gz: 728126a8268521381cb7a2deed69dd54b7864fbfb6da0ce943919805779050d913aea1725af04fde5c2c172d6936e18510a6058a01f5ffa685e040992d4a5efb
7
+ data.tar.gz: 5b946852623b383499b3934cab2db55d40cc02a21c2d8559136ae7695a38b84edd9c8168f7b35fe54e581b87d17ee08761b28e39daf99cd7f397dae107794566
data/README.md CHANGED
@@ -30,9 +30,10 @@
30
30
  - [Requirements](#requirements)
31
31
  - [Quick Start](#quick-start)
32
32
  - [API Reference](#api-reference)
33
- - [check_email](#check_emailemail)
34
- - [get_breaches](#get_breachesdomain)
35
- - [breach_analytics](#breach_analyticsemail)
33
+ - [check_email](#check_emailemail-include_details-false)
34
+ - [get_breaches](#get_breachesdomain-breach_id)
35
+ - [get_domain_breaches](#get_domain_breaches)
36
+ - [breach_analytics](#breach_analyticsemail-token-nil)
36
37
  - [check_password](#check_passwordpassword)
37
38
  - [Error Handling](#error-handling)
38
39
  - [Rate Limits](#rate-limits)
@@ -104,9 +105,12 @@ See [Configuration](#configuration) for all available options.
104
105
 
105
106
  ### Methods
106
107
 
107
- #### `check_email(email)`
108
+ #### `check_email(email, include_details: false)`
108
109
 
109
- Check if an email address has been exposed in any data breaches. When an API key is configured, uses the Plus API for detailed results including `breach_id` and `password_risk`. Otherwise, uses the free API.
110
+ Check if an email address has been exposed in any data breaches.
111
+
112
+ - **Without API key**: Uses the free API, returns `EmailBreachResponse` with breach names only. Pass `include_details: true` to request detailed breach information.
113
+ - **With API key**: Uses the Plus API (`plus-api.xposedornot.com`), returns `EmailBreachDetailedResponse` with full breach details (`include_details` is ignored - the Plus API is always queried with detailed results).
110
114
 
111
115
  ```ruby
112
116
  # Free API
@@ -122,9 +126,9 @@ puts result.breaches.first.breach_id
122
126
  puts result.breaches.first.password_risk
123
127
  ```
124
128
 
125
- #### `get_breaches(domain:)`
129
+ #### `get_breaches(domain:, breach_id:)`
126
130
 
127
- Get a list of all known data breaches, optionally filtered by domain.
131
+ Get a list of all known data breaches, optionally filtered by domain or breach ID.
128
132
 
129
133
  ```ruby
130
134
  # Get all breaches
@@ -133,6 +137,9 @@ breaches = client.get_breaches
133
137
  # Filter by domain
134
138
  adobe_breaches = client.get_breaches(domain: 'adobe.com')
135
139
 
140
+ # Fetch a specific breach by ID
141
+ adobe = client.get_breaches(breach_id: 'Adobe')
142
+
136
143
  breaches.each do |breach|
137
144
  puts "#{breach.breach_id} - #{breach.domain} (#{breach.exposed_records} records)"
138
145
  end
@@ -143,18 +150,37 @@ end
143
150
  | Parameter | Type | Description |
144
151
  |-----------|------|-------------|
145
152
  | `domain` | `String` | Optional. Filter breaches by domain |
153
+ | `breach_id` | `String` | Optional. Fetch a specific breach by ID |
146
154
 
147
155
  **Returns:** `Array<Models::Breach>` with properties such as `breach_id`, `breached_date`, `domain`, `industry`, `exposed_data`, `exposed_records`, and `verified`.
148
156
 
149
- #### `breach_analytics(email)`
157
+ #### `get_domain_breaches`
158
+
159
+ Get breach information for domains verified against your API key (requires an API key with verified domains configured at [console.xposedornot.com](https://console.xposedornot.com)).
160
+
161
+ ```ruby
162
+ client = XposedOrNot::Client.new(api_key: 'your-api-key')
163
+ report = client.get_domain_breaches
164
+
165
+ puts report.domain_summary # Breach counts per domain
166
+ puts report.yearly_metrics # Breach counts by year
167
+ puts report.top10_breaches # Top 10 largest breaches
168
+
169
+ report.breaches_details.each do |record|
170
+ puts "#{record.email} #{record.domain} #{record.breach}"
171
+ end
172
+ ```
173
+
174
+ #### `breach_analytics(email, token: nil)`
150
175
 
151
- Get detailed breach analytics for an email address, including breach summaries, metrics, and paste exposures.
176
+ Get detailed breach analytics for an email address, including breach summaries, metrics, and paste exposures. Pass `token` to access sensitive breach data.
152
177
 
153
178
  ```ruby
154
179
  analytics = client.breach_analytics('user@example.com')
155
180
 
181
+ puts analytics.breaches_count # Number of breaches
182
+ puts analytics.breach_names # Names of breaches the email was found in
156
183
  puts analytics.breaches_details.length
157
- puts analytics.breaches_summary
158
184
  puts analytics.breach_metrics
159
185
  puts analytics.exposed_pastes
160
186
  ```
@@ -4,18 +4,38 @@ module XposedOrNot
4
4
  module Endpoints
5
5
  # Breaches listing endpoint.
6
6
  module Breaches
7
- # Get a list of all known breaches, optionally filtered by domain.
7
+ # Get a list of all known breaches, optionally filtered by domain or breach ID.
8
8
  #
9
9
  # @param domain [String, nil] optional domain to filter results
10
+ # @param breach_id [String, nil] optional breach ID to fetch a specific breach
10
11
  # @return [Array<Models::Breach>] list of breach records
11
- def get_breaches(domain: nil)
12
+ def get_breaches(domain: nil, breach_id: nil)
12
13
  params = {}
13
14
  params[:domain] = domain if domain
15
+ params[:breach_id] = breach_id if breach_id
14
16
 
15
17
  response = request(:get, "/v1/breaches", base: :free, params: params)
16
18
  raw = response["exposedBreaches"] || []
17
19
  raw.map { |b| Models::Breach.new(b) }
18
20
  end
21
+
22
+ # Get breach information for domains verified against the API key.
23
+ #
24
+ # Requires an API key with verified domains configured at
25
+ # console.xposedornot.com.
26
+ #
27
+ # @return [Models::DomainBreachesResponse] metrics and exposed email records
28
+ # @raise [AuthenticationError] if no API key is configured or the key is invalid
29
+ def get_domain_breaches
30
+ unless @config.plus_api?
31
+ raise AuthenticationError,
32
+ "An API key is required for domain breach monitoring. " \
33
+ "Get one at console.xposedornot.com"
34
+ end
35
+
36
+ response = request(:post, "/v1/domain-breaches", base: :free)
37
+ Models::DomainBreachesResponse.new(response)
38
+ end
19
39
  end
20
40
  end
21
41
  end
@@ -12,37 +12,47 @@ module XposedOrNot
12
12
  # Otherwise, uses the free API.
13
13
  #
14
14
  # @param email [String] the email address to check
15
+ # @param include_details [Boolean] request detailed breach information from the
16
+ # free API; ignored when an API key is set (the Plus API is always queried
17
+ # with detailed results)
15
18
  # @return [Models::EmailBreachResponse, Models::EmailBreachDetailedResponse]
16
19
  # @raise [ValidationError] if the email is invalid
17
- # @raise [NotFoundError] if the email is not found in any breaches
18
- def check_email(email)
20
+ # @raise [NotFoundError] if the Plus API reports the email as not found
21
+ def check_email(email, include_details: false)
19
22
  Utils.validate_email(email)
20
23
 
21
24
  if @config.plus_api?
22
25
  check_email_detailed(email)
23
26
  else
24
- check_email_free(email)
27
+ check_email_free(email, include_details: include_details)
25
28
  end
26
29
  end
27
30
 
28
31
  # Get breach analytics for an email address.
29
32
  #
30
33
  # @param email [String] the email address to analyze
34
+ # @param token [String, nil] optional token for accessing sensitive breach data
31
35
  # @return [Models::BreachAnalyticsResponse]
32
36
  # @raise [ValidationError] if the email is invalid
33
- def breach_analytics(email)
37
+ def breach_analytics(email, token: nil)
34
38
  Utils.validate_email(email)
35
39
 
36
- response = request(:get, "/v1/breach-analytics", base: :free, params: { email: email })
40
+ params = { email: email }
41
+ params[:token] = token if token
42
+
43
+ response = request(:get, "/v1/breach-analytics", base: :free, params: params)
37
44
  Models::BreachAnalyticsResponse.new(response)
38
45
  end
39
46
 
40
47
  private
41
48
 
42
49
  # @param email [String]
50
+ # @param include_details [Boolean]
43
51
  # @return [Models::EmailBreachResponse]
44
- def check_email_free(email)
45
- response = request(:get, "/v1/check-email/#{URI.encode_www_form_component(email)}", base: :free)
52
+ def check_email_free(email, include_details: false)
53
+ params = include_details ? { include_details: "true" } : {}
54
+ response = request(:get, "/v1/check-email/#{URI.encode_www_form_component(email)}", base: :free,
55
+ params: params)
46
56
  Models::EmailBreachResponse.new(response)
47
57
  rescue NotFoundError
48
58
  # 404 means email not found in any breaches — valid result
@@ -19,6 +19,21 @@ module XposedOrNot
19
19
  # @return [Array<Hash>] exposed pastes
20
20
  attr_reader :exposed_pastes
21
21
 
22
+ # @return [Array<String>] names of breaches the email was found in
23
+ attr_reader :breach_names
24
+
25
+ # @return [Integer] number of breaches the email was found in
26
+ attr_reader :breaches_count
27
+
28
+ # @return [Integer] total number of exposures
29
+ attr_reader :exposures_count
30
+
31
+ # @return [String] date of first breach
32
+ attr_reader :first_breach
33
+
34
+ # @return [Integer] number of pastes the email was found in
35
+ attr_reader :pastes_count
36
+
22
37
  # @param data [Hash] raw response data from the API
23
38
  def initialize(data)
24
39
  exposed = data["ExposedBreaches"] || {}
@@ -28,6 +43,19 @@ module XposedOrNot
28
43
  @breach_metrics = data["BreachMetrics"] || {}
29
44
  @pastes_summary = data["PastesSummary"] || {}
30
45
  @exposed_pastes = data["ExposedPastes"] || []
46
+
47
+ site = @breaches_summary["site"]
48
+ if site.is_a?(String)
49
+ @breach_names = site.split(";").reject(&:empty?)
50
+ @breaches_count = @breach_names.length
51
+ else
52
+ @breach_names = []
53
+ @breaches_count = site || 0
54
+ end
55
+
56
+ @exposures_count = @breaches_summary["exposures"] || @breaches_details.length
57
+ @first_breach = @breaches_summary["first_breach"] || ""
58
+ @pastes_count = @pastes_summary["cnt"] || 0
31
59
  end
32
60
 
33
61
  # @return [Hash] hash representation
@@ -37,7 +65,12 @@ module XposedOrNot
37
65
  breaches_summary: @breaches_summary,
38
66
  breach_metrics: @breach_metrics,
39
67
  pastes_summary: @pastes_summary,
40
- exposed_pastes: @exposed_pastes
68
+ exposed_pastes: @exposed_pastes,
69
+ breach_names: @breach_names,
70
+ breaches_count: @breaches_count,
71
+ exposures_count: @exposures_count,
72
+ first_breach: @first_breach,
73
+ pastes_count: @pastes_count
41
74
  }
42
75
  end
43
76
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module XposedOrNot
4
+ module Models
5
+ # A single exposed email record from the domain-breaches endpoint.
6
+ class DomainBreachDetail
7
+ # @return [String] email address exposed in the breach
8
+ attr_reader :email
9
+
10
+ # @return [String] verified domain the email belongs to
11
+ attr_reader :domain
12
+
13
+ # @return [String] name of the breach the email was found in
14
+ attr_reader :breach
15
+
16
+ # @param data [Hash] raw record data from the API
17
+ def initialize(data)
18
+ @email = data["email"] || ""
19
+ @domain = data["domain"] || ""
20
+ @breach = data["breach"] || ""
21
+ end
22
+
23
+ # @return [Hash] hash representation
24
+ def to_h
25
+ { email: @email, domain: @domain, breach: @breach }
26
+ end
27
+ end
28
+
29
+ # Response from the domain-breaches endpoint.
30
+ #
31
+ # Contains breach metrics and statistics for domains verified
32
+ # against the API key.
33
+ class DomainBreachesResponse
34
+ # @return [String] response status ("success" or "error")
35
+ attr_reader :status
36
+
37
+ # @return [Array<DomainBreachDetail>] exposed email records across the verified domains
38
+ attr_reader :breaches_details
39
+
40
+ # @return [Hash] breach counts by year
41
+ attr_reader :yearly_metrics
42
+
43
+ # @return [Hash] summary of breaches by domain
44
+ attr_reader :domain_summary
45
+
46
+ # @return [Hash] summary of all breaches
47
+ attr_reader :breach_summary
48
+
49
+ # @return [Hash] top 10 largest breaches affecting the domains
50
+ attr_reader :top10_breaches
51
+
52
+ # @return [Hash] detailed information about each breach
53
+ attr_reader :detailed_breach_info
54
+
55
+ # @param data [Hash] raw response data from the API
56
+ def initialize(data)
57
+ metrics = data["metrics"] || {}
58
+ @status = data["status"] || ""
59
+ @breaches_details = (metrics["Breaches_Details"] || []).map { |b| DomainBreachDetail.new(b) }
60
+ @yearly_metrics = metrics["Yearly_Metrics"] || {}
61
+ @domain_summary = metrics["Domain_Summary"] || {}
62
+ @breach_summary = metrics["Breach_Summary"] || {}
63
+ @top10_breaches = metrics["Top10_Breaches"] || {}
64
+ @detailed_breach_info = metrics["Detailed_Breach_Info"] || {}
65
+ end
66
+
67
+ # @return [Hash] hash representation
68
+ def to_h
69
+ {
70
+ status: @status,
71
+ breaches_details: @breaches_details.map(&:to_h),
72
+ yearly_metrics: @yearly_metrics,
73
+ domain_summary: @domain_summary,
74
+ breach_summary: @breach_summary,
75
+ top10_breaches: @top10_breaches,
76
+ detailed_breach_info: @detailed_breach_info
77
+ }
78
+ end
79
+ end
80
+ end
81
+ end
@@ -7,6 +7,12 @@ module XposedOrNot
7
7
  # @return [Array<String>] list of breach names
8
8
  attr_reader :breaches
9
9
 
10
+ # @return [String] the email address that was checked
11
+ attr_reader :email
12
+
13
+ # @return [String] response status ("success" or "error")
14
+ attr_reader :status
15
+
10
16
  # @param data [Hash] raw response data from the API
11
17
  def initialize(data)
12
18
  raw = data["breaches"]
@@ -17,6 +23,8 @@ module XposedOrNot
17
23
  else
18
24
  []
19
25
  end
26
+ @email = data["email"] || ""
27
+ @status = data["status"] || ""
20
28
  end
21
29
 
22
30
  # @return [Boolean] true if the email was found in any breaches
@@ -31,7 +39,7 @@ module XposedOrNot
31
39
 
32
40
  # @return [Hash] hash representation
33
41
  def to_h
34
- { breaches: @breaches, breached: breached?, count: count }
42
+ { breaches: @breaches, breached: breached?, count: count, email: @email, status: @status }
35
43
  end
36
44
  end
37
45
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module XposedOrNot
4
- VERSION = "1.0.2"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/xposedornot.rb CHANGED
@@ -8,6 +8,7 @@ require_relative "xposedornot/models/breach"
8
8
  require_relative "xposedornot/models/email_breach_response"
9
9
  require_relative "xposedornot/models/email_breach_detailed_response"
10
10
  require_relative "xposedornot/models/breach_analytics_response"
11
+ require_relative "xposedornot/models/domain_breaches_response"
11
12
  require_relative "xposedornot/models/password_check_response"
12
13
  require_relative "xposedornot/endpoints/email"
13
14
  require_relative "xposedornot/endpoints/breaches"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xposedornot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - XposedOrNot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-22 00:00:00.000000000 Z
11
+ date: 2026-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -72,6 +72,7 @@ files:
72
72
  - lib/xposedornot/errors.rb
73
73
  - lib/xposedornot/models/breach.rb
74
74
  - lib/xposedornot/models/breach_analytics_response.rb
75
+ - lib/xposedornot/models/domain_breaches_response.rb
75
76
  - lib/xposedornot/models/email_breach_detailed_response.rb
76
77
  - lib/xposedornot/models/email_breach_response.rb
77
78
  - lib/xposedornot/models/password_check_response.rb