stitches 4.0.1 → 4.2.0.RC2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +29 -29
  3. data/.github/CODEOWNERS +1 -1
  4. data/.gitignore +1 -0
  5. data/.ruby-version +1 -1
  6. data/Gemfile.rails-6.1 +7 -0
  7. data/README.md +36 -4
  8. data/lib/stitches/add_disabled_at_to_api_clients_generator.rb +18 -0
  9. data/lib/stitches/allowlist_middleware.rb +20 -6
  10. data/lib/stitches/api_client_access_wrapper.rb +42 -11
  11. data/lib/stitches/api_key.rb +5 -5
  12. data/lib/stitches/configuration.rb +4 -0
  13. data/lib/stitches/generator_files/db/migrate/add_disabled_at_to_api_clients.rb +9 -0
  14. data/lib/stitches/generator_files/db/migrate/create_api_clients.rb +1 -0
  15. data/lib/stitches/valid_mime_type.rb +1 -1
  16. data/lib/stitches/version.rb +1 -1
  17. data/lib/stitches_norailtie.rb +1 -0
  18. data/owners.json +1 -1
  19. data/spec/api_key_middleware_spec.rb +368 -0
  20. data/spec/api_version_constraint_middleware_spec.rb +58 -0
  21. data/spec/configuration_spec.rb +1 -1
  22. data/spec/deprecation_spec.rb +1 -1
  23. data/spec/error_spec.rb +1 -1
  24. data/spec/errors_spec.rb +3 -3
  25. data/spec/fake_app/.rspec +1 -0
  26. data/spec/fake_app/.ruby-version +1 -0
  27. data/spec/fake_app/Gemfile +53 -0
  28. data/spec/fake_app/README.md +24 -0
  29. data/spec/fake_app/Rakefile +6 -0
  30. data/spec/fake_app/app/assets/config/manifest.js +2 -0
  31. data/spec/fake_app/app/assets/stylesheets/application.css +15 -0
  32. data/spec/fake_app/app/controllers/api.rb +2 -0
  33. data/spec/fake_app/app/controllers/api/api_controller.rb +31 -0
  34. data/spec/fake_app/app/controllers/api/v1.rb +2 -0
  35. data/spec/fake_app/app/controllers/api/v1/hellos_controller.rb +7 -0
  36. data/spec/fake_app/app/controllers/api/v1/pings_controller.rb +16 -0
  37. data/spec/fake_app/app/controllers/api/v2.rb +2 -0
  38. data/spec/fake_app/app/controllers/api/v2/hellos_controller.rb +7 -0
  39. data/spec/fake_app/app/controllers/api/v2/pings_controller.rb +16 -0
  40. data/spec/fake_app/app/controllers/application_controller.rb +2 -0
  41. data/spec/fake_app/app/helpers/application_helper.rb +2 -0
  42. data/spec/fake_app/app/models/api_client.rb +2 -0
  43. data/spec/fake_app/app/models/application_record.rb +3 -0
  44. data/spec/fake_app/bin/rails +4 -0
  45. data/spec/fake_app/bin/rake +4 -0
  46. data/spec/fake_app/bin/setup +33 -0
  47. data/spec/fake_app/config.ru +6 -0
  48. data/spec/fake_app/config/application.rb +35 -0
  49. data/spec/fake_app/config/boot.rb +3 -0
  50. data/spec/fake_app/config/credentials.yml.enc +1 -0
  51. data/spec/fake_app/config/database.yml +25 -0
  52. data/spec/fake_app/config/environment.rb +5 -0
  53. data/spec/fake_app/config/environments/development.rb +71 -0
  54. data/spec/fake_app/config/environments/production.rb +109 -0
  55. data/spec/fake_app/config/environments/test.rb +52 -0
  56. data/spec/fake_app/config/initializers/assets.rb +12 -0
  57. data/spec/fake_app/config/initializers/cookies_serializer.rb +5 -0
  58. data/spec/fake_app/config/initializers/filter_parameter_logging.rb +6 -0
  59. data/spec/fake_app/config/initializers/stitches.rb +24 -0
  60. data/spec/fake_app/config/locales/en.yml +33 -0
  61. data/spec/fake_app/config/master.key +1 -0
  62. data/spec/fake_app/config/puma.rb +43 -0
  63. data/spec/fake_app/config/routes.rb +17 -0
  64. data/spec/fake_app/config/storage.yml +34 -0
  65. data/spec/fake_app/db/development.sqlite3 +0 -0
  66. data/spec/fake_app/db/migrate/20210802153118_enable_uuid_ossp_extension.rb +7 -0
  67. data/spec/fake_app/db/migrate/20210802153119_create_api_clients.rb +14 -0
  68. data/spec/fake_app/db/schema_missing_disabled_at.rb +12 -0
  69. data/spec/fake_app/db/schema_missing_enabled.rb +11 -0
  70. data/spec/fake_app/db/schema_modern.rb +13 -0
  71. data/spec/fake_app/db/seeds.rb +7 -0
  72. data/spec/fake_app/db/test.sqlite3 +0 -0
  73. data/spec/fake_app/doc/api.md +4 -0
  74. data/spec/fake_app/lib/tasks/generate_api_key.rake +10 -0
  75. data/spec/fake_app/public/404.html +67 -0
  76. data/spec/fake_app/public/422.html +67 -0
  77. data/spec/fake_app/public/500.html +66 -0
  78. data/spec/fake_app/public/apple-touch-icon-precomposed.png +0 -0
  79. data/spec/fake_app/public/apple-touch-icon.png +0 -0
  80. data/spec/fake_app/public/favicon.ico +0 -0
  81. data/spec/fake_app/public/javascripts/apitome/application.js +31 -0
  82. data/spec/fake_app/public/robots.txt +1 -0
  83. data/spec/fake_app/public/stylesheets/apitome/application.css +269 -0
  84. data/spec/fake_app/test/application_system_test_case.rb +5 -0
  85. data/spec/fake_app/test/test_helper.rb +13 -0
  86. data/spec/fake_app/tmp/development_secret.txt +1 -0
  87. data/spec/integration/add_to_rails_app_spec.rb +9 -1
  88. data/spec/rails_helper.rb +64 -0
  89. data/spec/valid_mime_type_middleware_spec.rb +59 -0
  90. data/spec/valid_mime_type_spec.rb +6 -4
  91. data/stitches.gemspec +2 -0
  92. metadata +168 -11
  93. data/spec/api_client_access_wrapper_spec.rb +0 -52
  94. data/spec/api_key_spec.rb +0 -208
  95. data/spec/api_version_constraint_spec.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1224843bf19c711e4058e54025f2507fe4dd0085fb5afdd57d5d383bf8d1b03e
