Skip to content

Commit

Permalink
Merge pull request #21 from friendsofcat/team-based-flags
Browse files Browse the repository at this point in the history
Team based flags
  • Loading branch information
therobfonz authored Mar 21, 2022
2 parents 6e941ef + 2e52d57 commit 0941861
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ vendor
tests/logs
build
composer.lock
.phpunit.result.cache
2 changes: 1 addition & 1 deletion .phpunit.result.cache
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":1,"defects":{"Tests\\ExportImportRepositoryTest::testShouldExportFeatureFlags":4,"Tests\\ExportImportRepositoryTest::testShouldImportResults":4,"Tests\\ExportImportRepositoryTest::testShouldNotDuplicateResults":4,"Tests\\ExportImportRepositoryTest::testUpdatesExistingResult":4,"Tests\\FeatureFlagHelperTest::testCacheSettings":4,"Tests\\FeatureFlagHelperTest::testFormatRemoveQuotes":4,"Tests\\FeatureFlagSettingControllerTest::testShouldSeeNewSettings":4,"Tests\\FeatureFlagSettingControllerTest::testShouldGetSettings":4,"Tests\\FeatureFlagSettingControllerTest::testShouldImportSettings":3,"Tests\\FeatureFlagSettingControllerTest::testShouldImportSettingsFail":4,"Tests\\FeatureFlagSettingControllerTest::testStripQuotes":4,"Tests\\FeatureFlagSettingControllerTest::testStripSingleQuotes":4,"Tests\\FeatureFlagSettingControllerTest::testShouldStore":4,"Tests\\FeatureFlagSettingControllerTest::testShouldStoreFail":4,"Tests\\FeatureFlagSettingControllerTest::testShouldEdit":4,"Tests\\FeatureFlagSettingControllerTest::testShouldEditFail":4,"Tests\\FeatureFlagSettingControllerTest::testShouldUpdate":4,"Tests\\FeatureFlagSettingControllerTest::testShouldUpdateFail":4,"Tests\\FeatureFlagSettingControllerTest::testShouldDestroy":4,"Tests\\FeatureFlagSettingControllerTest::testShouldDestroyFail":4,"Tests\\FeatureFlagTest::testOn":4,"Tests\\FeatureFlagTest::testOff":4,"Tests\\FeatureFlagTest::testOnForUserEmail":4,"Tests\\FeatureFlagTest::testOffForUserEmail":4,"Tests\\FeatureFlagTest::testForNotFindFeature":4,"Tests\\FeatureFlagTest::testOnForUserRole":4,"Tests\\FeatureFlagTest::testOffForUserRole":4,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #0":4,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #1":4,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #2":4,"Tests\\FeatureFlagsForJavascriptTest::testGetNoResults":4,"Tests\\FeatureFlagsForJavascriptTest::testGetWithResults":4,"Tests\\FeatureTest::testExists":4,"Tests\\FeatureTest::testIsEnabledPassingKey":4,"Tests\\FeatureTest::testIsEnabledPassingKeyAndUser":4,"Tests\\FeatureTest::testIsEnabledPassingVariant":4,"Tests\\FeatureTest::testGetConfigFromCache":4,"Tests\\SettingsPageTest::testShouldSeeSettings":1,"Tests\\SettingsPageTest::testCanEditSettings":1,"Tests\\SettingsPageTest::testCanCreateSettings":1,"Tests\\SyncFlagsCommandTest::testShouldSyncFeatureFlags":4,"Tests\\SyncFlagsCommandTest::testShouldSyncNotOverwriteFeatureFlags":4,"Tests\\SyncFlagsCommandTest::testShouldSyncFeatureFlagsSkippingCleanup":4},"times":{"Tests\\ExportImportRepositoryTest::testShouldExportFeatureFlags":0.177,"Tests\\ExportImportRepositoryTest::testShouldImportResults":0.02,"Tests\\ExportImportRepositoryTest::testShouldNotDuplicateResults":0.019,"Tests\\ExportImportRepositoryTest::testUpdatesExistingResult":0.016,"Tests\\FeatureFlagHelperTest::testCacheSettings":0.021,"Tests\\FeatureFlagHelperTest::testFormatRemoveQuotes":0.015,"Tests\\FeatureFlagSettingControllerTest::testShouldSeeNewSettings":0.018,"Tests\\FeatureFlagSettingControllerTest::testShouldGetSettings":0.016,"Tests\\FeatureFlagSettingControllerTest::testShouldImportSettings":0.018,"Tests\\FeatureFlagSettingControllerTest::testShouldImportSettingsFail":0.021,"Tests\\FeatureFlagSettingControllerTest::testStripQuotes":0.014,"Tests\\FeatureFlagSettingControllerTest::testStripSingleQuotes":0.014,"Tests\\FeatureFlagSettingControllerTest::testShouldStore":0.022,"Tests\\FeatureFlagSettingControllerTest::testShouldStoreFail":0.02,"Tests\\FeatureFlagSettingControllerTest::testShouldEdit":0.021,"Tests\\FeatureFlagSettingControllerTest::testShouldEditFail":0.021,"Tests\\FeatureFlagSettingControllerTest::testShouldUpdate":0.02,"Tests\\FeatureFlagSettingControllerTest::testShouldUpdateFail":0.017,"Tests\\FeatureFlagSettingControllerTest::testShouldDestroy":0.02,"Tests\\FeatureFlagSettingControllerTest::testShouldDestroyFail":0.018,"Tests\\FeatureFlagTest::testOn":0.075,"Tests\\FeatureFlagTest::testOff":0.068,"Tests\\FeatureFlagTest::testOnForUserEmail":0.071,"Tests\\FeatureFlagTest::testOffForUserEmail":0.064,"Tests\\FeatureFlagTest::testForNotFindFeature":0.065,"Tests\\FeatureFlagTest::testOnForUserRole":0.066,"Tests\\FeatureFlagTest::testOffForUserRole":0.065,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #0":0.067,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #1":0.066,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #2":0.068,"Tests\\FeatureFlagsForJavascriptTest::testGetNoResults":0.015,"Tests\\FeatureFlagsForJavascriptTest::testGetWithResults":0.016,"Tests\\FeatureTest::testExists":0.068,"Tests\\FeatureTest::testIsEnabledPassingKey":0.065,"Tests\\FeatureTest::testIsEnabledPassingKeyAndUser":0.065,"Tests\\FeatureTest::testIsEnabledPassingVariant":0.065,"Tests\\FeatureTest::testGetConfigFromCache":0.015,"Tests\\SettingsPageTest::testShouldSeeSettings":0.001,"Tests\\SettingsPageTest::testCanEditSettings":0,"Tests\\SettingsPageTest::testCanCreateSettings":0,"Tests\\SyncFlagsCommandTest::testShouldSyncFeatureFlags":0.02,"Tests\\SyncFlagsCommandTest::testShouldSyncNotOverwriteFeatureFlags":0.018,"Tests\\SyncFlagsCommandTest::testShouldSyncFeatureFlagsSkippingCleanup":0.018}}
{"version":1,"defects":{"Tests\\SettingsPageTest::testShouldSeeSettings":4,"Tests\\SettingsPageTest::testCanEditSettings":4,"Tests\\SettingsPageTest::testCanCreateSettings":4},"times":{"Tests\\ExportImportRepositoryTest::testShouldExportFeatureFlags":0.15,"Tests\\ExportImportRepositoryTest::testShouldImportResults":0.015,"Tests\\ExportImportRepositoryTest::testShouldNotDuplicateResults":0.014,"Tests\\ExportImportRepositoryTest::testUpdatesExistingResult":0.016,"Tests\\FeatureFlagHelperTest::testCacheSettings":0.024,"Tests\\FeatureFlagHelperTest::testFormatRemoveQuotes":0.019,"Tests\\FeatureFlagSettingControllerTest::testShouldSeeNewSettings":0.02,"Tests\\FeatureFlagSettingControllerTest::testShouldGetSettings":0.018,"Tests\\FeatureFlagSettingControllerTest::testShouldImportSettings":0.023,"Tests\\FeatureFlagSettingControllerTest::testShouldImportSettingsFail":0.019,"Tests\\FeatureFlagSettingControllerTest::testStripQuotes":0.016,"Tests\\FeatureFlagSettingControllerTest::testStripSingleQuotes":0.015,"Tests\\FeatureFlagSettingControllerTest::testShouldStore":0.015,"Tests\\FeatureFlagSettingControllerTest::testShouldStoreFail":0.016,"Tests\\FeatureFlagSettingControllerTest::testShouldEdit":0.016,"Tests\\FeatureFlagSettingControllerTest::testShouldEditFail":0.015,"Tests\\FeatureFlagSettingControllerTest::testShouldUpdate":0.016,"Tests\\FeatureFlagSettingControllerTest::testShouldUpdateFail":0.015,"Tests\\FeatureFlagSettingControllerTest::testShouldDestroy":0.017,"Tests\\FeatureFlagSettingControllerTest::testShouldDestroyFail":0.016,"Tests\\FeatureFlagTest::testOn":0.088,"Tests\\FeatureFlagTest::testOff":0.073,"Tests\\FeatureFlagTest::testOnForUserEmail":0.08,"Tests\\FeatureFlagTest::testOffForUserEmail":0.071,"Tests\\FeatureFlagTest::testForNotFindFeature":0.067,"Tests\\FeatureFlagTest::testOnForUserRole":0.077,"Tests\\FeatureFlagTest::testOffForUserRole":0.076,"Tests\\FeatureFlagTest::testOnForUserTeam":0.064,"Tests\\FeatureFlagTest::testOffForUserTeam":0.07,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #0":0.068,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #1":0.071,"Tests\\FeatureFlagsEnablerTest::testItWorksWhenInterfaceImplented with data set #2":0.065,"Tests\\FeatureFlagsForJavascriptTest::testGetNoResults":0.013,"Tests\\FeatureFlagsForJavascriptTest::testGetWithResults":0.012,"Tests\\FeatureTest::testExists":0.064,"Tests\\FeatureTest::testIsEnabledPassingKey":0.084,"Tests\\FeatureTest::testIsEnabledPassingKeyAndUser":0.07,"Tests\\FeatureTest::testIsEnabledPassingVariant":0.065,"Tests\\FeatureTest::testGetConfigFromCache":0.013,"Tests\\SettingsPageTest::testShouldSeeSettings":0.12,"Tests\\SettingsPageTest::testCanEditSettings":0.014,"Tests\\SettingsPageTest::testCanCreateSettings":0.014,"Tests\\SyncFlagsCommandTest::testShouldSyncFeatureFlags":0.024,"Tests\\SyncFlagsCommandTest::testShouldSyncNotOverwriteFeatureFlags":0.017,"Tests\\SyncFlagsCommandTest::testShouldSyncFeatureFlagsSkippingCleanup":0.017}}
21 changes: 21 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,27 @@ class User extends Authenticatable implements FeatureFlagsUserRoles
}
~~~

### Enable for User Teams
You can enable a feature flag for specific user teams, by using the **teams** variant in the configuration form

i.e.

~~~
{ "teams": ["Team 1", "Team 2"]}
~~~

If you don't have a teams property in your User model, you just need to implement the **FeatureFlagsEnabler** Interface and use **FeatureFlagUserRoleTrait**

~~~
use FriendsOfCat\LaravelFeatureFlags\FeatureFlagsEnabler;
use FriendsOfCat\LaravelFeatureFlags\FeatureFlagUserRoleTrait;
class User extends Authenticatable implements FeatureFlagsUserRoles
{
use AuthenticableTrait, FeatureFlagUserRoleTrait;
}
~~~

## Usage Non Auth

Sometimes you are not using this at the Auth user level, it is rare for most of our use cases but for non authenticated situations you can just use this
Expand Down
37 changes: 36 additions & 1 deletion src/Feature.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ public function isEnabled($featureKey, $variant = null, $user = null)
}

