Release 0.6.1
This commit is contained in:
		@@ -166,7 +166,7 @@ class Agent(BaseAuditModel):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def checks(self):
 | 
			
		||||
        total, passing, failing = 0, 0, 0
 | 
			
		||||
        total, passing, failing, warning, info = 0, 0, 0, 0, 0
 | 
			
		||||
 | 
			
		||||
        if self.agentchecks.exists():  # type: ignore
 | 
			
		||||
            for i in self.agentchecks.all():  # type: ignore
 | 
			
		||||
@@ -174,13 +174,20 @@ class Agent(BaseAuditModel):
 | 
			
		||||
                if i.status == "passing":
 | 
			
		||||
                    passing += 1
 | 
			
		||||
                elif i.status == "failing":
 | 
			
		||||
                    if i.alert_severity == "error":
 | 
			
		||||
                        failing += 1
 | 
			
		||||
                    elif i.alert_severity == "warning":
 | 
			
		||||
                        warning += 1
 | 
			
		||||
                    elif i.alert_severity == "info":
 | 
			
		||||
                        info += 1
 | 
			
		||||
 | 
			
		||||
        ret = {
 | 
			
		||||
            "total": total,
 | 
			
		||||
            "passing": passing,
 | 
			
		||||
            "failing": failing,
 | 
			
		||||
            "has_failing_checks": failing > 0,
 | 
			
		||||
            "warning": warning,
 | 
			
		||||
            "info": info,
 | 
			
		||||
            "has_failing_checks": failing > 0 or warning > 0,
 | 
			
		||||
        }
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
import asyncio
 | 
			
		||||
import datetime as dt
 | 
			
		||||
import random
 | 
			
		||||
import requests
 | 
			
		||||
import urllib.parse
 | 
			
		||||
from time import sleep
 | 
			
		||||
from typing import Union
 | 
			
		||||
@@ -21,21 +20,9 @@ from tacticalrmm.utils import run_nats_api_cmd
 | 
			
		||||
logger.configure(**settings.LOG_CONFIG)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_exegen_url() -> str:
 | 
			
		||||
    urls: list[str] = settings.EXE_GEN_URLS
 | 
			
		||||
    for url in urls:
 | 
			
		||||
        try:
 | 
			
		||||
            r = requests.get(url, timeout=10)
 | 
			
		||||
        except:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if r.status_code == 200:
 | 
			
		||||
            return url
 | 
			
		||||
 | 
			
		||||
    return random.choice(urls)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def agent_update(pk: int, codesigntoken: str = None) -> str:
 | 
			
		||||
    from agents.utils import get_exegen_url
 | 
			
		||||
 | 
			
		||||
    agent = Agent.objects.get(pk=pk)
 | 
			
		||||
 | 
			
		||||
    if pyver.parse(agent.version) <= pyver.parse("1.3.0"):
 | 
			
		||||
@@ -52,7 +39,7 @@ def agent_update(pk: int, codesigntoken: str = None) -> str:
 | 
			
		||||
    inno = agent.win_inno_exe
 | 
			
		||||
 | 
			
		||||
    if codesigntoken is not None and pyver.parse(version) >= pyver.parse("1.5.0"):
 | 
			
		||||
        base_url = _get_exegen_url() + "/api/v1/winagents/?"
 | 
			
		||||
        base_url = get_exegen_url() + "/api/v1/winagents/?"
 | 
			
		||||
        params = {"version": version, "arch": agent.arch, "token": codesigntoken}
 | 
			
		||||
        url = base_url + urllib.parse.urlencode(params)
 | 
			
		||||
    else:
 | 
			
		||||
 
 | 
			
		||||
@@ -914,7 +914,7 @@ class TestAgentTasks(TacticalTestCase):
 | 
			
		||||
        self.authenticate()
 | 
			
		||||
        self.setup_coresettings()
 | 
			
		||||
 | 
			
		||||
    @patch("agents.tasks._get_exegen_url")
 | 
			
		||||
    @patch("agents.utils.get_exegen_url")
 | 
			
		||||
    @patch("agents.models.Agent.nats_cmd")
 | 
			
		||||
    def test_agent_update(self, nats_cmd, get_exe):
 | 
			
		||||
        from agents.tasks import agent_update
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								api/tacticalrmm/agents/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								api/tacticalrmm/agents/utils.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
import random
 | 
			
		||||
import requests
 | 
			
		||||