4
- data.tar.gz: 8f2c1f7f053d711e6419b8e19c23cc123ce7164513b7cb3978091d081612001a
3
+ metadata.gz: 781cc5ec8996b5c726e7e214d69c5d780ddbf4818fb9b0cb5ce15de6bb6e829c
4
+ data.tar.gz: f482c0e9a21b84330add05e8c9a2bfd3ef5986ac60f7f22766f79f480d1e2a4b
5
5
  SHA512:
6
- metadata.gz: f16b168bf89994f06816661fb0dda066c248a3c55a22bdeebebf32d4a0e784368b41a460f25a84c9e0c4a694b37d372a24cf739171191925f31df7df7a562be6
7
- data.tar.gz: 053d0ae0e44945437218bc87206038029065b0ff8b6f8321bbad8b878024bddb16432b0f23136286e6019805a716d541a37a2d5382479b9216a9cde0104bf5d9
6
+ metadata.gz: d71dfb5cc76e1d753d1b25e3a8e278097167f07e8f43e7f276041c043960bf3ba551d47cd3ba90a4d94d56538a217d4c55156b5d5cb59273aa104086852d4a26
7
+ data.tar.gz: fb6c236f22a81f1cb7373f3d50d6dc907e7ba2c684a07dc1f5ce94ac7e9b6039dda780821d763912dbb39139fc00b27e2d254c525b7ac9da3d1011a5f4bec9b3
data/.circleci/config.yml CHANGED
@@ -5,7 +5,7 @@ version: 2
5
5
  jobs:
