firetail 0.0.0 → 0.0.1.pre.alpha

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: 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