firetail 0.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +11 -0
  3. data/.github/workflows/main.yml +40 -0
  4. data/.gitignore +28 -0
  5. data/Gemfile +5 -0
  6. data/Gemfile.lock +74 -0
  7. data/LICENSE +165 -0
  8. data/LICENSE.txt +165 -21
  9. data/README.md +24 -10
  10. data/examples/rails/.gitattributes +8 -0
  11. data/examples/rails/.gitignore +31 -0
  12. data/examples/rails/.rspec +1 -0
  13. data/examples/rails/.ruby-version +1 -0
  14. data/examples/rails/Gemfile +44 -0
  15. data/examples/rails/Gemfile.lock +240 -0
  16. data/examples/rails/README.md +24 -0
  17. data/examples/rails/Rakefile +6 -0
  18. data/examples/rails/app/channels/application_cable/channel.rb +4 -0
  19. data/examples/rails/app/channels/application_cable/connection.rb +4 -0
  20. data/examples/rails/app/controllers/application_controller.rb +2 -0
  21. data/examples/rails/app/controllers/comments_controller.rb +52 -0
  22. data/examples/rails/app/controllers/concerns/.keep +0 -0
  23. data/examples/rails/app/controllers/posts_controller.rb +51 -0
  24. data/examples/rails/app/jobs/application_job.rb +7 -0
  25. data/examples/rails/app/mailers/application_mailer.rb +4 -0
  26. data/examples/rails/app/models/application_record.rb +3 -0
  27. data/examples/rails/app/models/comment.rb +4 -0
  28. data/examples/rails/app/models/concerns/.keep +0 -0
  29. data/examples/rails/app/models/post.rb +5 -0
  30. data/examples/rails/app/views/layouts/mailer.html.erb +13 -0
  31. data/examples/rails/app/views/layouts/mailer.text.erb +1 -0
  32. data/examples/rails/bin/bundle +114 -0
  33. data/examples/rails/bin/rails +5 -0
  34. data/examples/rails/bin/rake +5 -0
  35. data/examples/rails/bin/setup +33 -0
  36. data/examples/rails/bin/spring +14 -0
  37. data/examples/rails/config/application.rb +41 -0
  38. data/examples/rails/config/boot.rb +4 -0
  39. data/examples/rails/config/cable.yml +10 -0
  40. data/examples/rails/config/credentials.yml.enc +1 -0
  41. data/examples/rails/config/database.yml +25 -0
  42. data/examples/rails/config/environment.rb +5 -0
  43. data/examples/rails/config/environments/development.rb +66 -0
  44. data/examples/rails/config/environments/production.rb +113 -0
  45. data/examples/rails/config/environments/test.rb +60 -0
  46. data/examples/rails/config/firetail.yml +2 -0
  47. data/examples/rails/config/initializers/application_controller_renderer.rb +8 -0
  48. data/examples/rails/config/initializers/backtrace_silencers.rb +8 -0
  49. data/examples/rails/config/initializers/cors.rb +16 -0
  50. data/examples/rails/config/initializers/filter_parameter_logging.rb +6 -0
  51. data/examples/rails/config/initializers/inflections.rb +16 -0
  52. data/examples/rails/config/initializers/mime_types.rb +4 -0
  53. data/examples/rails/config/initializers/wrap_parameters.rb +14 -0
  54. data/examples/rails/config/locales/en.yml +33 -0
  55. data/examples/rails/config/puma.rb +43 -0
  56. data/examples/rails/config/routes.rb +6 -0
  57. data/examples/rails/config/schema.json +431 -0
  58. data/examples/rails/config/spring.rb +6 -0
  59. data/examples/rails/config/storage.yml +34 -0
  60. data/examples/rails/config.ru +6 -0
  61. data/examples/rails/db/migrate/20230730163722_create_posts.rb +8 -0
  62. data/examples/rails/db/migrate/20230730163741_create_comments.rb +9 -0
  63. data/examples/rails/db/migrate/20230730164121_add_fields_to_post.rb +6 -0
  64. data/examples/rails/db/migrate/20230730164214_add_fields_to_comments.rb +6 -0
  65. data/examples/rails/db/schema.rb +30 -0
  66. data/examples/rails/db/seeds.rb +7 -0
  67. data/examples/rails/lib/tasks/.keep +0 -0
  68. data/examples/rails/log/.keep +0 -0
  69. data/examples/rails/public/robots.txt +1 -0
  70. data/examples/rails/spec/models/comment_spec.rb +5 -0
  71. data/examples/rails/spec/models/post_spec.rb +5 -0
  72. data/examples/rails/spec/rails_helper.rb +63 -0
  73. data/examples/rails/spec/requests/comments_spec.rb +127 -0
  74. data/examples/rails/spec/requests/posts_spec.rb +127 -0
  75. data/examples/rails/spec/routing/comments_routing_spec.rb +30 -0
  76. data/examples/rails/spec/routing/posts_routing_spec.rb +30 -0
  77. data/examples/rails/spec/spec_helper.rb +94 -0
  78. data/examples/rails/storage/.keep +0 -0
  79. data/examples/rails/test/channels/application_cable/connection_test.rb +11 -0
  80. data/examples/rails/test/controllers/.keep +0 -0
  81. data/examples/rails/test/fixtures/files/.keep +0 -0
  82. data/examples/rails/test/integration/.keep +0 -0
  83. data/examples/rails/test/mailers/.keep +0 -0
  84. data/examples/rails/test/models/.keep +0 -0
  85. data/examples/rails/test/test_helper.rb +13 -0
  86. data/examples/rails/tmp/.keep +0 -0
  87. data/examples/rails/tmp/pids/.keep +0 -0
  88. data/examples/rails/vendor/.keep +0 -0
  89. data/firetail.gemspec +8 -1
  90. data/lib/backend.rb +34 -0
  91. data/lib/background_tasks.rb +43 -0
  92. data/lib/case_sensitive_headers.rb +29 -0
  93. data/lib/firetail/version.rb +1 -1
  94. data/lib/firetail.rb +264 -1
  95. data/lib/generators/firetail/install/templates/README +15 -0
  96. data/lib/generators/firetail/install/templates/firetail.yml +2 -0
  97. data/lib/generators/firetail/install/templates/schema.json +108 -0
  98. data/lib/generators/firetail/install_generator.rb +26 -0
  99. data/lib/railtie.rb +29 -0
  100. metadata +169 -8
data/lib/firetail.rb CHANGED
@@ -1,6 +1,269 @@
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.safe_load(ERB.new(File.read(default_location)).result)
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.prod.firetail.app/logs/bulk" # default goes to europe
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
+ })
176
+ @request.body.rewind
177
+ #Firetail.logger.debug "Request: #{body}"
178
+
179
+ # the time we calculate if request that is
180
+ # buffered max is 120 seconds
181
+ current_time = Time.now
182
+ # duration in millseconds
183
+ duration = (current_time - @init_time)
184
+
185
+ #Firetail.logger.debug "size in bytes #{ObjectSpace.memsize_of(@request_data.to_s)}"
186
+ #request data size in bytes
187
+ request_data_size = ObjectSpace.memsize_of(@request_data)
188
+ # It is difficult to calculate the object size in bytes,
189
+ # seems to not return the accurate values
190
+
191
+ # This will send the data we need in batches of 5 requests or when it is more than 120 seconds
192
+ # if there are more than 5 requests or is more than
193
+ # 2 minutes, then send to backend - this is for testing
194
+ if @reqres.length >= 5 || duration > 120
195
+ #Firetail.logger.debug "request data #{@reqres}"
196
+ # we parse the data hash into json-nl (json-newlines)
197
+ payload = @reqres.map { |data| JSON.generate(data) }.join("\n")
198
+
199
+ # send the data to backend API
200
+ # This is an async task
201
+ BackgroundTasks.http_task(@url,
202
+ @network_timeout,
203
+ @api_key,
204
+ @number_of_tries,
205
+ payload)
206
+
207
+ # reset back to the initial conditions
208
+ payload = nil
209
+ @reqres = []
210
+ @init_time = Time.now
211
+ end
212
+ rescue Exception => exception
213
+ Firetail.logger.error(exception.message)
214
+ end
215
+
216
+ def sha1_hash(value)
217
+ encode_utf8 = value.encode(Encoding::UTF_8)
218
+ hash = Digest::SHA1.hexdigest(encode_utf8)
219
+ sha1 = "sha1: #{hash}"
220
+ end
221
+
222
+ def jwt_decoder(value)
223
+ bearer_string = value
224
+ # if authorization exists, get the value at index
225
+ # split the values which has a space (example: "Bearer 123") and
226
+ # get the value at index 1
227
+ token = bearer_string.split(" ")[1]
228
+ # decode the token
229
+ jwt_value = JWT.decode token, nil, false
230
+ # get the subject value
231
+ subject = jwt_value[0]["sub"]
232
+ #Firetail.logger.debug("subject value: #{subject}")
233
+ end
234
+ end
235
+
236
+ def self.logger
237
+ @@logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
238
+ end
239
+
240
+ def self.logger=(logger)
241
+ @@logger = logger
242
+ end
243
+
244
+ # custom error message
245
+ # https://blog.frankel.ch/structured-errors-http-apis/
246
+ # https://www.rfc-editor.org/rfc/rfc7807
247
+ class Committee::ValidationError
248
+ def error_body
249
+ {
250
+ errors: [
251
+ {
252
+ type: "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}",
253
+ title: id,
254
+ detail: message,
255
+ status: status
256
+ }
257
+ ]
258
+ }
259
+ end
260
+
261
+ def render
262
+ [
263
+ status,
264
+ { "Content-Type" => "application/json" },
265
+ [JSON.generate(error_body)]
266
+ ]
267
+ end
268
+ end
6
269
  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", nil) %>
2
+ url: <%= ENV.fetch("FIRETAIL_URL", nil) %>
@@ -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,29 @@
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.exist?(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 Error => e
26
+ puts e
27
+ end
28
+ end
29
+ 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: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muhammad Nuzaihan
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-08 00:00:00.000000000 Z
11
+ date: 2024-04-29 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.1
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.1
55
125
  description: API security library that is designed for ruby
56
126
  email:
57
127
  - zaihan@flitnetics.com
@@ -59,19 +129,110 @@ executables: []
59
129
  extensions: []
60
130
  extra_rdoc_files: []
61
131
  files:
132
+ - ".github/pull_request_template.md"
133
+ - ".github/workflows/main.yml"
62
134
  - ".gitignore"
63
135
  - ".rspec"
64
136
  - ".travis.yml"
65
137
  - CODE_OF_CONDUCT.md
66
138
  - Gemfile
139
+ - Gemfile.lock
140
+ - LICENSE
67
141
  - LICENSE.txt
68
142
  - README.md
69
143
  - Rakefile
70
144
  - bin/console
71
145
  - bin/setup
146
+ - examples/rails/.gitattributes
147
+ - examples/rails/.gitignore
148
+ - examples/rails/.rspec
149
+ - examples/rails/.ruby-version
150
+ - examples/rails/Gemfile
151
+ - examples/rails/Gemfile.lock
152
+ - examples/rails/README.md
153
+ - examples/rails/Rakefile
154
+ - examples/rails/app/channels/application_cable/channel.rb
155
+ - examples/rails/app/channels/application_cable/connection.rb
156
+ - examples/rails/app/controllers/application_controller.rb
157
+ - examples/rails/app/controllers/comments_controller.rb
158
+ - examples/rails/app/controllers/concerns/.keep
159
+ - examples/rails/app/controllers/posts_controller.rb
160
+ - examples/rails/app/jobs/application_job.rb
161
+ - examples/rails/app/mailers/application_mailer.rb
162
+ - examples/rails/app/models/application_record.rb
163
+ - examples/rails/app/models/comment.rb
164
+ - examples/rails/app/models/concerns/.keep
165
+ - examples/rails/app/models/post.rb
166
+ - examples/rails/app/views/layouts/mailer.html.erb
167
+ - examples/rails/app/views/layouts/mailer.text.erb
168
+ - examples/rails/bin/bundle
169
+ - examples/rails/bin/rails
170
+ - examples/rails/bin/rake
171
+ - examples/rails/bin/setup
172
+ - examples/rails/bin/spring
173
+ - examples/rails/config.ru
174
+ - examples/rails/config/application.rb
175
+ - examples/rails/config/boot.rb
176
+ - examples/rails/config/cable.yml
177
+ - examples/rails/config/credentials.yml.enc
178
+ - examples/rails/config/database.yml
179
+ - examples/rails/config/environment.rb
180
+ - examples/rails/config/environments/development.rb
181
+ - examples/rails/config/environments/production.rb
182
+ - examples/rails/config/environments/test.rb
183
+ - examples/rails/config/firetail.yml
184
+ - examples/rails/config/initializers/application_controller_renderer.rb
185
+ - examples/rails/config/initializers/backtrace_silencers.rb
186
+ - examples/rails/config/initializers/cors.rb
187
+ - examples/rails/config/initializers/filter_parameter_logging.rb
188
+ - examples/rails/config/initializers/inflections.rb
189
+ - examples/rails/config/initializers/mime_types.rb
190
+ - examples/rails/config/initializers/wrap_parameters.rb
191
+ - examples/rails/config/locales/en.yml
192
+ - examples/rails/config/puma.rb
193
+ - examples/rails/config/routes.rb
194
+ - examples/rails/config/schema.json
195
+ - examples/rails/config/spring.rb
196
+ - examples/rails/config/storage.yml
197
+ - examples/rails/db/migrate/20230730163722_create_posts.rb
198
+ - examples/rails/db/migrate/20230730163741_create_comments.rb
199
+ - examples/rails/db/migrate/20230730164121_add_fields_to_post.rb
200
+ - examples/rails/db/migrate/20230730164214_add_fields_to_comments.rb
201
+ - examples/rails/db/schema.rb
202
+ - examples/rails/db/seeds.rb
203
+ - examples/rails/lib/tasks/.keep
204
+ - examples/rails/log/.keep
205
+ - examples/rails/public/robots.txt
206
+ - examples/rails/spec/models/comment_spec.rb
207
+ - examples/rails/spec/models/post_spec.rb
208
+ - examples/rails/spec/rails_helper.rb
209
+ - examples/rails/spec/requests/comments_spec.rb
210
+ - examples/rails/spec/requests/posts_spec.rb
211
+ - examples/rails/spec/routing/comments_routing_spec.rb
212
+ - examples/rails/spec/routing/posts_routing_spec.rb
213
+ - examples/rails/spec/spec_helper.rb
214
+ - examples/rails/storage/.keep
215
+ - examples/rails/test/channels/application_cable/connection_test.rb
216
+ - examples/rails/test/controllers/.keep
217
+ - examples/rails/test/fixtures/files/.keep
218
+ - examples/rails/test/integration/.keep
219
+ - examples/rails/test/mailers/.keep
220
+ - examples/rails/test/models/.keep
221
+ - examples/rails/test/test_helper.rb
222
+ - examples/rails/tmp/.keep
223
+ - examples/rails/tmp/pids/.keep
224
+ - examples/rails/vendor/.keep
72
225
  - firetail.gemspec
226
+ - lib/backend.rb
227
+ - lib/background_tasks.rb
228
+ - lib/case_sensitive_headers.rb
73
229
  - lib/firetail.rb
74
230
  - lib/firetail/version.rb
231
+ - lib/generators/firetail/install/templates/README
232
+ - lib/generators/firetail/install/templates/firetail.yml
233
+ - lib/generators/firetail/install/templates/schema.json
234
+ - lib/generators/firetail/install_generator.rb
235
+ - lib/railtie.rb
75
236
  homepage: https://www.firetail.io
76
237
  licenses:
77
238
  - MIT
@@ -80,7 +241,7 @@ metadata:
80
241
  homepage_uri: https://www.firetail.io
81
242
  source_code_uri: https://github.com/firetail-io/ruby
82
243
  changelog_uri: https://github.com/firetail-io/ruby/CHANGELOG.md
83
- post_install_message:
244
+ post_install_message:
84
245
  rdoc_options: []
85
246
  require_paths:
86
247
  - lib
@@ -95,8 +256,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
256
  - !ruby/object:Gem::Version
96
257
  version: '0'
97
258
  requirements: []
98
- rubygems_version: 3.0.8
99
- signing_key:
259
+ rubygems_version: 3.5.9
260
+ signing_key:
100
261
  specification_version: 4
101
262
  summary: Ruby library for firetail
102
263
  test_files: []