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 +4 -4
- data/fixtures/vcr_cassettes/server_error.yml +75 -0
- data/lib/hackerone/client.rb +16 -4
- data/lib/hackerone/client/activity.rb +72 -0
- data/lib/hackerone/client/report.rb +10 -8
- data/lib/hackerone/client/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e75818c133624c27e8d5986311b1ee3c77420916
|
4
|
+
data.tar.gz: b5e846599a80125cd47137ee42176777c8bf64cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/hackerone/client.rb
CHANGED
@@ -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
|
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
|
79
|
+
activities.select { |activity| activity.is_a? Activities::BountyAwarded }
|
74
80
|
end
|
75
81
|
|
76
82
|
def payment_amount(payment)
|
77
|
-
payment.
|
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
|
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.
|
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-
|
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
|