issue 0.0.1 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29925e2f5c0b58136fe7097671b9577766034701c97aeb78fc9999a8fb4e23ee
4
- data.tar.gz: 54d441c401a125e0e0ebea5baa48ead70dc3dcd5ad4a49c660673a4c626e3e07
3
+ metadata.gz: 10960451c8f6e5f752cc0a2b892ae8b8d122a14e1aaedc3671daa2da41cb80b8
4
+ data.tar.gz: b84a85ae117417a348dacfde4b387128190dcb72232e69abb96805eed8585926
5
5
  SHA512:
6
- metadata.gz: 495c6477690e7bc7c688876ac242bb7884f87c9746dcc3ba6e0e2b8cbd8a012a758afcf07a2ef9f09b1a9280afac97a255a317fdcbfabb4668860a442dd04f37
7
- data.tar.gz: 688bb57f456b5831a0840d8ad847bcd24a11baf42e43c09b1fe66fd2ae5292088da86aef45075c3c5025e39e792f51dff5d73594f7fea7f9a1d4605a2c05a0f2
6
+ metadata.gz: 60caa264fa776efee538761cfa9d06794859bca2490247e9cfdc76e1ea2c86a6e78b6e19fead11f98f522607c26224114b7db564404dd39657c35043f605ef87
7
+ data.tar.gz: 501ac0d34f7c80334a66ce90574b2677750b1b23287d2bb65682783fd21413504dec767e6decba5307ac8ddcf0c20beaa5df188f1e23d097ae2849baa66f2da0
data/lib/issue.rb CHANGED
@@ -1,5 +1,6 @@
1
- require 'issue/version'
2
-
3
1
  module Issue
4
-
2
+ require_relative "issue/version"
3
+ require_relative "issue/payload"
4
+ require_relative "issue/webhook"
5
+ require_relative "issue/error"
5
6
  end
@@ -0,0 +1,15 @@
1
+ module Issue
2
+ class Error
3
+ attr :status
4
+ attr :message
5
+
6
+ # Initialize Issue::Error object with:
7
+ # status: html status code
8
+ # msg: message to send back in response
9
+ def initialize(status, msg)
10
+ @status = status
11
+ @message = msg
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,112 @@
1
+ require "ostruct"
2
+ require "json"
3
+
4
+ module Issue
5
+ class Payload
6
+ attr_accessor :context
7
+
8
+ # Initialize Issue::Payload object with:
9
+ # json_data: the json sent from a GitHub webhook
10
+ # event: the value of the HTTP_X_GITHUB_EVENT header
11
+ #
12
+ # Initializing a new Issue::Payload instance makes all this info
13
+ # from the json webhook available via accessor methods:
14
+ #
15
+ # action
16
+ # event
17
+ # issue_id
18
+ # issue_title
19
+ # issue_body
20
+ # issue_author
21
+ # repo
22
+ # sender
23
+ # event_action
24
+ # raw_payload
25
+ #
26
+ # And if the case the event is 'issue_comment' also:
27
+ #
28
+ # comment_body
29
+ # comment_created_at
30
+ # comment_url
31
+ #
32
+ def initialize(json_data, event)
33
+ action = json_data.dig("action")
34
+ sender = json_data.dig("sender", "login")
35
+ issue_id = json_data.dig("issue", "number")
36
+ issue_title = json_data.dig("issue", "title")
37
+ issue_body = json_data.dig("issue", "body")
38
+ issue_labels = json_data.dig("issue", "labels")
39
+ issue_author = json_data.dig("issue", "user", "login")
40
+ repo = json_data.dig("repository", "full_name")
41
+
42
+ @context = OpenStruct.new(
43
+ action: action,
44
+ event: event,
45
+ issue_id: issue_id,
46
+ issue_title: issue_title,
47
+ issue_body: issue_body,
48
+ issue_author: issue_author,
49
+ issue_labels: issue_labels,
50
+ repo: repo,
51
+ sender: sender,
52
+ event_action: "#{event}.#{action}",
53
+ raw_payload: json_data
54
+ )
55
+
56
+ if event == "issue_comment"
57
+ @context[:comment_body] = json_data.dig("comment", "body")
58
+ @context[:comment_created_at] = json_data.dig("comment", "created_at")
59
+ @context[:comment_url] = json_data.dig("comment", "html_url")
60
+ end
61
+
62
+ @context.each_pair do |method_name, value|
63
+ define_singleton_method(method_name) {value}
64
+ end
65
+ end
66
+
67
+ # True if the payload is coming from an issue that has just been opened
68
+ def opened?
69
+ action == "opened" || action == "reopened"
70
+ end
71
+
72
+ # True if the payload is coming from an issue that has just been closed
73
+ def closed?
74
+ action == "closed"
75
+ end
76
+
77
+ # True if the payload is coming from a new comment
78
+ def commented?
79
+ action == "created"
80
+ end
81
+
82
+ # True if the payload is coming from an edition of a comment or issue
83
+ def edited?
84
+ action == "edited"
85
+ end
86
+
87
+ # True if the payload is coming from locking an issue
88
+ def locked?
89
+ action == "locked"
90
+ end
91
+
92
+ # True if the payload is coming from unlocking an issue
93
+ def unlocked?
94
+ action == "unlocked"
95
+ end
96
+
97
+ # True if the payload is coming from pinning or unpinning an issue
98
+ def pinned?
99
+ action == "pinned" || action == "unpinned"
100
+ end
101
+
102
+ # True if the payload is coming from un/assigning an issue
103
+ def assigned?
104
+ action == "assigned" || action == "unassigned"
105
+ end
106
+
107
+ # True if the payload is coming from un/labeling an issue
108
+ def labeled?
109
+ action == "labeled" || action == "unlabeled"
110
+ end
111
+ end
112
+ end
data/lib/issue/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Issue
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,92 @@
1
+ require "ostruct"
2
+ require "json"
3
+ require "openssl"
4
+ require "rack"
5
+
6
+ module Issue
7
+ class Webhook
8
+ attr_accessor :secret_token
9
+ attr_accessor :request
10
+ attr_accessor :accept_origin
11
+ attr_accessor :discard_sender
12
+ attr_accessor :accept_events
13
+ attr_accessor :error
14
+ attr_accessor :payload
15
+
16
+ # Initialize the Issue::Webhook object
17
+ # This method should receive a Hash with the following settings:
18
+ # * secret_token: the GitHub secret token needed to verify the request signature
19
+ # * accept_events: an Array of valid values for the HTTP_X_GITHUB_EVENT header. If empty any event will be precessed.
20
+ # * origin: the respository where the webhook should be sent to be accepted. If empty any request will be precessed.
21
+ # * discard_sender: an optional GitHub user handle to discard all events triggered by it.
22
+ def initialize(settings={})
23
+ @secret_token = settings[:secret_token]
24
+ @accept_origin = settings[:origin]
25
+ @discard_sender = settings[:discard_sender]
26
+ @accept_events = [settings[:accept_events]].flatten.compact.uniq.map(&:to_s)
27
+ end
28
+
29
+ # This method will parse the passed request.
30
+ # If the request signature is incorrect or any of the conditions set
31
+ # via the initialization settings are not met an error will be created
32
+ # with the appropiate html status and message. Otherwise a Issue::Payload
33
+ # object will be created with the information contained in the request payload.
34
+ #
35
+ # This method returns a pair [payload, error] where only one of them will be nil
36
+ def parse_request(request)
37
+ @payload = nil
38
+ @error = nil
39
+ @request = request
40
+
41
+ if verify_signature
42
+ parse_payload
43
+ end
44
+
45
+ return [payload, error]
46
+ end
47
+
48
+ # This method returns True if parsing a request has generated an Issue::Error object
49
+ # That object will be available at the #error accessor method.
50
+ def errored?
51
+ !error.nil?
52
+ end
53
+
54
+ private
55
+
56
+ def verify_signature
57
+ gh_signature = request.get_header "HTTP_X_HUB_SIGNATURE"
58
+ return error!(500, "Can't compute signature") if secret_token.nil? || secret_token.empty?
59
+ return error!(403, "Request missing signature") if gh_signature.nil? || gh_signature.empty?
60
+ request.body.rewind
61
+ payload_body = request.body.read
62
+ signature = "sha1=" + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha1"), secret_token, payload_body)
63
+ return error!(403, "Signatures didn't match!") unless Rack::Utils.secure_compare(signature, gh_signature)
64
+ true
65
+ end
66
+
67
+ def parse_payload
68
+ begin
69
+ request.body.rewind
70
+ json_payload = JSON.parse(request.body.read)
71
+ event = request.get_header "HTTP_X_GITHUB_EVENT"
72
+ sender = json_payload.dig("sender", "login")
73
+ origin = json_payload.dig("repository", "full_name")
74
+ rescue JSON::ParserError
75
+ return error!(400, "Malformed request")
76
+ end
77
+
78
+ return error!(422, "No payload") if json_payload.nil? || json_payload.empty?
79
+ return error!(422, "No event") if event.nil?
80
+ return error!(200, "Event discarded") unless (accept_events.empty? || accept_events.include?(event))
81
+ return error!(200, "Event origin discarded") if (discard_sender && sender == discard_sender)
82
+ return error!(403, "Event origin not allowed") if (accept_origin && origin != accept_origin)
83
+
84
+ @payload = Issue::Payload.new(json_payload, event)
85
+ end
86
+
87
+ def error!(status, msg)
88
+ @error = Issue::Error.new(status, msg)
89
+ false
90
+ end
91
+ end
92
+ end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: issue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juanjo Bazán
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-29 00:00:00.000000000 Z
11
+ date: 2021-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: openssl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rake
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -47,14 +75,17 @@ extra_rdoc_files: []
47
75
  files:
48
76
  - README.md
49
77
  - lib/issue.rb
78
+ - lib/issue/error.rb
79
+ - lib/issue/payload.rb
50
80
  - lib/issue/version.rb
81
+ - lib/issue/webhook.rb
51
82
  homepage: http://github.com/xuanxu/issue
52
83
  licenses:
53
84
  - MIT
54
85
  metadata:
55
86
  bug_tracker_uri: https://github.com/xuanxu/issue/issues
56
87
  changelog_uri: https://github.com/xuanxu/issue/blob/master/CHANGELOG.md
57
- documentation_uri: https://www.rubydoc.info/gems/emoticon
88
+ documentation_uri: https://www.rubydoc.info/gems/issue
58
89
  homepage_uri: http://github.com/xuanxu/issue
59
90
  source_code_uri: http://github.com/xuanxu/issue
60
91
  post_install_message: