firetail 0.0.0 → 1.0.1

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.
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: []