firetail 0.0.0 → 0.0.1.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97b28bec62c224d4517dfbe9acae7fbe5346eef7f037b34d74b087019b137114
4
- data.tar.gz: 20af8b16b0049f5a34c678e615868ecfc692a74c22dffa7070c485efeb9626a9
3
+ metadata.gz: 6c2911c879eebc409df8cd9ef8effa8339a7225e7626a896a602ffed00c02504
4
+ data.tar.gz: dde8fb62f7c0c770938b2c37a3f7440ce6ac1dba3450ce57f67a6186c9b2491d
5
5
  SHA512:
6
- metadata.gz: 59aaf80d74a4e40558ab2f029e0ac295edd2b0b250f05c1e8ee842f5404860f8afcd88d1a9f9eee91ac5746f0b723e17a5312696fb1ffc0a7d81f24f4e825e18
7
- data.tar.gz: 9726c187da5c76f2964223b6d2ef9034e4ba361b0d510175a775ebeff5663338952624b63bd396d41fc4f82e3d9cfde68fce0450470c5fe9e24ca284b0bad6d4
6
+ metadata.gz: a4e2d329a58d5d324c9ea7edd3502cf5379caa3408c970ab92a20b9c6218c5c4ef4d3fbd331c633cf80976ed6f2e394b6973fa608fd056e7978e0f78785a1436
7
+ data.tar.gz: 14515df3e82951f12c813105627d59c18579bbe967a297212a71844ec4dab4cf940a8973df8621ae930d1efb8b6a47feaa414b64e8f10f7d037543fd00b21870
@@ -0,0 +1,40 @@
1
+ name: Main
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+
9
+ # https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ # Uncomment ci_node_total and ci_node_index, ONLY if we have multiple tests
14
+ # and need to run it in parallel
15
+ # [n] - where the n is a number of parallel jobs you want to run your tests on.
16
+ # Use a higher number if you have slow tests to split them between more parallel jobs.
17
+ # Remember to update the value of the `ci_node_index` below to (0..n-1).
18
+ #ci_node_total: [8]
19
+ # Indexes for parallel jobs (starting from zero).
20
+ # E.g. use [0, 1] for 2 parallel jobs, [0, 1, 2] for 3 parallel jobs, etc.
21
+ #ci_node_index: [0, 1, 2, 3, 4, 5, 6, 7]
22
+ ruby-version: ['2.7', '3.0', '3.1']
23
+
24
+ env:
25
+ TZ: "Europe/Ireland"
26
+
27
+ steps:
28
+ - uses: actions/checkout@v2
29
+
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@v1
32
+ with:
33
+ # Not needed with a .ruby-version file
34
+ ruby-version: 2.7
35
+ # runs 'bundle install' and caches installed gems automatically
36
+ bundler-cache: true
37
+
38
+ - name: Run tests
39
+ run: |
40
+ bundle exec rspec
data/.gitignore CHANGED
@@ -6,6 +6,34 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ *.gem
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
13
+ /ext/target
14
+
15
+ # Ignore bundler config.
16
+ /rails_example/.bundle
17
+
18
+ # Ignore the default SQLite database.
19
+ /rails_example/db/*.sqlite3
20
+ /db/*.sqlite3-*
21
+
22
+ # Ignore all logfiles and tempfiles.
23
+ /rails/log/*
24
+ /rails/tmp/*
25
+ !/rails/log/.keep
26
+ !/rails/tmp/.keep
27
+
28
+ # Ignore pidfiles, but keep the directory.
29
+ /rails/tmp/pids/*
30
+ !/rails/tmp/pids/
31
+ !/rails/tmp/pids/.keep
32
+
33
+ # Ignore uploaded files in development.
34
+ /rails/storage/*
35
+ !/rails/storage/.keep
36
+ /rails/.byebug_history
37
+
38
+ # Ignore master key for decrypting credentials and more.
39
+ /rails/config/master.key
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in firetail.gemspec
4
4
  gemspec
5
+
6
+ gem 'rack', "~> 3.0.4.2"
7
+ group :development, :test do
8
+ gem "webmock", "~> 3.18"
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,72 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ firetail (0.0.0)
5
+ async (~> 1.30.3)
6
+ committee_firetail (~> 5.0.0)
7
+ json-schema (~> 3.0.0)
8
+ jwt (~> 2.5)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.8.1)
14
+ public_suffix (>= 2.0.2, < 6.0)
15
+ async (1.30.3)
16
+ console (~> 1.10)
17
+ nio4r (~> 2.3)
18
+ timers (~> 4.1)
19
+ committee_firetail (5.0.0)
20
+ json_schema (~> 0.14, >= 0.14.3)
21
+ openapi_parser_firetail (~> 1.0)
22
+ rack (>= 1.5)
23
+ console (1.16.2)
24
+ fiber-local
25
+ crack (0.4.5)
26
+ rexml
27
+ diff-lcs (1.5.0)
28
+ fiber-local (1.0.0)
29
+ hashdiff (1.0.1)
30
+ json-schema (3.0.0)
31
+ addressable (>= 2.8)
32
+ json_schema (0.21.0)
33
+ jwt (2.7.0)
34
+ nio4r (2.5.8)
35
+ openapi_parser_firetail (1.0.0)
36
+ jwt (~> 2.5)
37
+ public_suffix (5.0.1)
38
+ rack (3.0.4.2)
39
+ rake (13.0.6)
40
+ rexml (3.2.5)
41
+ rspec (3.12.0)
42
+ rspec-core (~> 3.12.0)
43
+ rspec-expectations (~> 3.12.0)
44
+ rspec-mocks (~> 3.12.0)
45
+ rspec-core (3.12.0)
46
+ rspec-support (~> 3.12.0)
47
+ rspec-expectations (3.12.1)
48
+ diff-lcs (>= 1.2.0, < 2.0)
49
+ rspec-support (~> 3.12.0)
50
+ rspec-mocks (3.12.1)
51
+ diff-lcs (>= 1.2.0, < 2.0)
52
+ rspec-support (~> 3.12.0)
53
+ rspec-support (3.12.0)
54
+ timers (4.3.5)
55
+ webmock (3.18.1)
56
+ addressable (>= 2.8.0)
57
+ crack (>= 0.3.2)
58
+ hashdiff (>= 0.4.0, < 2.0.0)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ bundler (~> 2.0)
65
+ firetail!
66
+ rack (~> 3.0.4.2)
67
+ rake (~> 13.0)
68
+ rspec (~> 3.0)
69
+ webmock (~> 3.18)
70
+
71
+ BUNDLED WITH
72
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/LICENSE.txt CHANGED
@@ -1,21 +1,165 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2022 Muhammad Nuzaihan
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/firetail.gemspec CHANGED
@@ -29,6 +29,13 @@ Gem::Specification.new do |spec|
29
29
  spec.require_paths = ["lib"]
30
30
 
31
31
  spec.add_development_dependency "bundler", "~> 2.0"
32
- spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rake", "~> 13.0"
33
33
  spec.add_development_dependency "rspec", "~> 3.0"
34
+ spec.add_development_dependency "webmock", "~> 3.18.1"
35
+
36
+ # These gems are needed for firetail in production
37
+ spec.add_dependency "async", "~> 1.30.3"
38
+ spec.add_dependency "jwt", "~> 2.5"
39
+ spec.add_dependency "json-schema", "~> 3.0.0"
40
+ spec.add_dependency "committee_firetail", "~> 5.0.0"
34
41
  end
data/lib/backend.rb ADDED
@@ -0,0 +1,37 @@
1
+ class Backend
2
+
3
+ def self.send_now(payload, options)
4
+ #Firetail.logger.debug "running backend"
5
+ # Parse it as URI
6
+ uri = URI(options[:url])
7
+
8
+ # Create a new request
9
+ http = Net::HTTP.new(uri.hostname, uri.port)
10
+ #http.set_debug_output($stdout) # Use this is you want to see the data output
11
+ http.use_ssl = true
12
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
13
+ http.read_timeout = options[:network_timeout]
14
+
15
+ begin
16
+ # Create a new request
17
+ req = CustomPost.new(uri.path,
18
+ {
19
+ 'content-type': 'application/nd-json',
20
+ 'x-ft-api-key': options[:api_key]
21
+ })
22
+
23
+ req.body = payload
24
+ # Create new thread
25
+ Thread.new {
26
+ Thread.current.report_on_exception = false
27
+ # Wait for thread completion of thread is not the current thread
28
+ Thread.list.each{ |t| t.join unless t == Thread.current }
29
+ # Send the request
30
+ request = http.request(req)
31
+ }
32
+ #Firetail.logger.debug "response from firetail: #{res}"
33
+ rescue StandardError => e
34
+ Firetail.logger.info "Firetail HTTP Request failed (#{e.message})"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,43 @@
1
+ require 'backend'
2
+
3
+ class BackgroundTasks
4
+
5
+ # send the data to backend API
6
+ # This is an async task
7
+ def self.http_task(url,
8
+ timeout,
9
+ api_key,
10
+ retries,
11
+ payload)
12
+ Async do |task|
13
+ task.async do
14
+ # below code includes exponential backoff algorithm
15
+ retries = 0
16
+ begin
17
+ # send to firetail backend
18
+ # values to use for backend object
19
+ options = {"url": url,
20
+ "network_timeout": timeout,
21
+ "api_key": api_key}
22
+
23
+ request = Backend.send_now(payload, options)
24
+ Firetail.logger.info "Successfully sent to Firetail"
25
+ rescue Net::HTTPError => e
26
+ # if request response code is an error
27
+ # then try sending.
28
+ # @number_of_retries is configurable in .yaml file
29
+
30
+ if retries <= retries
31
+ retries += 1
32
+ max_sleep_seconds = Float(2 ** retries)
33
+ sleep rand(0..max_sleep_seconds)
34
+ retry
35
+ else
36
+ raise "Giving up on the server after #{retries} retries. Got error: #{e.message}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,29 @@
1
+ class CustomPost < Net::HTTP::Post
2
+ def initialize_http_header(headers)
3
+ @header = {}
4
+ headers.each { |k, v| @header[k.to_s] = [v] }
5
+ end
6
+
7
+ def [](name)
8
+ _k, val = header_insensitive_match name
9
+ val
10
+ end
11
+
12
+ def []=(name, val)
13
+ key, _val = header_insensitive_match name
14
+ key = name if key.nil?
15
+ if val
16
+ @header[key] = [val]
17
+ else
18
+ @header.delete(key)
19
+ end
20
+ end
21
+
22
+ def capitalize(name)
23
+ name
24
+ end
25
+
26
+ def header_insensitive_match(name)
27
+ @header.find { |key, _value| key.match Regexp.new(name.to_s, Regexp::IGNORECASE) }
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Firetail
2
- VERSION = "0.0.0"
2
+ VERSION = "0.0.1-alpha"
3
3
  end
data/lib/firetail.rb CHANGED
@@ -1,6 +1,272 @@
1
1
  require "firetail/version"
2
+ require "rack"
3
+ require 'objspace'
4
+ require 'yaml'
5
+ require 'json'
6
+ require 'net/http'
7
+ require 'case_sensitive_headers' # a hack because firetail API headers is case-sensitive
8
+ require "async"
9
+ require 'digest/sha1'
10
+ require 'jwt'
11
+ require 'logger'
12
+ require 'background_tasks'
13
+ require 'committee'
14
+
15
+ # If the library detects rails, it will load rail's methods
16
+ if defined?(Rails)
17
+ require 'action_dispatch'
18
+ require 'action_pack'
19
+ require 'railtie'
20
+ end
2
21
 
3
22
  module Firetail
4
23
  class Error < StandardError; end
5
- # Your code goes here...
24
+
25
+ class Run
26
+ MAX_BULK_SIZE_IN_BYTES = 1 * 1024 * 1024 # 1 MB
27
+
28
+ def initialize app
29
+ @app = app
30
+ @reqres ||= [] # request data in stored in array memory
31
+ @init_time ||= Time.now # initialize time
32
+ end
33
+
34
+ def call(env)
35
+ # This block initialises the configuration and checks
36
+ # sets the values for certain necessary configuration
37
+ # If it is Rails
38
+ if defined?(Rails)
39
+ begin
40
+ default_location = File.join(Rails.root, "config/firetail.yml")
41
+ config = YAML.load_file(default_location)
42
+ rescue Errno::ENOENT
43
+ # error message if firetail is not installed
44
+ puts ""
45
+ puts "Please run 'rails generate firetail:install' first"
46
+ puts ""
47
+ end
48
+ else # other frameworks
49
+ config = YAML.load_file("firetail.yml")
50
+ end
51
+
52
+ raise Error.new "Please run 'rails generate firetail:install' first" if config.nil?
53
+ raise Error.new "API Key is missing from firetail.yml configuration" if config['api_key'].nil?
54
+
55
+ @api_key = config['api_key']
56
+ @url = config['url'] ? config['url'] : "https://api.logging.eu-west-1.sandbox.firetail.app/logs/bulk" # default goes to dev
57
+ @log_drains_timeout = config['log_drains_timeout'] ? config['log_drains_timeout'] : 5
58
+ @network_timeout = config['network_timeout'] ? config['network_timeout'] : 10
59
+ @number_of_retries = config['number_of_retries'] ? config['number_of_retries'] : 4
60
+ @retry_timeout = config['retry_timeout'] ? config['retry_timeout'] : 2
61
+ # End of configuration initialization
62
+
63
+ # Gets the rack middleware requests
64
+ @request = Rack::Request.new(env)
65
+ started_on = Time.now
66
+ begin
67
+ status, client_headers, body = response = @app.call(env)
68
+ log(env, status, body, started_on, Time.now)
69
+ rescue Exception => exception
70
+ log(env, status, body, started_on, Time.now, exception)
71
+ raise exception
72
+ end
73
+
74
+ response
75
+ end
76
+
77
+ def log(env,
78
+ status,
79
+ body,
80
+ started_on,
81
+ ended_on,
82
+ exception = nil)
83
+
84
+ # request values
85
+ time_spent = ended_on - started_on
86
+ request_ip = defined?(Rails) ? env['action_dispatch.remote_ip'].calculate_ip : env['REMOTE_ADDR']
87
+ request_method = env['REQUEST_METHOD']
88
+ request_path = env['REQUEST_PATH']
89
+ request_http_version = env['HTTP_VERSION']
90
+
91
+ # get the resource parameters if it is rails
92
+ if defined?(Rails)
93
+ resource = Rails.application.routes.recognize_path(request_path)
94
+ #Firetail.logger.debug "res: #{resource}"
95
+ # sample hash of the above resource:
96
+ # example url: /posts/1/comments/2/options/3
97
+ # hash = {:controller=>"options", :action=>"show", :comment_id => 3, :post_id=>"1", :id=>"1"}
98
+ # take the resource hash above, get keys, conver to string, split "_" to get name at first index, together
99
+ # with the key, to string and camelcase route id name and keys that only include "id", compact (remove nil) and add "s" to the key
100
+ rmap = resource.map {|k,v| [k.to_s.split("_")[0], "{#{k.to_s.camelize(:lower)}}"] if k.to_s.include? "id" }
101
+ .compact.map {|k,v| [k.to_s + "s", v] if k != "id" }
102
+
103
+ if resource.key? :id
104
+ # It will appear like: [["comments", "commentId"], ["posts", "postId"], ["id", "id"]],
105
+ # but we want post to be first in order, so we reverse sort, and drop "id", which will be first in array
106
+ # after being sorted
107
+ reverse_resource = rmap.reverse.drop(1)
108
+ resource_path = "/" + reverse_resource * "/" + "/" + resource[:controller] + "/" + "{id}"
109
+ # rebuild the resource path
110
+ # reverse_resource * "/" will loop the array and add "/"
111
+ #resource_path = "/" + reverse_resource * "/" + "/" + resource[:controller] + "/" + "{id}"
112
+ # end result is /posts/{postId}/comments/{commentId}/options/{id}
113
+ else
114
+ if rmap.empty?
115
+ # if resoruce is empty, means we are at the first level of the url path, so no need extra paths
116
+ resource_path = "/" + rmap * "/" + resource[:controller]
117
+ else
118
+ # resource path from rmap above without the [:id] key (which is the last parameter in URL)
119
+ # only used for index, create which does not have id
120
+ resource_path = "/" + rmap * "/" + "/" + resource[:controller]
121
+ end
122
+ end
123
+ else
124
+ resource_path = nil
125
+ end
126
+
127
+ #Firetail.logger.debug("resource path: #{resource_path}")
128
+ # select those with "HTTP_" prefix, these are request headers
129
+ request_headers = env.select {|key,val| key.start_with? 'HTTP_' } # find HTTP_ prefixes, these are requests only
130
+ .collect {|key, val| { "#{key.sub(/^HTTP_/, '')}": [val] }} # remove HTTP_ prefix
131
+ .reduce({}, :merge) # reduce from [{key:val},{key2: val2}] to {key: val, key2: val2}
132
+
133
+ # do the inverse of the above and get rack specific keys
134
+ response_headers = env.select {|key,val| !key.start_with? 'HTTP_' } # only keys with no HTTP_ prefix
135
+ .select {|key, val| key =~ /^[A-Z._]*$/} # select keys with uppercase and underline
136
+ .map {|key, val| { "#{key}": [val] }} # map to firetail api format
137
+ .reduce({}, :merge) # reduce from [{key:val},{key2: val2}] to {key: val, key2: val2}
138
+
139
+ # get the jwt "sub" information
140
+ if request_headers[:AUTHORIZATION]
141
+ subject = self.jwt_decoder(request_headers[:AUTHORIZATION])
142
+ else
143
+ subject = nil
144
+ end
145
+
146
+ # default time spent in ruby is in seconds, so multiple by 1000 to ms
147
+ time_spent_in_ms = time_spent * 1000
148
+ #Firetail.logger.debug "request params: #{@request.params.inspect}"
149
+ # add the request and response data
150
+ # to array of data for batching up
151
+ @request.body.rewind
152
+ if body.is_a? Array
153
+ body = body[0]
154
+ else
155
+ body = body.body
156
+ end
157
+ @reqres.push({
158
+ version: "1.0.0-alpha",
159
+ dateCreated: Time.now.utc.to_i,
160
+ executionTime: time_spent_in_ms,
161
+ request: {
162
+ httpProtocol: request_http_version,
163
+ headers: request_headers, # headers must be in: headers: {"key": ["value"]}, array in object
164
+ method: request_method,
165
+ body: @request.body.read,
166
+ ip: request_ip,
167
+ resource: resource_path,
168
+ uri: @request.url
169
+ },
170
+ response: {
171
+ statusCode: status,
172
+ body: body,
173
+ headers: response_headers,
174
+ },
175
+ oauth: {
176
+ subject: subject ? sha1_hash(subject) : nil,
177
+ }
178
+ })
179
+ @request.body.rewind
180
+ #Firetail.logger.debug "Request: #{body}"
181
+
182
+ # the time we calculate if request that is
183
+ # buffered max is 120 seconds
184
+ current_time = Time.now
185
+ # duration in millseconds
186
+ duration = (current_time - @init_time)
187
+
188
+ #Firetail.logger.debug "size in bytes #{ObjectSpace.memsize_of(@request_data.to_s)}"
189
+ #request data size in bytes
190
+ request_data_size = ObjectSpace.memsize_of(@request_data)
191
+ # It is difficult to calculate the object size in bytes,
192
+ # seems to not return the accurate values
193
+
194
+ # This will send the data we need in batches of 5 requests or when it is more than 120 seconds
195
+ # if there are more than 5 requests or is more than
196
+ # 2 minutes, then send to backend - this is for testing
197
+ if @reqres.length >= 5 || duration > 120
198
+ #Firetail.logger.debug "request data #{@reqres}"
199
+ # we parse the data hash into json-nl (json-newlines)
200
+ payload = @reqres.map { |data| JSON.generate(data) }.join("\n")
201
+
202
+ # send the data to backend API
203
+ # This is an async task
204
+ BackgroundTasks.http_task(@url,
205
+ @network_timeout,
206
+ @api_key,
207
+ @number_of_tries,
208
+ payload)
209
+
210
+ # reset back to the initial conditions
211
+ payload = nil
212
+ @reqres = []
213
+ @init_time = Time.now
214
+ end
215
+ rescue Exception => exception
216
+ Firetail.logger.error(exception.message)
217
+ end
218
+
219
+ def sha1_hash(value)
220
+ encode_utf8 = value.encode(Encoding::UTF_8)
221
+ hash = Digest::SHA1.hexdigest(encode_utf8)
222
+ sha1 = "sha1: #{hash}"
223
+ end
224
+
225
+ def jwt_decoder(value)
226
+ bearer_string = value
227
+ # if authorization exists, get the value at index
228
+ # split the values which has a space (example: "Bearer 123") and
229
+ # get the value at index 1
230
+ token = bearer_string.split(" ")[1]
231
+ # decode the token
232
+ jwt_value = JWT.decode token, nil, false
233
+ # get the subject value
234
+ subject = jwt_value[0]["sub"]
235
+ #Firetail.logger.debug("subject value: #{subject}")
236
+ end
237
+ end
238
+
239
+ def self.logger
240
+ @@logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
241
+ end
242
+
243
+ def self.logger=(logger)
244
+ @@logger = logger
245
+ end
246
+
247
+ # custom error message
248
+ # https://blog.frankel.ch/structured-errors-http-apis/
249
+ # https://www.rfc-editor.org/rfc/rfc7807
250
+ class Committee::ValidationError
251
+ def error_body
252
+ {
253
+ errors: [
254
+ {
255
+ type: "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}",
256
+ title: id,
257
+ detail: message,
258
+ status: status
259
+ }
260
+ ]
261
+ }
262
+ end
263
+
264
+ def render
265
+ [
266
+ status,
267
+ { "Content-Type" => "application/json" },
268
+ [JSON.generate(error_body)]
269
+ ]
270
+ end
271
+ end
6
272
  end
@@ -0,0 +1,15 @@
1
+ ====================================================================================
2
+
3
+ Thank you for installing Firetail!
4
+
5
+ Before you start using firetail, please edit the file in "config/firetail.yml"
6
+ with your API Key, Token and URL first before running your Rails app.
7
+
8
+ The middleware is already configured in "config/application.rb" (you can check that)
9
+
10
+ Also we have installed a sample copy of schema.json in "config/schema.json" (your API schema)
11
+ for you to better understand and create your schema based on your needs.
12
+
13
+ Happy coding!
14
+
15
+ - From the team at Firetail
@@ -0,0 +1,2 @@
1
+ api_key: ENV.fetch("FIRETAIL_API_KEY")
2
+ url: ENV.fetch("FIRETAIL_URL")
@@ -0,0 +1,108 @@
1
+ {
2
+ "openapi": "3.0.0",
3
+ "info": {
4
+ "title": "api-test",
5
+ "version": "1.0"
6
+ },
7
+ "servers": [
8
+ {
9
+ "url": "http://localhost:3000",
10
+ "description": "dev"
11
+ }
12
+ ],
13
+ "paths": {
14
+ "/posts": {
15
+ "post": {
16
+ "parameters": [
17
+ {
18
+ "in": "query",
19
+ "name": "page",
20
+ "required": true,
21
+ "schema": {
22
+ "type": "integer"
23
+ }
24
+ }
25
+ ],
26
+ "requestBody": {
27
+ "content": {
28
+ "application/json": {
29
+ "schema": {
30
+ "type": "object",
31
+ "required": [
32
+ "year"
33
+ ],
34
+ "properties": {
35
+ "year": {
36
+ "type": "integer"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
42
+ },
43
+ "responses": {
44
+ "200": {
45
+ "description": "correct response",
46
+ "content": {
47
+ "application/json": {
48
+ "schema": {
49
+ "type": "object",
50
+ "required": [
51
+ "title",
52
+ "page",
53
+ "year"
54
+ ],
55
+ "properties": {
56
+ "title": {
57
+ "type": "string"
58
+ },
59
+ "page": {
60
+ "type": "integer"
61
+ },
62
+ "year": {
63
+ "type": "integer"
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ },
73
+ "/dont_allow_additional_parameter": {
74
+ "post": {
75
+ "requestBody": {
76
+ "content": {
77
+ "application/json": {
78
+ "schema": {
79
+ "type": "object",
80
+ "additionalProperties": false,
81
+ "required": [
82
+ "only_param"
83
+ ],
84
+ "properties": {
85
+ "only_param": {
86
+ "type": "string"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ },
93
+ "responses": {
94
+ "200": {
95
+ "description": "No Content",
96
+ "content": {
97
+ "application/json": {
98
+ "schema": {
99
+ "type": "object"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,26 @@
1
+ module Firetail
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../install/templates", __FILE__)
5
+
6
+ desc "create firetail configuration template to config/firetail.yml and add middleware"
7
+ def add_firetail_configuration
8
+ template "firetail.yml", File.join("config", "firetail.yml")
9
+ end
10
+
11
+ desc "add firetail middleware to rails application.rb"
12
+ def add_firetail_middleware
13
+ application "config.middleware.use Firetail::Run"
14
+ end
15
+
16
+ desc "add firetail sample json-schema template"
17
+ def add_firetail_sample_schema
18
+ template "schema.json", File.join("config", "schema.json")
19
+ end
20
+
21
+ def show_readme
22
+ readme "README" if behavior == :invoke
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/railtie.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'committee'
2
+ require 'rails'
3
+
4
+ class Error < StandardError; end
5
+
6
+ class Railtie < Rails::Railtie
7
+
8
+ initializer "commitee.insert_middleware" do |app|
9
+ begin
10
+ schema_path = File.join(Rails.root, "config/schema.json")
11
+
12
+ # check if schema file exists in config/
13
+ if File.exists?(schema_path)
14
+ app.config.middleware.use Committee::Middleware::RequestValidation,
15
+ schema_path: schema_path,
16
+ coerce_date_times: true,
17
+ params_key: 'action_dispatch.request.request_parameters',
18
+ query_hash_key: 'action_dispatch.request.query_parameters'
19
+
20
+ app.config.middleware.use Committee::Middleware::ResponseValidation, schema_path: schema_path
21
+ else
22
+ puts "Need schema.json in \"config/\" directory"
23
+ puts "Try re-running \"rails g firetail:install\" again"
24
+ end
25
+ rescue
26
+ puts "Need schema.json in \"config/\" directory"
27
+ puts "Try re-running \"rails g firetail:install\" again"
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firetail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muhammad Nuzaihan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-08 00:00:00.000000000 Z
11
+ date: 2023-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,76 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.18.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.18.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: async
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.30.3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.30.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: jwt
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.5'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: json-schema
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: committee_firetail
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 5.0.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 5.0.0
55
125
  description: API security library that is designed for ruby
56
126
  email:
57
127
  - zaihan@flitnetics.com
@@ -59,19 +129,30 @@ executables: []
59
129
  extensions: []
60
130
  extra_rdoc_files: []
61
131
  files:
132
+ - ".github/workflows/main.yml"
62
133
  - ".gitignore"
63
134
  - ".rspec"
64
135
  - ".travis.yml"
65
136
  - CODE_OF_CONDUCT.md
66
137
  - Gemfile
138
+ - Gemfile.lock
139
+ - LICENSE
67
140
  - LICENSE.txt
68
141
  - README.md
69
142
  - Rakefile
70
143
  - bin/console
71
144
  - bin/setup
72
145
  - firetail.gemspec
146
+ - lib/backend.rb
147
+ - lib/background_tasks.rb
148
+ - lib/case_sensitive_headers.rb
73
149
  - lib/firetail.rb
74
150
  - lib/firetail/version.rb
151
+ - lib/generators/firetail/install/templates/README
152
+ - lib/generators/firetail/install/templates/firetail.yml
153
+ - lib/generators/firetail/install/templates/schema.json
154
+ - lib/generators/firetail/install_generator.rb
155
+ - lib/railtie.rb
75
156
  homepage: https://www.firetail.io
76
157
  licenses:
77
158
  - MIT
@@ -91,11 +172,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
172
  version: '0'
92
173
  required_rubygems_version: !ruby/object:Gem::Requirement
93
174
  requirements:
94
- - - ">="
175
+ - - ">"
95
176
  - !ruby/object:Gem::Version
96
- version: '0'
177
+ version: 1.3.1
97
178
  requirements: []
98
- rubygems_version: 3.0.8
179
+ rubygems_version: 3.1.6
99
180
  signing_key:
100
181
  specification_version: 4
101
182
  summary: Ruby library for firetail