hibp-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []