mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
chore!: removing userId strategy for new installations of Unleash (#9800)
This removes a strategy that was already deprecated, but only for new installations. I tested starting with an installation with this strategy being used and then updating, and I was still able to edit the strategy, so this should not impact current users. On a fresh install the strategy is no longer available. --------- Co-authored-by: Nuno Góis <github@nunogois.com>
This commit is contained in:
parent
8050f25add
commit
5019f4fcbc
4
frontend/cypress/global.d.ts
vendored
4
frontend/cypress/global.d.ts
vendored
@ -54,10 +54,6 @@ declare namespace Cypress {
|
||||
deleteSegment_UI(segmentName: string, id: string): Chainable;
|
||||
|
||||
// STRATEGY
|
||||
addUserIdStrategyToFeature_UI(
|
||||
featureName: string,
|
||||
projectName: string,
|
||||
): Chainable;
|
||||
addFlexibleRolloutStrategyToFeature_UI(
|
||||
options: AddFlexibleRolloutStrategyOptions,
|
||||
): Chainable;
|
||||
|
@ -257,57 +257,6 @@ export const deleteFeatureStrategy_UI = (
|
||||
return cy.wait('@deleteUserStrategy');
|
||||
};
|
||||
|
||||
export const addUserIdStrategyToFeature_UI = (
|
||||
featureToggleName: string,
|
||||
projectName: string,
|
||||
): Chainable<any> => {
|
||||
const project = projectName || 'default';
|
||||
cy.visit(
|
||||
`/projects/${project}/features/${featureToggleName}/strategies/create?environmentId=development&strategyName=userWithId`,
|
||||
);
|
||||
|
||||
if (ENTERPRISE) {
|
||||
cy.get('[data-testid=ADD_CONSTRAINT_ID]').click();
|
||||
cy.get('[data-testid=CONSTRAINT_AUTOCOMPLETE_ID]')
|
||||
.type('{downArrow}'.repeat(1))
|
||||
.type('{enter}');
|
||||
cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click();
|
||||
}
|
||||
|
||||
cy.get('[data-testid=STRATEGY_INPUT_LIST]')
|
||||
.type('user1')
|
||||
.type('{enter}')
|
||||
.type('user2')
|
||||
.type('{enter}');
|
||||
cy.get('[data-testid=ADD_TO_STRATEGY_INPUT_LIST]').click();
|
||||
|
||||
cy.intercept(
|
||||
'POST',
|
||||
`/api/admin/projects/default/features/${featureToggleName}/environments/*/strategies`,
|
||||
(req) => {
|
||||
expect(req.body.name).to.equal('userWithId');
|
||||
|
||||
expect(req.body.parameters.userIds.length).to.equal(11);
|
||||
|
||||
if (ENTERPRISE) {
|
||||
expect(req.body.constraints.length).to.equal(1);
|
||||
} else {
|
||||
expect(req.body.constraints.length).to.equal(0);
|
||||
}
|
||||
|
||||
req.continue((res) => {
|
||||
strategyId = res.body.id;
|
||||
});
|
||||
},
|
||||
).as('addStrategyToFeature');
|
||||
|
||||
// this one needs to wait until the dropdown selector of stickiness is set, that's why waitForAnimations: true
|
||||
cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`)
|
||||
.first()
|
||||
.click({ waitForAnimations: true });
|
||||
return cy.wait('@addStrategyToFeature');
|
||||
};
|
||||
|
||||
export const logout_UI = (): Chainable<any> => {
|
||||
return cy.visit('/logout');
|
||||
};
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
deleteSegment_UI,
|
||||
deleteFeatureStrategy_UI,
|
||||
addFlexibleRolloutStrategyToFeature_UI,
|
||||
addUserIdStrategyToFeature_UI,
|
||||
updateFlexibleRolloutStrategy_UI,
|
||||
do_login,
|
||||
} from './UI.ts';
|
||||
@ -45,10 +44,6 @@ Cypress.Commands.add('updateUserPassword_API', updateUserPassword_API);
|
||||
Cypress.Commands.add('createFeature_UI', createFeature_UI);
|
||||
Cypress.Commands.add('deleteFeatureStrategy_UI', deleteFeatureStrategy_UI);
|
||||
Cypress.Commands.add('createFeature_API', createFeature_API);
|
||||
Cypress.Commands.add(
|
||||
'addUserIdStrategyToFeature_UI',
|
||||
addUserIdStrategyToFeature_UI,
|
||||
);
|
||||
Cypress.Commands.add(
|
||||
'addFlexibleRolloutStrategyToFeature_UI',
|
||||
addFlexibleRolloutStrategyToFeature_UI,
|
||||
|
@ -98,17 +98,20 @@ const setupOtherRoutes = (feature: string) => {
|
||||
deprecated: false,
|
||||
},
|
||||
{
|
||||
displayName: 'UserIDs',
|
||||
name: 'userWithId',
|
||||
displayName: 'Gradual rollout',
|
||||
name: 'flexibleRollout',
|
||||
editable: false,
|
||||
description:
|
||||
'Enable the feature for a specific set of userIds.',
|
||||
'The gradual rollout strategy allows you to gradually roll out a feature to a percentage of users.',
|
||||
parameters: [
|
||||
{
|
||||
name: 'userIds',
|
||||
type: 'list',
|
||||
description: '',
|
||||
required: false,
|
||||
name: 'rollout',
|
||||
},
|
||||
{
|
||||
name: 'stickiness',
|
||||
},
|
||||
{
|
||||
name: 'groupId',
|
||||
},
|
||||
],
|
||||
deprecated: false,
|
||||
@ -214,12 +217,10 @@ const UnleashUiSetup: FC<{
|
||||
</SWRConfig>
|
||||
);
|
||||
|
||||
const strategiesAreDisplayed = async (
|
||||
firstStrategy: string,
|
||||
secondStrategy: string,
|
||||
) => {
|
||||
await screen.findByText(firstStrategy);
|
||||
await screen.findByText(secondStrategy);
|
||||
const strategiesAreDisplayed = async (strategies: string[]) => {
|
||||
for (const strategy of strategies) {
|
||||
await screen.findByText(strategy);
|
||||
}
|
||||
};
|
||||
|
||||
const getDeleteButtons = async () => {
|
||||
@ -299,7 +300,7 @@ test('open mode + non-project member can perform basic change request actions',
|
||||
const featureName = 'test';
|
||||
featureEnvironments(featureName, [
|
||||
{ name: 'development', strategies: [] },
|
||||
{ name: 'production', strategies: ['userWithId'] },
|
||||
{ name: 'production', strategies: ['flexibleRollout'] },
|
||||
{ name: 'custom', strategies: ['default'] },
|
||||
]);
|
||||
userIsMemberOfProjects([]);
|
||||
@ -318,7 +319,7 @@ test('open mode + non-project member can perform basic change request actions',
|
||||
);
|
||||
await openEnvironments(['development', 'production', 'custom']);
|
||||
|
||||
await strategiesAreDisplayed('UserIDs', 'Standard');
|
||||
await strategiesAreDisplayed(['Gradual rollout', 'Standard']);
|
||||
await deleteButtonsActiveInChangeRequestEnv();
|
||||
await copyButtonsActiveInOtherEnv();
|
||||
});
|
||||
@ -328,7 +329,7 @@ test('protected mode + project member can perform basic change request actions',
|
||||
const featureName = 'test';
|
||||
featureEnvironments(featureName, [
|
||||
{ name: 'development', strategies: [] },
|
||||
{ name: 'production', strategies: ['userWithId'] },
|
||||
{ name: 'production', strategies: ['flexibleRollout'] },
|
||||
{ name: 'custom', strategies: ['default'] },
|
||||
]);
|
||||
userIsMemberOfProjects([project]);
|
||||
@ -348,7 +349,7 @@ test('protected mode + project member can perform basic change request actions',
|
||||
|
||||
await openEnvironments(['development', 'production', 'custom']);
|
||||
|
||||
await strategiesAreDisplayed('UserIDs', 'Standard');
|
||||
await strategiesAreDisplayed(['Gradual rollout', 'Standard']);
|
||||
await deleteButtonsActiveInChangeRequestEnv();
|
||||
await copyButtonsActiveInOtherEnv();
|
||||
});
|
||||
@ -358,7 +359,7 @@ test.skip('protected mode + non-project member cannot perform basic change reque
|
||||
const featureName = 'test';
|
||||
featureEnvironments(featureName, [
|
||||
{ name: 'development', strategies: [] },
|
||||
{ name: 'production', strategies: ['userWithId'] },
|
||||
{ name: 'production', strategies: ['flexibleRollout'] },
|
||||
{ name: 'custom', strategies: ['default'] },
|
||||
]);
|
||||
userIsMemberOfProjects([]);
|
||||
@ -378,7 +379,7 @@ test.skip('protected mode + non-project member cannot perform basic change reque
|
||||
|
||||
await openEnvironments(['development', 'production', 'custom']);
|
||||
|
||||
await strategiesAreDisplayed('UserIDs', 'Standard');
|
||||
await strategiesAreDisplayed(['Gradual rollout', 'Standard']);
|
||||
await deleteButtonsInactiveInChangeRequestEnv();
|
||||
await copyButtonsActiveInOtherEnv();
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { IFeatureStrategy, IStrategy } from 'interfaces/strategy';
|
||||
import DefaultStrategy from 'component/feature/StrategyTypes/DefaultStrategy/DefaultStrategy';
|
||||
import FlexibleStrategy from 'component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy';
|
||||
import UserWithIdStrategy from 'component/feature/StrategyTypes/UserWithIdStrategy/UserWithId';
|
||||
import GeneralStrategy from 'component/feature/StrategyTypes/GeneralStrategy/GeneralStrategy';
|
||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||
import produce from 'immer';
|
||||
@ -52,15 +51,6 @@ export const FeatureStrategyType = ({
|
||||
errors={errors}
|
||||
/>
|
||||
);
|
||||
case 'userWithId':
|
||||
return (
|
||||
<UserWithIdStrategy
|
||||
parameters={strategy.parameters ?? {}}
|
||||
updateParameter={updateParameter}
|
||||
editable={hasAccess}
|
||||
errors={errors}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<GeneralStrategy
|
||||
|
@ -1,32 +0,0 @@
|
||||
import type { IFeatureStrategyParameters } from 'interfaces/strategy';
|
||||
import StrategyInputList from '../StrategyInputList/StrategyInputList.tsx';
|
||||
import { parseParameterStrings } from 'utils/parseParameter';
|
||||
import type { IFormErrors } from 'hooks/useFormErrors';
|
||||
|
||||
interface IUserWithIdStrategyProps {
|
||||
parameters: IFeatureStrategyParameters;
|
||||
updateParameter: (field: string, value: string) => void;
|
||||
editable: boolean;
|
||||
errors: IFormErrors;
|
||||
}
|
||||
|
||||
const UserWithIdStrategy = ({
|
||||
editable,
|
||||
parameters,
|
||||
updateParameter,
|
||||
errors,
|
||||
}: IUserWithIdStrategyProps) => {
|
||||
return (
|
||||
<div>
|
||||
<StrategyInputList
|
||||
name='userIds'
|
||||
list={parseParameterStrings(parameters.userIds)}
|
||||
disabled={!editable}
|
||||
setConfig={updateParameter}
|
||||
errors={errors}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserWithIdStrategy;
|
@ -3,7 +3,6 @@ import type { IReleasePlanMilestoneStrategy } from 'interfaces/releasePlans';
|
||||
import type { IStrategy } from 'interfaces/strategy';
|
||||
import { MilestoneStrategyTypeFlexible } from './MilestoneStrategyTypeFlexible.tsx';
|
||||
import GeneralStrategy from 'component/feature/StrategyTypes/GeneralStrategy/GeneralStrategy';
|
||||
import UserWithIdStrategy from 'component/feature/StrategyTypes/UserWithIdStrategy/UserWithId';
|
||||
import DefaultStrategy from 'component/feature/StrategyTypes/DefaultStrategy/DefaultStrategy';
|
||||
|
||||
interface IMilestoneStrategyTypeProps {
|
||||
@ -36,15 +35,6 @@ export const MilestoneStrategyType = ({
|
||||
editable={true}
|
||||
/>
|
||||
);
|
||||
case 'userWithId':
|
||||
return (
|
||||
<UserWithIdStrategy
|
||||
editable={true}
|
||||
parameters={strategy.parameters ?? {}}
|
||||
updateParameter={updateParameter}
|
||||
errors={errors}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<GeneralStrategy
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { FC, SVGProps } from 'react';
|
||||
import { SvgIcon, useTheme } from '@mui/material';
|
||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
||||
import PeopleIcon from '@mui/icons-material/People';
|
||||
import LanguageIcon from '@mui/icons-material/Language';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import CodeIcon from '@mui/icons-material/Code';
|
||||
@ -28,8 +27,6 @@ export const getFeatureStrategyIcon = (strategyName?: string) => {
|
||||
return LanguageIcon;
|
||||
case 'flexibleRollout':
|
||||
return RolloutSvgIcon;
|
||||
case 'userWithId':
|
||||
return PeopleIcon;
|
||||
case 'applicationHostname':
|
||||
return LocationOnIcon;
|
||||
case 'releasePlanTemplate':
|
||||
@ -47,7 +44,6 @@ export const BuiltInStrategies = [
|
||||
'gradualRolloutSessionId',
|
||||
'gradualRolloutUserId',
|
||||
'remoteAddress',
|
||||
'userWithId',
|
||||
];
|
||||
|
||||
export const GetFeatureStrategyIcon: FC<{ strategyName: string }> = ({
|
||||
@ -66,5 +62,4 @@ export const formattedStrategyNames: Record<string, string> = {
|
||||
gradualRolloutSessionId: 'Sessions',
|
||||
gradualRolloutUserId: 'Users',
|
||||
remoteAddress: 'IPs',
|
||||
userWithId: 'UserIDs',
|
||||
};
|
||||
|
@ -239,11 +239,3 @@ exports[`Should format specialised text for events when strategy removed 1`] = `
|
||||
"url": "unleashUrl/projects/my-other-project/features/new-feature",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Should format specialised text for events when userIds changed 1`] = `
|
||||
{
|
||||
"label": "Flag strategy updated",
|
||||
"text": "*user@company.com* updated *[new-feature](unleashUrl/projects/my-other-project/features/new-feature)* in project *[my-other-project](unleashUrl/projects/my-other-project)* by updating strategy *userWithId* in *production* userIds from empty set of userIds to [a,b]; constraints from empty set of constraints to [appName is one of (x,y)]",
|
||||
"url": "unleashUrl/projects/my-other-project/features/new-feature",
|
||||
}
|
||||
`;
|
||||
|
@ -352,46 +352,6 @@ const testCases: [string, IEvent][] = [
|
||||
},
|
||||
],
|
||||
),
|
||||
[
|
||||
'when userIds changed',
|
||||
{
|
||||
id: 920,
|
||||
type: FEATURE_STRATEGY_UPDATE,
|
||||
createdBy: 'user@company.com',
|
||||
createdByUserId: SYSTEM_USER_ID,
|
||||
createdAt: new Date('2022-06-01T10:03:11.549Z'),
|
||||
data: {
|
||||
name: 'userWithId',
|
||||
constraints: [
|
||||
{
|
||||
values: ['x', 'y'],
|
||||
inverted: false,
|
||||
operator: IN,
|
||||
contextName: 'appName',
|
||||
caseInsensitive: false,
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
userIds: 'a,b',
|
||||
},
|
||||
sortOrder: 9999,
|
||||
id: '9a995d94-5944-4897-a82f-0f7e65c2fb3f',
|
||||
},
|
||||
preData: {
|
||||
name: 'userWithId',
|
||||
constraints: [],
|
||||
parameters: {
|
||||
userIds: '',
|
||||
},
|
||||
sortOrder: 9999,
|
||||
id: '9a995d94-5944-4897-a82f-0f7e65c2fb3f',
|
||||
},
|
||||
tags: [],
|
||||
featureName: 'new-feature',
|
||||
project: 'my-other-project',
|
||||
environment: 'production',
|
||||
},
|
||||
],
|
||||
[
|
||||
'when IPs changed',
|
||||
{
|
||||
|
@ -135,8 +135,6 @@ export class FeatureEventFormatterMd implements FeatureEventFormatter {
|
||||
return this.flexibleRolloutStrategyChangeText(event);
|
||||
case 'default':
|
||||
return this.defaultStrategyChangeText(event);
|
||||
case 'userWithId':
|
||||
return this.userWithIdStrategyChangeText(event);
|
||||
case 'remoteAddress':
|
||||
return this.remoteAddressStrategyChangeText(event);
|
||||
case 'applicationHostname':
|
||||
@ -162,10 +160,6 @@ export class FeatureEventFormatterMd implements FeatureEventFormatter {
|
||||
return this.listOfValuesStrategyChangeText(event, 'IPs');
|
||||
}
|
||||
|
||||
private userWithIdStrategyChangeText(event: IEvent) {
|
||||
return this.listOfValuesStrategyChangeText(event, 'userIds');
|
||||
}
|
||||
|
||||
private listOfValuesStrategyChangeText(
|
||||
event: IEvent,
|
||||
propertyName: string,
|
||||
|
@ -63,9 +63,9 @@ exports[`should match snapshot from /api/client/features 1`] = `
|
||||
},
|
||||
],
|
||||
"meta": {
|
||||
"etag": ""61824cd0:20"",
|
||||
"etag": ""61824cd0:19"",
|
||||
"queryHash": "61824cd0",
|
||||
"revisionId": 20,
|
||||
"revisionId": 19,
|
||||
},
|
||||
"query": {
|
||||
"environment": "default",
|
||||
|
@ -354,7 +354,10 @@ class EventStore implements IEventStore {
|
||||
.select(EVENT_COLUMNS)
|
||||
.from(TABLE)
|
||||
.limit(100)
|
||||
.orderBy('created_at', 'desc');
|
||||
.orderBy([
|
||||
{ column: 'created_at', order: 'desc' },
|
||||
{ column: 'id', order: 'desc' },
|
||||
]);
|
||||
if (query) {
|
||||
qB = qB.where(query);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import DefaultStrategy from './default-strategy.js';
|
||||
import GradualRolloutRandomStrategy from './gradual-rollout-random.js';
|
||||
import GradualRolloutUserIdStrategy from './gradual-rollout-user-id.js';
|
||||
import GradualRolloutSessionIdStrategy from './gradual-rollout-session-id.js';
|
||||
import UserWithIdStrategy from './user-with-id-strategy.js';
|
||||
import RemoteAddressStrategy from './remote-address-strategy.js';
|
||||
import FlexibleRolloutStrategy from './flexible-rollout-strategy.js';
|
||||
import type { Strategy } from './strategy.js';
|
||||
@ -18,7 +17,6 @@ export const defaultStrategies: Array<Strategy> = [
|
||||
new GradualRolloutRandomStrategy(),
|
||||
new GradualRolloutUserIdStrategy(),
|
||||
new GradualRolloutSessionIdStrategy(),
|
||||
new UserWithIdStrategy(),
|
||||
new RemoteAddressStrategy(),
|
||||
new FlexibleRolloutStrategy(),
|
||||
new UnknownStrategy(),
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { Strategy } from './strategy.js';
|
||||
import type { Context } from '../context.js';
|
||||
|
||||
export default class UserWithIdStrategy extends Strategy {
|
||||
constructor() {
|
||||
super('userWithId');
|
||||
}
|
||||
|
||||
isEnabled(parameters: { userIds?: string }, context: Context): boolean {
|
||||
const userIdList = parameters.userIds
|
||||
? parameters.userIds.split(/\s*,\s*/)
|
||||
: [];
|
||||
return (
|
||||
context.userId !== undefined && userIdList.includes(context.userId)
|
||||
);
|
||||
}
|
||||
}
|
@ -432,13 +432,6 @@ describe('offline client', () => {
|
||||
stickiness: 'userId',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'userWithId',
|
||||
constraints: [],
|
||||
parameters: {
|
||||
userIds: 'uoea,ueoa',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'remoteAddress',
|
||||
constraints: [],
|
||||
|
@ -48,7 +48,6 @@ test('clientApplicationSchema go-sdk request', () => {
|
||||
"gradualRolloutSessionId",
|
||||
"gradualRolloutUserId",
|
||||
"remoteAddress",
|
||||
"userWithId",
|
||||
"flexibleRollout"
|
||||
],
|
||||
"started": "2022-06-24T09:59:12.822607943+02:00",
|
||||
@ -75,7 +74,6 @@ test('clientApplicationSchema node-sdk request', () => {
|
||||
"gradualRolloutRandom",
|
||||
"gradualRolloutUserId",
|
||||
"gradualRolloutSessionId",
|
||||
"userWithId",
|
||||
"remoteAddress",
|
||||
"flexibleRollout"
|
||||
],
|
||||
|
@ -95,14 +95,6 @@ const playgroundStrategies = (): Arbitrary<PlaygroundStrategySchema[]> =>
|
||||
}),
|
||||
),
|
||||
|
||||
playgroundStrategy(
|
||||
'userWithId',
|
||||
fc.record({
|
||||
userIds: fc
|
||||
.uniqueArray(fc.emailAddress())
|
||||
.map((ids) => ids.join(',')),
|
||||
}),
|
||||
),
|
||||
playgroundStrategy(
|
||||
'remoteAddress',
|
||||
fc.record({
|
||||
|
@ -6,7 +6,6 @@ exports.up = function (db, cb) {
|
||||
ALTER TABLE strategies ADD COLUMN sort_order integer DEFAULT 9999;
|
||||
UPDATE strategies SET sort_order = 0 WHERE name = 'default';
|
||||
UPDATE strategies SET sort_order = 1 WHERE name = 'flexibleRollout';
|
||||
UPDATE strategies SET sort_order = 2 WHERE name = 'userWithId';
|
||||
UPDATE strategies SET sort_order = 3 WHERE name = 'remoteAddress';
|
||||
UPDATE strategies SET sort_order = 4 WHERE name = 'applicationHostname';
|
||||
`,
|
||||
|
@ -6,7 +6,6 @@ exports.up = function (db, cb) {
|
||||
ALTER TABLE strategies ADD COLUMN display_name text;
|
||||
UPDATE strategies SET display_name = 'Standard', description = 'The standard strategy is strictly on / off for your entire userbase.' WHERE name = 'default';
|
||||
UPDATE strategies SET display_name = 'Gradual rollout', description = 'Roll out to a percentage of your userbase, and ensure that the experience is the same for the user on each visit.' WHERE name = 'flexibleRollout';
|
||||
UPDATE strategies SET display_name = 'UserIDs', description = 'Enable the feature for a specific set of userIds.' WHERE name = 'userWithId';
|
||||
UPDATE strategies SET display_name = 'IPs', description = 'Enable the feature for a specific set of IP addresses.' WHERE name = 'remoteAddress';
|
||||
UPDATE strategies SET display_name = 'Hosts', description = 'Enable the feature for a specific set of hostnames.' WHERE name = 'applicationHostname';
|
||||
`,
|
||||
|
@ -9,13 +9,9 @@ exports.up = function (db, callback) {
|
||||
and deprecated
|
||||
and not exists (select * from feature_strategies where strategy_name = name limit 1);
|
||||
|
||||
-- deprecate strategies on v5
|
||||
update strategies set deprecated = true where name in ('userWithId');
|
||||
|
||||
-- update strategy descriptions and sort order
|
||||
update strategies set sort_order = 1, description = 'This strategy turns on / off for your entire userbase. Prefer using "Gradual rollout" strategy (100%=on, 0%=off).' WHERE name = 'default';
|
||||
update strategies set sort_order = 0 WHERE name = 'flexibleRollout';
|
||||
update strategies set description = 'Enable the feature for a specific set of userIds. Prefer using "Gradual rollout" strategy with user id constraints.' WHERE name = 'userWithId';
|
||||
`,
|
||||
callback,
|
||||
);
|
||||
|
@ -4,18 +4,6 @@
|
||||
"description": "Default on/off strategy.",
|
||||
"parameters": []
|
||||
},
|
||||
{
|
||||
"name": "userWithId",
|
||||
"description": "Active for users with a userId defined in the userIds-list",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userIds",
|
||||
"type": "list",
|
||||
"description": "",
|
||||
"required": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "applicationHostname",
|
||||
"description": "Active for client instances with a hostName in the hostNames-list.",
|
||||
|
@ -107,14 +107,6 @@ export const strategies = (): Arbitrary<FeatureStrategySchema[]> =>
|
||||
}),
|
||||
),
|
||||
|
||||
strategy(
|
||||
'userWithId',
|
||||
fc.record({
|
||||
userIds: fc
|
||||
.uniqueArray(fc.emailAddress())
|
||||
.map((ids) => ids.join(',')),
|
||||
}),
|
||||
),
|
||||
strategy(
|
||||
'remoteAddress',
|
||||
fc.record({
|
||||
|
@ -152,26 +152,26 @@ describe.each([
|
||||
.expect(200);
|
||||
|
||||
if (etagVariant.feature_enabled) {
|
||||
expect(res.headers.etag).toBe(`"61824cd0:17:${etagVariant.name}"`);
|
||||
expect(res.headers.etag).toBe(`"61824cd0:16:${etagVariant.name}"`);
|
||||
expect(res.body.meta.etag).toBe(
|
||||
`"61824cd0:17:${etagVariant.name}"`,
|
||||
`"61824cd0:16:${etagVariant.name}"`,
|
||||
);
|
||||
} else {
|
||||
expect(res.headers.etag).toBe('"61824cd0:17"');
|
||||
expect(res.body.meta.etag).toBe('"61824cd0:17"');
|
||||
expect(res.headers.etag).toBe('"61824cd0:16"');
|
||||
expect(res.body.meta.etag).toBe('"61824cd0:16"');
|
||||
}
|
||||
});
|
||||
|
||||
test(`returns ${etagVariant.feature_enabled ? 200 : 304} for pre-calculated hash${etagVariant.feature_enabled ? ' because hash changed' : ''}`, async () => {
|
||||
const res = await app.request
|
||||
.get('/api/client/features')
|
||||
.set('if-none-match', '"61824cd0:17"')
|
||||
.set('if-none-match', '"61824cd0:16"')
|
||||
.expect(etagVariant.feature_enabled ? 200 : 304);
|
||||
|
||||
if (etagVariant.feature_enabled) {
|
||||
expect(res.headers.etag).toBe(`"61824cd0:17:${etagVariant.name}"`);
|
||||
expect(res.headers.etag).toBe(`"61824cd0:16:${etagVariant.name}"`);
|
||||
expect(res.body.meta.etag).toBe(
|
||||
`"61824cd0:17:${etagVariant.name}"`,
|
||||
`"61824cd0:16:${etagVariant.name}"`,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -193,13 +193,13 @@ describe.each([
|
||||
.expect(200);
|
||||
|
||||
if (etagVariant.feature_enabled) {
|
||||
expect(res.headers.etag).toBe(`"61824cd0:17:${etagVariant.name}"`);
|
||||
expect(res.headers.etag).toBe(`"61824cd0:16:${etagVariant.name}"`);
|
||||
expect(res.body.meta.etag).toBe(
|
||||
`"61824cd0:17:${etagVariant.name}"`,
|
||||
`"61824cd0:16:${etagVariant.name}"`,
|
||||
);
|
||||
} else {
|
||||
expect(res.headers.etag).toBe('"61824cd0:17"');
|
||||
expect(res.body.meta.etag).toBe('"61824cd0:17"');
|
||||
expect(res.headers.etag).toBe('"61824cd0:16"');
|
||||
expect(res.body.meta.etag).toBe('"61824cd0:16"');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -180,7 +180,6 @@ This endpoint gives insight into details about application seen per feature flag
|
||||
"abTest",
|
||||
"default",
|
||||
"betaUser",
|
||||
"userWithId",
|
||||
"byHostName",
|
||||
"gradualRolloutWithSessionId",
|
||||
"gradualRollout",
|
||||
|
@ -21,18 +21,6 @@ Used to fetch all defined strategies and their defined parameters.
|
||||
"description": "Default on/off strategy.",
|
||||
"parameters": []
|
||||
},
|
||||
{
|
||||
"name": "userWithId",
|
||||
"description": "Active for userId specified in the comma seperated 'userIds' parameter.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "userIds",
|
||||
"type": "list",
|
||||
"description": "List of unique userIds the feature should be active for.",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gradualRollout",
|
||||
"description": "Gradual rollout to logged in users",
|
||||
|
@ -8,6 +8,10 @@ Predefined strategy types are a legacy implementation. Please use the [default s
|
||||
|
||||
## UserIDs
|
||||
|
||||
:::warning
|
||||
The `userWithId` strategy was removed in Unleash v7.0.0 for new installations. Instead use a gradual rollout strategy with a user ID stickiness and constraints.
|
||||
:::
|
||||
|
||||
The `userWithId` strategy is active for users with a `userId` defined in the `userIds` list.
|
||||
|
||||
**Parameters:**
|
||||
|
Loading…
Reference in New Issue
Block a user