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":
|
||||
failing += 1
|
||||
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,11 +525,9 @@ 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);
|
||||
}
|
||||
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