stitches 4.0.0 → 4.2.0.RC1

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 +95 -30
  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 +11 -4
  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 +22 -4
  91. data/stitches.gemspec +2 -0
  92. metadata +171 -14
  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: 3ea8633778064ab7646860c9a0682a7290bfbea3d6f3f091c290f50d22f97de2
4
- data.tar.gz: 0eb1d04f15fc37ab0b0484ae6a73f953426cc5dd1b9efd056e42300caa4c2d04
3
+ metadata.gz: ff331a78189008795f3789617197c5bf4ac77fb9b2db8fe036256903668656ba
4
+ data.tar.gz: 2757ff4ef4739e826b60406726547b225693f44846d811c0c8fd0afa093eb55a
5
5
  SHA512:
6
- metadata.gz: f854d4c3feca2e48b6edfde3174564112b2c0c1d6cb6b93bed960985cc779c1119bcf5ddb65d43d85d3c349d9f440b61e14b1cef27aa6f8c1701768ab5ac1dd5
7
- data.tar.gz: b19d1b967d4a5e0dc57265475683bbfd8e9f255d15ee0af1a8130832d16e73e54b52b7e34fc025fe170a4322cb30cbddb6f2e631f7c81521953e4e48514bb547
6
+ metadata.gz: c6a9e99b2f0410ba3e1bff9c851fde7ec923154388667ea86c7a080354eb3943a2188e33336cc23e5ea530a98851e1fdf00ceb750cd246ebc95a3f43f2ecb95e
7
+ data.tar.gz: ed1f7f688b16629940ccd0f7b201ad6b47e9fcfdc005969dd3fdff7264fb45bd7c31d572a1dda5a962386bf567e07bb1823dbab66ccea40e8bed9650d67b59c9
data/.circleci/config.yml CHANGED
@@ -3,9 +3,33 @@
3
3
  ---
4
4
  version: 2
5
5
  jobs:
6
+ generate-and-push-docs:
7
+ docker:
8
+ - image: circleci/ruby:3.0.0
9
+ auth:
10
+ username: "$DOCKERHUB_USERNAME"
11
+ password: "$DOCKERHUB_PASSWORD"
12
+ steps:
13
+ - checkout
14
+ - run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
15
+ - run: bundle install --full-index
16
+ - run:
17
+ name: Generate documentation
18
+ command: ' if [[ $(bundle exec rake -T docs:generate:custom) ]]; then echo
19
+ "Generating docs using rake task docs:generate:custom" ; bundle exec rake
20
+ docs:generate:custom ; elif [[ $(bundle exec rake -T docs:generate) ]];
21
+ then echo "Generating docs using rake task docs:generate" ; bundle exec
22
+ rake docs:generate ; else echo "Skipping doc generation" ; exit 0 ; fi '
23
+ - run:
24
+ name: Push documentation to Unwritten
25
+ command: if [[ $(bundle exec rake -T docs:push) ]]; then bundle exec rake
26
+ docs:push; fi
6
27
  release:
7
28
  docker:
8
- - image: circleci/ruby:2.7.1
29
+ - image: circleci/ruby:3.0.0
30
+ auth:
31
+ username: "$DOCKERHUB_USERNAME"
32
+ password: "$DOCKERHUB_PASSWORD"
9
33
  steps:
10
34
  - checkout
11
35
  - run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
@@ -17,14 +41,22 @@ jobs:
17
41
  - run:
18
42
  name: Build/release gem to artifactory
19
43
  command: bundle exec rake push_artifactory
20
- ruby-2.7.1-rails-6.0:
44
+ ruby-3.0.0-rails-6.1:
21
45
  docker:
22
- - image: circleci/ruby:2.7.1
46
+ - image: circleci/ruby:3.0.0
47
+ auth:
48
+ username: "$DOCKERHUB_USERNAME"
49
+ password: "$DOCKERHUB_PASSWORD"
23
50
  environment:
24
- BUNDLE_GEMFILE: Gemfile.rails-6.0
51
+ BUNDLE_GEMFILE: Gemfile.rails-6.1
25
52
  working_directory: "~/stitches"
26
53
  steps:
27
54
  - checkout
