Adding the email rollout strategy to feature flag (#6541)
This PR adds the email based rollout strategy to features. We can now define a list of domain names in the init-flags.yml file and define the domains for which the feature will be active. Also added tests to assert the functionality for this flag flipping strategy.
This commit is contained in:
parent
b4762a2cae
commit
be675fbc6b
|
|
@ -20,6 +20,7 @@ public enum FeatureFlagEnum {
|
|||
// ------------------- Couldn't find a better way to do this ---------------------------------------------------- //
|
||||
TEST_FEATURE_1,
|
||||
TEST_FEATURE_2,
|
||||
TEST_FEATURE_3,
|
||||
// ------------------- End of features for testing -------------------------------------------------------------- //
|
||||
|
||||
// ------------------- These are actual feature flags meant to be used across the product ----------------------- //
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package com.appsmith.server.featureflags.strategies;
|
||||
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.domains.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.ff4j.core.FeatureStore;
|
||||
import org.ff4j.core.FlippingExecutionContext;
|
||||
import org.ff4j.strategy.AbstractFlipStrategy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class EmailBasedRolloutStrategy extends AbstractFlipStrategy {
|
||||
|
||||
List<String> validDomains = new ArrayList<>();
|
||||
|
||||
private static final String PARAM_EMAIL_DOMAINS = "emailDomains";
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void init(String featureName, Map<String, String> initParam) {
|
||||
super.init(featureName, initParam);
|
||||
assertRequiredParameter(PARAM_EMAIL_DOMAINS);
|
||||
if (!StringUtils.isEmpty(initParam.get(PARAM_EMAIL_DOMAINS))) {
|
||||
this.validDomains = Arrays.asList(initParam.get(PARAM_EMAIL_DOMAINS).split(","));
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean evaluate(String featureName, FeatureStore store, FlippingExecutionContext executionContext) {
|
||||
User user = (User) executionContext.getValue(FieldName.USER, true);
|
||||
log.debug("Checking if feature {} is active for user {}", featureName, user.getEmail());
|
||||
int atIndex = user.getEmail().indexOf("@");
|
||||
|
||||
if (atIndex > 0) {
|
||||
// If the email domain is valid, check the user's email ID against the list of validated domains
|
||||
String domain = user.getEmail().substring(atIndex + 1).toLowerCase();
|
||||
return validDomains.contains(domain);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ ff4j:
|
|||
enable: true
|
||||
description: Enable this feature based on email ID of the user
|
||||
flipstrategy:
|
||||
class: com.appsmith.server.featureflags.strategies.AppsmithUserStrategy
|
||||
class: com.appsmith.server.featureflags.strategies.EmailBasedRolloutStrategy
|
||||
param:
|
||||
- name: requiredKey
|
||||
value: requiredValue
|
||||
- name: emailDomains
|
||||
value: appsmith.com,wazirx.com,pharmeasy.in,allround.club
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.appsmith.server.featureflags.strategies;
|
||||
|
||||
import com.appsmith.server.domains.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ff4j.core.FlippingExecutionContext;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithUserDetails;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
public class EmailBasedRolloutStrategyTest {
|
||||
|
||||
EmailBasedRolloutStrategy strategy = new EmailBasedRolloutStrategy();
|
||||
|
||||
@Before
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void setup() {
|
||||
Map<String, String> initParams = new HashMap<>();
|
||||
initParams.put("emailDomains", "example.com,another-example.com");
|
||||
strategy.init("test-feature", initParams);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void testValidFeatureCheck() {
|
||||
FlippingExecutionContext executionContext = Mockito.mock(FlippingExecutionContext.class);
|
||||
|
||||
User user = new User();
|
||||
user.setEmail("test@EXAMPLE.com");
|
||||
Mockito.when(executionContext.getValue(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
|
||||
|
||||
boolean evaluate = strategy.evaluate("test-feature", null, executionContext);
|
||||
assertTrue(evaluate);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void testInvalidFeatureCheck() {
|
||||
FlippingExecutionContext executionContext = Mockito.mock(FlippingExecutionContext.class);
|
||||
|
||||
User user = new User();
|
||||
user.setEmail("test@random.com");
|
||||
Mockito.when(executionContext.getValue(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
|
||||
|
||||
boolean evaluate = strategy.evaluate("test-feature", null, executionContext);
|
||||
assertFalse(evaluate);
|
||||
}
|
||||
}
|
||||
|
|
@ -85,4 +85,18 @@ public class FeatureFlagServiceTest {
|
|||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void testFeatureCheckForEmailStrategy() {
|
||||
StepVerifier.create(featureFlagService.getAllFeatureFlagsForUser())
|
||||
.assertNext(result -> {
|
||||
assertNotNull(result);
|
||||
assertTrue("There should be a flag TEST_FEATURE_3",
|
||||
result.keySet().contains(FeatureFlagEnum.TEST_FEATURE_3.toString())
|
||||
);
|
||||
assertFalse(result.get(FeatureFlagEnum.TEST_FEATURE_3.toString()));
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,4 +25,13 @@ ff4j:
|
|||
class: org.ff4j.strategy.PonderationStrategy
|
||||
param:
|
||||
- name: weight
|
||||
value: 1
|
||||
value: 1
|
||||
|
||||
- uid: TEST_FEATURE_3
|
||||
enable: true
|
||||
description: The test feature should only be visible to certain users
|
||||
flipstrategy:
|
||||
class: com.appsmith.server.featureflags.strategies.EmailBasedRolloutStrategy
|
||||
param:
|
||||
- name: emailDomains
|
||||
value: test@example.com
|
||||
Loading…
Reference in New Issue
Block a user