hackerone-client 0.2.3 → 0.3.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
  SHA1:
3
- metadata.gz: 1377da005dc1141183d4f4ea57177a64965bb471
4
- data.tar.gz: fb7c070632d9991ac75bb56e1be490dcc69e5a0e
3
+ metadata.gz: e75818c133624c27e8d5986311b1ee3c77420916
4
+ data.tar.gz: b5e846599a80125cd47137ee42176777c8bf64cb
5
5
  SHA512:
6
- metadata.gz: 10ad6494e05446c28f9cbf8901c9bc88200258679ed364ff8f8cda734fa30b0239f6907e669a4a793a63e68a83b6191479e877da0477d45addf23b59819c9a1a
7
- data.tar.gz: 9d3291ac4094b8737c98fc5404f1246ba5e2b0f1533042d9f832ca8a8d711e2959e206aab93bb18535e18fd64de76aacf83b5dadbc6309784a172f496ef5d4d5
6
+ metadata.gz: 326cfa0c38f8cd35858c386b38b4f399074766c8dc52e15ae6b2950f5222e5a9995002335edc7ef059fd4ee56760e9134828e4475d6b5cda9b913214e3f10859
7
+ data.tar.gz: ff0bd09d8cfc186b67944bfae8f569ce843a495fad3546658a79bef11fba4582969d77b39e15ed4b376823bd841709761e7e7027ce42c038f2b904378f4460f0
@@ -0,0 +1,75 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.hackerone.com/v1/reports/500
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Authorization:
11
+ - Basic nope=
12
+ User-Agent:
13
+ - Faraday v0.11.0
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ response:
19
+ status:
20
+ code: 500
21
+ message: Error
22
+ headers:
23
+ Date:
24
+ - Wed, 15 Feb 2017 00:50:01 GMT
25
+ Content-Type:
26
+ - application/json; charset=utf-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Set-Cookie:
32
+ - __cfduid=123; expires=Thu, 15-Feb-18
33
+ 00:50:01 GMT; path=/; Domain=api.hackerone.com; HttpOnly
34
+ X-Request-Id:
35
+ - 345
36
+ Etag:
37
+ - W/"8dfc97642d70f82b560e989d44e19eac"
38
+ Cache-Control:
39
+ - max-age=0, private, must-revalidate
40
+ Strict-Transport-Security:
41
+ - max-age=31536000; includeSubDomains; preload
42
+ Content-Security-Policy:
43
+ - default-src 'none'; connect-src 'self' www.google-analytics.com errors.hackerone.net;
44
+ font-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self'
45
+ 'unsafe-inline'; form-action 'self'; frame-ancestors 'none'; report-uri https://errors.hackerone.net/api/30/csp-report/?sentry_key=123
46
+ X-Content-Type-Options:
47
+ - nosniff
48
+ X-Download-Options:
49
+ - noopen
50
+ X-Frame-Options:
51
+ - DENY
52
+ X-Permitted-Cross-Domain-Policies:
53
+ - none
54
+ X-Xss-Protection:
55
+ - 1; mode=block
56
+ Public-Key-Pins-Report-Only:
57
+ - pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";
58
+ pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0=";
59
+ pin-sha256="cGuxAXyFXFkWm61cF4HPWX8S0srS9j0aSqN0k4AP+4A="; pin-sha256="bIlWcjiKq1mftH/xd7Hw1JO77Cr+Gv+XYcGUQWwO+A4=";
60
+ pin-sha256="tXD+dGAP8rGY4PW1be90cOYEwg7pZ4G+yPZmIZWPTSg="; max-age=600; includeSubDomains;
61
+ report-uri="https://hackerone.report-uri.io/r/default/hpkp/reportOnly"
62
+ Server:
63
+ - cloudflare-nginx
64
+ Cf-Ray:
65
+ - 3314c3653e302126-LAX
66
+ body:
67
+ encoding: ASCII-8BIT
68
+ string: '{
69
+ "data": {
70
+ "error": "fail"
71
+ }
72
+ }'
73
+ http_version:
74
+ recorded_at: Wed, 15 Feb 2017 00:50:01 GMT
75
+ recorded_with: VCR 3.0.3
@@ -2,6 +2,7 @@ require "faraday"
2
2
  require 'active_support/time'
3
3
  require_relative "client/version"
4
4
  require_relative "client/report"
5
+ require_relative "client/activity"
5
6
 
6
7
  module HackerOne
7
8
  module Client
@@ -21,7 +22,13 @@ module HackerOne
21
22
  informative
22
23
  duplicate
23
24
  spam
24
- ).map(&:to_sym)
25
+ ).map(&:to_sym).freeze
26
+
27
+ STATES_REQUIRING_STATE_CHANGE_MESSAGE = %w(
28
+ needs-more-info
29
+ informative
30
+ duplicate
31
+ ).map(&:to_sym).freeze
25
32
 
26
33
  class << self
27
34
  ATTRS = [:low_range, :medium_range, :high_range, :critical_range].freeze
@@ -111,18 +118,23 @@ module HackerOne
111
118
  #
112
119
  # returns an HackerOne::Client::Report object or raises an error if
113
120
  # no report is found.
114
- def state_change(id, state)
121
+ def state_change(id, state, message = nil)
115
122
  raise ArgumentError, "state (#{state}) must be one of #{STATES}" unless STATES.include?(state)
116
123
 
117
124
  body = {
118
125
  data: {
119
126
  type: "state-change",
120
127
  attributes: {
121
- message: "This is has been triaged internally.",
122
128
  state: state
123
129
  }
124
130
  }
125
131
  }
