mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
chore: remove customRootRoles flag in favor of killswitch (#4431)
https://linear.app/unleash/issue/2-1303/adapt-existing-customrootroles-flag-to-a-customrootroleskillswitch Removes the existing `customRootRoles` flag in favor of a `customRootRolesKillSwitch` which should follow the same logic but negated/inverted. Once released, this will effectively make custom root roles GA, and we can use [customRootRolesKillSwitch](https://app.unleash-hosted.com/hosted/projects/eg/features/customRootRolesKillSwitch) to disable the feature if needed.
This commit is contained in:
parent
22273d79e3
commit
ded33a6d81
@ -41,7 +41,7 @@ export const RolesPage = () => {
|
|||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
const [selectedRole, setSelectedRole] = useState<IRole>();
|
const [selectedRole, setSelectedRole] = useState<IRole>();
|
||||||
|
|
||||||
const tabs = uiConfig.flags.customRootRoles
|
const tabs = !uiConfig.flags.customRootRolesKillSwitch
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
label: 'Root roles',
|
label: 'Root roles',
|
||||||
@ -65,7 +65,8 @@ export const RolesPage = () => {
|
|||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
const type =
|
const type =
|
||||||
!uiConfig.flags.customRootRoles || pathname.includes('project-roles')
|
uiConfig.flags.customRootRolesKillSwitch ||
|
||||||
|
pathname.includes('project-roles')
|
||||||
? PROJECT_ROLE_TYPE
|
? PROJECT_ROLE_TYPE
|
||||||
: ROOT_ROLE_TYPE;
|
: ROOT_ROLE_TYPE;
|
||||||
|
|
||||||
@ -157,7 +158,7 @@ export const RolesPage = () => {
|
|||||||
element={
|
element={
|
||||||
<RolesTable
|
<RolesTable
|
||||||
type={
|
type={
|
||||||
uiConfig.flags.customRootRoles
|
!uiConfig.flags.customRootRolesKillSwitch
|
||||||
? ROOT_ROLE_TYPE
|
? ROOT_ROLE_TYPE
|
||||||
: PROJECT_ROLE_TYPE
|
: PROJECT_ROLE_TYPE
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export interface IFlags {
|
|||||||
disableBulkToggle?: boolean;
|
disableBulkToggle?: boolean;
|
||||||
disableNotifications?: boolean;
|
disableNotifications?: boolean;
|
||||||
advancedPlayground?: boolean;
|
advancedPlayground?: boolean;
|
||||||
customRootRoles?: boolean;
|
customRootRolesKillSwitch?: boolean;
|
||||||
strategyVariant?: boolean;
|
strategyVariant?: boolean;
|
||||||
newProjectLayout?: boolean;
|
newProjectLayout?: boolean;
|
||||||
configurableFeatureTypeLifetimes?: boolean;
|
configurableFeatureTypeLifetimes?: boolean;
|
||||||
|
@ -70,7 +70,7 @@ exports[`should create default config 1`] = `
|
|||||||
"anonymiseEventLog": false,
|
"anonymiseEventLog": false,
|
||||||
"caseInsensitiveInOperators": false,
|
"caseInsensitiveInOperators": false,
|
||||||
"configurableFeatureTypeLifetimes": false,
|
"configurableFeatureTypeLifetimes": false,
|
||||||
"customRootRoles": false,
|
"customRootRolesKillSwitch": false,
|
||||||
"demo": false,
|
"demo": false,
|
||||||
"disableBulkToggle": false,
|
"disableBulkToggle": false,
|
||||||
"disableNotifications": false,
|
"disableNotifications": false,
|
||||||
@ -107,7 +107,7 @@ exports[`should create default config 1`] = `
|
|||||||
"anonymiseEventLog": false,
|
"anonymiseEventLog": false,
|
||||||
"caseInsensitiveInOperators": false,
|
"caseInsensitiveInOperators": false,
|
||||||
"configurableFeatureTypeLifetimes": false,
|
"configurableFeatureTypeLifetimes": false,
|
||||||
"customRootRoles": false,
|
"customRootRolesKillSwitch": false,
|
||||||
"demo": false,
|
"demo": false,
|
||||||
"disableBulkToggle": false,
|
"disableBulkToggle": false,
|
||||||
"disableNotifications": false,
|
"disableNotifications": false,
|
||||||
|
@ -14,12 +14,12 @@ import FakeEventStore from '../../test/fixtures/fake-event-store';
|
|||||||
import { IRole } from 'lib/types/stores/access-store';
|
import { IRole } from 'lib/types/stores/access-store';
|
||||||
import { IGroup } from 'lib/types';
|
import { IGroup } from 'lib/types';
|
||||||
|
|
||||||
function getSetup(customRootRoles: boolean = false) {
|
function getSetup(customRootRolesKillSwitch: boolean = true) {
|
||||||
const config = createTestConfig({
|
const config = createTestConfig({
|
||||||
getLogger,
|
getLogger,
|
||||||
experimental: {
|
experimental: {
|
||||||
flags: {
|
flags: {
|
||||||
customRootRoles: customRootRoles,
|
customRootRolesKillSwitch,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -161,7 +161,7 @@ test('should be able to validate and cleanup with additional properties', async
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('user with custom root role should get a user root role', async () => {
|
test('user with custom root role should get a user root role', async () => {
|
||||||
const { accessService } = getSetup(true);
|
const { accessService } = getSetup(false);
|
||||||
const customRootRole = await accessService.createRole({
|
const customRootRole = await accessService.createRole({
|
||||||
name: 'custom-root-role',
|
name: 'custom-root-role',
|
||||||
description: 'test custom root role',
|
description: 'test custom root role',
|
||||||
@ -185,11 +185,6 @@ test('throws error when trying to delete a project role in use by group', async
|
|||||||
};
|
};
|
||||||
const config = createTestConfig({
|
const config = createTestConfig({
|
||||||
getLogger,
|
getLogger,
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const eventStore = new FakeEventStore();
|
const eventStore = new FakeEventStore();
|
||||||
|
@ -519,7 +519,7 @@ export class AccessService {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
roleType === CUSTOM_ROOT_ROLE_TYPE &&
|
roleType === CUSTOM_ROOT_ROLE_TYPE &&
|
||||||
!this.flagResolver.isEnabled('customRootRoles')
|
this.flagResolver.isEnabled('customRootRolesKillSwitch')
|
||||||
) {
|
) {
|
||||||
throw new InvalidOperationError(
|
throw new InvalidOperationError(
|
||||||
'Custom root roles are not enabled.',
|
'Custom root roles are not enabled.',
|
||||||
@ -557,7 +557,7 @@ export class AccessService {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
roleType === CUSTOM_ROOT_ROLE_TYPE &&
|
roleType === CUSTOM_ROOT_ROLE_TYPE &&
|
||||||
!this.flagResolver.isEnabled('customRootRoles')
|
this.flagResolver.isEnabled('customRootRolesKillSwitch')
|
||||||
) {
|
) {
|
||||||
throw new InvalidOperationError(
|
throw new InvalidOperationError(
|
||||||
'Custom root roles are not enabled.',
|
'Custom root roles are not enabled.',
|
||||||
|
@ -20,7 +20,6 @@ export type IFlagKey =
|
|||||||
| 'disableBulkToggle'
|
| 'disableBulkToggle'
|
||||||
| 'disableNotifications'
|
| 'disableNotifications'
|
||||||
| 'advancedPlayground'
|
| 'advancedPlayground'
|
||||||
| 'customRootRoles'
|
|
||||||
| 'strategyVariant'
|
| 'strategyVariant'
|
||||||
| 'newProjectLayout'
|
| 'newProjectLayout'
|
||||||
| 'slackAppAddon'
|
| 'slackAppAddon'
|
||||||
@ -29,7 +28,8 @@ export type IFlagKey =
|
|||||||
| 'filterInvalidClientMetrics'
|
| 'filterInvalidClientMetrics'
|
||||||
| 'frontendNavigationUpdate'
|
| 'frontendNavigationUpdate'
|
||||||
| 'lastSeenByEnvironment'
|
| 'lastSeenByEnvironment'
|
||||||
| 'segmentChangeRequests';
|
| 'segmentChangeRequests'
|
||||||
|
| 'customRootRolesKillSwitch';
|
||||||
|
|
||||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
||||||
|
|
||||||
@ -97,10 +97,6 @@ const flags: IFlags = {
|
|||||||
process.env.DISABLE_NOTIFICATIONS,
|
process.env.DISABLE_NOTIFICATIONS,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
customRootRoles: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_CUSTOM_ROOT_ROLES,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
newProjectLayout: parseEnvVarBoolean(
|
newProjectLayout: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_NEW_PROJECT_LAYOUT,
|
process.env.UNLEASH_EXPERIMENTAL_NEW_PROJECT_LAYOUT,
|
||||||
false,
|
false,
|
||||||
@ -113,7 +109,6 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_SLACK_APP_ADDON,
|
process.env.UNLEASH_SLACK_APP_ADDON,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
|
||||||
emitPotentiallyStaleEvents: parseEnvVarBoolean(
|
emitPotentiallyStaleEvents: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_EMIT_POTENTIALLY_STALE_EVENTS,
|
process.env.UNLEASH_EXPERIMENTAL_EMIT_POTENTIALLY_STALE_EVENTS,
|
||||||
false,
|
false,
|
||||||
@ -138,6 +133,10 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_SEGMENT_CHANGE_REQUESTS,
|
process.env.UNLEASH_EXPERIMENTAL_SEGMENT_CHANGE_REQUESTS,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
customRootRolesKillSwitch: parseEnvVarBoolean(
|
||||||
|
process.env.UNLEASH_EXPERIMENTAL_CUSTOM_ROOT_ROLES_KILL_SWITCH,
|
||||||
|
false,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultExperimentalOptions: IExperimentalOptions = {
|
export const defaultExperimentalOptions: IExperimentalOptions = {
|
||||||
|
@ -206,13 +206,7 @@ test('A role with only CREATE_PROJECT_API_TOKEN can create project tokens', asyn
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const { request, destroy } = await setupAppWithCustomAuth(stores, preHook, {
|
const { request, destroy } = await setupAppWithCustomAuth(stores, preHook);
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
await request
|
await request
|
||||||
.post('/api/admin/projects/default/api-tokens')
|
.post('/api/admin/projects/default/api-tokens')
|
||||||
@ -261,13 +255,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
await request
|
await request
|
||||||
.post('/api/admin/api-tokens')
|
.post('/api/admin/api-tokens')
|
||||||
@ -312,13 +299,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
await request
|
await request
|
||||||
.post('/api/admin/api-tokens')
|
.post('/api/admin/api-tokens')
|
||||||
@ -363,13 +343,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
await request
|
await request
|
||||||
.post('/api/admin/api-tokens')
|
.post('/api/admin/api-tokens')
|
||||||
@ -417,13 +390,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
await stores.apiTokenStore.insert({
|
await stores.apiTokenStore.insert({
|
||||||
username: 'client',
|
username: 'client',
|
||||||
@ -486,13 +452,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
await stores.apiTokenStore.insert({
|
await stores.apiTokenStore.insert({
|
||||||
username: 'client',
|
username: 'client',
|
||||||
@ -650,13 +609,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const token = await stores.apiTokenStore.insert({
|
const token = await stores.apiTokenStore.insert({
|
||||||
username: 'cilent',
|
username: 'cilent',
|
||||||
@ -706,13 +658,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const token = await stores.apiTokenStore.insert({
|
const token = await stores.apiTokenStore.insert({
|
||||||
username: 'frontend',
|
username: 'frontend',
|
||||||
@ -763,13 +708,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const token = await stores.apiTokenStore.insert({
|
const token = await stores.apiTokenStore.insert({
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
@ -823,13 +761,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const token = await stores.apiTokenStore.insert({
|
const token = await stores.apiTokenStore.insert({
|
||||||
username: 'cilent',
|
username: 'cilent',
|
||||||
@ -879,13 +810,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const token = await stores.apiTokenStore.insert({
|
const token = await stores.apiTokenStore.insert({
|
||||||
username: 'frontend',
|
username: 'frontend',
|
||||||
@ -935,13 +859,6 @@ describe('Fine grained API token permissions', () => {
|
|||||||
const { request, destroy } = await setupAppWithCustomAuth(
|
const { request, destroy } = await setupAppWithCustomAuth(
|
||||||
stores,
|
stores,
|
||||||
preHook,
|
preHook,
|
||||||
{
|
|
||||||
experimental: {
|
|
||||||
flags: {
|
|
||||||
customRootRoles: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
const token = await stores.apiTokenStore.insert({
|
const token = await stores.apiTokenStore.insert({
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
|
Loading…
Reference in New Issue
Block a user