55
+ - run:
56
+ name: Check for Gemfile.lock presence
57
+ command: ' if (test -f Gemfile.lock) then echo "Dont commit Gemfile.lock (see
58
+ https://github.com/stitchfix/eng-wiki/blob/master/architecture-decisions/0009-rubygem-dependencies-will-be-managed-more-explicitly.md)"
59
+ 1>&2 ; exit 1 ; else exit 0 ; fi '
28
60
  - run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
29
61
  - run: bundle install --full-index
30
62
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
@@ -35,18 +67,26 @@ jobs:
35
67
  fi
36
68
  - run:
37
69
  name: Notify Pager Duty
38
- command: bundle exec y-notify "#devex-alerts"
70
+ command: bundle exec y-notify "#eng-runtime-alerts"
39
71
  when: on_fail
40
72
  - store_test_results:
41
73
  path: "/tmp/test-results"
42
- ruby-2.6.6-rails-6.0:
74
+ ruby-2.7.2-rails-6.1:
43
75
  docker:
44
- - image: circleci/ruby:2.6.6
76
+ - image: circleci/ruby:2.7.2
77
+ auth:
78
+ username: "$DOCKERHUB_USERNAME"
79
+ password: "$DOCKERHUB_PASSWORD"
45
80
  environment:
46
- BUNDLE_GEMFILE: Gemfile.rails-6.0
81
+ BUNDLE_GEMFILE: Gemfile.rails-6.1
47
82
  working_directory: "~/stitches"
48
83
  steps:
49
84
  - checkout
85
+ - run:
86
+ name: Check for Gemfile.lock presence
87
+ command: ' if (test -f Gemfile.lock) then echo "Dont commit Gemfile.lock (see
88
+ https://github.com/stitchfix/eng-wiki/blob/master/architecture-decisions/0009-rubygem-dependencies-will-be-managed-more-explicitly.md)"
89
+ 1>&2 ; exit 1 ; else exit 0 ; fi '
50
90
  - run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
51
91
  - run: bundle install --full-index
52
92
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
@@ -57,18 +97,26 @@ jobs:
57
97
  fi
58
98
  - run:
59
99
  name: Notify Pager Duty
60
- command: bundle exec y-notify "#devex-alerts"
100
+ command: bundle exec y-notify "#eng-runtime-alerts"
61
101
  when: on_fail
62
102
  - store_test_results:
63
103
  path: "/tmp/test-results"
64
- ruby-2.7.1-rails-5.2:
104
+ ruby-3.0.0-rails-6.0:
65
105
  docker:
66
- - image: circleci/ruby:2.7.1
106
+ - image: circleci/ruby:3.0.0
107
+ auth:
108
+ username: "$DOCKERHUB_USERNAME"
109
+ password: "$DOCKERHUB_PASSWORD"
67
110
  environment:
68
- BUNDLE_GEMFILE: Gemfile.rails-5.2
111
+ BUNDLE_GEMFILE: Gemfile.rails-6.0
69
112
  working_directory: "~/stitches"
70
113
  steps:
71
114
  - checkout
115
+ - run:
116
+ name: Check for Gemfile.lock presence
117
+ command: ' if (test -f Gemfile.lock) then echo "Dont commit Gemfile.lock (see
118
+ https://github.com/stitchfix/eng-wiki/blob/master/architecture-decisions/0009-rubygem-dependencies-will-be-managed-more-explicitly.md)"
119
+ 1>&2 ; exit 1 ; else exit 0 ; fi '
72
120
  - run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
73
121
  - run: bundle install --full-index
74
122
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
@@ -79,18 +127,26 @@ jobs:
79
127
  fi
80
128
  - run:
81
129
  name: Notify Pager Duty
82
- command: bundle exec y-notify "#devex-alerts"
130
+ command: bundle exec y-notify "#eng-runtime-alerts"
83
131
  when: on_fail
84
132
  - store_test_results:
85
133
  path: "/tmp/test-results"
86
- ruby-2.6.6-rails-5.2:
134
+ ruby-2.7.2-rails-6.0:
87
135
  docker:
