From 5f70859b8e46d87e9cb68d4ec6c922b7dc63b4da Mon Sep 17 00:00:00 2001 From: Rapolas <130578328+rapolaskaseliscgi@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:08:19 +0000 Subject: [PATCH] LAU-1291 remove launchdarkly --- charts/lau-frontend/Chart.yaml | 2 +- charts/lau-frontend/values.yaml | 2 - config/custom-environment-variables.yaml | 3 - config/default.yaml | 5 -- config/development.yaml | 2 - config/test.yaml | 2 - jest.config.js | 2 +- jest.setup.js | 25 --------- package.json | 1 - src/main/app.ts | 3 - .../featureToggle/LaunchDarklyClient.ts | 53 ------------------ src/main/modules/nunjucks/index.ts | 2 - src/main/modules/properties-volume/index.ts | 2 - src/main/routes/home.ts | 3 - src/main/service/FeatureToggleService.ts | 16 ------ src/main/views/common/navigation.njk | 2 - src/test/config.js | 5 -- src/test/end-to-end/helpers/featureToggles.js | 37 ------------ src/test/end-to-end/helpers/launchDarkly.js | 52 ----------------- .../components/LaunchDarklyClient.test.ts | 56 ------------------- .../unit/routes/caseChallengedAccess.test.ts | 20 ------- yarn.lock | 48 ---------------- 22 files changed, 2 insertions(+), 341 deletions(-) delete mode 100644 jest.setup.js delete mode 100644 src/main/components/featureToggle/LaunchDarklyClient.ts delete mode 100644 src/main/service/FeatureToggleService.ts delete mode 100644 src/test/end-to-end/helpers/featureToggles.js delete mode 100644 src/test/end-to-end/helpers/launchDarkly.js delete mode 100644 src/test/unit/components/LaunchDarklyClient.test.ts diff --git a/charts/lau-frontend/Chart.yaml b/charts/lau-frontend/Chart.yaml index f1f9d6f9..4d614a54 100644 --- a/charts/lau-frontend/Chart.yaml +++ b/charts/lau-frontend/Chart.yaml @@ -3,7 +3,7 @@ appVersion: "1.0" description: A Helm chart for Log and Audit Frontend App name: lau-frontend home: https://github.com/hmcts/lau-frontend -version: 0.2.7 +version: 0.2.8 dependencies: - name: nodejs version: 3.2.0 diff --git a/charts/lau-frontend/values.yaml b/charts/lau-frontend/values.yaml index e00e6ed3..757ea3d2 100644 --- a/charts/lau-frontend/values.yaml +++ b/charts/lau-frontend/values.yaml @@ -34,8 +34,6 @@ nodejs: - frontend-redis-access-key - idam-client-secret - s2s-secret - - launchdarkly-sdk-key - - lau-deleted-users-ft redis: architecture: standalone diff --git a/config/custom-environment-variables.yaml b/config/custom-environment-variables.yaml index 6422a4d0..95807af1 100644 --- a/config/custom-environment-variables.yaml +++ b/config/custom-environment-variables.yaml @@ -27,9 +27,6 @@ services: s2s: enabled: S2S_ENABLED url: S2S_URL -featureToggles: - ldKey: LD_SDK_KEY - ft_deletedUsers: 'LAU_DELETED_USERS' pages: userDetailsEnabled: USER_DETAILS_PAGE_ENABLED is_dev: IS_DEV diff --git a/config/default.yaml b/config/default.yaml index f5d4c64f..1c1a5bc2 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -62,11 +62,6 @@ services: lauSecret: 'AAAAAAAAAAAAAAAA' auto-suggest: data-file: 'data/auto-suggest-data-prod.json' -featureToggles: - enabled: true - ldKey: 'LD_SDK_KEY' - ft_deletedUsers: 'LAU_DELETED_USERS' - ft_challengeAccess: 'lau-challenged-access' pages: userDetailsEnabled: true session: diff --git a/config/development.yaml b/config/development.yaml index 25d45975..5da4455b 100644 --- a/config/development.yaml +++ b/config/development.yaml @@ -17,5 +17,3 @@ services: url: 'http://localhost:4552' auto-suggest: data-file: 'data/auto-suggest-data-dev.json' -featureToggles: - enabled: false diff --git a/config/test.yaml b/config/test.yaml index 6b179c93..490e3b29 100644 --- a/config/test.yaml +++ b/config/test.yaml @@ -9,5 +9,3 @@ services: s2s: enabled: false url: 'http://localhost:4552' -featureToggles: - enabled: false diff --git a/jest.config.js b/jest.config.js index 777ebc42..4e935329 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,5 +6,5 @@ module.exports = { '^.+\\.ts?$': 'ts-jest', }, moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], - setupFilesAfterEnv: ['./jest.setup.js'] + setupFilesAfterEnv: [] } diff --git a/jest.setup.js b/jest.setup.js deleted file mode 100644 index 863b83fd..00000000 --- a/jest.setup.js +++ /dev/null @@ -1,25 +0,0 @@ -jest.mock('launchdarkly-node-server-sdk', () => { - const LDClientMock = { - init: jest.fn().mockImplementation((sdkKey, options) => ({ - on: jest.fn().mockImplementation((event, callback) => { - if (event === 'ready') { - setTimeout(callback, 0); - } - }), - variation: jest.fn().mockImplementation((featureKey, user, defaultVal, callback) => { - // Mock your variation method behavior here - // For example, return 'true' for all features - callback(null, true); - }), - once: jest.fn().mockImplementation((event, callback) => { - // Mock your once method behavior here - // For example, execute the callback directly - if (event === 'ready') { - setTimeout(callback, 0); - } - }), - })), - }; - - return LDClientMock; -}); \ No newline at end of file diff --git a/package.json b/package.json index fdf4a77f..100e10b3 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,6 @@ "jquery": "^3.5.1", "js-yaml": "^4.1.0", "jwt-decode": "^4.0.0", - "launchdarkly-node-server-sdk": "^7.0.0", "lodash": "^4.17.21", "moment": "^2.29.4", "nunjucks": "^3.2.4", diff --git a/src/main/app.ts b/src/main/app.ts index 010a17eb..73642e34 100644 --- a/src/main/app.ts +++ b/src/main/app.ts @@ -11,7 +11,6 @@ import {SessionStorage} from './modules/session'; import {OidcMiddleware} from './modules/oidc'; import {HealthCheck} from './modules/health'; import {Container} from './modules/awilix'; -import {LaunchDarklyClient} from './components/featureToggle/LaunchDarklyClient'; import config from 'config'; import {AutoSuggest} from './modules/autosuggest/AutoSuggest'; @@ -38,8 +37,6 @@ app.use(express.json()); app.use(express.urlencoded({ extended: false })); - -LaunchDarklyClient.initialise(); new Helmet(config.get('security')).enableFor(app); new SessionStorage().enableFor(app); new CSRFToken().enableFor(app); diff --git a/src/main/components/featureToggle/LaunchDarklyClient.ts b/src/main/components/featureToggle/LaunchDarklyClient.ts deleted file mode 100644 index c688d491..00000000 --- a/src/main/components/featureToggle/LaunchDarklyClient.ts +++ /dev/null @@ -1,53 +0,0 @@ -import LaunchDarklySDK from 'launchdarkly-node-server-sdk'; -import config from 'config'; -import {AppError, ErrorCode} from '../../models/AppError'; - -export class LaunchDarklyClient { - - private static _instance: LaunchDarklyClient; - private client: LaunchDarklySDK.LDClient; - - private ready = false; - - private constructor() { - const options = config.get('featureToggles.enabled') ? {diagnosticOptOut: true} : {offline: true}; - this.client = LaunchDarklySDK.init(config.get('featureToggles.ldKey'), options); - this.client.once('ready', () => { - this.ready = true; - }); - } - - public static initialise(): void { - if (!this._instance) { - this._instance = new this(); - } - } - - public static get instance(): LaunchDarklyClient { - return this._instance || (this._instance = new this()); - } - - async variation(featureKey: string, offlineDefault = false): Promise { - return new Promise((resolve, reject) => { - - const variation = () => { - this.client.variation(featureKey, {key: 'lau-frontend'}, offlineDefault, (err, enabled) => { - if (err) { - reject(new AppError(err, ErrorCode.LAUNCH_DARKLY)); - } else { - resolve(enabled); - } - }); - }; - - if (this.ready) { - variation(); - } else { - this.client.once('ready', () => { - variation(); - }); - } - }); - } - -} diff --git a/src/main/modules/nunjucks/index.ts b/src/main/modules/nunjucks/index.ts index 91451454..f6a8a7e3 100644 --- a/src/main/modules/nunjucks/index.ts +++ b/src/main/modules/nunjucks/index.ts @@ -4,7 +4,6 @@ import * as nunjucks from 'nunjucks'; import {numberWithCommas} from '../../util/Util'; import {AppRequest} from '../../models/appRequest'; import config from 'config'; -import {FeatureToggleService} from './../../service/FeatureToggleService'; export class Nunjucks { constructor(public developmentMode: boolean) { @@ -34,7 +33,6 @@ export class Nunjucks { app.use(async (req: AppRequest, res, next) => { res.locals.isDev = JSON.parse(config.get('is_dev')); - res.locals.challengedAccessEnabled = await FeatureToggleService.getChallengedAccessFeatureToggle(); res.locals.userDetailsEnabled = JSON.parse(config.get('pages.userDetailsEnabled')); res.locals.pagePath = req.path; next(); diff --git a/src/main/modules/properties-volume/index.ts b/src/main/modules/properties-volume/index.ts index 00b10cb6..b076b9c8 100644 --- a/src/main/modules/properties-volume/index.ts +++ b/src/main/modules/properties-volume/index.ts @@ -10,8 +10,6 @@ export class PropertiesVolume { PropertiesVolume.setSecret('secrets.lau.frontend-redis-access-key', 'redis.password'); PropertiesVolume.setSecret('secrets.lau.idam-client-secret', 'services.idam-api.clientSecret'); PropertiesVolume.setSecret('secrets.lau.s2s-secret', 'services.s2s.lauSecret'); - PropertiesVolume.setSecret('secrets.lau.launchdarkly-sdk-key', 'featureToggles.ldKey'); - PropertiesVolume.setSecret('secrets.lau.lau-deleted-users-ft', 'featureToggles.ft_deletedUsers'); } } diff --git a/src/main/routes/home.ts b/src/main/routes/home.ts index ce5fe15f..d1dc2f25 100644 --- a/src/main/routes/home.ts +++ b/src/main/routes/home.ts @@ -139,9 +139,6 @@ async function caseDeletionHandler(req: AppRequest, res: Response) { } export async function challengedSpecificAccessHandler(req: AppRequest, res: Response) { - if(!res.locals.challengedAccessEnabled){ - return res.redirect('/'); - } const context: Context = { caseChallengedAccessForm: req.session?.caseChallengedAccessFormState || {}, challengedSpecificAccessPage: true, diff --git a/src/main/service/FeatureToggleService.ts b/src/main/service/FeatureToggleService.ts deleted file mode 100644 index 651771aa..00000000 --- a/src/main/service/FeatureToggleService.ts +++ /dev/null @@ -1,16 +0,0 @@ -import config from 'config'; -import {LaunchDarklyClient} from '../components/featureToggle/LaunchDarklyClient'; - -export class FeatureToggleService{ - public static async getDeletedUsersFeatureToggle(): Promise { - const deletedUsersFt = String(config.get('featureToggles.ft_deletedUsers')); - const deletedUsersFtValue = await LaunchDarklyClient.instance.variation(deletedUsersFt, false); - return deletedUsersFtValue; - } - - public static async getChallengedAccessFeatureToggle(): Promise { - const isDevelopment = Boolean(config.get('is_dev')); - const challengedAccessFt = String(config.get('featureToggles.ft_challengeAccess')); - return await LaunchDarklyClient.instance.variation(challengedAccessFt, isDevelopment); - } -} diff --git a/src/main/views/common/navigation.njk b/src/main/views/common/navigation.njk index bc527382..cf913499 100644 --- a/src/main/views/common/navigation.njk +++ b/src/main/views/common/navigation.njk @@ -6,11 +6,9 @@
  • Case audit
  • - {% if challengedAccessEnabled %}
  • Challenged & specific access
  • - {% endif %}
  • Log ons audit
  • diff --git a/src/test/config.js b/src/test/config.js index 056933ea..3cda3b15 100644 --- a/src/test/config.js +++ b/src/test/config.js @@ -22,11 +22,6 @@ module.exports = { microservice: process.env.S2S_MICROSERVICE_KEY_CMC, secret: process.env.S2S_MICROSERVICE_KEY_PWD, }, - featureToggles: { - enabled: process.env.LD_ENABLED || false, - launchDarklyKey: process.env.LAUNCHDARKLY_KEY, - flags: {}, - }, env: process.env.TEST_ENV || 'local', proxy: '', }; diff --git a/src/test/end-to-end/helpers/featureToggles.js b/src/test/end-to-end/helpers/featureToggles.js deleted file mode 100644 index 581b69da..00000000 --- a/src/test/end-to-end/helpers/featureToggles.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -const testConfig = require('src/test/config.js'); -const LaunchDarkly = require('./launchDarkly'); - -const logger = require('../logger'); - -class FeatureToggle { - constructor() { - this.launchDarkly = new LaunchDarkly().getInstance(); - } - - getToggleValue(key) { - const featureToggleKey = testConfig.featureToggles.flags[key]; - const roles = []; - const ldUser = { - key: 'lau-e2e-tests', - custom: { - roles, - }, - }; - const ldDefaultValue = false; - - try { - return this.launchDarkly.variation(featureToggleKey, ldUser, ldDefaultValue); - } catch (error) { - logger.info('launch darkly check toggle errors..', error); - } - } - - closeConnection() { - this.launchDarkly.close(); - } - -} - -module.exports = FeatureToggle; diff --git a/src/test/end-to-end/helpers/launchDarkly.js b/src/test/end-to-end/helpers/launchDarkly.js deleted file mode 100644 index e1924992..00000000 --- a/src/test/end-to-end/helpers/launchDarkly.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; - -const testConfig = require('src/test/config.js'); -const launchDarkly = require('launchdarkly-node-server-sdk'); - -class LaunchDarkly { - constructor() { - this.ready = false; - const enabled = testConfig.featureToggles.enabled && testConfig.featureToggles.enabled !== 'false'; - const options = enabled ? {diagnosticOptOut: true} : {offline: true}; - this.client = launchDarkly.init(testConfig.featureToggles.launchDarklyKey, options); - this.client.once('ready', () => { - this.ready = true; - }); - } - - variation(...params) { - if (this.ready) { - return this.client.variation(...params); - } - - return this.client.once('ready', () => { - this.ready = true; - return this.client.variation(...params); - }); - } - - close() { - this.client.close(); - } -} - -class Singleton { - constructor(options = {}, ftValue = {}) { - if (!this.instance) { - this.instance = new LaunchDarkly(options, ftValue); - } - } - - getInstance() { - return this.instance; - } - - close() { - if (this.instance) { - this.instance.close(); - delete this.instance; - } - } -} - -module.exports = Singleton; diff --git a/src/test/unit/components/LaunchDarklyClient.test.ts b/src/test/unit/components/LaunchDarklyClient.test.ts deleted file mode 100644 index 12e0600d..00000000 --- a/src/test/unit/components/LaunchDarklyClient.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {LaunchDarklyClient} from '../../../main/components/featureToggle/LaunchDarklyClient'; -import { FeatureToggleService } from '../../../main/service/FeatureToggleService'; -import config from 'config'; - -jest.mock('config'); - -describe('LaunchDarklyClient', () => { - - beforeEach(() => { - // Initialize the LaunchDarklyClient with the mock LDClientInterface - LaunchDarklyClient.initialise(); - }); - - it('initialises the client', async () => { - expect(LaunchDarklyClient.instance).toBeDefined(); - }); - it('successfully calls and returns truthy variation value', async () => { - // Simulate LDClient variation method returning true - jest.spyOn(LaunchDarklyClient.instance, 'variation').mockResolvedValue(true); - - const testFeature = await LaunchDarklyClient.instance.variation('test', true); - expect(testFeature).toBeTruthy(); - }); - it('successfully calls and returns falsy variation value', async () => { - // Simulate LDClient variation method returning false - jest.spyOn(LaunchDarklyClient.instance, 'variation').mockResolvedValue(false); - - const testFeature = await LaunchDarklyClient.instance.variation('test', false); - expect(testFeature).toBeFalsy(); - }); - it('successfully calls and returns true variation value when enviornment is development', async () => { - (config.get as jest.Mock).mockImplementation((key: string) => { - if (key === 'is_dev') return 'true'; - if (key === 'featureToggles.ft_challengeAccess') return 'ft_challengeAccess'; - return null; - }); - // Simulate LDClient variation method returning true when development environment - jest.spyOn(LaunchDarklyClient.instance, 'variation').mockResolvedValue(true); - - const result = await FeatureToggleService.getChallengedAccessFeatureToggle(); - expect(result).toBeTruthy(); - }); - it('successfully calls and returns false variation value when enviornment is not development', async () => { - (config.get as jest.Mock).mockImplementation((key: string) => { - if (key === 'is_dev') return 'false'; - if (key === 'featureToggles.ft_challengeAccess') return 'ft_challengeAccess'; - return null; - }); - // Simulate LDClient variation method returning true when development environment - jest.spyOn(LaunchDarklyClient.instance, 'variation').mockResolvedValue(false); - - const result = await FeatureToggleService.getChallengedAccessFeatureToggle(); - expect(result).toBeFalsy(); - - }); -}); diff --git a/src/test/unit/routes/caseChallengedAccess.test.ts b/src/test/unit/routes/caseChallengedAccess.test.ts index 6511b0ab..dd51dcf6 100644 --- a/src/test/unit/routes/caseChallengedAccess.test.ts +++ b/src/test/unit/routes/caseChallengedAccess.test.ts @@ -2,9 +2,6 @@ import nock from 'nock'; import request from 'supertest'; import {app} from '../../../main/app'; import caseChallengedAccessLogs from '../../data/caseChallengedAccessLogs.json'; -import {challengedSpecificAccessHandler} from '../../../main/routes/home'; -import {Response} from 'express'; -import { AppRequest } from 'models/appRequest'; describe('Case Challenged Access Route', () => { const agent = request(app); @@ -23,21 +20,4 @@ describe('Case Challenged Access Route', () => { expect(res.type).toBe('application/json'); nock.cleanAll(); }); - - it('redirect to route if feature toggle is false', async () => { - const res = { - locals: { - challengedAccessEnabled: false, - }, - redirect: jest.fn(), - render: jest.fn(), - } as unknown as Response; - const req = { - session: { - fromPost: false, - }, - } as AppRequest; - challengedSpecificAccessHandler(req, res); - expect(res.redirect).toHaveBeenCalledWith('/'); - }); }); diff --git a/yarn.lock b/yarn.lock index 96db1d0b..0a13cc6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7581,13 +7581,6 @@ __metadata: languageName: node linkType: hard -"clone@npm:2.x": - version: 2.1.2 - resolution: "clone@npm:2.1.2" - checksum: 10/d9c79efba655f0bf601ab299c57eb54cbaa9860fb011aee9d89ed5ac0d12df1660ab7642fddaabb9a26b7eff0e117d4520512cb70798319ff5d30a111b5310c2 - languageName: node - linkType: hard - "clone@npm:^1.0.2": version: 1.0.4 resolution: "clone@npm:1.0.4" @@ -12358,7 +12351,6 @@ __metadata: jquery: "npm:^3.5.1" js-yaml: "npm:^4.1.0" jwt-decode: "npm:^4.0.0" - launchdarkly-node-server-sdk: "npm:^7.0.0" lodash: "npm:^4.17.21" mini-css-extract-plugin: "npm:^2.2.0" mocha: "npm:^11.0.0" @@ -12403,28 +12395,6 @@ __metadata: languageName: unknown linkType: soft -"launchdarkly-eventsource@npm:1.4.4": - version: 1.4.4 - resolution: "launchdarkly-eventsource@npm:1.4.4" - checksum: 10/ed27acd89abc2546dbcd0f51c184171f21387315039055914211691cf02060ebf8ebc74ed51d4c8e816f3c73aa881e2c6fb17ea334a3c9b9877b46032ee297c9 - languageName: node - linkType: hard - -"launchdarkly-node-server-sdk@npm:^7.0.0": - version: 7.0.4 - resolution: "launchdarkly-node-server-sdk@npm:7.0.4" - dependencies: - async: "npm:^3.2.4" - launchdarkly-eventsource: "npm:1.4.4" - lru-cache: "npm:^6.0.0" - node-cache: "npm:^5.1.0" - semver: "npm:^7.5.4" - tunnel: "npm:0.0.6" - uuid: "npm:^8.3.2" - checksum: 10/52a524002b5ff645135b2e20c2a7bd8812f3c430c834e9fd39bd1dcf58355e216aacd6a2f5103a8eb82bac0f275c55bebc4c2594868b903b1c740d5a5fe762a5 - languageName: node - linkType: hard - "lazystream@npm:^1.0.0": version: 1.0.1 resolution: "lazystream@npm:1.0.1" @@ -12802,15 +12772,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10/fc1fe2ee205f7c8855fa0f34c1ab0bcf14b6229e35579ec1fd1079f31d6fc8ef8eb6fd17f2f4d99788d7e339f50e047555551ebd5e434dda503696e7c6591825 - languageName: node - linkType: hard - "lru-cache@npm:^7.14.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" @@ -13867,15 +13828,6 @@ __metadata: languageName: node linkType: hard -"node-cache@npm:^5.1.0": - version: 5.1.2 - resolution: "node-cache@npm:5.1.2" - dependencies: - clone: "npm:2.x" - checksum: 10/6ac71a9e65fdd8940883c3c188de4888ff592f5bf52e4d42436c49e2a575d635e7327acea490c49fa7c01d5fa81f7b6e060fd35cf6f6ec401fbd5f77a3ebeecf - languageName: node - linkType: hard - "node-domexception@npm:^1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0"