From 61ffa3035270021fb6226188290c708386872372 Mon Sep 17 00:00:00 2001 From: ShahanaFarooqui Date: Mon, 22 Apr 2024 22:27:52 -0700 Subject: [PATCH] 2FA and Password reset --- backend/controllers/shared/RTLConf.js | 23 ++++++++++++++----- backend/utils/config.js | 9 ++++---- server/controllers/shared/RTLConf.ts | 23 ++++++++++++++----- server/utils/config.ts | 9 ++++---- .../two-factor-auth.component.ts | 2 ++ .../app-settings/app-settings.component.ts | 1 - src/app/store/rtl.effects.ts | 1 + 7 files changed, 47 insertions(+), 21 deletions(-) diff --git a/backend/controllers/shared/RTLConf.js b/backend/controllers/shared/RTLConf.js index d5688d80..4e50be2c 100644 --- a/backend/controllers/shared/RTLConf.js +++ b/backend/controllers/shared/RTLConf.js @@ -47,10 +47,16 @@ export const removeSecureData = (config) => { return config; }; export const addSecureData = (config) => { - config.SSO.rtlCookiePath = common.appConfig.SSO.rtlCookiePath; - config.multiPass = common.appConfig.multiPass; + config.rtlConfFilePath = common.appConfig.rtlConfFilePath; + config.rtlPass = common.appConfig.rtlPass; config.multiPassHashed = common.appConfig.multiPassHashed; - config.secret2FA = common.appConfig.secret2FA; + config.SSO.rtlCookiePath = common.appConfig.SSO.rtlCookiePath; + if (common.appConfig.multiPass) { + config.multiPass = common.appConfig.multiPass; + } + if (config.secret2FA === common.appConfig.secret2FA) { + config.secret2FA = common.appConfig.secret2FA; + } config.nodes.map((node, i) => { if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].Authentication && common.appConfig.nodes[i].Authentication.macaroonPath) { node.Authentication.macaroonPath = common.appConfig.nodes[i].Authentication.macaroonPath; @@ -111,6 +117,7 @@ export const getApplicationSettings = (req, res, next) => { appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate; appConfData.enable2FA = common.appConfig.enable2FA; appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index); + common.appConfig.selectedNodeIndex = appConfData.selectedNodeIndex; const token = req.headers.authorization ? req.headers.authorization.split(' ')[1] : ''; jwt.verify(token, common.secret_key, (err, user) => { if (err) { @@ -232,12 +239,16 @@ export const updateApplicationSettings = (req, res, next) => { const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json'; try { const config = addSecureData(req.body); + common.appConfig = JSON.parse(JSON.stringify(config)); delete config.selectedNodeIndex; delete config.enable2FA; + delete config.allowPasswordUpdate; + delete config.rtlConfFilePath; + delete config.rtlPass; fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8'); - common.appConfig = config; - logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: maskPasswords(common.appConfig) }); - res.status(201).json(removeSecureData(config)); + const newConfig = JSON.parse(JSON.stringify(common.appConfig)); + logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: maskPasswords(newConfig) }); + res.status(201).json(removeSecureData(newConfig)); } catch (errRes) { const errMsg = 'Update Default Node Error'; diff --git a/backend/utils/config.js b/backend/utils/config.js index 1cfa8e1f..3d8d3c6c 100644 --- a/backend/utils/config.js +++ b/backend/utils/config.js @@ -115,10 +115,11 @@ export class ConfigService { } }; this.validateNodeConfig = (config) => { + config.allowPasswordUpdate = true; if ((process?.env?.RTL_SSO && +process?.env?.RTL_SSO === 0) || (typeof process?.env?.RTL_SSO === 'undefined' && +config.SSO.rtlSSO === 0)) { if (process?.env?.APP_PASSWORD && process?.env?.APP_PASSWORD.trim() !== '') { config.rtlPass = this.hash.update(process?.env?.APP_PASSWORD).digest('hex'); - this.common.appConfig.allowPasswordUpdate = false; + config.allowPasswordUpdate = false; } else if (config.multiPassHashed && config.multiPassHashed !== '') { config.rtlPass = config.multiPassHashed; @@ -354,13 +355,13 @@ export class ConfigService { }; this.setServerConfiguration = () => { try { - this.common.appConfig.rtlConfFilePath = (process?.env?.RTL_CONFIG_PATH) ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..'); - const confFileFullPath = this.common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json'; + const rtlConfFilePath = (process?.env?.RTL_CONFIG_PATH) ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..'); + const confFileFullPath = rtlConfFilePath + sep + 'RTL-Config.json'; if (!fs.existsSync(confFileFullPath)) { fs.writeFileSync(confFileFullPath, JSON.stringify(this.setDefaultConfig())); } const config = JSON.parse(fs.readFileSync(confFileFullPath, 'utf-8')); - config.rtlConfFilePath = this.common.appConfig.rtlConfFilePath; + config.rtlConfFilePath = rtlConfFilePath; this.updateLogByLevel(); this.validateNodeConfig(config); this.setSelectedNode(config); diff --git a/server/controllers/shared/RTLConf.ts b/server/controllers/shared/RTLConf.ts index dbf36f99..cae76593 100644 --- a/server/controllers/shared/RTLConf.ts +++ b/server/controllers/shared/RTLConf.ts @@ -52,10 +52,16 @@ export const removeSecureData = (config: ApplicationConfig) => { }; export const addSecureData = (config: ApplicationConfig) => { - config.SSO.rtlCookiePath = common.appConfig.SSO.rtlCookiePath; - config.multiPass = common.appConfig.multiPass; + config.rtlConfFilePath = common.appConfig.rtlConfFilePath; + config.rtlPass = common.appConfig.rtlPass; config.multiPassHashed = common.appConfig.multiPassHashed; - config.secret2FA = common.appConfig.secret2FA; + config.SSO.rtlCookiePath = common.appConfig.SSO.rtlCookiePath; + if (common.appConfig.multiPass) { + config.multiPass = common.appConfig.multiPass; + } + if (config.secret2FA === common.appConfig.secret2FA) { + config.secret2FA = common.appConfig.secret2FA; + } config.nodes.map((node, i) => { if (common.appConfig && common.appConfig.nodes && common.appConfig.nodes.length > i && common.appConfig.nodes[i].Authentication && common.appConfig.nodes[i].Authentication.macaroonPath) { node.Authentication.macaroonPath = common.appConfig.nodes[i].Authentication.macaroonPath; @@ -115,6 +121,7 @@ export const getApplicationSettings = (req, res, next) => { appConfData.allowPasswordUpdate = common.appConfig.allowPasswordUpdate; appConfData.enable2FA = common.appConfig.enable2FA; appConfData.selectedNodeIndex = (req.session.selectedNode && req.session.selectedNode.index ? req.session.selectedNode.index : common.selectedNode.index); + common.appConfig.selectedNodeIndex = appConfData.selectedNodeIndex; const token = req.headers.authorization ? req.headers.authorization.split(' ')[1] : ''; jwt.verify(token, common.secret_key, (err, user) => { if (err) { @@ -237,12 +244,16 @@ export const updateApplicationSettings = (req, res, next) => { const RTLConfFile = common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json'; try { const config = addSecureData(req.body); + common.appConfig = JSON.parse(JSON.stringify(config)); delete config.selectedNodeIndex; delete config.enable2FA; + delete config.allowPasswordUpdate; + delete config.rtlConfFilePath; + delete config.rtlPass; fs.writeFileSync(RTLConfFile, JSON.stringify(config, null, 2), 'utf-8'); - common.appConfig = config; - logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: maskPasswords(common.appConfig) }); - res.status(201).json(removeSecureData(config)); + const newConfig = JSON.parse(JSON.stringify(common.appConfig)); + logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'RTLConf', msg: 'Application Settings Updated', data: maskPasswords(newConfig) }); + res.status(201).json(removeSecureData(newConfig)); } catch (errRes) { const errMsg = 'Update Default Node Error'; const err = common.handleError({ statusCode: 500, message: errMsg, error: errRes }, 'RTLConf', errMsg, req.session.selectedNode); diff --git a/server/utils/config.ts b/server/utils/config.ts index bce33d2b..2df7edfb 100644 --- a/server/utils/config.ts +++ b/server/utils/config.ts @@ -123,10 +123,11 @@ export class ConfigService { }; private validateNodeConfig = (config) => { + config.allowPasswordUpdate = true; if ((process?.env?.RTL_SSO && +process?.env?.RTL_SSO === 0) || (typeof process?.env?.RTL_SSO === 'undefined' && +config.SSO.rtlSSO === 0)) { if (process?.env?.APP_PASSWORD && process?.env?.APP_PASSWORD.trim() !== '') { config.rtlPass = this.hash.update(process?.env?.APP_PASSWORD).digest('hex'); - this.common.appConfig.allowPasswordUpdate = false; + config.allowPasswordUpdate = false; } else if (config.multiPassHashed && config.multiPassHashed !== '') { config.rtlPass = config.multiPassHashed; } else if (config.multiPass && config.multiPass !== '') { @@ -333,13 +334,13 @@ export class ConfigService { public setServerConfiguration = () => { try { - this.common.appConfig.rtlConfFilePath = (process?.env?.RTL_CONFIG_PATH) ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..'); - const confFileFullPath = this.common.appConfig.rtlConfFilePath + sep + 'RTL-Config.json'; + const rtlConfFilePath = (process?.env?.RTL_CONFIG_PATH) ? process?.env?.RTL_CONFIG_PATH : join(this.directoryName, '../..'); + const confFileFullPath = rtlConfFilePath + sep + 'RTL-Config.json'; if (!fs.existsSync(confFileFullPath)) { fs.writeFileSync(confFileFullPath, JSON.stringify(this.setDefaultConfig())); } const config = JSON.parse(fs.readFileSync(confFileFullPath, 'utf-8')); - config.rtlConfFilePath = this.common.appConfig.rtlConfFilePath; + config.rtlConfFilePath = rtlConfFilePath; this.updateLogByLevel(); this.validateNodeConfig(config); this.setSelectedNode(config); diff --git a/src/app/shared/components/data-modal/two-factor-auth/two-factor-auth.component.ts b/src/app/shared/components/data-modal/two-factor-auth/two-factor-auth.component.ts index a1ca3b14..cc61460c 100644 --- a/src/app/shared/components/data-modal/two-factor-auth/two-factor-auth.component.ts +++ b/src/app/shared/components/data-modal/two-factor-auth/two-factor-auth.component.ts @@ -91,6 +91,7 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy { onVerifyToken(): boolean | void { if (this.appConfig?.enable2FA) { + this.appConfig.enable2FA = false; this.appConfig.secret2FA = ''; this.store.dispatch(updateApplicationSettings({ payload: this.appConfig })); this.generateSecret(); @@ -104,6 +105,7 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy { this.tokenFormGroup.controls.token.setErrors({ notValid: true }); return true; } + this.appConfig.enable2FA = true; this.appConfig.secret2FA = this.secretFormGroup.controls.secret.value; this.store.dispatch(updateApplicationSettings({ payload: this.appConfig })); this.tokenFormGroup.controls.token.setValue(''); diff --git a/src/app/shared/components/settings/app-settings/app-settings.component.ts b/src/app/shared/components/settings/app-settings/app-settings.component.ts index df215def..7b24428d 100644 --- a/src/app/shared/components/settings/app-settings/app-settings.component.ts +++ b/src/app/shared/components/settings/app-settings/app-settings.component.ts @@ -4,7 +4,6 @@ import { takeUntil } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { faWindowRestore, faPlus, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; -import { UI_MESSAGES } from '../../../services/consts-enums-functions'; import { RTLConfiguration } from '../../../models/RTLconfig'; import { LoggerService } from '../../../services/logger.service'; diff --git a/src/app/store/rtl.effects.ts b/src/app/store/rtl.effects.ts index eba8ee74..3aa5189e 100644 --- a/src/app/store/rtl.effects.ts +++ b/src/app/store/rtl.effects.ts @@ -287,6 +287,7 @@ export class RTLEffects implements OnDestroy { pipe(map((appConfig: RTLConfiguration) => { this.store.dispatch(updateRootAPICallStatus({ payload: { action: 'updateApplicationSettings', status: APICallStatusEnum.COMPLETED } })); this.store.dispatch(closeSpinner({ payload: UI_MESSAGES.UPDATE_APPLICATION_SETTINGS })); + this.store.dispatch(openSnackBar({ payload: 'Application Settings Updated Successfully!' })); return { type: RTLActions.SET_APPLICATION_SETTINGS, payload: appConfig