6
6
  generate-and-push-docs:
7
7
  docker:
8
- - image: circleci/ruby:2.7.2
8
+ - image: circleci/ruby:3.0.0
9
9
  auth:
10
10
  username: "$DOCKERHUB_USERNAME"
11
11
  password: "$DOCKERHUB_PASSWORD"
@@ -26,7 +26,7 @@ jobs:
26
26
  docs:push; fi
27
27
  release:
28
28
  docker:
29
- - image: circleci/ruby:2.7.2
29
+ - image: circleci/ruby:3.0.0
30
30
  auth:
31
31
  username: "$DOCKERHUB_USERNAME"
32
32
  password: "$DOCKERHUB_PASSWORD"
@@ -41,14 +41,14 @@ jobs:
41
41
  - run:
42
42
  name: Build/release gem to artifactory
43
43
  command: bundle exec rake push_artifactory
44
- ruby-2.7.2-rails-6.0:
44
+ ruby-3.0.0-rails-6.1:
45
45
  docker:
46
- - image: circleci/ruby:2.7.2
46
+ - image: circleci/ruby:3.0.0
47
47
  auth:
48
48
  username: "$DOCKERHUB_USERNAME"
49
49
  password: "$DOCKERHUB_PASSWORD"
50
50
  environment:
51
- BUNDLE_GEMFILE: Gemfile.rails-6.0
51
+ BUNDLE_GEMFILE: Gemfile.rails-6.1
52
52
  working_directory: "~/stitches"
53
53
  steps:
54
54
  - checkout
@@ -67,18 +67,18 @@ jobs:
67
67
  fi
68
68
  - run:
69
69
  name: Notify Pager Duty
70
- command: bundle exec y-notify "#devex-alerts"
70
+ command: bundle exec y-notify "#eng-runtime-alerts"
71
71
  when: on_fail
72
72
  - store_test_results:
73
73
  path: "/tmp/test-results"
74
- ruby-2.6.6-rails-6.0:
74
+ ruby-2.7.2-rails-6.1:
75
75
  docker:
76
- - image: circleci/ruby:2.6.6
76
+ - image: circleci/ruby:2.7.2
77
77
  auth:
78
78
  username: "$DOCKERHUB_USERNAME"
79
79
  password: "$DOCKERHUB_PASSWORD"
80
80
  environment:
81
- BUNDLE_GEMFILE: Gemfile.rails-6.0
81
+ BUNDLE_GEMFILE: Gemfile.rails-6.1
82
82
  working_directory: "~/stitches"
83
83
  steps:
84
84
  - checkout
@@ -97,18 +97,18 @@ jobs:
97
97
  fi
98
98
  - run:
99
99
  name: Notify Pager Duty
100
- command: bundle exec y-notify "#devex-alerts"
100
+ command: bundle exec y-notify "#eng-runtime-alerts"
101
101
  when: on_fail
102
102
  - store_test_results:
103
103
  path: "/tmp/test-results"
104
- ruby-2.7.2-rails-5.2:
104
+ ruby-3.0.0-rails-6.0:
105
105
  docker:
106
- - image: circleci/ruby:2.7.2
106
+ - image: circleci/ruby:3.0.0
107
107
  auth:
108
108
  username: "$DOCKERHUB_USERNAME"
109
109
  password: "$DOCKERHUB_PASSWORD"
110
110
  environment:
111
- BUNDLE_GEMFILE: Gemfile.rails-5.2
111
+ BUNDLE_GEMFILE: Gemfile.rails-6.0
112
112
  working_directory: "~/stitches"
113
113
  steps:
114
114
  - checkout
@@ -127,18 +127,18 @@ jobs:
127
127
  fi
128
128
  - run:
129
129
  name: Notify Pager Duty