import urllib.parse
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_exegen_url() -> str:
 | 
			
		||||
    urls: list[str] = settings.EXE_GEN_URLS
 | 
			
		||||
    for url in urls:
 | 
			
		||||
        try:
 | 
			
		||||
            r = requests.get(url, timeout=10)
 | 
			
		||||
        except:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        if r.status_code == 200:
 | 
			
		||||
            return url
 | 
			
		||||
 | 
			
		||||
    return random.choice(urls)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_winagent_url(arch: str) -> str:
 | 
			
		||||
    from core.models import CodeSignToken
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        codetoken = CodeSignToken.objects.first().token
 | 
			
		||||
        base_url = get_exegen_url() + "/api/v1/winagents/?"
 | 
			
		||||
        params = {
 | 
			
		||||
            "version": settings.LATEST_AGENT_VER,
 | 
			
		||||
            "arch": arch,
 | 
			
		||||
            "token": codetoken,
 | 
			
		||||
        }
 | 
			
		||||
        dl_url = base_url + urllib.parse.urlencode(params)
 | 
			
		||||
    except:
 | 
			
		||||
        dl_url = settings.DL_64 if arch == "64" else settings.DL_32
 | 
			
		||||
 | 
			
		||||
    return dl_url
 | 
			
		||||
@@ -353,6 +353,7 @@ class Reboot(APIView):
 | 
			
		||||
 | 
			
		||||
@api_view(["POST"])
 | 
			
		||||
def install_agent(request):
 | 
			
		||||
    from agents.utils import get_winagent_url
 | 
			
		||||
    from knox.models import AuthToken
 | 
			
		||||
 | 
			
		||||
    client_id = request.data["client"]
 | 
			
		||||