if ($variant != self::ON and $variant != self::OFF) {
return $this->isUserEnabled($variant, $user) || $this->isRoleEnabled($variant, $user);
return $this->isUserEnabled($variant, $user)
|| $this->isRoleEnabled($variant, $user)
|| $this->isTeamEnabled($variant, $user);
}

return $variant == self::ON;
Expand Down Expand Up @@ -119,6 +121,11 @@ private function getUserRoles($user)
return ($user && $user->roles) ? $user->roles : false;
}

private function getUserTeams($user)
{
return ($user && $user->teams) ? $user->teams : false;
}

public function isRoleEnabled($feature_variant, $user = null)
{
$fieldName = 'roles';
Expand All @@ -145,4 +152,32 @@ function ($value, $key) use ($feature_variant, $fieldName) {

return false;
}

public function isTeamEnabled($feature_variant, $user = null)
{
$fieldName = 'teams';

if (empty($feature_variant[$fieldName])) {
return false;
}

$user = $user ?? Auth::user();

if ($user_teams=
($user instanceof FeatureFlagsEnabler)
? $user->getFieldValueForFeatureFlags($fieldName)
: $this->getUserTeams($user)
) {
$filtered = Arr::where(
$user_teams,
function ($value, $key) use ($feature_variant, $fieldName) {
return in_array($value, $feature_variant[$fieldName]);
}
);

return ! empty($filtered);
}

return false;
}
}
10 changes: 4 additions & 6 deletions src/FeatureFlagHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,10 @@ private function transformFeatures($features, $value, $key)
{
$features[$value['key']] = $this->getAndSetValue($value);

if (isset($value['variants']['users'])) {
$features[$value['key']]['users'] = $value['variants']['users'];
}

if (isset($value['variants']['roles'])) {
$features[$value['key']]['roles'] = $value['variants']['roles'];
foreach (['users', 'roles', 'teams'] as $variant) {
if (isset($value['variants'][$variant])) {
$features[$value['key']][$variant] = $value['variants'][$variant];
}
}

return $features;
Expand Down
50 changes: 49 additions & 1 deletion tests/FeatureFlagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

class FeatureFlagTest extends TestCase
{
use RefreshDatabase, FeatureFlagHelper;
use RefreshDatabase;
use FeatureFlagHelper;

protected $user;

Expand Down Expand Up @@ -156,4 +157,51 @@ public function testOffForUserRole()

$this->assertFalse($this->app->get(Gate::class)->allows('feature-flag', 'testing'));
}

public function testOnForUserTeam()
{
$this->user = factory(FeatureFlagUser::class)->create(['email' => 'foo5@gmail.com']);
$this->user->setRawAttributes(['teams' => ['Team 1']]);

$this->be($this->user);

factory(FeatureFlag::class)->create(
[
'key' => 'testing',
'variants' => [
'teams' => [
'Team 1',
'Team 2'
]
]
]
);

$this->registerFeatureFlags();

$this->assertTrue($this->app->get(Gate::class)->allows('feature-flag', 'testing'));
}

public function testOffForUserTeam()
{
$this->user = factory(FeatureFlagUser::class)->create(['email' => 'foo5@gmail.com']);
$this->user->setRawAttributes(['teams' => ['Team 1']]);

$this->be($this->user);

factory(FeatureFlag::class)->create(
[
'key' => 'testing',
'variants' => [
'teams' => [
'Team 3'
]
]
]
);

$this->registerFeatureFlags();

$this->assertFalse($this->app->get(Gate::class)->allows('feature-flag', 'testing'));
}
}
5 changes: 3 additions & 2 deletions tests/fixtures/UserWithFeatureFlagsEnablerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

class UserWithFeatureFlagsEnablerInterface extends Model implements Authenticatable, FeatureFlagsEnabler
{
use AuthenticableTrait, FeatureFlagUserRoleTrait;
use AuthenticableTrait;
use FeatureFlagUserRoleTrait;

protected $table = 'users';
protected $fillable = ['name', 'email', 'password', 'roles'];
protected $fillable = ['name', 'email', 'password', 'roles', 'teams'];

public function __construct(array $attributes = [ ])
{
Expand Down

0 comments on commit 0941861

Please sign in to comment.