130
- command: bundle exec y-notify "#devex-alerts"
130
+ command: bundle exec y-notify "#eng-runtime-alerts"
131
131
  when: on_fail
132
132
  - store_test_results:
133
133
  path: "/tmp/test-results"
134
- ruby-2.6.6-rails-5.2:
134
+ ruby-2.7.2-rails-6.0:
135
135
  docker:
136
- - image: circleci/ruby:2.6.6
136
+ - image: circleci/ruby:2.7.2
137
137
  auth:
138
138
  username: "$DOCKERHUB_USERNAME"
139
139
  password: "$DOCKERHUB_PASSWORD"
140
140
  environment:
141
- BUNDLE_GEMFILE: Gemfile.rails-5.2
141
+ BUNDLE_GEMFILE: Gemfile.rails-6.0
142
142
  working_directory: "~/stitches"
143
143
  steps:
144
144
  - checkout
@@ -157,7 +157,7 @@ jobs:
157
157
  fi
158
158
  - run:
159
159
  name: Notify Pager Duty
160
- command: bundle exec y-notify "#devex-alerts"
160
+ command: bundle exec y-notify "#eng-runtime-alerts"
161
161
  when: on_fail
162
162
  - store_test_results:
163
163
  path: "/tmp/test-results"
@@ -168,10 +168,10 @@ workflows:
168
168
  - release:
169
169
  context: org-global
170
170
  requires:
171
+ - ruby-3.0.0-rails-6.1
172
+ - ruby-2.7.2-rails-6.1
173
+ - ruby-3.0.0-rails-6.0
171
174
  - ruby-2.7.2-rails-6.0
172
- - ruby-2.6.6-rails-6.0
173
- - ruby-2.7.2-rails-5.2
174
- - ruby-2.6.6-rails-5.2
175
175
  filters:
176
176
  tags:
177
177
  only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?(RC|rc)[-\.]?\w*)?$/
@@ -186,22 +186,22 @@ workflows:
186
186
  only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?(RC|rc)[-\.]?\w*)?$/
187
187
  branches:
188
188
  ignore: /.*/
189
- - ruby-2.7.2-rails-6.0:
189
+ - ruby-3.0.0-rails-6.1:
190
190
  context: org-global
191
191
  filters:
192
192
  tags:
193
193
  only: &1 /.*/
194
- - ruby-2.6.6-rails-6.0:
194
+ - ruby-2.7.2-rails-6.1:
195
195
  context: org-global
196
196
  filters:
197
197
  tags:
198
198
  only: *1
199
- - ruby-2.7.2-rails-5.2:
199
+ - ruby-3.0.0-rails-6.0:
200
200
  context: org-global
201
201
  filters:
202
202
  tags:
203
203
  only: *1
204
- - ruby-2.6.6-rails-5.2:
204
+ - ruby-2.7.2-rails-6.0:
205
205
  context: org-global
206
206
  filters:
207
207
  tags:
@@ -215,11 +215,11 @@ workflows:
215
215
  only:
216
216
  - master
217
217
  jobs:
218
- - ruby-2.7.2-rails-6.0:
218
+ - ruby-3.0.0-rails-6.1:
219
219
  context: org-global
220
- - ruby-2.6.6-rails-6.0:
220
+ - ruby-2.7.2-rails-6.1:
221
221
  context: org-global
222
- - ruby-2.7.2-rails-5.2:
222
+ - ruby-3.0.0-rails-6.0:
223
223
  context: org-global
224
- - ruby-2.6.6-rails-5.2:
224
+ - ruby-2.7.2-rails-6.0:
225
225
  context: org-global
data/.github/CODEOWNERS CHANGED
@@ -8,4 +8,4 @@
8
8
  # This file uses the GitHub CODEOWNERS convention to assign PR reviewers:
9
9
  # https://help.github.com/articles/about-codeowners/
10
10
 
11
- * @brettfishman @bwebster @stitchfix/devex
11
+ * @brettfishman @bwebster @stitchfix/runtime-infrastructure
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  pkg
2
2
  spec/reports
