hackerone-client 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|