From bc19934a93e173cc01ade6549a580db5c8272204 Mon Sep 17 00:00:00 2001 From: mhmdkrmabd Date: Wed, 2 Oct 2024 20:32:45 +0300 Subject: [PATCH 1/2] Minor updates and changes - Improved the name validation process of workspaces and connections. - The `Replication Strategy` attribute has been removed for virtual keyspaces. - Improvements for the `Add/Edit Connection` dialog. - Added new phrases to the localization files. --- localization/ar.json | 1 + localization/en.json | 3 +- localization/es.json | 1 + localization/fr.json | 1 + localization/gl.json | 1 + localization/iw.json | 1 + localization/zh.json | 1 + renderer/js/events/clusters.js | 20 +- renderer/js/events/workspaces.js | 2 +- renderer/js/funcs.js | 4 + renderer/js/init.js | 392 ++++++++++++++++--------------- 11 files changed, 230 insertions(+), 197 deletions(-) diff --git a/localization/ar.json b/localization/ar.json index d096686..8c3d66c 100755 --- a/localization/ar.json +++ b/localization/ar.json @@ -310,6 +310,7 @@ "the connection has been successfully updated": "لقد تم تحديث الاتصال بنجاح", "the current release version has been successfully copied to the clipboard": "تم نسخ نسخة الإصدار الحالي إلى الحافظة بنجاح", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "إن نسخة Apache Cassandra هي [b]$data[/b]، قد تحدث بعض السلوكيات غير المرغوبة ومشاكل توافق", + "the given name seems invalid, please provide a unique valid name": "يبدو أن الاسم المُعطى للاتصال غير صالح، يُرجى إعطاء اسم صالح ومميز للاتصال", "the importing process has finished, results for the workspaces are: $data": "لقد انتهت عملية الاستيراد، نتائج مساحات العمل: $data", "the local cluster [b]$data[/b] has been successfully deleted": "لقد تم حذف العنقود المحلي [b]$data[/b] بنجاح", "the local cluster [b]$data[/b] has been successfully stopped": "لقد تم إيقاف العنقود المحلي [b]$data[/b] بنجاح", diff --git a/localization/en.json b/localization/en.json index 2dd4c39..a69d943 100755 --- a/localization/en.json +++ b/localization/en.json @@ -311,6 +311,7 @@ "the connection has been successfully updated": "the connection has been successfully updated", "the current release version has been successfully copied to the clipboard": "the current release version has been successfully copied to the clipboard", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered", + "the given name seems invalid, please provide a unique valid name": "the given name seems invalid, please provide a unique valid name", "the importing process has finished, results for the workspaces are: $data": "the importing process has finished, results for the workspaces are: $data", "the local cluster [b]$data[/b] has been successfully deleted": "the local cluster [b]$data[/b] has been successfully deleted", "the local cluster [b]$data[/b] has been successfully stopped": "the local cluster [b]$data[/b] has been successfully stopped", @@ -336,8 +337,8 @@ "there is no difference between the previous and new metadata": "there is no difference between the previous and new metadata", "there's a new update!": "there's a new update!", "there's an active work area for the local cluster [b]$data[/b], please consider to close it before attempting to delete the local cluster again": "there's an active work area for the local cluster [b]$data[/b], please consider to close it before attempting to delete the local cluster again", - "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to edit or delete it": "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to edit or delete it", "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to delete the workspace [b]$data[/b]": "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to delete the workspace [b]$data[/b]", + "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to edit or delete it": "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to edit or delete it", "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to test it": "this connection [b]$data[/b] has an active work area, make sure to close its work area before attempting to test it", "this limit can be changed from the app's settings in the limits section": "this limit can be changed from the app's settings in the limits section", "this update needs an app restart": "this update needs an app restart", diff --git a/localization/es.json b/localization/es.json index edde685..33d0cc2 100644 --- a/localization/es.json +++ b/localization/es.json @@ -311,6 +311,7 @@ "the connection has been successfully updated": "La conexión se ha actualizado correctamente", "the current release version has been successfully copied to the clipboard": "La versión actual se ha copiado correctamente en el portapapeles", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "la versión detectada de Apache Cassandra es [b]$data[/b], se pueden encontrar comportamientos no deseados y problemas de compatibilidad", + "the given name seems invalid, please provide a unique valid name": "El nombre dado parece inválido, proporcione un nombre válido y único", "the importing process has finished, results for the workspaces are: $data": "El proceso de importación ha finalizado, los resultados de los espacios de trabajo son: $data", "the local cluster [b]$data[/b] has been successfully deleted": "El clúster local [b]$data[/b] se ha eliminado correctamente", "the local cluster [b]$data[/b] has been successfully stopped": "El clúster local [b]$data[/b] se ha detenido correctamente", diff --git a/localization/fr.json b/localization/fr.json index c3bc2f1..62a58c7 100755 --- a/localization/fr.json +++ b/localization/fr.json @@ -311,6 +311,7 @@ "the connection has been successfully updated": "La connexion a été mise à jour avec succès", "the current release version has been successfully copied to the clipboard": "La version actuelle a été copiée avec succès dans le presse-papiers", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "la version détectée d’Apache Cassandra est [b]$data[/b), des comportements indésirables et des problèmes de compatibilité peuvent être rencontrés", + "the given name seems invalid, please provide a unique valid name": "le nom donné semble invalide, veuillez fournir un nom valide unique", "the importing process has finished, results for the workspaces are: $data": "Le processus d’importation est terminé, les résultats pour les espaces de travail sont les suivants : $data", "the local cluster [b]$data[/b] has been successfully deleted": "Le cluster local [b]$data[/b] a été supprimé avec succès", "the local cluster [b]$data[/b] has been successfully stopped": "Le cluster local [b]$data[/b] a été arrêté avec succès", diff --git a/localization/gl.json b/localization/gl.json index 0c6a619..b59f506 100755 --- a/localization/gl.json +++ b/localization/gl.json @@ -311,6 +311,7 @@ "the connection has been successfully updated": "A conexión actualizouse con éxito", "the current release version has been successfully copied to the clipboard": "A versión actual foi copiada con éxito no portapapeis.", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "A versión detectada de Apache Cassandra é [b]$data[/b], poden atoparse problemas de comportamento e compatibilidade non desexados", + "the given name seems invalid, please provide a unique valid name": "o nome de pila non parece válido, proporcione un nome único e válido", "the importing process has finished, results for the workspaces are: $data": "O proceso de importación rematou, os resultados dos espazos de traballo son: $data", "the local cluster [b]$data[/b] has been successfully deleted": "O cluster local [b]$data[/b] foi eliminado con éxito", "the local cluster [b]$data[/b] has been successfully stopped": "O cluster local [b]$data[/b] foi detido con éxito", diff --git a/localization/iw.json b/localization/iw.json index 4f1d802..42f1022 100755 --- a/localization/iw.json +++ b/localization/iw.json @@ -311,6 +311,7 @@ "the connection has been successfully updated": "החיבור עודכן בהצלחה", "the current release version has been successfully copied to the clipboard": "גירסת ההפצה הנוכחית הועתקה בהצלחה ללוח", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "הגרסה שזוהתה של Apache Cassandra היא [b]$data[/b], ייתכן שתיתקל בבעיות התנהגות ותאימות לא רצויות", + "the given name seems invalid, please provide a unique valid name": "השם הפרטי נראה לא חוקי, אנא ספק שם חוקי ייחודי", "the importing process has finished, results for the workspaces are: $data": "תהליך הייבוא הסתיים, התוצאות עבור סביבות העבודה הן: $data", "the local cluster [b]$data[/b] has been successfully deleted": "האשכול המקומי [b]$data[/b] נמחק בהצלחה", "the local cluster [b]$data[/b] has been successfully stopped": "האשכול המקומי [b]$data[/b] הופסק בהצלחה", diff --git a/localization/zh.json b/localization/zh.json index cb74621..643dda3 100755 --- a/localization/zh.json +++ b/localization/zh.json @@ -311,6 +311,7 @@ "the connection has been successfully updated": "连接已成功更新", "the current release version has been successfully copied to the clipboard": "当前发行版已成功复制到剪贴板", "the detected version of Apache Cassandra is [b]$data[/b], unwanted behaviour and compatibility issues may be encountered": "检测到的 Apache Cassandra 版本为 [b]$data[/b],则可能会遇到不需要的行为和兼容性问题", + "the given name seems invalid, please provide a unique valid name": "给定的名称似乎无效,请提供一个唯一有效的名称", "the importing process has finished, results for the workspaces are: $data": "导入过程已完成,工作区的结果是:$data", "the local cluster [b]$data[/b] has been successfully deleted": "已成功删除本地群集 [b]$data[/b]", "the local cluster [b]$data[/b] has been successfully stopped": "已成功停止本地群集 [b]$data[/b]", diff --git a/renderer/js/events/clusters.js b/renderer/js/events/clusters.js index cec015f..3f2b508 100755 --- a/renderer/js/events/clusters.js +++ b/renderer/js/events/clusters.js @@ -7095,6 +7095,9 @@ let input = $(this), // Point at the current input workspaceID = getActiveWorkspaceID() // Get the active workspace's ID + // Remove any visual feedback about having an invalid value + input.removeClass('is-invalid') + // Ignore the input field if it is not associated with a section in the `cqlsh.rc` config file if (getAttributes(input, 'info-section') == 'none') return @@ -7119,9 +7122,6 @@ // Convert final value to string value = `${value}` - // Remove any visual feedback about having an invalid value - input.removeClass('is-invalid') - // Inner function to update the editor's content let update = async () => { isUpdatingEditor = true // Change the value to `true`; to prevent collisions @@ -8015,6 +8015,20 @@ */ extraCondition = editingMode ? clusterName != editedClusterObject.name : true + try { + if (Sanitize(minifyText(clusterName)).length > 0) + throw 0 + + // Enable the buttons in the footer + button.add('#testConnectionCluster').add('#switchEditor').removeAttr('disabled') + + // Show feedback to the user + showToast(I18next.capitalize(I18next.t(!editingMode ? 'add connection' : 'update connection')), I18next.capitalizeFirstLetter(I18next.t('the given name seems invalid, please provide a unique valid name')) + '.', 'failure') + + // Skip the upcoming code - terminate the saving/updating process - + return + } catch (e) {} + try { // If there's no duplication then skip this try-catch block if ([undefined, null].includes(exists) || !extraCondition) diff --git a/renderer/js/events/workspaces.js b/renderer/js/events/workspaces.js index 4863cb2..581dcf9 100755 --- a/renderer/js/events/workspaces.js +++ b/renderer/js/events/workspaces.js @@ -918,7 +918,7 @@ $(document).on('getWorkspaces refreshWorkspaces', function(e) { let nameExists = allWorkspaces.find((workspace) => manipulateText(workspace.name) == manipulateText(name.val()) && workspace.id != workspaceID) // If the name exists, or the name is invalid - if (nameExists != undefined || name.val().trim().length <= 0 || Sanitize(name.val()).length <= 0) { + if (nameExists != undefined || name.val().trim().length <= 0 || Sanitize(minifyText(name.val())).length <= 0) { // Add `invalid` class for the name input field name.parent().addClass('mdc-text-field--invalid') diff --git a/renderer/js/funcs.js b/renderer/js/funcs.js index 929e79f..e02816c 100755 --- a/renderer/js/funcs.js +++ b/renderer/js/funcs.js @@ -896,6 +896,7 @@ let convertTableToTabulator = (json, container, callback) => { * @Return: {object} a valid tree structure to be rendered */ let buildTreeview = (metadata, ignoreTitles = false) => { + console.log(metadata); /** * Due to the way JSTree is coded, there's an issue with the paths in Windows * To solve this issue, this inner function replaces the backward slashes @@ -1152,6 +1153,9 @@ let buildTreeview = (metadata, ignoreTitles = false) => { buildTreeViewForChild(keyspacesID, keyspaceID, `Keyspace`, keyspace, 'keyspace') try { + if (keyspace.replication_strategy == undefined) + throw 0 + let replicationStrategy = JSON.parse(repairJSON(keyspace.replication_strategy)), replicationStrategyID = getRandomID(30) diff --git a/renderer/js/init.js b/renderer/js/init.js index b6a5885..1700fd3 100755 --- a/renderer/js/init.js +++ b/renderer/js/init.js @@ -823,234 +823,242 @@ $(document).on('initialize', () => { */ editor.layout() + let updateTimeout + // Once there is a change in the editor (by pasting, typing, etc...) editor.getModel().onDidChangeContent(() => { - // If the editor is updating then stop once - if (isUpdatingEditor) { - isUpdatingEditor = false + try { + clearTimeout(updateTimeout) + } catch (e) {} - // By doing this, the `ChangeContent` event is triggered again after updating the content - editor.setValue(editor.getValue()) + updateTimeout = setTimeout(() => { + // If the editor is updating then stop once + if (isUpdatingEditor) { + isUpdatingEditor = false - // Skip the upcoming code - return - } + // By doing this, the `ChangeContent` event is triggered again after updating the content + editor.setValue(editor.getValue()) - // Disable the save cluster button - $('#addCluster').attr('disabled', 'disabled') + // Skip the upcoming code + return + } - // Detected sensitive data - username, password - - let detectedSensitiveData = false, - // Get the currently active workspace's ID - workspaceID = getActiveWorkspaceID() + // Disable the save cluster button + $('#addCluster').attr('disabled', 'disabled') - // Get and parse the content of the current `cqlsh.rc `file and change inputs' values as needed - Modules.Clusters.getCQLSHRCContent(workspaceID, null, editor).then((_content) => { - try { - // Update the global cqlsh values array with the current values from the editor - cqlshValues = _content - - // Define the sections [connection, ui, SSL, etc...] - let _sections = Object.keys(_content) - - // If there are no sections then the cqlsh is not - in terms of syntax - correct or something is missing then stop this process - if (_sections.length <= 0) - throw 0 - - // Loop through each section - for (let _section of _sections) { - // Define the current section's keys [hostname, port, SSL, etc...] - let _keys = Object.keys(_content[_section]) - - // If the current section has no keys then skip this section and move to the next one - if (_keys.length <= 0) - continue - - // Loop through each key/option - for (let _key of _keys) { - // Check if this key/option is considered to be sensitive data that shouldn't be in the config file - if (Modules.Consts.SensitiveData.includes(_key)) - detectedSensitiveData = true - - // Get the current key/option input field's object - let inputObject = getElementMDBObject($(`[info-section="${_section}"][info-key="${_key}"]`)), - // Get the value for the key/option - optionValue = _content[_section][_key], - // Point at the input field - input = $(`[info-section="${_section}"][info-key="${_key}"]`) - - // Try to set the value using the `setValue` method - try { - input.val(optionValue) - } catch (e) {} + // Detected sensitive data - username, password - + let detectedSensitiveData = false, + // Get the currently active workspace's ID + workspaceID = getActiveWorkspaceID() - // Add values to the checkbox inputs - try { - // If the input's type is not `checkbox` then skip this try-catch block - if (input.attr('type') != 'checkbox') - throw 0 + // Get and parse the content of the current `cqlsh.rc `file and change inputs' values as needed + Modules.Clusters.getCQLSHRCContent(workspaceID, null, editor).then((_content) => { + try { + // Update the global cqlsh values array with the current values from the editor + cqlshValues = _content - // Update the checkbox's status - input.prop('checked', optionValue == 'true') - } catch (e) {} + // Define the sections [connection, ui, SSL, etc...] + let _sections = Object.keys(_content) - // Add values to the file input fields - try { - // If the input field's type is not `file` then skip this try-catch block - if (input.attr('type') == 'text' && input.parent().attr('role') != 'file-selector') - throw 0 + // If there are no sections then the cqlsh is not - in terms of syntax - correct or something is missing then stop this process + if (_sections.length <= 0) + throw 0 - /** - * Update the tooltip's content and state - * Get the object - */ - let tooltipObject = mdbObjects.filter((object) => object.type == 'Tooltip' && object.element.is(input)) + // Loop through each section + for (let _section of _sections) { + // Define the current section's keys [hostname, port, SSL, etc...] + let _keys = Object.keys(_content[_section]) + + // If the current section has no keys then skip this section and move to the next one + if (_keys.length <= 0) + continue + + // Loop through each key/option + for (let _key of _keys) { + // Check if this key/option is considered to be sensitive data that shouldn't be in the config file + if (Modules.Consts.SensitiveData.includes(_key)) + detectedSensitiveData = true + + // Get the current key/option input field's object + let inputObject = getElementMDBObject($(`[info-section="${_section}"][info-key="${_key}"]`)), + // Get the value for the key/option + optionValue = _content[_section][_key], + // Point at the input field + input = $(`[info-section="${_section}"][info-key="${_key}"]`) + + // Try to set the value using the `setValue` method + try { + input.val(optionValue) + } catch (e) {} - // If the path to the file is invalid or inaccessible then don't adopt it - if (!pathIsAccessible(optionValue)) { - // Clear the input's value - input.val('') + // Add values to the checkbox inputs + try { + // If the input's type is not `checkbox` then skip this try-catch block + if (input.attr('type') != 'checkbox') + throw 0 - // Clear the file's name preview - input.parent().attr('file-name', '-') + // Update the checkbox's status + input.prop('checked', optionValue == 'true') + } catch (e) {} - // Disable the tooltip + // Add values to the file input fields + try { + // If the input field's type is not `file` then skip this try-catch block + if (input.attr('type') == 'text' && input.parent().attr('role') != 'file-selector') + throw 0 + + /** + * Update the tooltip's content and state + * Get the object + */ + let tooltipObject = mdbObjects.filter((object) => object.type == 'Tooltip' && object.element.is(input)) + + // If the path to the file is invalid or inaccessible then don't adopt it + if (!pathIsAccessible(optionValue)) { + // Clear the input's value + input.val('') + + // Clear the file's name preview + input.parent().attr('file-name', '-') + + // Disable the tooltip + try { + tooltipObject[0].object.disable() + } catch (e) {} + + // Skip the upcoming code in this try-catch block + throw 0 + } + + // Enable the tooltip and update its content try { - tooltipObject[0].object.disable() + tooltipObject[0].object.enable() + tooltipObject[0].object.setContent(optionValue) } catch (e) {} - // Skip the upcoming code in this try-catch block - throw 0 - } - - // Enable the tooltip and update its content - try { - tooltipObject[0].object.enable() - tooltipObject[0].object.setContent(optionValue) + // Set the selected file's path + input.val(optionValue) + input.parent().attr('file-name', Path.basename(optionValue)) } catch (e) {} - // Set the selected file's path - input.val(optionValue) - input.parent().attr('file-name', Path.basename(optionValue)) - } catch (e) {} - - // Update the input's object - inputObject.update() - inputObject._deactivate() + // Update the input's object + inputObject.update() + inputObject._deactivate() + } } - } - } catch (e) {} finally { - // Check if there's any disabled key/option after the change and clear its input field in the UI - $('[info-section][info-key]').each(function() { - // Get the input's Material Design object - let object_ = getElementMDBObject($(this)), - // Get the inputs' section, and its related key/option's name - [section_, key_] = getAttributes($(this), ['info-section', 'info-key']) - - // If the input section is `none` then skip it and move to the next key/option - if (section_ == 'none') - return - - try { - /** - * Find the input's value from the editor - * If it is not `undefined`; then it means this value has been updated already and no need to handle it as an empty or `undefined` value - */ - if (_content[section_][key_] != undefined) + } catch (e) {} finally { + // Check if there's any disabled key/option after the change and clear its input field in the UI + $('[info-section][info-key]').each(function() { + // Get the input's Material Design object + let object_ = getElementMDBObject($(this)), + // Get the inputs' section, and its related key/option's name + [section_, key_] = getAttributes($(this), ['info-section', 'info-key']) + + // If the input section is `none` then skip it and move to the next key/option + if (section_ == 'none') return - // Handle when the input is actually a file selector try { - // If the input is not a file selector then skip this try-catch block - if ($(this).parent().attr('file-name') == undefined) - throw 0 - /** - * Update the tooltip's content and state - * Get the object + * Find the input's value from the editor + * If it is not `undefined`; then it means this value has been updated already and no need to handle it as an empty or `undefined` value */ - let tooltipObject = mdbObjects.filter((object) => object.type == 'Tooltip' && object.element.is($(this))) - - // Clear the file's name preview - $(this).parent().attr('file-name', '-') + if (_content[section_][key_] != undefined) + return - // Disable the tooltip + // Handle when the input is actually a file selector try { - tooltipObject[0].object.disable() + // If the input is not a file selector then skip this try-catch block + if ($(this).parent().attr('file-name') == undefined) + throw 0 + + /** + * Update the tooltip's content and state + * Get the object + */ + let tooltipObject = mdbObjects.filter((object) => object.type == 'Tooltip' && object.element.is($(this))) + + // Clear the file's name preview + $(this).parent().attr('file-name', '-') + + // Disable the tooltip + try { + tooltipObject[0].object.disable() + } catch (e) {} } catch (e) {} - } catch (e) {} - /** - * If it is `undefined` then it hasn't been found in the `cqlsh.rc` file - * Set the input value to '' - */ - try { - $(this).val('') - } catch (e) { - // If the previous set didn't work then try to call the `selected` attribute + /** + * If it is `undefined` then it hasn't been found in the `cqlsh.rc` file + * Set the input value to '' + */ try { - $(this).prop('checked', getAttributes($(this), 'default-value') == 'true' ? true : false) - } catch (e) {} - } finally { - // Update the object - object_.update() - object_._deactivate() - } - } catch (e) {} - }) - } + $(this).val('') + } catch (e) { + // If the previous set didn't work then try to call the `selected` attribute + try { + $(this).prop('checked', getAttributes($(this), 'default-value') == 'true' ? true : false) + } catch (e) {} + } finally { + // Update the object + object_.update() + object_._deactivate() + } + } catch (e) {} + }) + } - // Remove all decorations - if (editorDecorations != null) - editor.removeDecorations(editorDecorations) + // Remove all decorations + if (editorDecorations != null) + editor.removeDecorations(editorDecorations) - // Sensitive data has been detected, if not, just stop here - if (!detectedSensitiveData) - return + // Sensitive data has been detected, if not, just stop here + if (!detectedSensitiveData) + return - /** - * If sensitive data has been detected then get the line number for those data and add red highlighter to them - * - * Define the alerts array which will be passed to the editor to decorate them - */ - let alerts = [], - // Get the editor's model object - editorModel = editor.getModel(), - // Get the number of lines in the editor - lines = editorModel.getLineCount() - - // Loop through editor's lines - for (let i = 1; i <= lines; i++) { - try { - // Get the current line based on the index - let line = editorModel.getLineContent(i), - // Get the option in that current line if possible, and make sure it is active if so - active = line.match(/^((?![\;\[])|(\;*\s*\[)).+/gm), - // Split that active option, and look at the key - [key, value] = active[0].split(/\s*\=\s*/gm) - - // The key/option name is not considered sensitive data - if (!Modules.Consts.SensitiveData.includes(key)) - continue - - // If the key is considered sensitive data then add highlighter to that data line - let alert = { - range: new monaco.Range(i, 0, i, 0), - options: { - isWholeLine: true, - className: 'line-forbidden', - glyphMarginClassName: 'forbidden', + /** + * If sensitive data has been detected then get the line number for those data and add red highlighter to them + * + * Define the alerts array which will be passed to the editor to decorate them + */ + let alerts = [], + // Get the editor's model object + editorModel = editor.getModel(), + // Get the number of lines in the editor + lines = editorModel.getLineCount() + + // Loop through editor's lines + for (let i = 1; i <= lines; i++) { + try { + // Get the current line based on the index + let line = editorModel.getLineContent(i), + // Get the option in that current line if possible, and make sure it is active if so + active = line.match(/^((?![\;\[])|(\;*\s*\[)).+/gm), + // Split that active option, and look at the key + [key, value] = active[0].split(/\s*\=\s*/gm) + + // The key/option name is not considered sensitive data + if (!Modules.Consts.SensitiveData.includes(key)) + continue + + // If the key is considered sensitive data then add highlighter to that data line + let alert = { + range: new monaco.Range(i, 0, i, 0), + options: { + isWholeLine: true, + className: 'line-forbidden', + glyphMarginClassName: 'forbidden', + } } - } - // Push that alert to be applied later in the editor - alerts.push(alert) - } catch (e) {} - } + // Push that alert to be applied later in the editor + alerts.push(alert) + } catch (e) {} + } - // Apply highlighters/decorations - editorDecorations = editor.deltaDecorations([], alerts) - }) + // Apply highlighters/decorations + editorDecorations = editor.deltaDecorations([], alerts) + }) + }, 250) }) } catch (e) { try { From d52e216295698b132c9a078ae0c266c70ca26254 Mon Sep 17 00:00:00 2001 From: mhmdkrmabd Date: Thu, 3 Oct 2024 05:21:52 +0300 Subject: [PATCH 2/2] Minor updates and changes - SSH and Cassandra credentials --- renderer/js/events/clusters.js | 91 ++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/renderer/js/events/clusters.js b/renderer/js/events/clusters.js index 3f2b508..7f9377a 100755 --- a/renderer/js/events/clusters.js +++ b/renderer/js/events/clusters.js @@ -1690,7 +1690,6 @@ if (isConnectionLost) return - try { if (!((['connectionerror:', ',last_host']).some((keyword) => minifyText(allOutput).includes(keyword)))) throw 0 @@ -8222,6 +8221,12 @@ editedClusterObject = newEditedCluster } catch (e) {} + // Refresh clusters for the currently active workspace + $(document).trigger('refreshClusters', workspaceID) + + // Get workspaces; to sync with newly added/updated clusters + $(document).trigger('getWorkspaces') + { setTimeout(() => { let clusterElement = $(`div.clusters-container div.cluster[data-id="${finalCluster.info.id}"]`), @@ -8235,6 +8240,34 @@ // Point at the status element - the flashing circle at the top right - statusElement = clusterElement.children('div.status') + + try { + if (!secrets[0]) + throw 0 + + getKey('public', (key) => { + try { + // If the received key is valid to be used then skip this try-catch block + if (key.length <= 0) + throw 0 + + for (secret of secrets) { + if (typeof secret !== 'object') + continue + + try { + if (`${secret.value}`.length <= 0) + throw 0 + + let value = encrypt(key, secret.value) + + clusterElement.attr(`data-${secret.name.toLowerCase().replace('ssh', 'ssh-')}`, value) + } catch (e) {} + } + } catch (e) {} + }) + } catch (e) {} + try { if (tempClusterID == null) throw 0 @@ -8285,12 +8318,6 @@ }) }, 1000) } - - // Refresh clusters for the currently active workspace - $(document).trigger('refreshClusters', workspaceID) - - // Get workspaces; to sync with newly added/updated clusters - $(document).trigger('getWorkspaces') } // End of the inner function to do processes after saving/updating cluster @@ -8356,6 +8383,30 @@ // Determine the proper function to be called based on whether the current mode is `edit` or not let clustersCallFunction = editingMode ? Modules.Clusters.updateCluster : Modules.Clusters.saveCluster + /** + * Encrypt all provided secrets - for Apache Cassandra and SSH - + * + * Create an array of names and values of the secrets + */ + let secrets = [{ + name: 'username', + value: username + }, { + name: 'password', + value: password + }, { + name: 'sshUsername', + value: sshUsername + }, { + name: 'sshPassword', + value: sshPassword + }, + { + name: 'sshPassphrase', + value: sshPassphrase + } + ] + try { // If there's no need to wait for the encryption process then skip this try-catch block if (!waitForEncryption) @@ -8378,30 +8429,6 @@ return } catch (e) {} - /** - * Encrypt all provided secrets - for Apache Cassandra and SSH - - * - * Create an array of names and values of the secrets - */ - let secrets = [{ - name: 'username', - value: username - }, { - name: 'password', - value: password - }, { - name: 'sshUsername', - value: sshUsername - }, { - name: 'sshPassword', - value: sshPassword - }, - { - name: 'sshPassphrase', - value: sshPassphrase - } - ] - // Values will be saved in the `secrets` object finalCluster.info.secrets = [], // Array to be a copy from the original secrets before manipulation @@ -8443,7 +8470,7 @@ clustersCallFunction(workspaceID, finalCluster).then((status) => postProcess(status, editingMode ? { ...savedSecrets, ...finalCluster.info.credentials - } : null)) + } : [true, ...secrets])) }) // Skip the upcoming code