summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2018-09-11 16:40:42 -0500
committerRobert Speicher <rspeicher@gmail.com>2018-09-13 11:52:54 -0500
commit6b46db0d8a53691f1c680d435c8e9572e1e16041 (patch)
tree7e27718f45e4157cf38ae1ffd010b0da7ca8783a
parent733cae702222771a734db5b3b5ab8fe3e2eb7538 (diff)
downloadgitlab-ce-6b46db0d8a53691f1c680d435c8e9572e1e16041.tar.gz
Add `Feature.enabled_and_licensed?` helper method
When no license is available (such as in CE), this is equivalent to calling `enabled?`. When a license is available but the specified feature isn't license-gated, this is also equivalent to calling `enabled?`. When a license is available and the specified feature is license-gated, this method will check both that the feature is enabled, and that it's available to the license.
-rw-r--r--lib/feature.rb26
-rw-r--r--spec/lib/feature_spec.rb50
2 files changed, 76 insertions, 0 deletions
diff --git a/lib/feature.rb b/lib/feature.rb
index f4b57376313..db05fd01f0f 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -54,6 +54,32 @@ class Feature
!default_enabled || Feature.persisted?(feature) ? feature.enabled?(thing) : true
end
+ # Check if a feature is both enabled and licensed
+ #
+ # When no license is available (such as in CE), this is equivalent to
+ # calling `enabled?`.
+ #
+ # When a license is available but the specified feature isn't license-gated,
+ # this is also equivalent to calling `enabled?`.
+ #
+ # When a license is available and the specified feature is license-gated,
+ # this method will check both that the feature is enabled, and that it's
+ # available to the license.
+ def enabled_and_licensed?(key, thing = nil, default_enabled: false)
+ return false unless enabled?(key, thing, default_enabled: default_enabled)
+ return true unless defined?(License)
+
+ license = License.current
+
+ if license.features.include?(key)
+ license.feature_available?(key)
+ else
+ # Not all feature flags are gated by License. If the license doesn't
+ # define this key as a feature, we'll consider it good.
+ true
+ end
+ end
+
def disabled?(key, thing = nil, default_enabled: false)
# we need to make different method calls to make it easy to mock / define expectations in test mode
thing.nil? ? !enabled?(key, default_enabled: default_enabled) : !enabled?(key, thing, default_enabled: default_enabled)
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 48c0ba8a653..6c29c1b1e2c 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -159,6 +159,56 @@ describe Feature do
end
end
+ describe '.enabled_and_licensed?' do
+ it 'passes all arguments to `enabled?`' do
+ expect(described_class).to receive(:enabled?)
+ .with(:foo, 'thing', default_enabled: true)
+ .and_return(false)
+
+ expect(described_class.enabled_and_licensed?(:foo, 'thing', default_enabled: true))
+ .to eq false
+ end
+
+ context 'with an enabled feature' do
+ before do
+ allow(described_class).to receive(:enabled?).and_return(true)
+ end
+
+ # Behavior changes slightly when we're in EE and License is available
+ if defined?(License)
+ context 'with an unregistered license feature' do
+ it 'returns true' do
+ expect(described_class.enabled_and_licensed?(:not_a_real_feature))
+ .to eq true
+ end
+ end
+
+ context 'with a registered license feature' do
+ it 'delegates to `License.feature_available?`' do
+ license = License.current
+
+ expect(license.features).to receive(:include?)
+ .with(:a_very_real_feature)
+ .and_return(true)
+ expect(license).to receive(:feature_available?)
+ .with(:a_very_real_feature)
+ .and_return(true)
+ expect(License).to receive(:current).and_return(license)
+
+ expect(described_class.enabled_and_licensed?(:a_very_real_feature))
+ .to eq true
+ end
+ end
+ else
+ context 'with no License definition' do
+ it 'returns true' do
+ expect(described_class.enabled_and_licensed?(:foo)).to eq true
+ end
+ end
+ end
+ end
+ end
+
describe '.disable?' do
it 'returns true for undefined feature' do
expect(described_class.disabled?(:some_random_feature_flag)).to be_truthy