diff --git a/docs/api/admin/feature-toggles-api.md b/docs/api/admin/feature-toggles-api.md index 1334c2fe19..68192282c8 100644 --- a/docs/api/admin/feature-toggles-api.md +++ b/docs/api/admin/feature-toggles-api.md @@ -24,6 +24,14 @@ This endpoint is the one all admin ui should use to fetch all available feature "name": "default", "parameters": {} } + ], + "variants": [ + { + "name": "variant1", + }, + { + "name": "variant2", + } ] }, { @@ -43,7 +51,8 @@ This endpoint is the one all admin ui should use to fetch all available feature "percentage": "10" } } - ] + ], + "variants": [] } ] } @@ -63,7 +72,8 @@ Used to fetch details about a specific featureToggle. This is mostly provded to "name": "default", "parameters": {} } - ] + ], + "variants": [] } ``` @@ -107,7 +117,8 @@ Returns 200-respose if the feature toggle was created successfully. "name": "default", "parameters": {} } - ] + ], + "variants": [] } ``` @@ -145,6 +156,7 @@ Used to fetch list of archived feature toggles "parameters": {} } ], + "variants": [], "strategy": "default", "parameters": {} } diff --git a/lib/db/feature-toggle-store.js b/lib/db/feature-toggle-store.js index 4aeef4f840..d61ee4083c 100644 --- a/lib/db/feature-toggle-store.js +++ b/lib/db/feature-toggle-store.js @@ -13,6 +13,7 @@ const FEATURE_COLUMNS = [ 'description', 'enabled', 'strategies', + 'variants', 'created_at', ]; const TABLE = 'features'; @@ -85,6 +86,7 @@ class FeatureToggleStore { description: row.description, enabled: row.enabled > 0, strategies: row.strategies, + variants: row.variants, createdAt: row.created_at, }; } @@ -96,6 +98,7 @@ class FeatureToggleStore { enabled: data.enabled ? 1 : 0, archived: data.archived ? 1 : 0, strategies: JSON.stringify(data.strategies), + variants: data.variants ? JSON.stringify(data.variants) : null, created_at: data.createdAt, // eslint-disable-line }; } diff --git a/lib/options.js b/lib/options.js index 3fffbd8e65..ab9ef02a44 100644 --- a/lib/options.js +++ b/lib/options.js @@ -18,7 +18,7 @@ const DEFAULT_OPTIONS = { enableRequestLogger: isDev(), secret: 'UNLEASH-SECRET', sessionAge: THIRTY_DAYS, - adminAuthentication: 'unsecure', + adminAuthentication: 'none', }; module.exports = { diff --git a/lib/routes/admin-api/feature-schema.js b/lib/routes/admin-api/feature-schema.js index f8bdde07ce..bc635d43d1 100644 --- a/lib/routes/admin-api/feature-schema.js +++ b/lib/routes/admin-api/feature-schema.js @@ -10,6 +10,11 @@ const strategiesSchema = joi.object().keys({ parameters: joi.object(), }); +const variantsSchema = joi.object().keys({ + name: nameType, + percentage: joi.number(), +}); + const featureShema = joi .object() .keys({ @@ -21,6 +26,10 @@ const featureShema = joi .required() .min(1) .items(strategiesSchema), + variants: joi + .array() + .optional() + .items(variantsSchema), }) .options({ allowUnknown: false, stripUnknown: true }); diff --git a/migrations/20190123204125-add-variants-to-features.js b/migrations/20190123204125-add-variants-to-features.js new file mode 100644 index 0000000000..933de85e52 --- /dev/null +++ b/migrations/20190123204125-add-variants-to-features.js @@ -0,0 +1,15 @@ +'use strict'; + +exports.up = function(db, callback) { + db.runSql( + ` + ALTER TABLE features ADD "variants" json; + ALTER TABLE features ALTER COLUMN "variants" SET DEFAULT '[]'; + `, + callback + ); +}; + +exports.down = function(db, callback) { + db.runSql(`ALTER TABLE features DROP COLUMN "variants";`, callback); +}; diff --git a/test/e2e/api/admin/feature.e2e.test.js b/test/e2e/api/admin/feature.e2e.test.js index e7d11d0cd5..357b54fe33 100644 --- a/test/e2e/api/admin/feature.e2e.test.js +++ b/test/e2e/api/admin/feature.e2e.test.js @@ -50,6 +50,26 @@ test.serial('creates new feature toggle', async t => { .then(destroy); }); +test.serial('creates new feature toggle with variants', async t => { + t.plan(1); + const { request, destroy } = await setupApp('feature_api_serial'); + await request + .post('/api/admin/features') + .send({ + name: 'com.test.variants', + enabled: false, + strategies: [{ name: 'default' }], + variants: [{ name: 'variant1' }, { name: 'variant2' }], + }) + .set('Content-Type', 'application/json'); + await request + .get('/api/admin/features/com.test.variants') + .expect(res => { + t.true(res.body.variants.length === 2); + }) + .then(destroy); +}); + test.serial('creates new feature toggle with createdBy unknown', async t => { t.plan(1); const { request, destroy } = await setupApp('feature_api_serial');