diff --git a/api/tacticalrmm/agents/models.py b/api/tacticalrmm/agents/models.py index 324edc68..55e9fea1 100644 --- a/api/tacticalrmm/agents/models.py +++ b/api/tacticalrmm/agents/models.py @@ -10,6 +10,7 @@ import validators import random import string from loguru import logger +from packaging import version as pyver from django.db import models from django.conf import settings @@ -423,6 +424,12 @@ class Agent(models.Model): else: return "failed" + def not_supported(self, version_added): + if pyver.parse(self.version) < pyver.parse(version_added): + return True + + return False + class AgentOutage(models.Model): agent = models.ForeignKey( diff --git a/api/tacticalrmm/checks/migrations/0006_check_event_id_is_wildcard.py b/api/tacticalrmm/checks/migrations/0006_check_event_id_is_wildcard.py new file mode 100644 index 00000000..fbfb71c5 --- /dev/null +++ b/api/tacticalrmm/checks/migrations/0006_check_event_id_is_wildcard.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1 on 2020-08-24 03:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('checks', '0005_auto_20200810_0544'), + ] + + operations = [ + migrations.AddField( + model_name='check', + name='event_id_is_wildcard', + field=models.BooleanField(default=False), + ), + ] diff --git a/api/tacticalrmm/checks/models.py b/api/tacticalrmm/checks/models.py index 4df35f08..87823c6d 100644 --- a/api/tacticalrmm/checks/models.py +++ b/api/tacticalrmm/checks/models.py @@ -130,6 +130,7 @@ class Check(models.Model): max_length=255, choices=EVT_LOG_NAME_CHOICES, null=True, blank=True ) event_id = models.IntegerField(null=True, blank=True) + event_id_is_wildcard = models.BooleanField(default=False) event_type = models.CharField( max_length=255, choices=EVT_LOG_TYPE_CHOICES, null=True, blank=True ) diff --git a/api/tacticalrmm/checks/views.py b/api/tacticalrmm/checks/views.py index 85a68434..8503a3b9 100644 --- a/api/tacticalrmm/checks/views.py +++ b/api/tacticalrmm/checks/views.py @@ -12,6 +12,7 @@ from rest_framework.decorators import ( permission_classes, ) +from tacticalrmm.utils import notify_error from agents.models import Agent from automation.models import Policy @@ -52,6 +53,21 @@ class GetAddCheck(APIView): if "script" in request.data["check"]: script = get_object_or_404(Script, pk=request.data["check"]["script"]) + # set event id to 0 if wildcard because it needs to be an integer field for db + # will be ignored anyway by the agent when doing wildcard check + if ( + request.data["check"]["check_type"] == "eventlog" + and request.data["check"]["event_id_is_wildcard"] + ): + if agent and agent.not_supported(version_added="0.10.2"): + return notify_error( + { + "non_field_errors": "Wildcard is only available in agent 0.10.2 or greater" + } + ) + + request.data["check"]["event_id"] = 0 + serializer = CheckSerializer( data=request.data["check"], partial=True, context=parent ) @@ -92,6 +108,18 @@ class GetUpdateDeleteCheck(APIView): if "check_alert" not in request.data.keys(): [request.data.pop(i) for i in check.non_editable_fields] + # set event id to 0 if wildcard because it needs to be an integer field for db + # will be ignored anyway by the agent when doing wildcard check + if check.check_type == "eventlog" and request.data["event_id_is_wildcard"]: + if check.agent.not_supported(version_added="0.10.2"): + return notify_error( + { + "non_field_errors": "Wildcard is only available in agent 0.10.2 or greater" + } + ) + + request.data["event_id"] = 0 + serializer = CheckSerializer(instance=check, data=request.data, partial=True) serializer.is_valid(raise_exception=True) obj = serializer.save() diff --git a/api/tacticalrmm/tacticalrmm/settings.py b/api/tacticalrmm/tacticalrmm/settings.py index a1683811..643c55f6 100644 --- a/api/tacticalrmm/tacticalrmm/settings.py +++ b/api/tacticalrmm/tacticalrmm/settings.py @@ -11,7 +11,7 @@ AUTH_USER_MODEL = "accounts.User" # bump this version everytime vue code is changed # to alert user they need to manually refresh their browser -APP_VER = "0.0.26" +APP_VER = "0.0.27" # https://github.com/wh1te909/salt LATEST_SALT_VER = "1.0.3" diff --git a/web/src/components/modals/checks/EventLogCheck.vue b/web/src/components/modals/checks/EventLogCheck.vue index da4227e1..60ad2258 100644 --- a/web/src/components/modals/checks/EventLogCheck.vue +++ b/web/src/components/modals/checks/EventLogCheck.vue @@ -41,13 +41,9 @@ @@ -110,7 +106,7 @@ export default { agentpk: Number, policypk: Number, mode: String, - checkpk: Number + checkpk: Number, }, mixins: [mixins], data() { @@ -122,25 +118,32 @@ export default { event_type: "INFO", fail_when: "contains", search_last_days: 1, - fails_b4_alert: 1 + fails_b4_alert: 1, + event_id_is_wildcard: false, }, logNameOptions: ["Application", "System", "Security"], failWhenOptions: [ { label: "Log contains", value: "contains" }, - { label: "Log does not contain", value: "not_contains" } + { label: "Log does not contain", value: "not_contains" }, ], - failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + failOptions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], }; }, methods: { getCheck() { - axios.get(`/checks/${this.checkpk}/check/`).then(r => (this.eventlogcheck = r.data)); + axios.get(`/checks/${this.checkpk}/check/`).then(r => { + this.eventlogcheck = r.data; + if (r.data.check_type === "eventlog" && r.data.event_id_is_wildcard) { + this.eventlogcheck.event_id = "*"; + } + }); }, addCheck() { const pk = this.policypk ? { policy: this.policypk } : { pk: this.agentpk }; + this.eventlogcheck.event_id_is_wildcard = this.eventlogcheck.event_id === "*" ? true : false; const data = { ...pk, - check: this.eventlogcheck + check: this.eventlogcheck, }; axios .post("/checks/checks/", data) @@ -152,6 +155,7 @@ export default { .catch(e => this.notifyError(e.response.data.non_field_errors)); }, editCheck() { + this.eventlogcheck.event_id_is_wildcard = this.eventlogcheck.event_id === "*" ? true : false; axios .patch(`/checks/${this.checkpk}/check/`, this.eventlogcheck) .then(r => { @@ -167,12 +171,23 @@ export default { } else { this.$store.dispatch("loadChecks", this.agentpk); } - } + }, + validateEventID(val) { + if (val === null || val.toString().replace(/\s/g, "") === "") { + return false; + } else if (val === "*") { + return true; + } else if (!isNaN(val)) { + return true; + } else { + return false; + } + }, }, mounted() { if (this.mode === "edit") { this.getCheck(); } - } + }, }; \ No newline at end of file