diff --git a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js index 1f36d05ea..45a43a6a9 100644 --- a/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js +++ b/packages/bruno-app/src/components/Environments/EnvironmentSettings/EnvironmentList/EnvironmentDetails/EnvironmentVariables/index.js @@ -5,7 +5,6 @@ import { useDispatch } from 'react-redux'; import SingleLineEditor from 'components/SingleLineEditor'; import StyledWrapper from './StyledWrapper'; import { uuid } from 'utils/common'; -import { maskInputValue } from 'utils/collections'; import { useFormik } from 'formik'; import * as Yup from 'yup'; import { variableNameRegex } from 'utils/common/regex'; @@ -96,10 +95,10 @@ const EnvironmentVariables = ({ environment, collection, setIsModified, original
Enabled | +Enabled | Name | Value | -Secret | +Secret |
|
-
- {variable.secret ? (
- {maskInputValue(variable.value)}
- ) : (
+ |
+ |
- + |
{
+ if (typeof enabled !== 'boolean') return;
+
+ console.log('Enabling masked editor: ' + enabled);
+ if (enabled == true) {
+ if (!this.maskedEditor) this.maskedEditor = new MaskedEditor(this.editor, '*');
+ this.maskedEditor.enable();
+ } else {
+ this.maskedEditor?.disable();
+ this.maskedEditor = null;
+ }
+ };
+
_onEdit = () => {
if (!this.ignoreChangeEvent && this.editor) {
this.cachedValue = this.editor.getValue();
@@ -110,6 +131,12 @@ class SingleLineEditor extends Component {
this.cachedValue = String(this.props.value);
this.editor.setValue(String(this.props.value) || '');
}
+ if (!isEqual(this.props.isSecret, prevProps.isSecret)) {
+ // If the secret flag has changed, update the editor to reflect the change
+ this._enableMaskedEditor(this.props.isSecret);
+ // also set the maskInput flag to the new value
+ this.setState({ maskInput: this.props.isSecret });
+ }
this.ignoreChangeEvent = false;
}
@@ -123,8 +150,35 @@ class SingleLineEditor extends Component {
this.editor.setOption('mode', 'brunovariables');
};
+ toggleVisibleSecret = () => {
+ const isVisible = !this.state.maskInput;
+ this.setState({ maskInput: isVisible });
+ this._enableMaskedEditor(isVisible);
+ };
+
+ /**
+ * @brief Eye icon to show/hide the secret value
+ * @returns ReactComponent The eye icon
+ */
+ secretEye = (isSecret) => {
+ return isSecret === true ? (
+
+ ) : null;
+ };
+
render() {
- return
+
+ );
}
}
export default SingleLineEditor;
diff --git a/packages/bruno-app/src/utils/common/codemirror.js b/packages/bruno-app/src/utils/common/codemirror.js
index f4013a366..cbb1a2b3a 100644
--- a/packages/bruno-app/src/utils/common/codemirror.js
+++ b/packages/bruno-app/src/utils/common/codemirror.js
@@ -12,6 +12,64 @@ const pathFoundInVariables = (path, obj) => {
return value !== undefined;
};
+/**
+ * Changes the render behaviour for a given CodeMirror editor.
+ * Replaces all **rendered** characters, not the actual value, with the provided character.
+ */
+export class MaskedEditor {
+ /**
+ * @param {import('codemirror').Editor} editor CodeMirror editor instance
+ * @param {string} maskChar Target character being applied to all content
+ */
+ constructor(editor, maskChar) {
+ this.editor = editor;
+ this.maskChar = maskChar;
+ this.enabled = false;
+ }
+
+ /**
+ * Set and apply new masking character
+ */
+ enable = () => {
+ this.enabled = true;
+ this.editor.setValue(this.editor.getValue());
+ this.editor.on('inputRead', this.maskContent);
+ this.update();
+ };
+
+ /** Disables masking of the editor field. */
+ disable = () => {
+ this.enabled = false;
+ this.editor.off('inputRead', this.maskContent);
+ this.editor.setValue(this.editor.getValue());
+ };
+
+ /** Updates the rendered content if enabled. */
+ update = () => {
+ if (this.enabled) this.maskContent();
+ };
+
+ /** Replaces all rendered characters, with the provided character. */
+ maskContent = () => {
+ const content = this.editor.getValue();
+ this.editor.operation(() => {
+ // Clear previous masked text
+ this.editor.getAllMarks().forEach((mark) => mark.clear());
+ // Apply new masked text
+ for (let i = 0; i < content.length; i++) {
+ if (content[i] !== '\n') {
+ const maskedNode = document.createTextNode(this.maskChar);
+ this.editor.markText(
+ { line: this.editor.posFromIndex(i).line, ch: this.editor.posFromIndex(i).ch },
+ { line: this.editor.posFromIndex(i + 1).line, ch: this.editor.posFromIndex(i + 1).ch },
+ { replacedWith: maskedNode, handleMouseEvents: true }
+ );
+ }
+ }
+ });
+ };
+}
+
export const defineCodeMirrorBrunoVariablesMode = (_variables, mode, highlightPathParams) => {
CodeMirror.defineMode('brunovariables', function (config, parserConfig) {
const { pathParams = {}, ...variables } = _variables || {};
|