have_i_been_pwned_api 0.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +406 -0
- data/Rakefile +8 -0
- data/lib/have_i_been_pwned_api/client.rb +71 -0
- data/lib/have_i_been_pwned_api/configuration.rb +37 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/breach.rb +25 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/breached_account.rb +33 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/breached_domain.rb +26 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/breaches.rb +30 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/data_classes.rb +23 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/latest_breach.rb +24 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches/subscribed_domains.rb +22 -0
- data/lib/have_i_been_pwned_api/endpoints/breaches.rb +18 -0
- data/lib/have_i_been_pwned_api/endpoints/endpoint.rb +33 -0
- data/lib/have_i_been_pwned_api/endpoints/pastes/paste_account.rb +25 -0
- data/lib/have_i_been_pwned_api/endpoints/pastes.rb +12 -0
- data/lib/have_i_been_pwned_api/endpoints/pwned_passwords/check_pwd.rb +41 -0
- data/lib/have_i_been_pwned_api/endpoints/pwned_passwords.rb +12 -0
- data/lib/have_i_been_pwned_api/endpoints/stealer_logs/by_email.rb +24 -0
- data/lib/have_i_been_pwned_api/endpoints/stealer_logs/by_email_domain.rb +24 -0
- data/lib/have_i_been_pwned_api/endpoints/stealer_logs/by_website_domain.rb +24 -0
- data/lib/have_i_been_pwned_api/endpoints/stealer_logs.rb +14 -0
- data/lib/have_i_been_pwned_api/endpoints/subscription/status.rb +22 -0
- data/lib/have_i_been_pwned_api/endpoints/subscription.rb +12 -0
- data/lib/have_i_been_pwned_api/error.rb +48 -0
- data/lib/have_i_been_pwned_api/models/breaches/breach.rb +43 -0
- data/lib/have_i_been_pwned_api/models/breaches/breach_collection.rb +21 -0
- data/lib/have_i_been_pwned_api/models/breaches/breached_domain.rb +16 -0
- data/lib/have_i_been_pwned_api/models/breaches/domain.rb +39 -0
- data/lib/have_i_been_pwned_api/models/breaches/truncated_breach.rb +13 -0
- data/lib/have_i_been_pwned_api/models/pastes/paste.rb +37 -0
- data/lib/have_i_been_pwned_api/models/pastes/paste_collection.rb +17 -0
- data/lib/have_i_been_pwned_api/models/subscription/subscription_status.rb +38 -0
- data/lib/have_i_been_pwned_api/models.rb +14 -0
- data/lib/have_i_been_pwned_api/version.rb +5 -0
- data/lib/have_i_been_pwned_api.rb +24 -0
- data/lib/utils/autoloader.rb +20 -0
- data/lib/utils/strings.rb +13 -0
- data/sig/have_i_been_pwned_api.rbs +4 -0
- metadata +88 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Breaches
|
7
|
+
class Breaches < Endpoint
|
8
|
+
ALLOWED_PARAMS = %i[domain is_spam_list].freeze
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def call(**kwargs)
|
12
|
+
params = parse_optional_params(kwargs, ALLOWED_PARAMS)
|
13
|
+
|
14
|
+
data = Client.get(uri(params))
|
15
|
+
Models::BreachCollection.new(data, truncated: false)
|
16
|
+
rescue NotFound
|
17
|
+
Models::BreachCollection.new({})
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def uri(params)
|
23
|
+
uri = URI("#{endpoint_url}breaches")
|
24
|
+
uri.query = URI.encode_www_form(params) unless params.empty?
|
25
|
+
uri
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Breaches
|
7
|
+
class DataClasses < Endpoint
|
8
|
+
class << self
|
9
|
+
def call
|
10
|
+
Client.get(uri)
|
11
|
+
rescue NotFound
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def uri
|
18
|
+
URI("#{endpoint_url}dataclasses")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Breaches
|
7
|
+
class LatestBreach < Endpoint
|
8
|
+
class << self
|
9
|
+
def call
|
10
|
+
data = Client.get(uri)
|
11
|
+
Models::Breach.new(data)
|
12
|
+
rescue NotFound
|
13
|
+
Models::Breach.new({})
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def uri
|
19
|
+
URI("#{endpoint_url}latestbreach")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Breaches
|
7
|
+
class SubscribedDomains < Endpoint
|
8
|
+
class << self
|
9
|
+
def call
|
10
|
+
data = Client.get(uri)
|
11
|
+
Array(data).map { |d| Models::Domain.new(d) }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def uri
|
17
|
+
URI("#{endpoint_url}subscribeddomains")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "breaches/latest_breach"
|
4
|
+
require_relative "breaches/breached_account"
|
5
|
+
require_relative "breaches/breach"
|
6
|
+
require_relative "breaches/breached_domain"
|
7
|
+
require_relative "breaches/breaches"
|
8
|
+
require_relative "breaches/data_classes"
|
9
|
+
require_relative "breaches/subscribed_domains"
|
10
|
+
|
11
|
+
require_relative "../../utils/strings"
|
12
|
+
require_relative "../../utils/autoloader"
|
13
|
+
|
14
|
+
module HaveIBeenPwnedApi
|
15
|
+
module Breaches
|
16
|
+
Utils::Autoloader.define_endpoint_methods(self)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HaveIBeenPwnedApi
|
4
|
+
class Endpoint
|
5
|
+
class << self
|
6
|
+
def type
|
7
|
+
:premium
|
8
|
+
end
|
9
|
+
|
10
|
+
def endpoint_url
|
11
|
+
config.base_url_for_endpoint_type(type)
|
12
|
+
end
|
13
|
+
|
14
|
+
def config
|
15
|
+
HaveIBeenPwnedApi.config
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def parse_optional_params(kwargs, allowed_params)
|
21
|
+
params = {}
|
22
|
+
kwargs.map do |key, value|
|
23
|
+
raise Error, "Invalid argument #{key}" unless allowed_params.include?(key)
|
24
|
+
|
25
|
+
key = key.to_s.gsub("_", "")
|
26
|
+
params[key] = value unless value.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
params
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Pastes
|
7
|
+
class PasteAccount < Endpoint
|
8
|
+
class << self
|
9
|
+
def call(account:)
|
10
|
+
data = Client.get(uri(account))
|
11
|
+
Models::PasteCollection.new(data)
|
12
|
+
rescue NotFound
|
13
|
+
Models::PasteCollection.new({})
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def uri(account)
|
19
|
+
encoded_account = URI.encode_www_form_component(account)
|
20
|
+
URI("#{endpoint_url}pasteaccount/#{encoded_account}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "pastes/paste_account"
|
4
|
+
|
5
|
+
require_relative "../../utils/strings"
|
6
|
+
require_relative "../../utils/autoloader"
|
7
|
+
|
8
|
+
module HaveIBeenPwnedApi
|
9
|
+
module Pastes
|
10
|
+
Utils::Autoloader.define_endpoint_methods(self)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
require "digest"
|
5
|
+
|
6
|
+
module HaveIBeenPwnedApi
|
7
|
+
module PwnedPasswords
|
8
|
+
class CheckPwd < Endpoint
|
9
|
+
class << self
|
10
|
+
def type
|
11
|
+
:free
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(password:, add_padding: false)
|
15
|
+
digest = hash_password(password)
|
16
|
+
|
17
|
+
data = Client.get(uri(digest[..4]),
|
18
|
+
headers: { add_padding: add_padding })
|
19
|
+
|
20
|
+
count_password_appereances(digest, data)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def count_password_appereances(digest, data)
|
26
|
+
partial_hash = Regexp.escape(digest[5..])
|
27
|
+
count = data.match(/#{partial_hash}:(\d+)/) { $1.to_i }
|
28
|
+
count.nil? ? 0 : count
|
29
|
+
end
|
30
|
+
|
31
|
+
def hash_password(password)
|
32
|
+
Digest::SHA1.hexdigest(password).upcase
|
33
|
+
end
|
34
|
+
|
35
|
+
def uri(digest_chars)
|
36
|
+
URI("#{endpoint_url}range/#{digest_chars}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "pwned_passwords/check_pwd"
|
4
|
+
|
5
|
+
require_relative "../../utils/strings"
|
6
|
+
require_relative "../../utils/autoloader"
|
7
|
+
|
8
|
+
module HaveIBeenPwnedApi
|
9
|
+
module PwnedPasswords
|
10
|
+
Utils::Autoloader.define_endpoint_methods(self)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module StealerLogs
|
7
|
+
class ByEmail < Endpoint
|
8
|
+
class << self
|
9
|
+
def call(email:)
|
10
|
+
Client.get(uri(email))
|
11
|
+
rescue NotFound
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def uri(email)
|
18
|
+
encoded_email = URI.encode_www_form_component(email)
|
19
|
+
URI("#{endpoint_url}stealerlogsbyemail/#{encoded_email}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module StealerLogs
|
7
|
+
class ByEmailDomain < Endpoint
|
8
|
+
class << self
|
9
|
+
def call(domain:)
|
10
|
+
Client.get(uri(domain))
|
11
|
+
rescue NotFound
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def uri(domain)
|
18
|
+
encoded_domain = URI.encode_www_form_component(domain)
|
19
|
+
URI("#{endpoint_url}stealerlogsbyemaildomain/#{encoded_domain}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module StealerLogs
|
7
|
+
class ByWebsiteDomain < Endpoint
|
8
|
+
class << self
|
9
|
+
def call(domain:)
|
10
|
+
Client.get(uri(domain))
|
11
|
+
rescue NotFound
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def uri(domain)
|
18
|
+
encoded_domain = URI.encode_www_form_component(domain)
|
19
|
+
URI("#{endpoint_url}stealerlogsbywebsitedomain/#{encoded_domain}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "stealer_logs/by_email"
|
4
|
+
require_relative "stealer_logs/by_email_domain"
|
5
|
+
require_relative "stealer_logs/by_website_domain"
|
6
|
+
|
7
|
+
require_relative "../../utils/strings"
|
8
|
+
require_relative "../../utils/autoloader"
|
9
|
+
|
10
|
+
module HaveIBeenPwnedApi
|
11
|
+
module StealerLogs
|
12
|
+
Utils::Autoloader.define_endpoint_methods(self)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../endpoint"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Subscription
|
7
|
+
class Status < Endpoint
|
8
|
+
class << self
|
9
|
+
def call
|
10
|
+
data = Client.get(uri)
|
11
|
+
Models::SubscriptionStatus.new(data)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def uri
|
17
|
+
URI("#{endpoint_url}subscription/status")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "subscription/status"
|
4
|
+
|
5
|
+
require_relative "../../utils/strings"
|
6
|
+
require_relative "../../utils/autoloader"
|
7
|
+
|
8
|
+
module HaveIBeenPwnedApi
|
9
|
+
module Subscription
|
10
|
+
Utils::Autoloader.define_endpoint_methods(self)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HaveIBeenPwnedApi
|
4
|
+
class Error < StandardError
|
5
|
+
attr_reader :detail
|
6
|
+
|
7
|
+
DEFAULT_MESSAGE = "An unexpected error occurred"
|
8
|
+
|
9
|
+
# @param message [String] custom error message
|
10
|
+
# @param detail [String, nil] raw response body or other debug info
|
11
|
+
def initialize(message = nil, detail: nil)
|
12
|
+
super(message || self.class::DEFAULT_MESSAGE)
|
13
|
+
@detail = detail
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
if detail && !detail.empty?
|
18
|
+
"#{super} - Error detail: #{detail}"
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class BadRequest < Error
|
26
|
+
DEFAULT_MESSAGE = "Bad request — invalid resource format"
|
27
|
+
end
|
28
|
+
|
29
|
+
class Unauthorized < Error
|
30
|
+
DEFAULT_MESSAGE = "Missing or invalid API key"
|
31
|
+
end
|
32
|
+
|
33
|
+
class Forbidden < Error
|
34
|
+
DEFAULT_MESSAGE = "Forbidden — Check error details"
|
35
|
+
end
|
36
|
+
|
37
|
+
class NotFound < Error
|
38
|
+
DEFAULT_MESSAGE = "Resource Not found"
|
39
|
+
end
|
40
|
+
|
41
|
+
class RateLimitExceeded < Error
|
42
|
+
DEFAULT_MESSAGE = "Rate limit exceeded"
|
43
|
+
end
|
44
|
+
|
45
|
+
class ServiceUnavailable < Error
|
46
|
+
DEFAULT_MESSAGE = "Service unavailable"
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Models
|
7
|
+
class Breach
|
8
|
+
ATTRS = %w[ Name Title Domain BreachDate AddedDate ModifiedDate
|
9
|
+
PwnCount Description DataClasses IsVerified
|
10
|
+
IsFabricated IsSensitive IsRetired IsSpamList
|
11
|
+
IsMalware IsSubscriptionFree IsStealerLog LogoPath].freeze
|
12
|
+
|
13
|
+
DATE_FIELDS = %w[BreachDate].freeze
|
14
|
+
DATETIME_FIELDS = %w[AddedDate ModifiedDate].freeze
|
15
|
+
|
16
|
+
ATTRS.each do |k|
|
17
|
+
attr_reader Utils::Strings.underscore(k).to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(attrs)
|
21
|
+
ATTRS.each do |k|
|
22
|
+
key = Utils::Strings.underscore(k)
|
23
|
+
raw = attrs[k]
|
24
|
+
value = parse_date_field(k, raw)
|
25
|
+
instance_variable_set("@#{key}", value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_date_field(field, raw)
|
32
|
+
case field
|
33
|
+
when *DATE_FIELDS
|
34
|
+
raw && Date.iso8601(raw)
|
35
|
+
when *DATETIME_FIELDS
|
36
|
+
raw && DateTime.parse(raw)
|
37
|
+
else
|
38
|
+
raw
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HaveIBeenPwnedApi
|
4
|
+
module Models
|
5
|
+
class BreachCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :breaches
|
9
|
+
|
10
|
+
def initialize(data, truncated: true)
|
11
|
+
@breaches = data.map do |h|
|
12
|
+
if truncated
|
13
|
+
TruncatedBreach.new(h["Name"])
|
14
|
+
else
|
15
|
+
Breach.new(h)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HaveIBeenPwnedApi
|
4
|
+
module Models
|
5
|
+
class BreachedDomain
|
6
|
+
attr_reader :entries
|
7
|
+
|
8
|
+
def initialize(attrs)
|
9
|
+
@entries = {}
|
10
|
+
attrs.each do |account_alias, breaches|
|
11
|
+
@entries[account_alias] = breaches
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Models
|
7
|
+
class Domain
|
8
|
+
ATTRS = %w[ DomainName PwnCount PwnCountExcludingSpamLists
|
9
|
+
PwnCountExcludingSpamListsAtLastSubscriptionRenewal
|
10
|
+
NextSubscriptionRenewal ].freeze
|
11
|
+
|
12
|
+
DATETIME_FIELDS = %w[NextSubscriptionRenewal].freeze
|
13
|
+
|
14
|
+
ATTRS.each do |k|
|
15
|
+
attr_reader Utils::Strings.underscore(k).to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(attrs)
|
19
|
+
ATTRS.each do |k|
|
20
|
+
key = Utils::Strings.underscore(k)
|
21
|
+
raw = attrs[k]
|
22
|
+
value = parse_date_field(k, raw)
|
23
|
+
instance_variable_set("@#{key}", value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def parse_date_field(field, raw)
|
30
|
+
case field
|
31
|
+
when *DATETIME_FIELDS
|
32
|
+
raw && DateTime.parse(raw)
|
33
|
+
else
|
34
|
+
raw
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Models
|
7
|
+
class Paste
|
8
|
+
ATTRS = %w[Source Id Title Domain Date EmailCount].freeze
|
9
|
+
|
10
|
+
DATETIME_FIELDS = %w[Date].freeze
|
11
|
+
|
12
|
+
ATTRS.each do |k|
|
13
|
+
attr_reader Utils::Strings.underscore(k).to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(attrs)
|
17
|
+
ATTRS.each do |k|
|
18
|
+
key = Utils::Strings.underscore(k)
|
19
|
+
raw = attrs[k]
|
20
|
+
value = parse_date_field(k, raw)
|
21
|
+
instance_variable_set("@#{key}", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse_date_field(field, raw)
|
28
|
+
case field
|
29
|
+
when *DATETIME_FIELDS
|
30
|
+
raw && DateTime.parse(raw)
|
31
|
+
else
|
32
|
+
raw
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HaveIBeenPwnedApi
|
4
|
+
module Models
|
5
|
+
class PasteCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :pastes
|
9
|
+
|
10
|
+
def initialize(data)
|
11
|
+
@pastes = data.map do |h|
|
12
|
+
Paste.new(h)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module HaveIBeenPwnedApi
|
6
|
+
module Models
|
7
|
+
class SubscriptionStatus
|
8
|
+
ATTRS = %w[SubscriptionName Description SubscribedUntil
|
9
|
+
Rpm DomainSearchMaxBreachedAccounts].freeze
|
10
|
+
|
11
|
+
DATETIME_FIELDS = %w[SubscribedUntil].freeze
|
12
|
+
|
13
|
+
ATTRS.each do |k|
|
14
|
+
attr_reader Utils::Strings.underscore(k).to_sym
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(attrs)
|
18
|
+
ATTRS.each do |k|
|
19
|
+
key = Utils::Strings.underscore(k)
|
20
|
+
raw = attrs[k]
|
21
|
+
value = parse_date_field(k, raw)
|
22
|
+
instance_variable_set("@#{key}", value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def parse_date_field(field, raw)
|
29
|
+
case field
|
30
|
+
when *DATETIME_FIELDS
|
31
|
+
raw && DateTime.parse(raw)
|
32
|
+
else
|
33
|
+
raw
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HaveIBeenPwnedApi
|
4
|
+
module Models
|
5
|
+
autoload :Breach, "have_i_been_pwned_api/models/breaches/breach"
|
6
|
+
autoload :TruncatedBreach, "have_i_been_pwned_api/models/breaches/truncated_breach"
|
7
|
+
autoload :BreachedDomain, "have_i_been_pwned_api/models/breaches/breached_domain"
|
8
|
+
autoload :BreachCollection, "have_i_been_pwned_api/models/breaches/breach_collection"
|
9
|
+
autoload :Domain, "have_i_been_pwned_api/models/breaches/domain"
|
10
|
+
autoload :Paste, "have_i_been_pwned_api/models/pastes/paste"
|
11
|
+
autoload :PasteCollection, "have_i_been_pwned_api/models/pastes/paste_collection"
|
12
|
+
autoload :SubscriptionStatus, "have_i_been_pwned_api/models/subscription/subscription_status"
|
13
|
+
end
|
14
|
+
end
|