ejson-rails 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31b8ead062c2323086dbdaa211878c04ce3cb3ee3203882ca13efa9b6ba8f3a3
4
- data.tar.gz: 3bc548e0db8eac2a33ccdf849e0fb2dbcddd7fe7ea0a537cab1e6e153fccb01e
3
+ metadata.gz: d6d62b4bf362a99bed1a71b0a16cc83bd610157b8e3a06d8998a8c4d1a9479f9
4
+ data.tar.gz: b74ef1b02227276aed05fc815d876218046bdef4533013d4ca61c0287a79e22a
5
5
  SHA512:
6
- metadata.gz: 03b463b72d2a9efdf4e8e9f461a4146e60c52ba53a4d0c17554b4ff1582aa34d332310c70f5f73061279486963f199900002d29b23356fc84411b2e230913a58
7
- data.tar.gz: 42f3dc896ce52a593c67e65fe7c72dd5b6ec4d3cc22690350cd9a964ee06c6799cc362390e938f8e1dbcee01259c48195aed2632f84342460ab089c9476ef018
6
+ metadata.gz: d8d136c6ef01aaf7011c0f8edb1f301654e813de2de0cff764422dabb929cea9b8df2e73eea3cb5f5a991a67166004f6bd62f0c0419984071fa8bc8b3009d549
7
+ data.tar.gz: 325e1a3e46fb0abfdd33b85002359768318dfac8fa6682cc9c09a17130604aa445aa98efcce57156a94cf9abda1d5bbec1315b4178b8830fe1e5e1d0f596f98a
@@ -10,13 +10,13 @@ jobs:
10
10
  matrix:
11
11
  entry:
12
12
  - name: Minimum Rails
13
- ruby: '2.7'
13
+ ruby: '3.1'
14
14
  gemfile: Gemfile.rails-min
15
15
  - name: Latest Rails
16
- ruby: '3.2'
16
+ ruby: '3.3'
17
17
  gemfile: Gemfile.rails-latest
18
18
  - name: Edge Rails
19
- ruby: '3.2'
19
+ ruby: '3.3'
20
20
  gemfile: "Gemfile.rails-edge"
21
21
 
22
22
  name: ${{ matrix.entry.name }}
data/.rubocop.yml CHANGED
@@ -4,6 +4,5 @@ inherit_gem:
4
4
  AllCops:
5
5
  NewCops: disable
6
6
  SuggestExtensions: false
7
- TargetRubyVersion: 3.2
8
7
  Exclude:
9
8
  - vendor/bundle/**/*
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.0
1
+ 3.3.0
data/Gemfile.lock CHANGED
@@ -1,108 +1,141 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ejson-rails (0.2.0)
4
+ ejson-rails (0.2.2)
5
5
  ejson
