stitches 4.0.1 → 4.2.0.RC2

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