3
+ spec/fake_app/log/
3
4
  .vimrc
4
5
  *.sw?
5
6
  .idea/
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.2
1
+ ruby-2.7.2
data/Gemfile.rails-6.1 ADDED
@@ -0,0 +1,7 @@
1
+ # DO NOT MODIFY - this is managed by Git Reduce in goro
2
+ #
3
+ source 'https://stitchfix01.jfrog.io/stitchfix01/api/gems/eng-gems/'
4
+
5
+ gemspec
6
+
7
+ gem 'rails', '~> 6.1.0'
data/README.md CHANGED
@@ -35,7 +35,7 @@ Then, set it up:
35
35
 
36
36
  ### Upgrading from an older version
37
37
 
38
- - When upgrading to version 4.0.0 you may now take advantage of an in-memory cache
38
+ - When upgrading to version 4.0.0 and above you may now take advantage of an in-memory cache
39
39
 
40
40
  You can enabled it like so
41
41
 
@@ -46,18 +46,46 @@ Stitches.configure do |config|
46
46
  end
47
47
  ```
48
48
 
49
- - If you have a version lower than 3.3.0, you need to run two generators, one of which creates a new database migration on your
50
- `api_clients` table:
49
+ You can also set a leniency for disabled API keys, which will allow old API keys to continue to be used if they have a
50
+ `disabled_at` field set as long as the leniency is not exceeded. Note that if the `disabled_at` field is not populated
51
+ the behavior will remain the same as it always was, and the request will be denied when the `enabled` field is set to
52
+ `true`. If Stitches allows a call due to leniency settings, a log message will be generated with a severity depending on
53
+ how long ago the API key was disabled.
54
+
55
+ ```ruby
56
+ Stitches.configure do |config|
57
+ config.disabled_key_leniency_in_seconds = 3 * 24 * 60 * 60 # Time in seconds, defaults to three days
58
+ config.disabled_key_leniency_error_log_threshold_in_seconds = 2 * 24 * 60 * 60 # Time in seconds, defaults to two days
59
+ end
60
+ ```
61
+
62
+ If a disabled key is used within the `disabled_key_leniency_in_seconds`, it will be allowed.
63
+
64
+ Anytime a disabled key is used a log will be generated. If it is before the
65
+ `disabled_key_leniency_error_log_threshold_in_seconds` it will be a warning log message, if it is after that, it will be
66
+ an error message. `disabled_key_leniency_error_log_threshold_in_seconds` should never be a greater number than
67
+ `disabled_key_leniency_in_seconds`, as this provides an escallating series of warnings before finally disabling access.
68
+
69
+ - If you are upgrading from a version older than 3.3.0 you need to run three generators, two of which create database
70
+ migrations on your `api_clients` table:
51
71
 
52
72
  ```
53
73
  > bin/rails generate stitches:add_enabled_to_api_clients
54
74
  > bin/rails generate stitches:add_deprecation
75
+ > bin/rails generate stitches:add_disabled_at_to_api_clients
55
76
  ```
56
77
 
57
- - If you have a version lower than 3.6.0, you need to run one generator:
78
+ - If you are upgrading from a version between 3.3.0 and 3.5.0 you need to run two generators:
58
79
 
59
80
  ```
60
81
  > bin/rails generate stitches:add_deprecation