88
- - image: circleci/ruby:2.6.6
136
+ - image: circleci/ruby:2.7.2
137
+ auth:
138
+ username: "$DOCKERHUB_USERNAME"
139
+ password: "$DOCKERHUB_PASSWORD"
89
140
  environment:
90
- BUNDLE_GEMFILE: Gemfile.rails-5.2
141
+ BUNDLE_GEMFILE: Gemfile.rails-6.0
91
142
  working_directory: "~/stitches"
92
143
  steps:
93
144
  - checkout
145
+ - run:
146
+ name: Check for Gemfile.lock presence
147
+ command: ' if (test -f Gemfile.lock) then echo "Dont commit Gemfile.lock (see
148
+ https://github.com/stitchfix/eng-wiki/blob/master/architecture-decisions/0009-rubygem-dependencies-will-be-managed-more-explicitly.md)"
149
+ 1>&2 ; exit 1 ; else exit 0 ; fi '
94
150
  - run: bundle config stitchfix01.jfrog.io $ARTIFACTORY_USER:$ARTIFACTORY_TOKEN
95
151
  - run: bundle install --full-index
96
152
  - run: bundle exec rspec --format RspecJunitFormatter --out /tmp/test-results/rspec.xml
@@ -101,7 +157,7 @@ jobs:
101
157
  fi
102
158
  - run:
103
159
  name: Notify Pager Duty
104
- command: bundle exec y-notify "#devex-alerts"
160
+ command: bundle exec y-notify "#eng-runtime-alerts"
105
161
  when: on_fail
106
162
  - store_test_results:
107
163
  path: "/tmp/test-results"
@@ -112,31 +168,40 @@ workflows:
112
168
  - release:
113
169
  context: org-global
114
170
  requires:
115
- - ruby-2.7.1-rails-6.0
116
- - ruby-2.6.6-rails-6.0
117
- - ruby-2.7.1-rails-5.2
118
- - ruby-2.6.6-rails-5.2
171
+ - ruby-3.0.0-rails-6.1
172
+ - ruby-2.7.2-rails-6.1
173
+ - ruby-3.0.0-rails-6.0
174
+ - ruby-2.7.2-rails-6.0
175
+ filters:
176
+ tags:
177
+ only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?(RC|rc)[-\.]?\w*)?$/
178
+ branches:
179
+ ignore: /.*/
180
+ - generate-and-push-docs:
181
+ context: org-global
182
+ requires:
183
+ - release
119
184
  filters:
120
185
  tags:
121
- only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?(RC|rc)[-\.]?\d*)?$/
186
+ only: /^[0-9]+\.[0-9]+\.[0-9]+(\.?(RC|rc)[-\.]?\w*)?$/
122
187
  branches:
123
188
  ignore: /.*/
124
- - ruby-2.7.1-rails-6.0:
189
+ - ruby-3.0.0-rails-6.1:
125
190
  context: org-global
126
191
  filters:
127
192
  tags:
128
193
  only: &1 /.*/
129
- - ruby-2.6.6-rails-6.0:
194
+ - ruby-2.7.2-rails-6.1:
130
195
  context: org-global
131
196
  filters:
132
197
  tags:
133
198
  only: *1
134
- - ruby-2.7.1-rails-5.2:
199
+ - ruby-3.0.0-rails-6.0:
135
200
  context: org-global
136
201
  filters:
137
202
  tags:
138
203
  only: *1
139
- - ruby-2.6.6-rails-5.2:
204
+ - ruby-2.7.2-rails-6.0:
140
205
  context: org-global
141
206
  filters:
142
207
  tags:
@@ -150,11 +215,11 @@ workflows:
150
215
  only:
151
216
  - master
152
217
  jobs:
153
- - ruby-2.7.1-rails-6.0:
218
+ - ruby-3.0.0-rails-6.1:
154
219
  context: org-global
155
- - ruby-2.6.6-rails-6.0:
220
+ - ruby-2.7.2-rails-6.1:
156
221
  context: org-global
157
- - ruby-2.7.1-rails-5.2:
222
+ - ruby-3.0.0-rails-6.0:
158
223
  context: org-global
159
- - ruby-2.6.6-rails-5.2:
224
+ - ruby-2.7.2-rails-6.0:
160
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.1
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