-
-
Notifications
You must be signed in to change notification settings - Fork 270
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new Rails/EnvironmentVariableAccess cop
- Loading branch information
Showing
7 changed files
with
214 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Rails | ||
# This cop looks for direct access to environment variables through the | ||
# `ENV` variable within the application code. This can lead to runtime | ||
# errors due to misconfiguration that could have been discovered at boot | ||
# time if the environment variables were loaded as part of initialization | ||
# and copied into the application's configuration or secrets. The cop can | ||
# be configured to allow either reads or writes if required. | ||
# | ||
# @example | ||
# # bad | ||
# ENV["FOO"] | ||
# ENV.fetch("FOO") | ||
# ENV["FOO"] = "bar" | ||
# | ||
# # good | ||
# Rails.application.config.foo | ||
# Rails.application.config.foo = "bar" | ||
# Rails.application.config.x.foo.bar | ||
# Rails.application.secrets.foo | ||
class EnvironmentVariableAccess < Base | ||
READ_MSG = 'Do not read from `ENV` directly post initialization.' | ||
WRITE_MSG = 'Do not write to `ENV` directly post initialization.' | ||
|
||
def on_const(node) | ||
add_offense(node, message: READ_MSG) if env_read?(node) && !allow_reads? | ||
add_offense(node, message: WRITE_MSG) if env_write?(node) && !allow_writes? | ||
end | ||
|
||
def_node_search :env_read?, <<~PATTERN | ||
^(send (const {cbase nil?} :ENV) !:[]= ...) | ||
PATTERN | ||
|
||
def_node_search :env_write?, <<~PATTERN | ||
{^(indexasgn (const {cbase nil?} :ENV) ...) | ||
^(send (const {cbase nil?} :ENV) :[]= ...)} | ||
PATTERN | ||
|
||
private | ||
|
||
def allow_reads? | ||
cop_config['AllowReads'] == true | ||
end | ||
|
||
def allow_writes? | ||
cop_config['AllowWrites'] == true | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
spec/rubocop/cop/rails/environment_variable_access_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Rails::EnvironmentVariableAccess, :config do | ||
context 'when not allowing reads' do | ||
it 'registers an offense when indexing into `ENV`' do | ||
expect_offense(<<~RUBY) | ||
ENV["foo"] | ||
^^^ Do not read from `ENV` directly post initialization. | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when calling methods on `ENV`' do | ||
expect_offense(<<~RUBY) | ||
ENV.fetch("FOO") | ||
^^^ Do not read from `ENV` directly post initialization. | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when calling methods on dereferenced `ENV`' do | ||
expect_offense(<<~RUBY) | ||
::ENV.fetch("FOO") | ||
^^^^^ Do not read from `ENV` directly post initialization. | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense on namespaced `ENV` access' do | ||
expect_no_offenses(<<~RUBY) | ||
Foo::ENV.fetch("BAR") | ||
RUBY | ||
end | ||
end | ||
|
||
context 'when allowing reads' do | ||
let(:cop_config) do | ||
{ 'AllowReads' => true } | ||
end | ||
|
||
it 'does not register an offense when indexing into `ENV`' do | ||
expect_no_offenses(<<~RUBY) | ||
ENV["foo"] | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when calling methods on `ENV`' do | ||
expect_no_offenses(<<~RUBY) | ||
ENV.fetch("FOO") | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when calling methods on dereferenced `ENV`' do | ||
expect_no_offenses(<<~RUBY) | ||
::ENV.fetch("FOO") | ||
RUBY | ||
end | ||
end | ||
|
||
context 'when not allowing writes' do | ||
it 'registers an offense when writing to an `ENV` key' do | ||
expect_offense(<<~RUBY) | ||
ENV["foo"] = "bar" | ||
^^^ Do not write to `ENV` directly post initialization. | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when writing to a dereferenced `ENV` key' do | ||
expect_offense(<<~RUBY) | ||
::ENV["foo"] = "bar" | ||
^^^^^ Do not write to `ENV` directly post initialization. | ||
RUBY | ||
end | ||
end | ||
|
||
context 'when allowing writes' do | ||
let(:cop_config) do | ||
{ 'AllowWrites' => true } | ||
end | ||
|
||
it 'does not register an offense when writing to an `ENV` key' do | ||
expect_no_offenses(<<~RUBY) | ||
ENV["foo"] = "bar" | ||
RUBY | ||
end | ||
end | ||
end |