6
- railties (>= 5.2)
6
+ railties (>= 6.1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionpack (7.0.6)
12
- actionview (= 7.0.6)
13
- activesupport (= 7.0.6)
14
- rack (~> 2.0, >= 2.2.4)
11
+ actionpack (7.1.3.2)
12
+ actionview (= 7.1.3.2)
13
+ activesupport (= 7.1.3.2)
14
+ nokogiri (>= 1.8.5)
15
+ racc
16
+ rack (>= 2.2.4)
17
+ rack-session (>= 1.0.1)
15
18
  rack-test (>= 0.6.3)
16
- rails-dom-testing (~> 2.0)
17
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
18
- actionview (7.0.6)
19
- activesupport (= 7.0.6)
19
+ rails-dom-testing (~> 2.2)
20
+ rails-html-sanitizer (~> 1.6)
21
+ actionview (7.1.3.2)
22
+ activesupport (= 7.1.3.2)
20
23
  builder (~> 3.1)
21
- erubi (~> 1.4)
22
- rails-dom-testing (~> 2.0)
23
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
24
- activesupport (7.0.6)
24
+ erubi (~> 1.11)
25
+ rails-dom-testing (~> 2.2)
26
+ rails-html-sanitizer (~> 1.6)
27
+ activesupport (7.1.3.2)
28
+ base64
29
+ bigdecimal
25
30
  concurrent-ruby (~> 1.0, >= 1.0.2)
31
+ connection_pool (>= 2.2.5)
32
+ drb
26
33
  i18n (>= 1.6, < 2)
27
34
  minitest (>= 5.1)
35
+ mutex_m
28
36
  tzinfo (~> 2.0)
29
37
  ast (2.4.2)
38
+ base64 (0.2.0)
39
+ bigdecimal (3.1.6)
30
40
  builder (3.2.4)
31
- concurrent-ruby (1.2.2)
41
+ concurrent-ruby (1.2.3)
42
+ connection_pool (2.4.1)
32
43
  crass (1.0.6)
33
- diff-lcs (1.4.4)
34
- ejson (1.3.1)
44
+ diff-lcs (1.5.1)
45
+ drb (2.2.1)
46
+ ejson (1.4.1)
35
47
  erubi (1.12.0)
36
48
  i18n (1.14.1)
37
49
  concurrent-ruby (~> 1.0)
38
- json (2.6.3)
39
- loofah (2.21.3)
50
+ io-console (0.6.0)
51
+ irb (1.10.0)
52
+ rdoc
53
+ reline (>= 0.3.8)
54
+ json (2.7.1)
55
+ language_server-protocol (3.17.0.3)
56
+ loofah (2.22.0)
40
57
  crass (~> 1.0.2)
41
58
  nokogiri (>= 1.12.0)
42
- method_source (1.0.0)
43
- mini_portile2 (2.8.4)
44
- minitest (5.18.1)
45
- nokogiri (1.15.3)
59
+ mini_portile2 (2.8.5)
60
+ minitest (5.22.2)
61
+ mutex_m (0.2.0)
62
+ nokogiri (1.15.6)
46
63
  mini_portile2 (~> 2.8.2)
47
64
  racc (~> 1.4)
48
- parallel (1.22.1)
49
- parser (3.2.0.0)
65
+ parallel (1.24.0)
66
+ parser (3.3.0.5)
50
67
  ast (~> 2.4.1)
51
- racc (1.7.1)
52
- rack (2.2.7)
68
+ racc
69
+ psych (5.1.2)
70
+ stringio
71
+ racc (1.7.3)
72
+ rack (3.0.9.1)
73
+ rack-session (2.0.0)
74
+ rack (>= 3.0.0)
53
75
  rack-test (2.1.0)
54
76
  rack (>= 1.3)
55
- rails-dom-testing (2.1.1)
77
+ rackup (2.1.0)
78
+ rack (>= 3)
79
+ webrick (~> 1.8)
80
+ rails-dom-testing (2.2.0)
56
81
  activesupport (>= 5.0.0)
57
82
  minitest
58
83
  nokogiri (>= 1.6)
59
84
  rails-html-sanitizer (1.6.0)
60
85
  loofah (~> 2.21)
61
86
  nokogiri (~> 1.14)
62
- railties (7.0.6)
63
- actionpack (= 7.0.6)
64
- activesupport (= 7.0.6)
65
- method_source
87
+ railties (7.1.3.2)
88
+ actionpack (= 7.1.3.2)
89
+ activesupport (= 7.1.3.2)
90
+ irb
91
+ rackup (>= 1.0.0)
66
92
  rake (>= 12.2)
67
- thor (~> 1.0)
68
- zeitwerk (~> 2.5)
93
+ thor (~> 1.0, >= 1.2.2)
94
+ zeitwerk (~> 2.6)
69
95
  rainbow (3.1.1)
70
96
  rake (13.0.6)
71
- regexp_parser (2.6.1)
72
- rexml (3.2.5)
73
- rspec (3.10.0)
74
- rspec-core (~> 3.10.0)
75
- rspec-expectations (~> 3.10.0)
76
- rspec-mocks (~> 3.10.0)
77
- rspec-core (3.10.1)
78
- rspec-support (~> 3.10.0)
79
- rspec-expectations (3.10.1)
97
+ rdoc (6.6.3.1)
98
+ psych (>= 4.0.0)
99
+ regexp_parser (2.9.0)
100
+ reline (0.4.1)
101
+ io-console (~> 0.5)
102
+ rexml (3.2.6)
103
+ rspec (3.12.0)
104
+ rspec-core (~> 3.12.0)
105
+ rspec-expectations (~> 3.12.0)
106
+ rspec-mocks (~> 3.12.0)
107
+ rspec-core (3.12.2)
108
+ rspec-support (~> 3.12.0)
109
+ rspec-expectations (3.12.3)
80
110
  diff-lcs (>= 1.2.0, < 2.0)
81
- rspec-support (~> 3.10.0)
82
- rspec-mocks (3.10.2)
111
+ rspec-support (~> 3.12.0)
112
+ rspec-mocks (3.12.6)
83
113
  diff-lcs (>= 1.2.0, < 2.0)
84
- rspec-support (~> 3.10.0)
85
- rspec-support (3.10.2)
86
- rubocop (1.43.0)
114
+ rspec-support (~> 3.12.0)
115
+ rspec-support (3.12.1)
116
+ rubocop (1.62.1)
87
117
  json (~> 2.3)
118
+ language_server-protocol (>= 3.17.0)
88
119
  parallel (~> 1.10)
89
- parser (>= 3.2.0.0)
120
+ parser (>= 3.3.0.2)
90
121
  rainbow (>= 2.2.2, < 4.0)
91
122
  regexp_parser (>= 1.8, < 3.0)
92
123
  rexml (>= 3.2.5, < 4.0)
93
- rubocop-ast (>= 1.24.1, < 2.0)
124
+ rubocop-ast (>= 1.31.1, < 2.0)
94
125
  ruby-progressbar (~> 1.7)
95
126
  unicode-display_width (>= 2.4.0, < 3.0)
96
- rubocop-ast (1.24.1)
97
- parser (>= 3.1.1.0)
127
+ rubocop-ast (1.31.2)
128
+ parser (>= 3.3.0.4)
98
129
  rubocop-shopify (2.11.1)
99
130
  rubocop (~> 1.42)
100
- ruby-progressbar (1.11.0)
101
- thor (1.2.2)
131
+ ruby-progressbar (1.13.0)
132
+ stringio (3.1.0)
133
+ thor (1.3.0)
102
134
  tzinfo (2.0.6)
103
135
  concurrent-ruby (~> 1.0)
104
- unicode-display_width (2.4.2)
105
- zeitwerk (2.6.8)
136
+ unicode-display_width (2.5.0)
137
+ webrick (1.8.1)
138
+ zeitwerk (2.6.12)
106
139
 
107
140
  PLATFORMS
108
141
  ruby
@@ -115,4 +148,4 @@ DEPENDENCIES
115
148
  rubocop-shopify
116
149
 
117
150
  BUNDLED WITH
118
- 2.3.17
151
+ 2.5.7
data/README.md CHANGED
@@ -20,39 +20,90 @@ Or install it yourself as:
20
20
 
21
21
  $ gem install ejson-rails
22
22
 
23
+ ## Configuration
24
+
25
+ By default, the gem will look for decrypted secrets in `project/config/secrets.json` or `project/config/secrets.{current_rails_environment}.json` if that doesn't exist.
26
+
27
+ If your application or environment has a unique way of retrieving decrypted secrets, you can do so by setting `EJSON::Rails::Railtie.ejson_secret_source` to a callable object in `config/application.rb`. For example:
28
+
29
+ ```ruby
30
+ # config/application.rb
31
+
32
+ # This must be placed BEFORE your application constant which inherits from Rails::Application
33
+ EJSON::Rails::Railtie.ejson_secret_source = FooBar::SecretCredentialReader
34
+
35
+ # Custom credential reader that lives somewhere else
36
+ module FooBar
37
+ class SecretCredentialReader
38
+ class << self
39
+ def call
40
+ '{"secret": "secret_from_ejson_secret_source"}'
41
+ end
42
+ end
43
+ end
44
+ end
45
+ ```
46
+
47
+ For simple cases, you can use a `proc`:
48
+
49
+ ```ruby
50
+ EJSON::Rails::Railtie.ejson_secret_source = proc { '{"secret": "secret_from_ejson_secret_source"}' }
51
+ ```
52
+
23
53
  ## Usage
24
54
 
25
- Decrypted secrets from `project/config/secrets.json` (or `project/config/secrets.{current_rails_environment}.json` if that doesn't exist) will be accessible via `Rails.application.secrets`. For example:
55
+ Decrypted secrets and credentials will be accessible via `Rails.application.secrets`. For example:
56
+
57
+ `# project/config/secrets.json`
26
58
 
27
59
  ```json
28
- // project/config/secrets.json
29
60
  { "some_secret": "key" }
30
61
  ```
31
62
 
32
- will be accessible via `Rails.application.secrets.some_secret` or `Rails.application.secrets[:some_secret]` on boot. JSON files are loaded once and contents are `deep_merge`'d into your app's existing rails secrets.
63
+ will be accessible via `Rails.application.secrets.some_secret` or `Rails.application.secrets[:some_secret]` upon booting. JSON files are loaded once and contents are `deep_merge`'d into your app's existing rails secrets.
33
64
 
34
65
  Secrets will also be accessible via `Rails.application.credentials`, e.g. `Rails.application.credentials.some_secret` or `Rails.application.credentials[:some_secret]`. To avoid subtle compatibility issues, if a credential already exists, an error will occur.
35
66
 
67
+ If you set the `EJSON_RAILS_DELETE_SECRETS` environment variable to `true` the gem will automatically delete the secrets from the filesystem after loading them into Rails. It will delete both paths (`project/config/secrets.json` and `project/config/secrets.{current_rails_environment}.json`) if the files exist and are writable.
68
+
36
69
  NOTE: This gem does not decrypt ejson for you. You will need to configure this as part of your deployment pipeline.
37
70
 
38
71
  ## Migrating to credentials
39
72
 
40
73
  Rails 7.1 has deprecated application secrets in favor of credentials. ejson-rails can migrate secrets to application credentials.
41
74
 
42
- Even before running Rails 7.1, you can migrate your secrets in a few steps.
75
+ Even before running Rails 7.1, you can migrate your secrets in several steps:
76
+
77
+ 1. Convert secrets from YAML to JSON
78
+ 2. Move any ERB embedded within the YAML to the corresponding environment file
79
+ 3. Use `Rails.application.credentials` in place of Rails secrets
80
+
81
+ ### 1. Convert secrets from config/secrets.yml to config/secrets.json
43
82
 
44
- First, move the development and test secrets to JSON secrets:
83
+ Typically, secrets share the same structure across different environments. While test secrets are often placeholders, development secrets may sometimes use environment variables to communicate with external services.
84
+ In that case, the easiest way to migrate is to use the test secrets in all local environments, and override for development as needed:
45
85
 
46
86
  ```sh-session
47
- bin/rails runner 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
48
- bin/rails runner -e test 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
87
+ # Recommended
88
+ bin/rails runner -e test 'Rails.root.join("config/secrets.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
49
89
  ```
50
90
 
51
- Secrets support ERB while EJSON secrets don't, so if your secrets contain ERB, you will need to move that logic to the environment configurations:
91
+ > [!NOTE]
92
+ > Alternatively, if its necessary to configure distinct values between the development/test environment, you can use separate JSON files for the development/test environments:
93
+ >
94
+ > ```sh-session
95
+ > bin/rails runner 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
96
+ > bin/rails runner -e test 'Rails.root.join("config/secrets.#{Rails.env}.json").write(JSON.pretty_generate(Rails.application.secrets.to_h.without(:secret_key_base)))'
97
+ > ```
98
+
99
+ ### 2. Move any ERB into the corresponding environment files
100
+
101
+ YAML supports ERB while JSON secrets do not. If your secrets contain ERB, you will need to move that logic to the corresponding environment file:
52
102
 
53
103
  **Before**:
54
104
 
55
105
  `config/secrets.yml`
106
+
56
107
  ```yaml
57
108
  development:
58
109
  some_external_service:
@@ -61,7 +112,8 @@ development:
61
112
 
62
113
  **After**:
63
114
 
64
- `config/secrets.development.json` as generated by the command above.
115
+ `config/secrets.json` as generated by the _recommended_ command above.
116
+
65
117
  ```json
66
118
  {
67
119
  "some_external_service": {
@@ -72,19 +124,20 @@ development:
72
124
  ```
73
125
 
74
126
  `config/environments/development.rb`
127
+
75
128
  ```ruby
76
129
  Rails.application.configure do
77
130
  # elided
78
131
 
79
- # credential should be set using []=, not the dynamic accessors
80
- credentials[:some_external_service][:api_token] = ENV.fetch("SOME_EXTERNAL_SERVICE_API_TOKEN", "12345")
81
-
82
- # top-level values must be set through `credentials.config`
83
- credentials.config[:something_else_entirely] = ENV.fetch("SOMETHING_ELSE_ENTIRELY", "abc")
132
+ credentials.some_external_service.api_token = ENV.fetch("SOME_EXTERNAL_SERVICE_API_TOKEN", "12345")
133
+ credentials.something_else_entirely = ENV.fetch("SOMETHING_ELSE_ENTIRELY", "abc")
84
134
  end
85
135
  ```
86
136
 
87
- Note that the code accesses the credentials as a Hash with `[]` and `[]=`. This is important because the dynamic accessor methods will set values in a different object, and credentials will behave inconsistently after that:
137
+ #### Rails 7.0 Note
138
+
139
+ > [!NOTE]
140
+ > In Rails 7.0, credentials are accessed as a Hash with [] and []=.. This is important because the dynamic accessor methods will set values in a different object, and credentials will behave inconsistently after that:
88
141
 
89
142
  ```ruby
90
143
  Rails.application.credentials.some_external_service.api_token = "foo"
@@ -106,7 +159,9 @@ Rails.application.credentials[:some_external_service][:api_token] = "foo"
106
159
  Rails.application.credentials.some_external_service.api_token # => "12345"
107
160
  ```
108
161
 
109
- You're now ready to use credentials instead of secrets:
162
+ ### 3. Use `Rails.application.credentials`
163
+
164
+ You are now ready to replace Rails secrets with Rails credentials:
110
165
 
111
166
  ```sh-session
112
167
  git ls-files | xargs ruby -pi -e 'gsub("Rails.application.secrets", "Rails.application.credentials")' --
@@ -118,7 +173,7 @@ To avoid the deprecation warning from the use of secrets in `ejson-rails` once y
118
173
  gem 'ejson-rails', require: 'ejson/rails/skip_secrets'
119
174
  ```
120
175
 
121
- This will no longer merge secrets from JSON in `Rails.application.secrets`. This will be the default in the next major version.
176
+ With this require, ejson-rails will no longer merge secrets from JSON into `Rails.application.secrets`. This will be the default in the next major version.
122
177
 
123
178
  ## Development
124
179
 
data/ejson-rails.gemspec CHANGED
@@ -23,10 +23,10 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.metadata = { "allowed_push_host" => "https://rubygems.org" }
25
25
 
26
- spec.required_ruby_version = ">= 2.7.0"
26
+ spec.required_ruby_version = ">= 3.1.0"
27
27
 
28
28
  spec.add_dependency("ejson")
29
- spec.add_dependency("railties", ">= 5.2")
29
+ spec.add_dependency("railties", ">= 6.1")
30
30
 
31
31
  spec.add_development_dependency("rake", "~> 13.0")
32
32
  spec.add_development_dependency("rspec", "~> 3.0")
@@ -2,4 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  eval_gemfile('../Gemfile')
4
4
 
5
- gem 'railties', '5.2'
5
+ gem 'railties', '6.1'
@@ -6,25 +6,41 @@ module EJSON
6
6
  private_constant :Rails
7
7
 
8
8
  class Railtie < Rails::Railtie
9
- singleton_class.attr_accessor(:set_secrets)
9
+ singleton_class.attr_accessor(:ejson_secret_source, :set_secrets)
10
10
  @set_secrets = true
11
11
 
12
12
  config.before_configuration do
13
- json_file = json_files.detect { |file| valid?(file) }
14
- next unless json_file
13
+ secrets = load_secrets_from_config || load_secrets_from_disk
14
+ next unless secrets
15
+
16
+ secrets = JSON.parse(secrets, symbolize_names: true)
15
17
 
16
- secrets = JSON.parse(json_file.read, symbolize_names: true)
17
18
  Rails.application.secrets.deep_merge!(secrets) if set_secrets
18
19
  # Merging into `credentials.config` because in Rails 7.0, reading a credential with
19
20
  # Rails.application.credentials[:some_credential] won't work otherwise.
20
21
  Rails.application.credentials.config.deep_merge!(secrets) do |key|
21
22
  raise "A credential already exists with the same name: #{key}"
22
23
  end
24
+
25
+ # Delete the loaded JSON files so they are no longer readable by the app.
26
+ if ENV["EJSON_RAILS_DELETE_SECRETS"] == "true"
27
+ json_files.each do |pathname|
28
+ File.delete(pathname) if File.writable?(pathname)
29
+ end
30
+ end
23
31
  end
24
32
 
25
33
  class << self
26
34
  private
27
35
 
36
+ def load_secrets_from_config
37
+ ejson_secret_source&.call
38
+ end
39
+
40
+ def load_secrets_from_disk
41
+ json_files.detect { |file| valid?(file) }&.read
42
+ end
43
+
28
44
  def valid?(pathname)
29
45
  pathname.exist?
30
46
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module EJSON
4
4
  module Rails
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.2"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ejson-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gannon McGibbon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-24 00:00:00.000000000 Z
11
+ date: 2024-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ejson
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '5.2'
33
+ version: '6.1'
34
34
  type: :runtime
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: '5.2'
40
+ version: '6.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -109,14 +109,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
109
  requirements:
110
110
  - - ">="
111
111
  - !ruby/object:Gem::Version
112
- version: 2.7.0
112
+ version: 3.1.0
113
113
  required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  requirements: []
119
- rubygems_version: 3.4.16
119
+ rubygems_version: 3.5.10
120
120
  signing_key:
121
121
  specification_version: 4
122
122
  summary: Asymmetric keywise encryption for JSON on Rails