hibp-client 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.
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hibp
4
+ # Hibp::Query
5
+ #
6
+ # Used to build and execute request to the HIBP API
7
+ #
8
+ class Query
9
+ attr_reader :endpoint, :headers, :parser
10
+
11
+ # @param endpoint [String] -
12
+ # A specific API endpoint to call appropriate method
13
+ #
14
+ # @param headers [Hash] -
15
+ # Specific request headers
16
+ #
17
+ # @param parser [Hibp::Parser] -
18
+ # A tool to parse and convert data into appropriate models
19
+ #
20
+ def initialize(endpoint:, headers: {}, parser: Parsers::Json.new)
21
+ @endpoint = endpoint
22
+ @headers = headers
23
+
24
+ @parser = parser
25
+ @query_params = {}
26
+ end
27
+
28
+ # Apply query filtration
29
+ #
30
+ # @param filters [Hash] - (optional, default: {})
31
+ # Additional filtration params
32
+ #
33
+ # @option filters [String] :domain -
34
+ # Filters the result set to only breaches against the domain specified.
35
+ # It is possible that one site (and consequently domain), is compromised on multiple occasions.
36
+ # (breaches and account_breaches queries)
37
+ #
38
+ # @option filters [Boolean] :truncate - (default: true)
39
+ # Short/Full data switcher(only name or full breach data)
40
+ # (only for account_breaches query)
41
+ #
42
+ # @option filters [Boolean] :unverified -
43
+ # Returns breaches that have been flagged as "unverified".
44
+ # (only for account_breaches query)
45
+ #
46
+ # @return [Hibp::Query]
47
+ #
48
+ def where(filters = {})
49
+ tap do
50
+ @query_params.merge!(convert_filters(filters))
51
+ end
52
+ end
53
+
54
+ # Perform query execution(data fetching)
55
+ #
56
+ # @return [
57
+ # Array<String>,
58
+ # Array<Hibp::Models::Breach>,
59
+ # Array<Hibp::Models::Paste>,
60
+ # Hibp::Models::Breach
61
+ # ]
62
+ #
63
+ def fetch
64
+ confugure_request.get(headers: @headers, params: @query_params)
65
+ end
66
+
67
+ private
68
+
69
+ def confugure_request
70
+ Request.new(parser: @parser, endpoint: @endpoint)
71
+ end
72
+
73
+ def convert_filters(params)
74
+ mappings = {
75
+ truncate: 'truncateResponse',
76
+ domain: 'domain',
77
+ unverified: 'includeUnverified'
78
+ }
79
+
80
+ params.each_with_object({}) do |(origin_key, value), acc|
81
+ acc[mappings.fetch(origin_key)] = value
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hibp
4
+ # Hibp::Request
5
+ #
6
+ # Used to make requests to the hibp API
7
+ #
8
+ # @see https://haveibeenpwned.com/API/v3
9
+ #
10
+ class Request
11
+ attr_reader :headers
12
+
13
+ # @param parser [Hibp::Parser] -
14
+ # A tool to parse and convert data into appropriate models
15
+ #
16
+ # @param endpoint [String] -
17
+ # A specific API endpoint to call appropriate method
18
+ #
19
+ def initialize(endpoint:, parser: Parsers::Json.new)
20
+ @endpoint = endpoint
21
+ @parser = parser
22
+
23
+ @headers = {
24
+ 'Content-Type' => 'application/json',
25
+ 'User-Agent' => "Ruby HIBP-Client #{Hibp::VERSION}"
26
+ }
27
+ end
28
+
29
+ # Perform a GET request
30
+ #
31
+ # @param params [Hash] -
32
+ # Additional query params
33
+ #
34
+ # @param headers [Hash] -
35
+ # Additional HTTP headers
36
+ #
37
+ # @raise [Hibp::ServiceError]
38
+ #
39
+ def get(params: nil, headers: nil)
40
+ response = rest_client.get(@endpoint) do |request|
41
+ configure_request(request: request, params: params, headers: headers)
42
+ end
43
+
44
+ @parser ? @parser.parse_response(response) : response.body
45
+ rescue Faraday::ClientError::ResourceNotFound
46
+ nil
47
+ rescue StandardError => e
48
+ handle_error(e)
49
+ end
50
+
51
+ private
52
+
53
+ def rest_client
54
+ Faraday.new do |faraday|
55
+ faraday.headers = @headers
56
+
57
+ faraday.response(:raise_error)
58
+ faraday.adapter(Faraday.default_adapter)
59
+ end
60
+ end
61
+
62
+ def configure_request(request: nil, params: nil, headers: nil, body: nil)
63
+ return if request.nil?
64
+
65
+ request.params.merge!(params) if params
66
+ request.headers.merge!(headers) if headers
67
+ request.body = body if body
68
+ end
69
+
70
+ def handle_error(error)
71
+ error_params = parsable_error?(error) ? parse_error(error) : {}
72
+
73
+ error_to_raise = ServiceError.new(error.message, error_params)
74
+
75
+ raise error_to_raise
76
+ end
77
+
78
+ def parsable_error?(error)
79
+ error.is_a?(Faraday::Error::ClientError) && error.response
80
+ end
81
+
82
+ def parse_error(error)
83
+ error_params = {
84
+ status_code: error.response[:status],
85
+ raw_body: error.response[:body]
86
+ }
87
+
88
+ begin
89
+ parsed_response = Oj.load(error.response[:body], {})
90
+
91
+ return error_params unless parsed_response
92
+
93
+ error_params[:body] = parsed_response
94
+
95
+ %w[title detail].each do |section|
96
+ next if parsed_response[section].nil?
97
+
98
+ error_params[section.to_sym] = parsed_response[section]
99
+ end
100
+ rescue Oj::ParseError
101
+ end
102
+
103
+ error_params
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hibp
4
+ # Hibp::ServiceError
5
+ #
6
+ # Used to represent an error that may occur when performing a request to the API
7
+ #
8
+ class ServiceError < StandardError
9
+ attr_reader :body, :raw_body, :status_code
10
+
11
+ # @param message [String] - (optional, '') Message to describe an error
12
+ # @param params [Hash] - (optional, {}) Additional error information
13
+ #
14
+ # @option params [String] :body -
15
+ # A JSON formatted error object that provides more details about the specifics of the error
16
+ #
17
+ # @option params [String] :title -
18
+ # Error summary
19
+ #
20
+ # @option params [String] :detail -
21
+ # Error detailed description
22
+ #
23
+ # @option params [String] :raw_body -
24
+ # Raw body from response
25
+ #
26
+ # @option params [String] :status_code -
27
+ # Http status code
28
+ #
29
+ def initialize(message = '', params = {})
30
+ @body = params[:body]
31
+ @raw_body = params[:raw_body]
32
+ @status_code = params[:status_code]
33
+
34
+ super(message)
35
+ end
36
+
37
+ def to_s
38
+ "#{super} #{instance_variables_to_s}"
39
+ end
40
+
41
+ private
42
+
43
+ def instance_variables_to_s
44
+ attr_values = %i[body raw_body status_code].map do |attr|
45
+ attr_value = send(attr)
46
+
47
+ "@#{attr}=#{attr_value.inspect}"
48
+ end
49
+
50
+ attr_values.join(', ')
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hibp
4
+ VERSION = '0.1.0'
5
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hibp-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Warshavski
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-07-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.6.13
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.6.13
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: A simple tool to check if an account(email address and username) has
84
+ been compromised in a data breach
85
+ email:
86
+ - p.warshavski@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - hibp.gemspec
101
+ - lib/hibp.rb
102
+ - lib/hibp/client.rb
103
+ - lib/hibp/helpers/attribute_assignment.rb
104
+ - lib/hibp/helpers/json_conversion.rb
105
+ - lib/hibp/models/breach.rb
106
+ - lib/hibp/models/password.rb
107
+ - lib/hibp/models/paste.rb
108
+ - lib/hibp/parsers/breach.rb
109
+ - lib/hibp/parsers/json.rb
110
+ - lib/hibp/parsers/password.rb
111
+ - lib/hibp/parsers/paste.rb
112
+ - lib/hibp/query.rb
113
+ - lib/hibp/request.rb
114
+ - lib/hibp/service_error.rb
115
+ - lib/hibp/version.rb
116
+ homepage: https://github.com/Warshavski/hibp
117
+ licenses:
118
+ - MIT
119
+ metadata:
120
+ homepage_uri: https://github.com/Warshavski/hibp
121
+ source_code_uri: https://github.com/Warshavski/hibp
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.7.6
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: A simple tool to check if an account(email address and username) has been
142
+ compromised in a data breach
143
+ test_files: []