82
+ > bin/rails generate stitches:add_disabled_at_to_api_clients
83
+ ```
84
+
85
+ - If you are upgrading from a version between 3.6.0 and 4.0.2 you need to run one generator:
86
+
87
+ ```
88
+ > bin/rails generate stitches:add_disabled_at_to_api_clients
61
89
  ```
62
90
 
63
91
  ## Example Microservice Endpoint
@@ -143,6 +171,10 @@ Also, the integration test does a lot of "testing the implementation", but since
143
171
  failing with a successful result, we have to make sure that the various `inject_into_file` calls are actually working. Do not do
144
172
  any fancy refactors here, just keep it up to date.
145
173
 
174
+ ## Releases
175
+
176
+ See the release process for open source gems in the Stitch Fix engineering wiki under technical topics.
177
+
146
178
  ---
147
179
 
148
180
  Provided with love by your friends at [Stitch Fix Engineering](http://technology.stitchfix.com)
@@ -0,0 +1,18 @@
1
+ require 'rails/generators'
2
+
3
+ module Stitches
4
+ class AddDisabledAtToApiClientsGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ source_root(File.expand_path(File.join(File.dirname(__FILE__),"generator_files")))
8
+
9
+ def self.next_migration_number(path)
10
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
11
+ end
12
+
13
+ desc "Upgrade your api_clients table so it includes the `disabled_at` field"
14
+ def update_api_clients_table
15
+ migration_template "db/migrate/add_disabled_at_to_api_clients.rb", "db/migrate/add_disabled_at_to_api_clients.rb"
16
+ end
17
+ end
18
+ end
@@ -3,15 +3,14 @@ module Stitches
3
3
  class AllowlistMiddleware
4
4
  def initialize(app, options={})
5
5
  @app = app
6
- @configuration = options[:configuration] || Stitches.configuration
7
- @except = options[:except] || @configuration.allowlist_regexp
6
+ @configuration = options[:configuration]
7
+ @except = options[:except]
8
8
 
9
- unless @except.nil? || @except.is_a?(Regexp)
10
- raise ":except must be a Regexp"
11
- end
9
+ allowlist_regex
12
10
  end
11
+
13
12
  def call(env)
14
- if @except && @except.match(env["PATH_INFO"])
13
+ if allowlist_regex && allowlist_regex.match(env["PATH_INFO"])
15
14
  @app.call(env)
16
15
  else
17
16
  do_call(env)
@@ -24,5 +23,20 @@ module Stitches
24
23
  raise 'subclass must implement'
25
24
  end
26
25
 
26
+ def configuration
27
+ @configuration || Stitches.configuration
28
+ end
29
+
30
+ private
31
+
32
+ def allowlist_regex
33
+ regex = @except || configuration.allowlist_regexp
34
+
35
+ if !regex.nil? && !regex.is_a?(Regexp)
36
+ raise ":except must be a Regexp"
37
+ end
38
+
39
+ regex
40
+ end
27
41
  end
28
42
  end
@@ -2,26 +2,57 @@ require 'lru_redux'
2
2
 
3
3
  module Stitches::ApiClientAccessWrapper
4
4
 
5
- def self.fetch_for_key(key)
5
+ def self.fetch_for_key(key, configuration)
6
6
  if cache_enabled
7
- fetch_for_key_from_cache(key)
7
+ fetch_for_key_from_cache(key, configuration)
8
8
  else
9
- fetch_for_key_from_db(key)
9
+ fetch_for_key_from_db(key, configuration)
10
10
  end
11
11
  end
12
12
 
13
- def self.fetch_for_key_from_cache(key)
13
+ def self.fetch_for_key_from_cache(key, configuration)
14
14
  api_key_cache.getset(key) do
15
- fetch_for_key_from_db(key)
15
+ fetch_for_key_from_db(key, configuration)
16
16
  end
17
17
  end
18
18
 
19
- def self.fetch_for_key_from_db(key)
20
- if ::ApiClient.column_names.include?("enabled")
21
- ::ApiClient.find_by(key: key, enabled: true)
19
+ def self.fetch_for_key_from_db(key, configuration)
20
+ api_client = ::ApiClient.find_by(key: key)
21
+ return unless api_client
22
+
23
+ unless api_client.respond_to?(:enabled?)
24
+ logger.warn('api_keys is missing "enabled" column. Run "rails g stitches:add_enabled_to_api_clients"')
25
+ return api_client
26
+ end
27
+
28
+ unless api_client.respond_to?(:disabled_at)
29
+ logger.warn('api_keys is missing "disabled_at" column. Run "rails g stitches:add_disabled_at_to_api_clients"')
30
+ end
31
+
32
+ return api_client if api_client.enabled?
33
+
34
+ disabled_at = api_client.respond_to?(:disabled_at) ? api_client.disabled_at : nil
35
+ if disabled_at && disabled_at > configuration.disabled_key_leniency_in_seconds.seconds.ago
36
+ message = "Allowing disabled ApiClient: #{api_client.name} with key #{api_client.key} disabled at #{disabled_at}"
37
+ if disabled_at > configuration.disabled_key_leniency_error_log_threshold_in_seconds.seconds.ago
38
+ logger.warn(message)
39
+ else
40
+ logger.error(message)
41
+ end
42
+ return api_client
43
+ else
44
+ logger.error("Rejecting disabled ApiClient: #{api_client.name} with key #{api_client.key}")
45
+ end
46
+ nil
47
+ end
48
+
49
+ def self.logger
50
+ if defined?(StitchFix::Logger::LogWriter)
51
+ StitchFix::Logger::LogWriter
52
+ elsif defined?(Rails.logger)
53
+ Rails.logger
22
54
  else
23
- ActiveSupport::Deprecation.warn('api_keys is missing "enabled" column. Run "rails g stitches:add_enabled_to_api_clients"')
24
- ::ApiClient.find_by(key: key)
55
+ ::Logger.new('/dev/null')
25
56
  end
26
57
  end
27
58
 
@@ -39,4 +70,4 @@ module Stitches::ApiClientAccessWrapper
39
70
  def self.cache_enabled
40
71
  Stitches.configuration.max_cache_ttl.positive?
41
72
  end
42
- end
73
+ end
@@ -25,12 +25,12 @@ module Stitches
25
25
  def do_call(env)
26
26
  authorization = env["HTTP_AUTHORIZATION"]
27
27
  if authorization
28
- if authorization =~ /#{@configuration.custom_http_auth_scheme}\s+key=(.*)\s*$/
28
+ if authorization =~ /#{configuration.custom_http_auth_scheme}\s+key=(.*)\s*$/
29
29
  key = $1
30
- client = Stitches::ApiClientAccessWrapper.fetch_for_key(key)
30
+ client = Stitches::ApiClientAccessWrapper.fetch_for_key(key, configuration)
31
31
  if client.present?
32
- env[@configuration.env_var_to_hold_api_client_primary_key] = client.id
33
- env[@configuration.env_var_to_hold_api_client] = client
32
+ env[configuration.env_var_to_hold_api_client_primary_key] = client.id
33
+ env[configuration.env_var_to_hold_api_client] = client
34
34
  @app.call(env)
35
35
  else
36
36
  unauthorized_response("key invalid")
@@ -59,7 +59,7 @@ module Stitches
59
59
  def unauthorized_response(reason)
60
60
  status = 401
61
61
  body = "Unauthorized - #{reason}"
62
- header = { "WWW-Authenticate" => "#{@configuration.custom_http_auth_scheme} realm=#{rails_app_module}" }
62
+ header = { "WWW-Authenticate" => "#{configuration.custom_http_auth_scheme} realm=#{rails_app_module}" }
63
63
  Rack::Response.new(body, status, header).finish
64
64
  end
65
65
 
@@ -15,8 +15,12 @@ class Stitches::Configuration
15
15
  @env_var_to_hold_api_client= NonNullString.new("env_var_to_hold_api_client","STITCHES_API_CLIENT")
16
16
  @max_cache_ttl = NonNullInteger.new("max_cache_ttl", 0)
17
17
  @max_cache_size = NonNullInteger.new("max_cache_size", 0)
18
+ @disabled_key_leniency_in_seconds = ActiveSupport::Duration.days(3)
19
+ @disabled_key_leniency_error_log_threshold_in_seconds = ActiveSupport::Duration.days(2)
18
20
  end
19
21
 
22
+ attr_accessor :disabled_key_leniency_in_seconds, :disabled_key_leniency_error_log_threshold_in_seconds
23
+
20
24
  # A RegExp that allows URLS around the mime type and api key requirements.
21
25
  # nil means that ever request must have a proper mime type and api key.
22
26
  attr_reader :allowlist_regexp