From ddd7f414795a6aabb1638e145383b6fc213ed592 Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Wed, 12 Oct 2022 05:43:48 +0300 Subject: [PATCH 01/27] initial --- src/config/config_service.py | 10 ++++++---- src/model/script_config.py | 5 +++++ src/web/server.py | 11 +++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/config/config_service.py b/src/config/config_service.py index c1182374..76edec32 100644 --- a/src/config/config_service.py +++ b/src/config/config_service.py @@ -3,13 +3,14 @@ import os import re from collections import namedtuple -from typing import Union +from typing import List, Union from auth.authorization import Authorizer from config.exceptions import InvalidConfigException from model import script_config from model.model_helper import InvalidFileException -from model.script_config import get_sorted_config +from model.script_config import get_sorted_config, GetShortConfigFailedError +from src.model.script_config import ShortConfig from utils import os_utils, file_utils, process_utils, custom_json, custom_yaml from utils.file_utils import to_filename from utils.string_utils import is_blank, strip @@ -176,7 +177,7 @@ def list_configs(self, user, mode=None): conf_service = self - def load_script(path, content): + def load_script(path, content) -> Union[ShortConfig, GetShortConfigFailedError]: try: config_object = self.load_config_file(path, content) short_config = script_config.read_short(path, config_object) @@ -193,6 +194,7 @@ def load_script(path, content): return short_config except: LOGGER.exception('Could not load script: ' + path) + return GetShortConfigFailedError(path) return self._visit_script_configs(load_script) @@ -209,7 +211,7 @@ def load_config_model(self, name, user, parameter_values=None, skip_invalid_para return self._load_script_config(path, config_object, user, parameter_values, skip_invalid_parameters) - def _visit_script_configs(self, visitor): + def _visit_script_configs(self, visitor) -> List[ Union[ShortConfig, GetShortConfigFailedError] ]: configs_dir = self._script_configs_folder files = os.listdir(configs_dir) diff --git a/src/model/script_config.py b/src/model/script_config.py index 3823c29d..dac281da 100644 --- a/src/model/script_config.py +++ b/src/model/script_config.py @@ -28,6 +28,11 @@ def __init__(self): self.admin_users = [] self.group = None +class GetShortConfigFailedError(object): + def __init__(self, path): + self.path = path + # self.group = 'Parsing failed' + self.cannotParse = True @observable_fields( 'script_command', diff --git a/src/web/server.py b/src/web/server.py index b052fa3c..3d2d68d7 100755 --- a/src/web/server.py +++ b/src/web/server.py @@ -137,9 +137,16 @@ def get(self, user): configs = self.application.config_service.list_configs(user, mode) - scripts = [{'name': conf.name, 'group': conf.group} for conf in configs] + scripts = [] + failed = [] - self.write(json.dumps({'scripts': scripts})) + for conf in configs: + if hasattr(conf, 'cannotParse'): + failed.append({'path': conf.path }) + else: + scripts.append({'name': conf.name, 'group': conf.group }) + + self.write(json.dumps({'scripts': scripts, 'failed': failed})) class AdminUpdateScriptEndpoint(BaseRequestHandler): From aa827623a6979bddc24fad75de07bc1517b581bf Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Fri, 14 Oct 2022 04:56:58 +0300 Subject: [PATCH 02/27] frontend initial (tests not fixed) --- .../components/scripts/ScriptFailedGroup.vue | 44 +++++++++++++++++++ .../components/scripts/ScriptListGroup.css | 20 +++++++++ .../components/scripts/ScriptListGroup.vue | 23 +--------- .../components/scripts/ScriptsList.vue | 12 ++++- web-src/src/main-app/store/scripts.js | 9 +++- 5 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 web-src/src/main-app/components/scripts/ScriptFailedGroup.vue create mode 100644 web-src/src/main-app/components/scripts/ScriptListGroup.css diff --git a/web-src/src/main-app/components/scripts/ScriptFailedGroup.vue b/web-src/src/main-app/components/scripts/ScriptFailedGroup.vue new file mode 100644 index 00000000..171519fb --- /dev/null +++ b/web-src/src/main-app/components/scripts/ScriptFailedGroup.vue @@ -0,0 +1,44 @@ + + + + {{failedItems.name}} + + {{ failedItems.isActive ? 'expand_less' : 'expand_more' }} + + + + + {{ item.path }} + + + + + + + + \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptListGroup.css b/web-src/src/main-app/components/scripts/ScriptListGroup.css new file mode 100644 index 00000000..f9395280 --- /dev/null +++ b/web-src/src/main-app/components/scripts/ScriptListGroup.css @@ -0,0 +1,20 @@ +.script-list-group .collection-item.script-group { + border: none; + display: flex; + flex-direction: row; + padding-right: 16px; + align-items: center; +} + +.script-list-group .collection-item.script-group span { + flex: 1 1 auto; +} + +.script-list-group .collection-item.script-group i { + flex: 0 0 auto; + line-height: 16px; +} + +.script-list-group .collection-item.script-list-item { + padding-left: 36px; +} \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptListGroup.vue b/web-src/src/main-app/components/scripts/ScriptListGroup.vue index ab9e5283..8f9013c7 100644 --- a/web-src/src/main-app/components/scripts/ScriptListGroup.vue +++ b/web-src/src/main-app/components/scripts/ScriptListGroup.vue @@ -30,26 +30,5 @@ export default { \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptsList.vue b/web-src/src/main-app/components/scripts/ScriptsList.vue index f283a29f..6fd087a8 100644 --- a/web-src/src/main-app/components/scripts/ScriptsList.vue +++ b/web-src/src/main-app/components/scripts/ScriptsList.vue @@ -4,6 +4,7 @@ + @@ -11,11 +12,12 @@ import {isBlankString, isEmptyString, isNull, removeElement} from '@/common/utils/common'; import {mapState} from 'vuex'; import ScriptListGroup from './ScriptListGroup'; +import ScriptFailedGroup from './ScriptFailedGroup'; import ScriptListItem from './ScriptListItem'; export default { name: 'ScriptsList', - components: {ScriptListGroup, ScriptListItem}, + components: {ScriptListGroup, ScriptListItem, ScriptFailedGroup}, props: { searchText: { type: String, @@ -30,7 +32,7 @@ export default { }, computed: { - ...mapState('scripts', ['scripts', 'selectedScript']), + ...mapState('scripts', ['scripts', 'selectedScript', 'failedScripts']), items() { let groups = this.scripts.filter(script => !isBlankString(script.group)) @@ -55,6 +57,12 @@ export default { result.sort((o1, o2) => o1.name.toLowerCase().localeCompare(o2.name.toLowerCase())); return result; + }, + + failedItems() { + const groupName = 'Failed to parse' + const result = {name: groupName, isGroup: true, scripts: [...this.failedScripts], isActive: this.activeGroup == groupName} + return result } }, methods: { diff --git a/web-src/src/main-app/store/scripts.js b/web-src/src/main-app/store/scripts.js index d3a8ac2f..3c8061f7 100644 --- a/web-src/src/main-app/store/scripts.js +++ b/web-src/src/main-app/store/scripts.js @@ -9,6 +9,7 @@ export default { state: { scripts: [], + failedScripts: [], selectedScript: null, predefinedParameters: null }, @@ -21,12 +22,14 @@ export default { axiosInstance.get('scripts') .then(({data}) => { - const {scripts} = data; + const scripts = data.scripts; + const failedScripts = data.failed; scripts.sort(function (script1, script2) { return script1.name.toLowerCase().localeCompare(script2.name.toLowerCase()); }); commit('SET_SCRIPTS', scripts); + commit('SET_FAILED_SCRIPTS', failedScripts); dispatch('selectScriptByHash'); }); }, @@ -73,6 +76,10 @@ export default { state.scripts = scripts }, + SET_FAILED_SCRIPTS(state, failedScripts) { + state.failedScripts = failedScripts + }, + SELECT_SCRIPT(state, {selectedScript, predefinedParameters}) { state.selectedScript = selectedScript; state.predefinedParameters = predefinedParameters; From fa4672ad898c71e5c8fd1429f9275b8c32feab4f Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Fri, 14 Oct 2022 05:05:21 +0300 Subject: [PATCH 03/27] a lil clarification in group name --- web-src/src/main-app/components/scripts/ScriptsList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-src/src/main-app/components/scripts/ScriptsList.vue b/web-src/src/main-app/components/scripts/ScriptsList.vue index 6fd087a8..5bf762de 100644 --- a/web-src/src/main-app/components/scripts/ScriptsList.vue +++ b/web-src/src/main-app/components/scripts/ScriptsList.vue @@ -60,7 +60,7 @@ export default { }, failedItems() { - const groupName = 'Failed to parse' + const groupName = 'Failed to parse (these files have invalid JSON structure)' const result = {name: groupName, isGroup: true, scripts: [...this.failedScripts], isActive: this.activeGroup == groupName} return result } From 0cf987329fcab7aaefe6e018d2bd7d0b90d28a3c Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Sun, 16 Oct 2022 01:42:24 +0300 Subject: [PATCH 04/27] added parsing_failed to ShortConfig type (.py files only) --- src/config/config_service.py | 12 +++++++----- src/model/script_config.py | 7 +------ src/web/server.py | 11 ++--------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/config/config_service.py b/src/config/config_service.py index 76edec32..5f7ff8b5 100644 --- a/src/config/config_service.py +++ b/src/config/config_service.py @@ -9,8 +9,7 @@ from config.exceptions import InvalidConfigException from model import script_config from model.model_helper import InvalidFileException -from model.script_config import get_sorted_config, GetShortConfigFailedError -from src.model.script_config import ShortConfig +from model.script_config import get_sorted_config, ShortConfig from utils import os_utils, file_utils, process_utils, custom_json, custom_yaml from utils.file_utils import to_filename from utils.string_utils import is_blank, strip @@ -177,7 +176,7 @@ def list_configs(self, user, mode=None): conf_service = self - def load_script(path, content) -> Union[ShortConfig, GetShortConfigFailedError]: + def load_script(path, content) -> ShortConfig: try: config_object = self.load_config_file(path, content) short_config = script_config.read_short(path, config_object) @@ -194,7 +193,10 @@ def load_script(path, content) -> Union[ShortConfig, GetShortConfigFailedError]: return short_config except: LOGGER.exception('Could not load script: ' + path) - return GetShortConfigFailedError(path) + failed_short_config = ShortConfig() + failed_short_config.name = path + failed_short_config.parsing_failed = True + return failed_short_config return self._visit_script_configs(load_script) @@ -211,7 +213,7 @@ def load_config_model(self, name, user, parameter_values=None, skip_invalid_para return self._load_script_config(path, config_object, user, parameter_values, skip_invalid_parameters) - def _visit_script_configs(self, visitor) -> List[ Union[ShortConfig, GetShortConfigFailedError] ]: + def _visit_script_configs(self, visitor) -> List[ ShortConfig ]: configs_dir = self._script_configs_folder files = os.listdir(configs_dir) diff --git a/src/model/script_config.py b/src/model/script_config.py index dac281da..f1ff0773 100644 --- a/src/model/script_config.py +++ b/src/model/script_config.py @@ -27,12 +27,7 @@ def __init__(self): self.allowed_users = [] self.admin_users = [] self.group = None - -class GetShortConfigFailedError(object): - def __init__(self, path): - self.path = path - # self.group = 'Parsing failed' - self.cannotParse = True + self.parsing_failed = False @observable_fields( 'script_command', diff --git a/src/web/server.py b/src/web/server.py index 3d2d68d7..b052fa3c 100755 --- a/src/web/server.py +++ b/src/web/server.py @@ -137,16 +137,9 @@ def get(self, user): configs = self.application.config_service.list_configs(user, mode) - scripts = [] - failed = [] + scripts = [{'name': conf.name, 'group': conf.group} for conf in configs] - for conf in configs: - if hasattr(conf, 'cannotParse'): - failed.append({'path': conf.path }) - else: - scripts.append({'name': conf.name, 'group': conf.group }) - - self.write(json.dumps({'scripts': scripts, 'failed': failed})) + self.write(json.dumps({'scripts': scripts})) class AdminUpdateScriptEndpoint(BaseRequestHandler): From 1e406ea19dfd098ce7d7910e6bb4ad4be993df0b Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Sun, 16 Oct 2022 02:03:02 +0300 Subject: [PATCH 05/27] reverting vue changes --- .../components/scripts/ScriptFailedGroup.vue | 44 ------------------- .../components/scripts/ScriptListGroup.css | 20 --------- .../components/scripts/ScriptListGroup.vue | 20 ++++++++- .../components/scripts/ScriptsList.vue | 12 +---- web-src/src/main-app/store/scripts.js | 8 +--- 5 files changed, 22 insertions(+), 82 deletions(-) delete mode 100644 web-src/src/main-app/components/scripts/ScriptFailedGroup.vue delete mode 100644 web-src/src/main-app/components/scripts/ScriptListGroup.css diff --git a/web-src/src/main-app/components/scripts/ScriptFailedGroup.vue b/web-src/src/main-app/components/scripts/ScriptFailedGroup.vue deleted file mode 100644 index 171519fb..00000000 --- a/web-src/src/main-app/components/scripts/ScriptFailedGroup.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - {{failedItems.name}} - - {{ failedItems.isActive ? 'expand_less' : 'expand_more' }} - - - - - {{ item.path }} - - - - - - - - \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptListGroup.css b/web-src/src/main-app/components/scripts/ScriptListGroup.css deleted file mode 100644 index f9395280..00000000 --- a/web-src/src/main-app/components/scripts/ScriptListGroup.css +++ /dev/null @@ -1,20 +0,0 @@ -.script-list-group .collection-item.script-group { - border: none; - display: flex; - flex-direction: row; - padding-right: 16px; - align-items: center; -} - -.script-list-group .collection-item.script-group span { - flex: 1 1 auto; -} - -.script-list-group .collection-item.script-group i { - flex: 0 0 auto; - line-height: 16px; -} - -.script-list-group .collection-item.script-list-item { - padding-left: 36px; -} \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptListGroup.vue b/web-src/src/main-app/components/scripts/ScriptListGroup.vue index 8f9013c7..3d1711b9 100644 --- a/web-src/src/main-app/components/scripts/ScriptListGroup.vue +++ b/web-src/src/main-app/components/scripts/ScriptListGroup.vue @@ -30,5 +30,23 @@ export default { \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptsList.vue b/web-src/src/main-app/components/scripts/ScriptsList.vue index 5bf762de..6cbd8c68 100644 --- a/web-src/src/main-app/components/scripts/ScriptsList.vue +++ b/web-src/src/main-app/components/scripts/ScriptsList.vue @@ -4,7 +4,6 @@ - @@ -12,12 +11,11 @@ import {isBlankString, isEmptyString, isNull, removeElement} from '@/common/utils/common'; import {mapState} from 'vuex'; import ScriptListGroup from './ScriptListGroup'; -import ScriptFailedGroup from './ScriptFailedGroup'; import ScriptListItem from './ScriptListItem'; export default { name: 'ScriptsList', - components: {ScriptListGroup, ScriptListItem, ScriptFailedGroup}, + components: {ScriptListGroup, ScriptListItem}, props: { searchText: { type: String, @@ -32,7 +30,7 @@ export default { }, computed: { - ...mapState('scripts', ['scripts', 'selectedScript', 'failedScripts']), + ...mapState('scripts', ['scripts', 'selectedScript']), items() { let groups = this.scripts.filter(script => !isBlankString(script.group)) @@ -58,12 +56,6 @@ export default { return result; }, - - failedItems() { - const groupName = 'Failed to parse (these files have invalid JSON structure)' - const result = {name: groupName, isGroup: true, scripts: [...this.failedScripts], isActive: this.activeGroup == groupName} - return result - } }, methods: { groupClicked(groupName) { diff --git a/web-src/src/main-app/store/scripts.js b/web-src/src/main-app/store/scripts.js index 3c8061f7..4e92c997 100644 --- a/web-src/src/main-app/store/scripts.js +++ b/web-src/src/main-app/store/scripts.js @@ -22,14 +22,12 @@ export default { axiosInstance.get('scripts') .then(({data}) => { - const scripts = data.scripts; - const failedScripts = data.failed; + const {scripts} = data; scripts.sort(function (script1, script2) { return script1.name.toLowerCase().localeCompare(script2.name.toLowerCase()); }); commit('SET_SCRIPTS', scripts); - commit('SET_FAILED_SCRIPTS', failedScripts); dispatch('selectScriptByHash'); }); }, @@ -76,10 +74,6 @@ export default { state.scripts = scripts }, - SET_FAILED_SCRIPTS(state, failedScripts) { - state.failedScripts = failedScripts - }, - SELECT_SCRIPT(state, {selectedScript, predefinedParameters}) { state.selectedScript = selectedScript; state.predefinedParameters = predefinedParameters; From 56d0b8e2a36358de519d191ce7f913d0b26c78a6 Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Sun, 16 Oct 2022 02:05:55 +0300 Subject: [PATCH 06/27] additional Vue reverts --- .../components/scripts/ScriptListGroup.vue | 37 ++++++++++--------- .../components/scripts/ScriptsList.vue | 2 +- web-src/src/main-app/store/scripts.js | 1 - 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/web-src/src/main-app/components/scripts/ScriptListGroup.vue b/web-src/src/main-app/components/scripts/ScriptListGroup.vue index 3d1711b9..ab9e5283 100644 --- a/web-src/src/main-app/components/scripts/ScriptListGroup.vue +++ b/web-src/src/main-app/components/scripts/ScriptListGroup.vue @@ -31,22 +31,25 @@ export default { \ No newline at end of file diff --git a/web-src/src/main-app/components/scripts/ScriptsList.vue b/web-src/src/main-app/components/scripts/ScriptsList.vue index 6cbd8c68..f283a29f 100644 --- a/web-src/src/main-app/components/scripts/ScriptsList.vue +++ b/web-src/src/main-app/components/scripts/ScriptsList.vue @@ -55,7 +55,7 @@ export default { result.sort((o1, o2) => o1.name.toLowerCase().localeCompare(o2.name.toLowerCase())); return result; - }, + } }, methods: { groupClicked(groupName) { diff --git a/web-src/src/main-app/store/scripts.js b/web-src/src/main-app/store/scripts.js index 4e92c997..d3a8ac2f 100644 --- a/web-src/src/main-app/store/scripts.js +++ b/web-src/src/main-app/store/scripts.js @@ -9,7 +9,6 @@ export default { state: { scripts: [], - failedScripts: [], selectedScript: null, predefinedParameters: null }, From 62df42980a8a4f8ec58ac95432a472899a7e6821 Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 03:49:02 +0300 Subject: [PATCH 07/27] server.py parsing_failed parameter transmission fixed --- src/web/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/server.py b/src/web/server.py index b052fa3c..60684f9e 100755 --- a/src/web/server.py +++ b/src/web/server.py @@ -137,7 +137,7 @@ def get(self, user): configs = self.application.config_service.list_configs(user, mode) - scripts = [{'name': conf.name, 'group': conf.group} for conf in configs] + scripts = [{'name': conf.name, 'group': conf.group, 'parsing_failed': conf.parsing_failed } for conf in configs] self.write(json.dumps({'scripts': scripts})) From a33f79ee7c373d1604f6b9aa6c33b95e38feb69e Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 03:50:21 +0300 Subject: [PATCH 08/27] bad script red highlight added --- .../src/main-app/components/scripts/ScriptListItem.vue | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web-src/src/main-app/components/scripts/ScriptListItem.vue b/web-src/src/main-app/components/scripts/ScriptListItem.vue index 3c653da1..088d1275 100644 --- a/web-src/src/main-app/components/scripts/ScriptListItem.vue +++ b/web-src/src/main-app/components/scripts/ScriptListItem.vue @@ -1,7 +1,7 @@ + v-bind:class="{ active: descriptor.active, 'parsing-failed': descriptor.parsingFailed}"> {{ descriptor.name }} @@ -44,7 +44,8 @@ export default { name: this.script.name, state: this.getState(this.script.name), active: this.selectedScript === this.script.name, - hash: this.toHash(this.script.name) + hash: this.toHash(this.script.name), + parsingFailed: this.script.parsing_failed, } }, ...mapState('scripts', ['selectedScript']) @@ -74,6 +75,10 @@ export default { padding-right: 32px; } +.scripts-list .collection-item.parsing-failed { + color: var(--error-color); +} + .scripts-list .collection-item .menu-item-state { width: 24px; height: 24px; From b0e23c69c832f4d5130676d1ba394da372582ffb Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 04:06:11 +0300 Subject: [PATCH 09/27] added cannot-parse icon --- .../components/scripts/ScriptListItem.vue | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/web-src/src/main-app/components/scripts/ScriptListItem.vue b/web-src/src/main-app/components/scripts/ScriptListItem.vue index 088d1275..498aaee0 100644 --- a/web-src/src/main-app/components/scripts/ScriptListItem.vue +++ b/web-src/src/main-app/components/scripts/ScriptListItem.vue @@ -6,6 +6,7 @@ check + close @@ -54,6 +55,8 @@ export default { getState(scriptName) { let state = 'idle'; + if(this.script.parsing_failed) return 'cannot-parse' + forEachKeyValue(this.$store.state.executions.executors, function (id, executor) { if (executor.state.scriptName !== scriptName) { return; @@ -77,6 +80,7 @@ export default { .scripts-list .collection-item.parsing-failed { color: var(--error-color); + } .scripts-list .collection-item .menu-item-state { @@ -101,11 +105,15 @@ export default { } .scripts-list .collection-item .menu-item-state.executing, -.scripts-list .collection-item .menu-item-state.finished { +.scripts-list .collection-item .menu-item-state.finished, +.scripts-list .collection-item .menu-item-state.cannot-parse { display: inline; } -.scripts-list .collection-item .menu-item-state.executing > .check-icon { +/* state: executing */ + +.scripts-list .collection-item .menu-item-state.executing > .check-icon, +.scripts-list .collection-item .menu-item-state.executing > .failed-icon { display: none; } @@ -113,14 +121,29 @@ export default { display: block; } +/* state: finished */ + .scripts-list .collection-item .menu-item-state.finished > .check-icon { display: block; } -.scripts-list .collection-item .menu-item-state.finished > .preloader-wrapper { +.scripts-list .collection-item .menu-item-state.finished > .preloader-wrapper, +.scripts-list .collection-item .menu-item-state.finished > .failed-icon { display: none; } +/* state: cannot-parse */ + +.scripts-list .collection-item .menu-item-state.cannot-parse > .check-icon, +.scripts-list .collection-item .menu-item-state.cannot-parse > .preloader-wrapper { + display: none; +} + + +.scripts-list .collection-item .menu-item-state.cannot-parse > .failed-icon { + display: block; +} + .scripts-list .collection-item .preloader-wrapper .spinner-layer { border-color: var(--primary-color); } From fa578132dc722be107e9dbdac4152daddfdfcd04 Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 04:07:39 +0300 Subject: [PATCH 10/27] changed "parsing-failed" icon --- web-src/src/main-app/components/scripts/ScriptListItem.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web-src/src/main-app/components/scripts/ScriptListItem.vue b/web-src/src/main-app/components/scripts/ScriptListItem.vue index 498aaee0..159ce4f8 100644 --- a/web-src/src/main-app/components/scripts/ScriptListItem.vue +++ b/web-src/src/main-app/components/scripts/ScriptListItem.vue @@ -6,7 +6,7 @@ check - close + cancel @@ -80,7 +80,7 @@ export default { .scripts-list .collection-item.parsing-failed { color: var(--error-color); - + } .scripts-list .collection-item .menu-item-state { From 1d9c2b8b59afb5732ffbfed2ef71fed6b469419e Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 04:09:48 +0300 Subject: [PATCH 11/27] yet again icon change --- web-src/src/main-app/components/scripts/ScriptListItem.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-src/src/main-app/components/scripts/ScriptListItem.vue b/web-src/src/main-app/components/scripts/ScriptListItem.vue index 159ce4f8..074fe385 100644 --- a/web-src/src/main-app/components/scripts/ScriptListItem.vue +++ b/web-src/src/main-app/components/scripts/ScriptListItem.vue @@ -6,7 +6,7 @@ check - cancel + do_not_disturb_alt From 7338f3e3f9478adf6b41cfe9d84960578cab0d86 Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 06:49:43 +0300 Subject: [PATCH 12/27] (backend) added BadConfigFileException and (mostly) its catchers --- src/config/config_service.py | 40 ++++++++++++++++++++++++++------- src/web/script_config_socket.py | 5 ++++- src/web/server.py | 11 ++++++++- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/config/config_service.py b/src/config/config_service.py index 5f7ff8b5..b93a99f2 100644 --- a/src/config/config_service.py +++ b/src/config/config_service.py @@ -2,8 +2,7 @@ import logging import os import re -from collections import namedtuple -from typing import List, Union +from typing import List, NamedTuple, Union from auth.authorization import Authorizer from config.exceptions import InvalidConfigException @@ -23,7 +22,10 @@ LOGGER = logging.getLogger('config_service') -ConfigSearchResult = namedtuple('ConfigSearchResult', ['short_config', 'path', 'config_object']) +class ConfigSearchResult(NamedTuple): + short_config: ShortConfig + path: str + config_object: any def _script_name_to_file_name(script_name): @@ -59,6 +61,9 @@ def load_config(self, name, user): if search_result is None: return None + if(search_result.short_config.parsing_failed == True): + raise BadConfigFileException() + (short_config, path, config_object) = search_result if config_object.get('name') is None: @@ -191,12 +196,13 @@ def load_script(path, content) -> ShortConfig: return None return short_config - except: - LOGGER.exception('Could not load script: ' + path) + except json.decoder.JSONDecodeError: failed_short_config = ShortConfig() failed_short_config.name = path failed_short_config.parsing_failed = True return failed_short_config + except Exception: + LOGGER.exception('Could not load script: ' + path) return self._visit_script_configs(load_script) @@ -206,6 +212,9 @@ def load_config_model(self, name, user, parameter_values=None, skip_invalid_para if search_result is None: return None + if(search_result.short_config.parsing_failed == True): + raise BadConfigFileException() + (short_config, path, config_object) = search_result if not self._can_access_script(user, short_config): @@ -240,15 +249,23 @@ def _visit_script_configs(self, visitor) -> List[ ShortConfig ]: return result - def _find_config(self, name) -> Union[ConfigSearchResult, None]: - def find_and_load(path, content): + def _find_config(self, name) -> Union[ ConfigSearchResult , None]: + def find_and_load(path: str, content): try: config_object = self.load_config_file(path, content) short_config = script_config.read_short(path, config_object) if short_config is None: return None - except: + except json.decoder.JSONDecodeError: + if name == path: + failed_short_config = ShortConfig() + failed_short_config.name = path + failed_short_config.parsing_failed = True + raise StopIteration(ConfigSearchResult(failed_short_config, path, None)) + else: + return None + except Exception: LOGGER.exception('Could not load script config: ' + path) return None @@ -368,3 +385,10 @@ def __init__(self, message): class InvalidAccessException(Exception): def __init__(self, message=None): super().__init__(message) + + +class BadConfigFileException(Exception): + HTTP_CODE = 422 + VERBOSE_ERROR = 'Cannot parse script config file' + def __init__(self, message=None): + super().__init__(message) diff --git a/src/web/script_config_socket.py b/src/web/script_config_socket.py index d02ab0f6..b3849ba0 100644 --- a/src/web/script_config_socket.py +++ b/src/web/script_config_socket.py @@ -13,7 +13,7 @@ from tornado import gen from auth.user import User -from config.config_service import ConfigNotAllowedException +from config.config_service import ConfigNotAllowedException, BadConfigFileException from model import external_model from model.external_model import parameter_to_external from model.model_helper import read_bool @@ -184,6 +184,9 @@ def load_model(): except ConfigNotAllowedException: self.close(code=403, reason='Access to the script is denied') return None + except BadConfigFileException: + self.close(code=422, reason=BadConfigFileException.VERBOSE_ERROR) + return None except Exception: message = 'Failed to load script config ' + config_name LOGGER.exception(message) diff --git a/src/web/server.py b/src/web/server.py index 60684f9e..f2970952 100755 --- a/src/web/server.py +++ b/src/web/server.py @@ -20,7 +20,7 @@ from auth.identification import AuthBasedIdentification, IpBasedIdentification from auth.tornado_auth import TornadoAuth from communications.alerts_service import AlertsService -from config.config_service import ConfigService, ConfigNotAllowedException, InvalidAccessException +from config.config_service import ConfigService, ConfigNotAllowedException, InvalidAccessException, BadConfigFileException from config.exceptions import InvalidConfigException from execution.execution_service import ExecutionService from execution.logging import ExecutionLoggingService @@ -191,6 +191,10 @@ def get(self, user, script_name): LOGGER.warning('Admin access to the script "' + script_name + '" is denied for ' + user.get_audit_name()) respond_error(self, 403, 'Access to the script is denied') return + except BadConfigFileException: + LOGGER.warning(BadConfigFileException.VERBOSE_ERROR + ' : ' + script_name) + respond_error(self, 422, BadConfigFileException.VERBOSE_ERROR) + return if config is None: raise tornado.web.HTTPError(404, str('Failed to find config for name: ' + script_name)) @@ -401,6 +405,11 @@ def post(self, user): respond_error(self, 403, 'Access to the script is denied') return + except BadConfigFileException: + LOGGER.warning(BadConfigFileException.VERBOSE_ERROR + ' : ' + script_name) + respond_error(self, 422, BadConfigFileException.VERBOSE_ERROR) + return None + except Exception as e: LOGGER.exception("Error while calling the script") From 6d6e8f8804796e5c00fe6c78363060ac0e33fd49 Mon Sep 17 00:00:00 2001 From: RollingHog <46373241+RollingHog@users.noreply.github.com> Date: Mon, 17 Oct 2022 07:13:39 +0300 Subject: [PATCH 13/27] (frontend) added processing of code 422 in main block --- .../src/main-app/components/scripts/MainAppContent.vue | 8 +++++++- web-src/src/main-app/store/scriptConfig.js | 9 ++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/web-src/src/main-app/components/scripts/MainAppContent.vue b/web-src/src/main-app/components/scripts/MainAppContent.vue index 38d5f8e4..09b25235 100644 --- a/web-src/src/main-app/components/scripts/MainAppContent.vue +++ b/web-src/src/main-app/components/scripts/MainAppContent.vue @@ -9,6 +9,9 @@ Failed to load script info: script '{{ selectedScript }}' not found + + Cannot parse script config file + Failed to load script info. Try to reload the page. Error message: @@ -21,7 +24,7 @@
Failed to load script info: script '{{ selectedScript }}' not found
+ Cannot parse script config file +
Failed to load script info. Try to reload the page. Error message: @@ -21,7 +24,7 @@