@@ -375,7 +376,7 @@ def install_agent(request):
 | 
			
		||||
    inno = (
 | 
			
		||||
        f"winagent-v{version}.exe" if arch == "64" else f"winagent-v{version}-x86.exe"
 | 
			
		||||
    )
 | 
			
		||||
    download_url = settings.DL_64 if arch == "64" else settings.DL_32
 | 
			
		||||
    download_url = get_winagent_url(arch)
 | 
			
		||||
 | 
			
		||||
    _, token = AuthToken.objects.create(
 | 
			
		||||
        user=request.user, expiry=dt.timedelta(hours=request.data["expires"])
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,10 @@ class GetUpdateDeleteCheck(APIView):
 | 
			
		||||
        check = get_object_or_404(Check, pk=pk)
 | 
			
		||||
 | 
			
		||||
        # remove fields that should not be changed when editing a check from the frontend
 | 
			
		||||
        if "check_alert" not in request.data.keys():
 | 
			
		||||
        if (
 | 
			
		||||
            "check_alert" not in request.data.keys()
 | 
			
		||||
            and "check_reset" 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
 | 
			
		||||
@@ -108,6 +111,11 @@ class GetUpdateDeleteCheck(APIView):
 | 
			
		||||
        if check.policy:
 | 
			
		||||
            update_policy_check_fields_task(checkpk=pk)
 | 
			
		||||
 | 
			
		||||
        # resolve any alerts that are open
 | 
			
		||||
        if "check_reset" in request.data.keys():
 | 
			
		||||
            if obj.alert.filter(resolved=False).exists():
 | 
			
		||||
                obj.alert.get(resolved=False).resolve()
 | 
			
		||||
 | 
			
		||||
        return Response(f"{obj.readable_desc} was edited!")
 | 
			
		||||
 | 
			
		||||
    def delete(self, request, pk):
 | 
			
		||||
 
 | 
			
		||||
@@ -86,16 +86,24 @@ class Client(BaseAuditModel):
 | 
			
		||||
            .prefetch_related("agentchecks")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        failing = 0
 | 
			
		||||
        data = {"error": False, "warning": False}
 | 
			
		||||
 | 
			
		||||
        for agent in agents:
 | 
			
		||||
            if agent.checks["has_failing_checks"]:
 | 
			
		||||
                failing += 1
 | 
			
		||||
 | 
			
		||||
                if agent.checks["warning"]:
 | 
			
		||||
                    data["warning"] = True
 | 
			
		||||
 | 
			
		||||
                if agent.checks["failing"]:
 | 
			
		||||
                    data["error"] = True
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
            if agent.overdue_email_alert or agent.overdue_text_alert:
 | 
			
		||||
                if agent.status == "overdue":
 | 
			
		||||
                    failing += 1
 | 
			
		||||
                    data["error"] = True
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
        return failing > 0
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def serialize(client):
 | 
			
		||||
@@ -184,16 +192,24 @@ class Site(BaseAuditModel):
 | 
			
		||||
            .prefetch_related("agentchecks")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        failing = 0
 | 
			
		||||
        data = {"error": False, "warning": False}
 | 
			
		||||
 | 
			
		||||
        for agent in agents:
 | 
			
		||||
 | 
			
		||||
            if agent.checks["has_failing_checks"]:
 | 
			
		||||
                failing += 1
 | 
			
		||||
                if agent.checks["warning"]:
 | 
			
		||||
                    data["warning"] = True
 | 
			
		||||
 | 
			
		||||
                if agent.checks["failing"]:
 | 
			
		||||
                    data["error"] = True
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
            if agent.overdue_email_alert or agent.overdue_text_alert:
 | 
			
		||||
                if agent.status == "overdue":
 | 
			
		||||
                    failing += 1
 | 
			
		||||
                    data["error"] = True
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
        return failing > 0
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def serialize(site):
 | 
			
		||||
 
 | 
			
		||||
@@ -95,7 +95,6 @@ class SiteTreeSerializer(ModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Site
 | 
			
		||||
        fields = "__all__"
 | 
			
		||||
        ordering = ("failing_checks",)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientTreeSerializer(ModelSerializer):
 | 
			
		||||
@@ -106,7 +105,6 @@ class ClientTreeSerializer(ModelSerializer):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Client
 | 
			
		||||
        fields = "__all__"
 | 
			
		||||
        ordering = ("failing_checks",)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DeploymentSerializer(ModelSerializer):
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@
 | 
			
		||||
    "name": "Disk - Cleanup C: drive",
 | 
			
		||||
    "description": "Cleans the C: drive's Window Temperary files, Windows SoftwareDistribution folder, the local users Temperary folder, IIS logs (if applicable) and empties the recycling bin. All deleted files will go into a log transcript in $env:TEMP. By default this script leaves files that are newer than 7 days old however this variable can be edited.",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Other"
 | 
			
		||||
    "category": "TRMM (Win):Maintenance"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "guid": "2f28e8c1-ae0f-4b46-a826-f513974526a3",
 | 
			
		||||
@@ -75,7 +75,7 @@
 | 
			
		||||
    "guid": "3c46290b-85db-4cd2-93a2-943c8c93b3b1",
 | 
			
		||||
    "filename": "Speedtest.py",
 | 
			
		||||
    "submittedBy": "https://github.com/wh1te909",
 | 
			
		||||
    "name": "Network - Speed Test",
 | 
			
		||||
    "name": "Speed Test - Python",
 | 
			
		||||
    "description": "Runs a Speed Test using Python",
 | 
			
		||||
    "shell": "python",
 | 
			
		||||
    "category": "TRMM (Win):Network"
 | 
			
		||||
@@ -102,7 +102,7 @@
 | 
			
		||||
    "guid": "2ea35fa2-c227-4d17-a40e-4d39f252e27a",
 | 
			
		||||
    "filename": "Win_Bitlocker_Create_Status_Report.ps1",
 | 
			
		||||
    "submittedBy": "https://github.com/ThatsNASt",
 | 
			
		||||
    "name": "Create Bitlocker Status Report",
 | 
			
		||||
    "name": "Bitlocker - Create Status Report",
 | 
			
		||||
    "description": "Creates a Bitlocker status report.",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Storage"
 | 
			
		||||
@@ -228,7 +228,7 @@
 | 
			
		||||
    "guid": "24f19ead-fdfe-46b4-9dcb-4cd0e12a3940",
 | 
			
		||||
    "filename": "Win_Speedtest.ps1",
 | 
			
		||||
    "submittedBy": "https://github.com/dinger1986",
 | 
			
		||||
    "name": "Speed Test Powershell",
 | 
			
		||||
    "name": "Speed Test - Powershell",
 | 
			
		||||
    "description": "Speed Test with Powershell(win 10 or server2016+)",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Network"
 | 
			
		||||
@@ -327,7 +327,7 @@
 | 
			
		||||
    "guid": "5615aa90-0272-427b-8acf-0ca019612501",
 | 
			
		||||
    "filename": "Win_Chocolatey_Update_Installed.bat",
 | 
			
		||||
    "submittedBy": "https://github.com/silversword411",
 | 
			
		||||
    "name": "Chocolatey Update Installed Apps",
 | 
			
		||||
    "name": "Update Installed Apps",
 | 
			
		||||
    "description": "Update all apps that were installed using Chocolatey.",
 | 
			
		||||
    "shell": "cmd",
 | 
			
		||||
    "category": "TRMM (Win):3rd Party Software>Chocolatey"
 | 
			
		||||
@@ -394,7 +394,7 @@
 | 
			
		||||
    "name": "Updates - Finish and restart",
 | 
			
		||||
    "description": "Finish installing Windows updates and restart PC",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Other"
 | 
			
		||||
    "category": "TRMM (Win):Updates"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "guid": "63f89be0-a9c9-4c61-9b55-bce0b28b90b2",
 | 
			
		||||
@@ -403,7 +403,7 @@
 | 
			
		||||
    "name": "Updates - Finish and Shutdown",
 | 
			
		||||
    "description": "Finish installing Windows updates and shutdown PC",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Other"
 | 
			
		||||
    "category": "TRMM (Win):Updates"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "guid": "e09895d5-ca13-44a2-a38c-6e77c740f0e8",
 | 
			
		||||
@@ -460,6 +460,16 @@
 | 
			
		||||
    "category": "TRMM (Win):Network",
 | 
			
		||||
    "default_timeout": "90"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "guid": "abe78170-7cf9-435b-9666-c5ef6c11a106",
 | 
			
		||||
    "filename": "Win_Network_IPv6_Disable.ps1",
 | 
			
		||||
    "submittedBy": "https://github.com/silversword411",
 | 
			
		||||
    "name": "Network IPv6 - Disable",
 | 
			
		||||
    "description": "Disable IPv6 on all adapters",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Network",
 | 
			
		||||
    "default_timeout": "90"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "guid": "6ce5682a-49db-4c0b-9417-609cf905ac43",
 | 
			
		||||
    "filename": "Win_Win10_Change_Key_and_Activate.ps1",
 | 
			
		||||
@@ -563,9 +573,9 @@
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "guid": "77da9c87-5a7a-4ba1-bdde-3eeb3b01d62d",
 | 
			
		||||
    "filename": "Win_Set_Network_To_Private.ps1",
 | 
			
		||||
    "filename": "Win_Network_Set_To_Private.ps1",
 | 
			
		||||
    "submittedBy": "https://github.com/tremor021",
 | 
			
		||||
    "name": "Set Network To Private",
 | 
			
		||||
    "name": "Network Category - Set Network To Private",
 | 
			
		||||
    "description": "Sets current network type to Private",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Network"
 | 
			
		||||
@@ -574,7 +584,7 @@
 | 
			
		||||
    "guid": "768f42d5-7b45-45ed-8233-254ae537aaa2",
 | 
			
		||||
    "filename": "Win_TaskScheduler_Add_Task.ps1",
 | 
			
		||||
    "submittedBy": "https://github.com/tremor021",
 | 
			
		||||
    "name": "Add task to TaskScheduler",
 | 
			
		||||
    "name": "Task Scheduler - Add a task",
 | 
			
		||||
    "description": "Add a task to Task Scheduler, needs editing",
 | 
			
		||||
    "shell": "powershell",
 | 
			
		||||
    "category": "TRMM (Win):Other"
 | 
			
		||||
 
 | 
			
		||||
@@ -15,14 +15,14 @@ EXE_DIR = os.path.join(BASE_DIR, "tacticalrmm/private/exe")
 | 
			
		||||
AUTH_USER_MODEL = "accounts.User"
 | 
			
		||||
 | 
			
		||||
# latest release
 | 
			
		||||
TRMM_VERSION = "0.6.0"
 | 
			
		||||
TRMM_VERSION = "0.6.1"
 | 
			
		||||
 | 
			
		||||
# bump this version everytime vue code is changed
 | 
			
		||||
# to alert user they need to manually refresh their browser
 | 
			
		||||
APP_VER = "0.0.129"
 | 
			
		||||
APP_VER = "0.0.130"
 | 
			
		||||
 | 
			
		||||
# https://github.com/wh1te909/rmmagent
 | 
			
		||||
LATEST_AGENT_VER = "1.5.0"
 | 
			
		||||
LATEST_AGENT_VER = "1.5.1"
 | 
			
		||||
 | 
			
		||||
MESH_VER = "0.7.93"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ def generate_winagent_exe(
 | 
			
		||||
    file_name: str,
 | 
			
		||||
) -> Union[Response, FileResponse]:
 | 
			
		||||
 | 
			
		||||
    from agents.tasks import _get_exegen_url
 | 
			
		||||
    from agents.utils import get_exegen_url
 | 
			
		||||
 | 
			
		||||
    inno = (
 | 
			
		||||
        f"winagent-v{settings.LATEST_AGENT_VER}.exe"
 | 
			
		||||
@@ -62,7 +62,7 @@ def generate_winagent_exe(
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        codetoken = CodeSignToken.objects.first().token
 | 
			
		||||
        base_url = _get_exegen_url() + "/api/v1/winagents/?"
 | 
			
		||||
        base_url = get_exegen_url() + "/api/v1/winagents/?"
 | 
			
		||||
        params = {
 | 
			
		||||
            "version": settings.LATEST_AGENT_VER,
 | 
			
		||||
            "arch": arch,
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ A backup script is provided for quick and easy way to backup all settings into o
 | 
			
		||||
 | 
			
		||||
Download the backup script:
 | 
			
		||||
```bash
 | 
			
		||||
wget https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/backup.sh
 | 
			
		||||
wget -N https://raw.githubusercontent.com/wh1te909/tacticalrmm/master/backup.sh
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
From the Web UI, click **Tools > Server Maintenance**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								scripts/Win_Network_IPv6_Disable.ps1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								scripts/Win_Network_IPv6_Disable.ps1
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#CVE-2020-16898 | Windows TCP/IP Remote Code Execution Vulnerability
 | 
			
		||||
#https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-16898
 | 
			
		||||
 | 
			
		||||
#Disable IPv6 on All Adapers
 | 
			
		||||
Disable-NetAdapterBinding -Name "*" -ComponentID ms_tcpip6
 | 
			
		||||
 | 
			
		||||
#Confirm That all NIC's no longer have IPv6 Enabled
 | 
			
		||||
(Get-NetAdapterBinding -Name '*' -ComponentID ms_tcpip6).Enabled
 | 
			
		||||
@@ -303,17 +303,18 @@
 | 
			
		||||
            />
 | 
			
		||||
          </q-td>
 | 
			
		||||
          <q-td key="checks-status" :props="props">
 | 
			
		||||
            <q-icon v-if="props.row.maintenance_mode" name="fas fa-check-double" size="1.2em" color="warning">
 | 
			
		||||
            <q-icon v-if="props.row.maintenance_mode" name="construction" size="1.2em" color="green">
 | 
			
		||||
              <q-tooltip>Maintenance Mode Enabled</q-tooltip>
 | 
			
		||||
            </q-icon>
 | 
			
		||||
            <q-icon
 | 
			
		||||
              v-else-if="props.row.checks.has_failing_checks"
 | 
			
		||||
              name="fas fa-check-double"
 | 
			
		||||
              size="1.2em"
 | 
			
		||||
              color="negative"
 | 
			
		||||
            >
 | 
			
		||||
            <q-icon v-else-if="props.row.checks.failing > 0" name="fas fa-check-double" size="1.2em" color="negative">
 | 
			
		||||
              <q-tooltip>Checks failing</q-tooltip>
 | 
			
		||||
            </q-icon>
 | 
			
		||||
            <q-icon v-else-if="props.row.checks.warning > 0" name="fas fa-check-double" size="1.2em" color="warning">
 | 
			
		||||
              <q-tooltip>Checks warning</q-tooltip>
 | 
			
		||||
            </q-icon>
 | 
			
		||||
            <q-icon v-else-if="props.row.checks.info > 0" name="fas fa-check-double" size="1.2em" color="info">
 | 
			
		||||
              <q-tooltip>Checks info</q-tooltip>
 | 
			
		||||
            </q-icon>
 | 
			
		||||
            <q-icon v-else name="fas fa-check-double" size="1.2em" color="positive">
 | 
			
		||||
              <q-tooltip>Checks passing</q-tooltip>
 | 
			
		||||
            </q-icon>
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@
 | 
			
		||||
      <template v-else>
 | 
			
		||||
        <q-table
 | 
			
		||||
          dense
 | 
			
		||||
          :table-class="{ 'table-bgcolor': !$q.dark.isActive, 'table-bgcolor-dark': $q.dark.isActive }"
 | 
			
		||||
          class="tabs-tbl-sticky"
 | 
			
		||||
          :style="{ 'max-height': tabsTableHeight }"
 | 
			
		||||
          :data="tasks"
 | 
			
		||||
 
 | 
			
		||||
@@ -124,6 +124,13 @@
 | 
			
		||||
                    <q-item-section>Delete</q-item-section>
 | 
			
		||||
                  </q-item>
 | 
			
		||||
                  <q-separator></q-separator>
 | 
			
		||||
                  <q-item clickable v-close-popup @click="resetCheck(props.row.id)">
 | 
			
		||||
                    <q-item-section side>
 | 
			
		||||
                      <q-icon name="info" />
 | 
			
		||||
                    </q-item-section>
 | 
			
		||||
                    <q-item-section>Reset Check Status</q-item-section>
 | 
			
		||||
                  </q-item>
 | 
			
		||||
                  <q-separator></q-separator>
 | 
			
		||||
                  <q-item clickable v-close-popup>
 | 
			
		||||
                    <q-item-section>Close</q-item-section>
 | 
			
		||||
                  </q-item>
 | 
			
		||||
@@ -431,7 +438,25 @@ export default {
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    resetCheck(check) {
 | 
			
		||||
      const data = {
 | 
			
		||||
        check_reset: true,
 | 
			
		||||
        status: "passing",
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      axios
 | 
			
		||||
        .patch(`/checks/${check}/check/`, data)
 | 
			
		||||
        .then(r => {
 | 
			
		||||
          this.$emit("refreshEdit");
 | 
			
		||||
          this.$store.dispatch("loadChecks", this.selectedAgentPk);
 | 
			
		||||
          this.notifySuccess("The check was reset");
 | 
			
		||||
        })
 | 
			
		||||
        .catch(e => {
 | 
			
		||||
          this.notifyError("There was an issue resetting the check");
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    onRefresh(id) {
 | 
			
		||||
      this.$emit("refreshEdit");
 | 
			
		||||
      this.$store.dispatch("loadChecks", id);
 | 
			
		||||
      this.$store.dispatch("loadAutomatedTasks", id);
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -283,10 +283,18 @@
 | 
			
		||||
                    <q-tooltip> Batch </q-tooltip>
 | 
			
		||||
                  </q-icon>
 | 
			
		||||
                </q-td>
 | 
			
		||||
                <!-- name -->
 | 
			
		||||
                <q-td>{{ props.row.name }}</q-td>
 | 
			
		||||
                <!-- args -->
 | 
			
		||||
                <q-td>
 | 
			
		||||
                  <span v-if="props.row.args.length > 0">{{ props.row.args }}</span>
 | 
			
		||||
                  <span v-if="props.row.args.length > 0">
 | 
			
		||||
                    {{ truncateText(props.row.args.toString()) }}
 | 
			
		||||
                    <q-tooltip v-if="props.row.args.toString().length >= 60" content-style="font-size: 12px">
 | 
			
		||||
                      {{ props.row.args }}
 | 
			
		||||
                    </q-tooltip>
 | 
			
		||||
                  </span>
 | 
			
		||||
                </q-td>
 | 
			
		||||
 | 
			
		||||
                <q-td>{{ props.row.category }}</q-td>
 | 
			
		||||
                <q-td>
 | 
			
		||||
                  {{ truncateText(props.row.description) }}
 | 
			
		||||
@@ -363,6 +371,7 @@ export default {
 | 
			
		||||
          label: "Default Args",
 | 
			
		||||
          field: "args",
 | 
			
		||||
          align: "left",
 | 
			
		||||
          sortable: true,
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: "category",
 | 
			
		||||
@@ -516,12 +525,10 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    categories() {
 | 
			
		||||
      let list = [];
 | 
			
		||||
      this.scripts.forEach(script => {
 | 
			
		||||
      this.visibleScripts.forEach(script => {
 | 
			
		||||
        if (!!script.category && !list.includes(script.category)) {
 | 
			
		||||
          if (script.category !== "Community") {
 | 
			
		||||
          list.push(script.category);
 | 
			
		||||
        }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      return list;
 | 
			
		||||
    },
 | 
			
		||||
@@ -538,8 +545,7 @@ export default {
 | 
			
		||||
        let scriptsTemp = Object.assign([], this.visibleScripts);
 | 
			
		||||
        let categoriesTemp = Object.assign([], this.categories);
 | 
			
		||||
 | 
			
		||||
        // add Community and Unassigned values and categories array
 | 
			
		||||
        if (this.showCommunityScripts) categoriesTemp.push("Community");
 | 
			
		||||
        // add Unassigned category
 | 
			
		||||
        categoriesTemp.push("Unassigned");
 | 
			
		||||
 | 
			
		||||
        const sorted = categoriesTemp.sort();
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
        <SummaryTab />
 | 
			
		||||
      </q-tab-panel>
 | 
			
		||||
      <q-tab-panel name="checks" class="q-pb-xs q-pt-none">
 | 
			
		||||
        <ChecksTab />
 | 
			
		||||
        <ChecksTab @refreshEdit="$emit('refreshEdit')" />
 | 
			
		||||
      </q-tab-panel>
 | 
			
		||||
      <q-tab-panel name="tasks" class="q-pb-xs q-pt-none">
 | 
			
		||||
        <AutomatedTasksTab />
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
    <q-btn class="q-mr-sm" dense flat push icon="refresh" @click="refreshSummary" />
 | 
			
		||||
    <span>
 | 
			
		||||
      <b>{{ summary.hostname }}</b>
 | 
			
		||||
      <span v-if="summary.maintenance_mode"> • <q-badge color="warning"> Maintenance Mode </q-badge> </span>
 | 
			
		||||
      <span v-if="summary.maintenance_mode"> • <q-badge color="green"> Maintenance Mode </q-badge> </span>
 | 
			
		||||
      • {{ summary.operating_system }} • Agent v{{ summary.version }}
 | 
			
		||||
    </span>
 | 
			
		||||
    <hr />
 | 
			
		||||
@@ -72,6 +72,14 @@
 | 
			
		||||
            <q-avatar size="lg" square icon="cancel" color="red" text-color="white" />
 | 
			
		||||
            <small>{{ summary.checks.failing }} checks failing</small>
 | 
			
		||||
          </q-chip>
 | 
			
		||||
          <q-chip v-if="summary.checks.warning" square size="lg">
 | 
			
		||||
            <q-avatar size="lg" square icon="warning" color="warning" text-color="white" />
 | 
			
		||||
            <small>{{ summary.checks.warning }} checks warning</small>
 | 
			
		||||
          </q-chip>
 | 
			
		||||
          <q-chip v-if="summary.checks.info" square size="lg">
 | 
			
		||||
            <q-avatar size="lg" square icon="info" color="info" text-color="white" />
 | 
			
		||||
            <small>{{ summary.checks.info }} checks info</small>
 | 
			
		||||
          </q-chip>
 | 
			
		||||
          <span v-if="awaitingSync(summary.checks.total, summary.checks.passing, summary.checks.failing)"
 | 
			
		||||
            >{{ summary.checks.total }} checks awaiting first synchronization</span
 | 
			
		||||
          >
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,7 @@
 | 
			
		||||
      <div class="col-3">Day of month to run:</div>
 | 
			
		||||
      <div class="col-4"></div>
 | 
			
		||||
      <q-select
 | 
			
		||||
        :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
        v-show="winupdatepolicy.run_time_frequency !== 'inherit'"
 | 
			
		||||
        dense
 | 
			
		||||
        class="col-5"
 | 
			
		||||
        outlined
 | 
			
		||||
@@ -103,11 +103,10 @@
 | 
			
		||||
        map-options
 | 
			
		||||
      />
 | 
			
		||||
    </q-card-section>
 | 
			
		||||
    <q-card-section class="row">
 | 
			
		||||
    <q-card-section class="row" v-show="winupdatepolicy.run_time_frequency !== 'inherit'">
 | 
			
		||||
      <div class="col-3">Scheduled Time:</div>
 | 
			
		||||
      <div class="col-4"></div>
 | 
			
		||||
      <q-select
 | 
			
		||||
        :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
        dense
 | 
			
		||||
        class="col-5"
 | 
			
		||||
        outlined
 | 
			
		||||
@@ -118,51 +117,17 @@
 | 
			
		||||
      />
 | 
			
		||||
    </q-card-section>
 | 
			
		||||
    <q-card-section
 | 
			
		||||
      v-if="winupdatepolicy.run_time_frequency === 'daily' || winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
      v-if="winupdatepolicy.run_time_frequency === 'daily'"
 | 
			
		||||
      v-show="winupdatepolicy.run_time_frequency !== 'inherit'"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="q-gutter-sm">
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="1"
 | 
			
		||||
          label="Monday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="2"
 | 
			
		||||
          label="Tuesday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="3"
 | 
			
		||||
          label="Wednesday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="4"
 | 
			
		||||
          label="Thursday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="5"
 | 
			
		||||
          label="Friday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="6"
 | 
			
		||||
          label="Saturday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.run_time_frequency === 'inherit'"
 | 
			
		||||
          v-model="winupdatepolicy.run_time_days"
 | 
			
		||||
          :val="0"
 | 
			
		||||
          label="Sunday"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="1" label="Monday" />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="2" label="Tuesday" />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="3" label="Wednesday" />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="4" label="Thursday" />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="5" label="Friday" />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="6" label="Saturday" />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.run_time_days" :val="0" label="Sunday" />
 | 
			
		||||
      </div>
 | 
			
		||||
    </q-card-section>
 | 
			
		||||
    <!-- Reboot After Installation -->
 | 
			
		||||
@@ -189,20 +154,15 @@
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.reprocess_failed_inherit" label="Inherit failed patch settings" />
 | 
			
		||||
      </div>
 | 
			
		||||
    </q-card-section>
 | 
			
		||||
    <q-card-section class="row">
 | 
			
		||||
    <q-card-section class="row" v-show="!winupdatepolicy.reprocess_failed_inherit">
 | 
			
		||||
      <div class="col-5">
 | 
			
		||||
        <q-checkbox
 | 
			
		||||
          :disable="winupdatepolicy.reprocess_failed_inherit"
 | 
			
		||||
          v-model="winupdatepolicy.reprocess_failed"
 | 
			
		||||
          label="Reprocess failed patches"
 | 
			
		||||
        />
 | 
			
		||||
        <q-checkbox v-model="winupdatepolicy.reprocess_failed" label="Reprocess failed patches" />
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="col-3">
 | 
			
		||||
        <q-input
 | 
			
		||||
          dense
 | 
			
		||||
          v-model.number="winupdatepolicy.reprocess_failed_times"
 | 
			
		||||
          :disable="winupdatepolicy.reprocess_failed_inherit"
 | 
			
		||||
          type="number"
 | 
			
		||||
          filled
 | 
			
		||||
          label="Times"
 | 
			
		||||
@@ -210,11 +170,7 @@
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="col-3"></div>
 | 
			
		||||
      <q-checkbox
 | 
			
		||||
        v-model="winupdatepolicy.email_if_fail"
 | 
			
		||||
        :disable="winupdatepolicy.reprocess_failed_inherit"
 | 
			
		||||
        label="Send an email when patch installation fails"
 | 
			
		||||
      />
 | 
			
		||||
      <q-checkbox v-model="winupdatepolicy.email_if_fail" label="Send an email when patch installation fails" />
 | 
			
		||||
    </q-card-section>
 | 
			
		||||
    <q-card-actions align="left" v-if="policy">
 | 
			
		||||
      <q-btn label="Submit" color="primary" @click="submit" />
 | 
			
		||||
@@ -249,6 +205,7 @@ export default {
 | 
			
		||||
        run_time_hour: 3,
 | 
			
		||||
        run_time_frequency: "daily",
 | 
			
		||||
        run_time_days: [],
 | 
			
		||||
        run_time_day: 1,
 | 
			
		||||
        reboot_after_install: "never",
 | 
			
		||||
        reprocess_failed_inherit: false,
 | 
			
		||||
        reprocess_failed: false,
 | 
			
		||||
 
 | 
			
		||||
@@ -256,8 +256,9 @@ export default function () {
 | 
			
		||||
                alert_template: site.alert_template
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              if (site.maintenance_mode) { siteNode["color"] = "warning" }
 | 
			
		||||
              else if (site.failing_checks) { siteNode["color"] = "negative" }
 | 
			
		||||
              if (site.maintenance_mode) { siteNode["color"] = "green" }
 | 
			
		||||
              else if (site.failing_checks.error) { siteNode["color"] = "negative" }
 | 
			
		||||
              else if (site.failing_checks.warning) { siteNode["color"] = "warning" }
 | 
			
		||||
 | 
			
		||||
              childSites.push(siteNode);
 | 
			
		||||
            }
 | 
			
		||||
@@ -274,8 +275,9 @@ export default function () {
 | 
			
		||||
              children: childSites
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (client.maintenance_mode) clientNode["color"] = "warning"
 | 
			
		||||
            else if (client.failing_checks) clientNode["color"] = "negative"
 | 
			
		||||
            if (client.maintenance_mode) clientNode["color"] = "green"
 | 
			
		||||
            else if (client.failing_checks.error) { clientNode["color"] = "negative" }
 | 
			
		||||
            else if (client.failing_checks.warning) { clientNode["color"] = "warning" }
 | 
			
		||||
 | 
			
		||||
            output.push(clientNode);
 | 
			
		||||
          }
 | 
			
		||||
 
 | 
			
		||||
@@ -343,7 +343,7 @@
 | 
			
		||||
              <q-avatar color="primary" text-color="white" size="30px" icon="drag_indicator" />
 | 
			
		||||
            </template>
 | 
			
		||||
            <template v-slot:after>
 | 
			
		||||
              <SubTableTabs />
 | 
			
		||||
              <SubTableTabs @refreshEdit="refreshEntireSite" />
 | 
			
		||||
            </template>
 | 
			
		||||
          </q-splitter>
 | 
			
		||||
        </template>
 | 
			
		||||
@@ -727,10 +727,10 @@ export default {
 | 
			
		||||
      let data = {
 | 
			
		||||
        id: node.id,
 | 
			
		||||
        type: node.raw.split("|")[0],
 | 
			
		||||
        action: node.color === "warning" ? false : true,
 | 
			
		||||
        action: node.color === "green" ? false : true,
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const text = node.color === "warning" ? "Maintenance mode was disabled" : "Maintenance mode was enabled";
 | 
			
		||||
      const text = node.color === "green" ? "Maintenance mode was disabled" : "Maintenance mode was enabled";
 | 
			
		||||
      this.$store
 | 
			
		||||
        .dispatch("toggleMaintenanceMode", data)
 | 
			
		||||
        .then(response => {
 | 
			
		||||
@@ -742,7 +742,7 @@ export default {
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    menuMaintenanceText(node) {
 | 
			
		||||
      return node.color === "warning" ? "Disable Maintenance Mode" : "Enable Maintenance Mode";
 | 
			
		||||
      return node.color === "green" ? "Disable Maintenance Mode" : "Enable Maintenance Mode";
 | 
			
		||||
    },
 | 
			
		||||
    clearFilter() {
 | 
			
		||||
      this.filterTextLength = 0;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user