132
+
133
+ if message
134
+ body[:message] = message
135
+ elsif STATES_REQUIRING_STATE_CHANGE_MESSAGE.include?(state)
136
+ fail ArgumentError, "State #{state} requires a message. No message was supplied."
137
+ end
126
138
  post("reports/#{id}/state_changes", body)
127
139
  end
128
140
 
@@ -165,7 +177,7 @@ module HackerOne
165
177
  if response.status.to_s.start_with?("4")
166
178
  raise ArgumentError, "API called failed, probably your fault: #{response.body}"
167
179
  elsif response.status.to_s.start_with?("5")
168
- raise Runtime, "API called failed, probobly their fault: #{response.body}"
180
+ raise RuntimeError, "API called failed, probably their fault: #{response.body}"
169
181
  elsif response.success?
170
182
  Report.new(JSON.parse(response.body, :symbolize_names => true)[:data])
171
183
  else
@@ -0,0 +1,72 @@
1
+ module HackerOne
2
+ module Client
3
+ module Activities
4
+ class Activity
5
+ delegate :message, :created_at, :updated_at, to: :attributes
6
+ delegate :actor, to: :relationships
7
+
8
+ def initialize(activity)
9
+ @activity = OpenStruct.new activity
10
+ end
11
+
12
+ def internal?
13
+ attributes.internal
14
+ end
15
+
16
+ private
17
+
18
+ def relationships
19
+ OpenStruct.new(activity.relationships)
20
+ end
21
+
22
+ def attributes
23
+ OpenStruct.new(activity.attributes)
24
+ end
25
+
26
+ attr_reader :activity
27
+ end
28
+
29
+ class BountyAwarded < Activity
30
+ def bounty_amount
31
+ formatted_bounty_amount = attributes.bounty_amount || "0"
32
+ formatted_bounty_amount.gsub(/[^\d]/, "").to_i
33
+ end
34
+
35
+ def bonus_amount
36
+ formatted_bonus_amount = attributes.bonus_amount || "0"
37
+ formatted_bonus_amount.gsub(/[^\d]/, "").to_i
38
+ end
39
+ end
40
+
41
+ class SwagAwarded < Activity
42
+ delegate :swag, to: :relationships
43
+ end
44
+
45
+ class UserAssignedToBug < Activity
46
+ delegate :assigned_user, to: :relationships
47
+ end
48
+
49
+ class BugTriaged < Activity
50
+ end
51
+
52
+ class ReferenceIdAdded < Activity
53
+ delegate :reference, :reference_url, to: :attributes
54
+ end
55
+
56
+ ACTIVITY_TYPE_CLASS_MAPPING = {
57
+ 'activity-bounty-awarded' => BountyAwarded,
58
+ 'activity-swag-awarded' => SwagAwarded,
59
+ 'activity-user-assigned-to-bug' => UserAssignedToBug,
60
+ 'activity-bug-triaged' => BugTriaged,
61
+ 'activity-reference-id-added' => ReferenceIdAdded
62
+ }.freeze
63
+
64
+ def self.build(activity_data)
65
+ activity_type_class = ACTIVITY_TYPE_CLASS_MAPPING.fetch \
66
+ activity_data[:type], Activity
67
+
68
+ activity_type_class.new activity_data
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,10 +1,9 @@
1
1
  require_relative './weakness'
2
+ require_relative './activity'
2
3
 
3
4
  module HackerOne
4
5
  module Client
5
6
  class Report
6
- PAYOUT_ACTIVITY_KEY = "activity-bounty-awarded"
7
-
8
7
  def initialize(report)
9
8
  @report = report
10
9
  end
@@ -68,17 +67,20 @@ module HackerOne
68
67
  classification_label().split("-").first
69
68
  end
70
69
 
70
+ def activities
71
+ relationships.dig(:activities, :data)&.map do |activity_data|
72
+ Activities.build(activity_data)
73
+ end
74
+ end
75
+
71
76
  private
77
+
72
78
  def payments
73
- activities.select { |activity| activity[:type] == PAYOUT_ACTIVITY_KEY }
79
+ activities.select { |activity| activity.is_a? Activities::BountyAwarded }
74
80
  end
75
81
 
76
82
  def payment_amount(payment)
77
- payment.fetch(:attributes, {}).fetch(:bounty_amount, "0").gsub(/[^\d]/, "").to_i
78
- end
79
-
80
- def activities
81
- relationships.fetch(:activities, {}).fetch(:data, [])
83
+ payment.bounty_amount
82
84
  end
83
85
 
84
86
  def attributes
@@ -1,5 +1,5 @@
1
1
  module Hackerone
2
2
  module Client
3
- VERSION = "0.2.3"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hackerone-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Matatall
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-22 00:00:00.000000000 Z
11
+ date: 2017-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -137,9 +137,11 @@ files:
137
137
  - fixtures/vcr_cassettes/missing_report.yml
138
138
  - fixtures/vcr_cassettes/report.yml
139
139
  - fixtures/vcr_cassettes/report_list.yml
140
+ - fixtures/vcr_cassettes/server_error.yml
140
141
  - fixtures/vcr_cassettes/stage_change.yml
141
142
  - hackerone-client.gemspec
142
143
  - lib/hackerone/client.rb
144
+ - lib/hackerone/client/activity.rb
143
145
  - lib/hackerone/client/report.rb
144
146
  - lib/hackerone/client/version.rb
145
147
  - lib/hackerone/client/weakness.rb