From 87fa5ff7a67106f7ed553c3c87d0fc6d65a0fa4c Mon Sep 17 00:00:00 2001 From: wh1te909 Date: Wed, 31 Mar 2021 03:01:46 +0000 Subject: [PATCH] feat: add default timeout in script manager closes #352 --- .../migrations/0006_script_default_timeout.py | 18 ++++++++++++++++++ api/tacticalrmm/scripts/models.py | 1 + api/tacticalrmm/scripts/serializers.py | 2 ++ api/tacticalrmm/scripts/tests.py | 4 ++++ api/tacticalrmm/scripts/views.py | 1 + web/src/components/AgentTable.vue | 5 +++-- web/src/components/ScriptManager.vue | 10 +++++++++- .../components/modals/agents/BulkAction.vue | 12 ++++++------ web/src/components/modals/agents/RunScript.vue | 14 +++++++------- .../modals/scripts/ScriptFormModal.vue | 17 +++++++++++++++-- .../modals/scripts/ScriptUploadModal.vue | 13 +++++++++++++ 11 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 api/tacticalrmm/scripts/migrations/0006_script_default_timeout.py diff --git a/api/tacticalrmm/scripts/migrations/0006_script_default_timeout.py b/api/tacticalrmm/scripts/migrations/0006_script_default_timeout.py new file mode 100644 index 00000000..9be463b0 --- /dev/null +++ b/api/tacticalrmm/scripts/migrations/0006_script_default_timeout.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.7 on 2021-03-31 01:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scripts', '0005_auto_20201207_1606'), + ] + + operations = [ + migrations.AddField( + model_name='script', + name='default_timeout', + field=models.PositiveIntegerField(default=90), + ), + ] diff --git a/api/tacticalrmm/scripts/models.py b/api/tacticalrmm/scripts/models.py index 36d38eae..0bd44471 100644 --- a/api/tacticalrmm/scripts/models.py +++ b/api/tacticalrmm/scripts/models.py @@ -29,6 +29,7 @@ class Script(BaseAuditModel): favorite = models.BooleanField(default=False) category = models.CharField(max_length=100, null=True, blank=True) code_base64 = models.TextField(null=True, blank=True) + default_timeout = models.PositiveIntegerField(default=90) def __str__(self): return self.name diff --git a/api/tacticalrmm/scripts/serializers.py b/api/tacticalrmm/scripts/serializers.py index e2c6ca7d..c56e08b6 100644 --- a/api/tacticalrmm/scripts/serializers.py +++ b/api/tacticalrmm/scripts/serializers.py @@ -14,6 +14,7 @@ class ScriptTableSerializer(ModelSerializer): "shell", "category", "favorite", + "default_timeout", ] @@ -28,6 +29,7 @@ class ScriptSerializer(ModelSerializer): "category", "favorite", "code_base64", + "default_timeout", ] diff --git a/api/tacticalrmm/scripts/tests.py b/api/tacticalrmm/scripts/tests.py index 41e0fca5..17776d11 100644 --- a/api/tacticalrmm/scripts/tests.py +++ b/api/tacticalrmm/scripts/tests.py @@ -36,6 +36,7 @@ class TestScriptViews(TacticalTestCase): "shell": "powershell", "category": "New", "code": "Some Test Code\nnew Line", + "default_timeout": 99, } # test without file upload @@ -55,6 +56,7 @@ class TestScriptViews(TacticalTestCase): "shell": "cmd", "category": "New", "filename": file, + "default_timeout": 4455, } # test with file upload @@ -79,6 +81,7 @@ class TestScriptViews(TacticalTestCase): "description": "Description Change", "shell": script.shell, "code": "Test Code\nAnother Line", + "default_timeout": 13344556, } # test edit a userdefined script @@ -104,6 +107,7 @@ class TestScriptViews(TacticalTestCase): "shell": script.shell, "favorite": True, "code": "Test Code\nAnother Line", + "default_timeout": 54345, } # test marking a builtin script as favorite resp = self.client.put( diff --git a/api/tacticalrmm/scripts/views.py b/api/tacticalrmm/scripts/views.py index a1fa7a65..594dd87e 100644 --- a/api/tacticalrmm/scripts/views.py +++ b/api/tacticalrmm/scripts/views.py @@ -30,6 +30,7 @@ class GetAddScripts(APIView): "category": request.data["category"], "description": request.data["description"], "shell": request.data["shell"], + "default_timeout": request.data["default_timeout"], "script_type": "userdefined", # force all uploads to be userdefined. built in scripts cannot be edited by user } diff --git a/web/src/components/AgentTable.vue b/web/src/components/AgentTable.vue index 357de6b6..80b4d420 100644 --- a/web/src/components/AgentTable.vue +++ b/web/src/components/AgentTable.vue @@ -511,9 +511,10 @@ export default { }, 500); }, runFavScript(scriptpk, agentpk) { + let default_timeout = this.favoriteScripts.find(i => i.value === scriptpk).timeout; const data = { pk: agentpk, - timeout: 900, + timeout: default_timeout, scriptPK: scriptpk, output: "forget", args: [], @@ -532,7 +533,7 @@ export default { } this.favoriteScripts = r.data .filter(k => k.favorite === true) - .map(script => ({ label: script.name, value: script.id })) + .map(script => ({ label: script.name, value: script.id, timeout: script.default_timeout })) .sort((a, b) => a.label.localeCompare(b.label)); }); }, diff --git a/web/src/components/ScriptManager.vue b/web/src/components/ScriptManager.vue index df35c308..0b9dff01 100644 --- a/web/src/components/ScriptManager.vue +++ b/web/src/components/ScriptManager.vue @@ -291,6 +291,7 @@ props.row.description }} + {{ props.row.default_timeout }} @@ -368,8 +369,15 @@ export default { align: "left", sortable: false, }, + { + name: "default_timeout", + label: "Default Timeout (seconds)", + field: "default_timeout", + align: "left", + sortable: true, + }, ], - visibleColumns: ["favorite", "name", "category", "desc", "shell"], + visibleColumns: ["favorite", "name", "category", "desc", "shell", "default_timeout"], }; }, methods: { diff --git a/web/src/components/modals/agents/BulkAction.vue b/web/src/components/modals/agents/BulkAction.vue index 5d71514f..4967a8c3 100644 --- a/web/src/components/modals/agents/BulkAction.vue +++ b/web/src/components/modals/agents/BulkAction.vue @@ -92,6 +92,7 @@ map-options emit-value options-dense + @input="setDefaultTimeout" /> @@ -138,11 +139,7 @@ style="max-width: 150px" label="Timeout (seconds)" stack-label - :rules="[ - val => !!val || '*Required', - val => val >= 10 || 'Minimum is 10 seconds', - val => val <= 25200 || 'Maximum is 25,200 seconds', - ]" + :rules="[val => !!val || '*Required', val => val >= 5 || 'Minimum is 5 seconds']" /> @@ -200,6 +197,9 @@ export default { }, }, methods: { + setDefaultTimeout() { + this.timeout = this.scriptOptions.find(i => i.value === this.scriptPK).timeout; + }, getScripts() { let scripts; this.$axios.get("/scripts/scripts/").then(r => { @@ -209,7 +209,7 @@ export default { scripts = r.data.filter(i => i.script_type !== "builtin"); } this.scriptOptions = scripts - .map(script => ({ label: script.name, value: script.id })) + .map(script => ({ label: script.name, value: script.id, timeout: script.default_timeout })) .sort((a, b) => a.label.localeCompare(b.label)); }); }, diff --git a/web/src/components/modals/agents/RunScript.vue b/web/src/components/modals/agents/RunScript.vue index 93ce7322..31b66039 100644 --- a/web/src/components/modals/agents/RunScript.vue +++ b/web/src/components/modals/agents/RunScript.vue @@ -17,6 +17,7 @@ map-options emit-value options-dense + @input="setDefaultTimeout" /> @@ -73,11 +74,7 @@ style="max-width: 150px" label="Timeout (seconds)" stack-label - :rules="[ - val => !!val || '*Required', - val => val >= 10 || 'Minimum is 10 seconds', - val => val <= 25200 || 'Maximum is 25,200 seconds', - ]" + :rules="[val => !!val || '*Required', val => val >= 5 || 'Minimum is 5 seconds']" /> @@ -92,7 +89,7 @@