Compare commits

..

16 Commits

Author SHA1 Message Date
wh1te909
28edc31d43 Release 0.5.3 2021-04-11 08:08:58 +00:00
wh1te909
0f9872a818 bump versions 2021-04-11 08:08:48 +00:00
wh1te909
76ce4296f3 fix graphics 2021-04-11 07:25:37 +00:00
wh1te909
3dd2671380 add graphics 2021-04-11 06:50:16 +00:00
wh1te909
298ca31332 remove unused func 2021-04-11 05:43:17 +00:00
wh1te909
8f911aa6b9 more tests 2021-04-11 05:35:24 +00:00
wh1te909
82a5c7d9b1 add test 2021-04-11 05:17:49 +00:00
wh1te909
7f013dcdba refactor nats-api / optimize queries 2021-04-11 05:04:33 +00:00
wh1te909
68e2e16076 add feat #377 2021-04-11 03:23:40 +00:00
wh1te909
ea23c763c9 add feat #376 2021-04-11 02:01:40 +00:00
wh1te909
5dcecb3206 fix alert text for policy diskspace check where disk doesn't exist 2021-04-10 22:09:24 +00:00
Dan
5bd48e2d0e Merge pull request #380 from silversword411/develop
Community Script Additions
2021-04-10 13:36:26 -07:00
silversword411
afd0a02589 3 scripts added from dinger1986 2021-04-10 13:44:02 -04:00
silversword411
2379192d53 Merge branch 'develop' of https://github.com/silversword411/tacticalrmm into develop 2021-04-10 13:27:35 -04:00
silversword411
a6489290c8 2 scripts added 2021-04-10 13:26:39 -04:00
silversword411
5f74c43415 2 scripts added 2021-04-10 13:22:54 -04:00
31 changed files with 311 additions and 84 deletions

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-04-11 01:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0013_user_client_tree_sort'),
]
operations = [
migrations.AddField(
model_name='user',
name='client_tree_splitter',
field=models.PositiveIntegerField(default=11),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2 on 2021-04-11 03:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0014_user_client_tree_splitter'),
]
operations = [
migrations.AddField(
model_name='user',
name='loading_bar_color',
field=models.CharField(default='red', max_length=255),
),
]

View File

@@ -36,6 +36,8 @@ class User(AbstractUser, BaseAuditModel):
client_tree_sort = models.CharField(
max_length=50, choices=CLIENT_TREE_SORT_CHOICES, default="alphafail"
)
client_tree_splitter = models.PositiveIntegerField(default=11)
loading_bar_color = models.CharField(max_length=255, default="red")
agent = models.OneToOneField(
"agents.Agent",

View File

@@ -13,6 +13,8 @@ class UserUISerializer(ModelSerializer):
"agent_dblclick_action",
"default_agent_tbl_tab",
"client_tree_sort",
"client_tree_splitter",
"loading_bar_color",
]

View File

@@ -278,6 +278,8 @@ class TestUserAction(TacticalTestCase):
"agent_dblclick_action": "editagent",
"default_agent_tbl_tab": "mixed",
"client_tree_sort": "alpha",
"client_tree_splitter": 14,
"loading_bar_color": "green",
}
r = self.client.patch(url, data, format="json")
self.assertEqual(r.status_code, 200)

View File

@@ -195,6 +195,27 @@ class Agent(BaseAuditModel):
except:
return ["unknown cpu model"]
@property
def graphics(self):
ret, mrda = [], []
try:
graphics = self.wmi_detail["graphics"]
for i in graphics:
caption = [x["Caption"] for x in i if "Caption" in x][0]
if "microsoft remote display adapter" in caption.lower():
mrda.append("yes")
continue
ret.append([x["Caption"] for x in i if "Caption" in x][0])
# only return this if no other graphics cards
if not ret and mrda:
return "Microsoft Remote Display Adapter"
return ", ".join(ret)
except:
return "Graphics info requires agent v1.4.14"
@property
def local_ips(self):
ret = []
@@ -322,7 +343,7 @@ class Agent(BaseAuditModel):
online = [
agent
for agent in Agent.objects.only(
"pk", "last_seen", "overdue_time", "offline_time"
"pk", "agent_id", "last_seen", "overdue_time", "offline_time"
)
if agent.status == "online"
]
@@ -819,12 +840,6 @@ class RecoveryAction(models.Model):
def __str__(self):
return f"{self.agent.hostname} - {self.mode}"
def send(self):
ret = {"recovery": self.mode}
if self.mode == "command":
ret["cmd"] = self.command
return ret
class Note(models.Model):
agent = models.ForeignKey(

View File

@@ -16,6 +16,7 @@ class AgentSerializer(serializers.ModelSerializer):
local_ips = serializers.ReadOnlyField()
make_model = serializers.ReadOnlyField()
physical_disks = serializers.ReadOnlyField()
graphics = serializers.ReadOnlyField()
checks = serializers.ReadOnlyField()
timezone = serializers.ReadOnlyField()
all_timezones = serializers.SerializerMethodField()

View File

@@ -1,9 +1,6 @@
import asyncio
import datetime as dt
import json
import random
import subprocess
import tempfile
from time import sleep
from typing import Union
@@ -17,6 +14,7 @@ from core.models import CoreSettings
from logs.models import PendingAction
from scripts.models import Script
from tacticalrmm.celery import app
from tacticalrmm.utils import run_nats_api_cmd
logger.configure(**settings.LOG_CONFIG)
@@ -257,30 +255,13 @@ def run_script_email_results_task(
logger.error(e)
def _get_nats_config() -> dict:
return {
"key": settings.SECRET_KEY,
"natsurl": f"tls://{settings.ALLOWED_HOSTS[0]}:4222",
}
@app.task
def monitor_agents_task() -> None:
agents = Agent.objects.only(
"pk", "agent_id", "last_seen", "overdue_time", "offline_time"
)
ret = [i.agent_id for i in agents if i.status != "online"]
config = _get_nats_config()
config["agents"] = ret
with tempfile.NamedTemporaryFile() as fp:
with open(fp.name, "w") as f:
json.dump(config, f)
cmd = ["/usr/local/bin/nats-api", "-c", fp.name, "-m", "monitor"]
try:
subprocess.run(cmd, capture_output=True, timeout=30)
except Exception as e:
logger.error(e)
ids = [i.agent_id for i in agents if i.status != "online"]
run_nats_api_cmd("monitor", ids)
@app.task
@@ -288,15 +269,5 @@ def get_wmi_task() -> None:
agents = Agent.objects.only(
"pk", "agent_id", "last_seen", "overdue_time", "offline_time"
)
ret = [i.agent_id for i in agents if i.status == "online"]
config = _get_nats_config()
config["agents"] = ret
with tempfile.NamedTemporaryFile() as fp:
with open(fp.name, "w") as f:
json.dump(config, f)
cmd = ["/usr/local/bin/nats-api", "-c", fp.name, "-m", "wmi"]
try:
subprocess.run(cmd, capture_output=True, timeout=30)
except Exception as e:
logger.error(e)
ids = [i.agent_id for i in agents if i.status == "online"]
run_nats_api_cmd("wmi", ids)

View File

@@ -40,7 +40,7 @@ logger.configure(**settings.LOG_CONFIG)
@api_view()
def get_agent_versions(request):
agents = Agent.objects.only("pk")
agents = Agent.objects.prefetch_related("site").only("pk", "hostname")
return Response(
{
"versions": [settings.LATEST_AGENT_VER],

View File

@@ -633,12 +633,15 @@ class Check(BaseAuditModel):
if self.error_threshold:
text += f" Error Threshold: {self.error_threshold}%"
percent_used = [
d["percent"] for d in self.agent.disks if d["device"] == self.disk
][0]
percent_free = 100 - percent_used
try:
percent_used = [
d["percent"] for d in self.agent.disks if d["device"] == self.disk
][0]
percent_free = 100 - percent_used
body = subject + f" - Free: {percent_free}%, {text}"
body = subject + f" - Free: {percent_free}%, {text}"
except:
body = subject + f" - Disk {self.disk} does not exist"
elif self.check_type == "script":
@@ -710,11 +713,15 @@ class Check(BaseAuditModel):
if self.error_threshold:
text += f" Error Threshold: {self.error_threshold}%"
percent_used = [
d["percent"] for d in self.agent.disks if d["device"] == self.disk
][0]
percent_free = 100 - percent_used
body = subject + f" - Free: {percent_free}%, {text}"
try:
percent_used = [
d["percent"] for d in self.agent.disks if d["device"] == self.disk
][0]
percent_free = 100 - percent_used
body = subject + f" - Free: {percent_free}%, {text}"
except:
body = subject + f" - Disk {self.disk} does not exist"
elif self.check_type == "script":
body = subject + f" - Return code: {self.retcode}"
elif self.check_type == "ping":

View File

@@ -65,6 +65,8 @@ def dashboard_info(request):
"dbl_click_action": request.user.agent_dblclick_action,
"default_agent_tbl_tab": request.user.default_agent_tbl_tab,
"client_tree_sort": request.user.client_tree_sort,
"client_tree_splitter": request.user.client_tree_splitter,
"loading_bar_color": request.user.loading_bar_color,
}
)

View File

@@ -397,5 +397,42 @@
"shell": "powershell",
"category": "TRMM (Win):Other",
"default_timeout": "90"
},
{
"guid": "83f6c6ea-6120-4fd3-bec8-d3abc505dcdf",
"filename": "Win_TRMM_Start_Menu_Delete_Shortcut.ps1",
"submittedBy": "https://github.com/silversword411",
"name": "TRMM Delete Start Menu Shortcut for App",
"description": "Tactical RMM delete its application shortcut that's installed in the start menu",
"shell": "powershell",
"category": "TRMM (Win):TacticalRMM Related",
"default_timeout": "10"
},
{
"guid": "60130fca-7636-446e-acd7-cc5d29d609c2",
"filename": "Win_Firewall_Check_Status.ps1",
"submittedBy": "https://github.com/dinger1986",
"name": "Windows Firewall - Check Status",
"description": "Windows Firewall - Check state, report status",
"shell": "powershell",
"category": "TRMM (Win):Network"
},
{
"guid": "93379675-c01c-433f-87df-a11597c959f0",
"filename": "Win_UAC_Check_Status.ps1",
"submittedBy": "https://github.com/dinger1986",
"name": "Windows UAC - Check Status",
"description": "Windows UAC - Report status",
"shell": "powershell",
"category": "TRMM (Win):Security"
},
{
"guid": "7ea6a11a-05c0-4151-b5c1-cb8af029299f",
"filename": "Win_AzureAD_Check_Connection_Status.ps1",
"submittedBy": "https://github.com/dinger1986",
"name": "Azure AD - Check Status",
"description": "Azure AD - Check if joined or not",
"shell": "powershell",
"category": "TRMM (Win):Azure>AD"
}
]

View File

@@ -15,14 +15,14 @@ EXE_DIR = os.path.join(BASE_DIR, "tacticalrmm/private/exe")
AUTH_USER_MODEL = "accounts.User"
# latest release
TRMM_VERSION = "0.5.2"
TRMM_VERSION = "0.5.3"
# bump this version everytime vue code is changed
# to alert user they need to manually refresh their browser
APP_VER = "0.0.127"
APP_VER = "0.0.128"
# https://github.com/wh1te909/rmmagent
LATEST_AGENT_VER = "1.4.13"
LATEST_AGENT_VER = "1.4.14"
MESH_VER = "0.7.93"

View File

@@ -12,6 +12,7 @@ from .utils import (
generate_winagent_exe,
get_bit_days,
reload_nats,
run_nats_api_cmd,
)
@@ -74,6 +75,12 @@ class TestUtils(TestCase):
mock_subprocess.assert_called_once()
@patch("subprocess.run")
def test_run_nats_api_cmd(self, mock_subprocess):
ids = ["a", "b", "c"]
_ = run_nats_api_cmd("monitor", ids)
mock_subprocess.assert_called_once()
def test_bitdays_to_string(self):
a = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
all_days = [

View File

@@ -228,3 +228,20 @@ class KnoxAuthMiddlewareInstance:
KnoxAuthMiddlewareStack = lambda inner: KnoxAuthMiddlewareInstance(
AuthMiddlewareStack(inner)
)
def run_nats_api_cmd(mode: str, ids: list[str], timeout: int = 30) -> None:
config = {
"key": settings.SECRET_KEY,
"natsurl": f"tls://{settings.ALLOWED_HOSTS[0]}:4222",
"agents": ids,
}
with tempfile.NamedTemporaryFile() as fp:
with open(fp.name, "w") as f:
json.dump(config, f)
cmd = ["/usr/local/bin/nats-api", "-c", fp.name, "-m", mode]
try:
subprocess.run(cmd, capture_output=True, timeout=timeout)
except Exception as e:
logger.error(e)

View File

@@ -14,8 +14,29 @@ class TestWinUpdateViews(TacticalTestCase):
self.authenticate()
self.setup_coresettings()
def test_get_winupdates(self):
@patch("agents.models.Agent.nats_cmd")
def test_run_update_scan(self, nats_cmd):
agent = baker.make_recipe("agents.agent")
url = f"/winupdate/{agent.pk}/runupdatescan/"
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
nats_cmd.assert_called_with({"func": "getwinupdates"}, wait=False)
self.check_not_authenticated("get", url)
@patch("agents.models.Agent.nats_cmd")
def test_install_updates(self, nats_cmd):
agent = baker.make_recipe("agents.agent")
baker.make("winupdate.WinUpdate", agent=agent, _quantity=4)
baker.make("winupdate.WinUpdatePolicy", agent=agent)
url = f"/winupdate/{agent.pk}/installnow/"
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
nats_cmd.assert_called_once()
self.check_not_authenticated("get", url)
def test_get_winupdates(self):
agent = baker.make_recipe("agents.agent")
baker.make("winupdate.WinUpdate", agent=agent, _quantity=4)
@@ -27,8 +48,8 @@ class TestWinUpdateViews(TacticalTestCase):
resp = self.client.get(url, format="json")
serializer = UpdateSerializer(agent)
self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.data["winupdates"]), 4)
self.assertEqual(resp.data, serializer.data)
self.assertEqual(len(resp.data["winupdates"]), 4) # type: ignore
self.assertEqual(resp.data, serializer.data) # type: ignore
self.check_not_authenticated("get", url)
@@ -99,7 +120,7 @@ class TestWinUpdateViews(TacticalTestCase):
resp = self.client.patch(url, invalid_data, format="json")
self.assertEqual(resp.status_code, 404)
data = {"pk": winupdate.pk, "policy": "inherit"}
data = {"pk": winupdate.pk, "policy": "inherit"} # type: ignore
resp = self.client.patch(url, data, format="json")
self.assertEqual(resp.status_code, 200)

View File

@@ -1,12 +1,11 @@
import asyncio
from django.shortcuts import get_object_or_404
from packaging import version as pyver
from rest_framework.decorators import api_view
from rest_framework.response import Response
from agents.models import Agent
from tacticalrmm.utils import get_default_timezone, notify_error
from tacticalrmm.utils import get_default_timezone
from .models import WinUpdate
from .serializers import UpdateSerializer
@@ -24,9 +23,6 @@ def get_win_updates(request, pk):
def run_update_scan(request, pk):
agent = get_object_or_404(Agent, pk=pk)
agent.delete_superseded_updates()
if pyver.parse(agent.version) < pyver.parse("1.3.0"):
return notify_error("Requires agent version 1.3.0 or greater")
asyncio.run(agent.nats_cmd({"func": "getwinupdates"}, wait=False))
return Response("ok")
@@ -35,9 +31,6 @@ def run_update_scan(request, pk):
def install_updates(request, pk):
agent = get_object_or_404(Agent, pk=pk)
agent.delete_superseded_updates()
if pyver.parse(agent.version) < pyver.parse("1.3.0"):
return notify_error("Requires agent version 1.3.0 or greater")
agent.approve_updates()
nats_data = {
"func": "installwinupdates",

View File

@@ -0,0 +1,15 @@
$ErrorActionPreference = 'silentlycontinue'
$aadchk = dsregcmd /status | Where-Object { $_ -match 'AzureAdJoined : ' } | ForEach-Object { $_.Trim() }
if ($aadchk -Eq 'AzureAdJoined : Yes') {
Write-Output "Machine is Azure Ad Joined"
exit 0
}
else {
Write-Output "Machine is not Azure Ad Joined"
exit 1
}
Exit $LASTEXITCODE

View File

@@ -1,20 +1,18 @@
# Checks local disks for errors reported in event viewer within the last 24 hours
$ErrorActionPreference= 'silentlycontinue'
$ErrorActionPreference = 'silentlycontinue'
$TimeSpan = (Get-Date) - (New-TimeSpan -Day 1)
if (Get-WinEvent -FilterHashtable @{LogName='system';ID='11','9','15','52','129','7','98';Level=2,3;ProviderName='*disk*','*storsvc*','*ntfs*';StartTime=$TimeSpan})
if (Get-WinEvent -FilterHashtable @{LogName = 'system'; ID = '11', '9', '15', '52', '129', '7', '98'; Level = 2, 3; ProviderName = '*disk*', '*storsvc*', '*ntfs*'; StartTime = $TimeSpan } -MaxEvents 10 | Where-Object -Property Message -Match Volume*)
{
Write-Output "Disk errors detected please investigate"
Get-WinEvent -FilterHashtable @{LogName='system';ID='11','9','15','52','129','7','98';Level=2,3;ProviderName='*disk*','*storsvc*','*ntfs*';StartTime=$TimeSpan}
exit 1
Write-Output "Disk errors detected please investigate"
Get-WinEvent -FilterHashtable @{LogName = 'system'; ID = '11', '9', '15', '52', '129', '7', '98'; Level = 2, 3; ProviderName = '*disk*', '*storsvc*', '*ntfs*'; StartTime = $TimeSpan }
exit 1
}
else
{
Write-Output "Disks are Healthy"
exit 0
else {
Write-Output "Disks are Healthy"
exit 0
}

View File

@@ -0,0 +1,17 @@
$ErrorActionPreference = 'silentlycontinue'
$fwenabled = (get-netfirewallprofile -policystore activestore).Enabled
if ($fwenabled.Contains('True')) {
Write-Output "Firewall is Enabled"
netsh advfirewall show currentprofile
exit 0
}
else {
Write-Host "Firewall is Disabled"
exit 1
}
Exit $LASTEXITCODE

View File

@@ -0,0 +1 @@
Remove-Item -Path "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Tactical RMM Agent.lnk" -Force

View File

@@ -0,0 +1,22 @@
$ErrorActionPreference = 'silentlycontinue'
$PSDenabled = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).PromptOnSecureDesktop
$CPAenabled = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).ConsentPromptBehaviorAdmin
if ($PSDenabled -Eq 1 -And $CPAenabled -Eq 5) {
Write-Output "UAC is Enabled"
exit 0
}
elseif ($PSDenabled -Eq 1 -And $CPAenabled -Eq 2) {
Write-Output "UAC is Enabled"
exit 0
}
else {
Write-Output "UAC is Disabled"
exit 1
}
Exit $LASTEXITCODE

View File

@@ -89,7 +89,6 @@ module.exports = function () {
],
config: {
loadingBar: {
color: "red",
size: "4px"
},
notify: {

View File

@@ -23,6 +23,7 @@
<q-tab name="base_board" label="Motherboard" />
<q-tab name="comp_sys_prod" label="Computer System Product" />
<q-tab name="network_config" label="Network Config" />
<q-tab name="graphics" label="Graphics" />
<q-tab name="desktop_monitor" label="Monitors" />
<q-tab name="network_adapter" label="Network Adapters" />
</q-tabs>
@@ -63,6 +64,9 @@
<q-tab-panel name="desktop_monitor">
<WmiDetail :info="desktop_monitor" />
</q-tab-panel>
<q-tab-panel name="graphics">
<WmiDetail :info="graphics" />
</q-tab-panel>
<q-tab-panel name="network_adapter">
<WmiDetail :info="network_adapter" />
</q-tab-panel>
@@ -125,6 +129,9 @@ export default {
network_adapter() {
return this.assets.network_adapter;
},
graphics() {
return this.assets.graphics;
},
},
};
</script>

View File

@@ -39,6 +39,13 @@
</q-item-section>
<q-item-section>{{ disk }}</q-item-section>
</q-item>
<!-- graphics -->
<q-item>
<q-item-section avatar>
<q-icon name="fas fa-tv" />
</q-item-section>
<q-item-section>{{ summary.graphics }}</q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-icon name="fas fa-globe-americas" />

View File

@@ -46,6 +46,18 @@
class="col-4"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-4">Loading Bar Color:</div>
<div class="col-4"></div>
<q-select
outlined
dense
options-dense
v-model="loading_bar_color"
:options="loadingBarColors"
class="col-4"
/>
</q-card-section>
<q-card-section class="row">
<div class="col-2">Client Sort:</div>
<div class="col-2"></div>
@@ -73,6 +85,7 @@
</template>
<script>
import { loadingBarColors } from "@/mixins/data";
import mixins from "@/mixins/mixins";
export default {
@@ -80,11 +93,13 @@ export default {
mixins: [mixins],
data() {
return {
loadingBarColors,
agentDblClickAction: "",
defaultAgentTblTab: "",
clientTreeSort: "",
tab: "ui",
splitterModel: 20,
loading_bar_color: "",
clientTreeSortOptions: [
{
label: "Sort alphabetically, moving failing clients to the top",
@@ -131,6 +146,7 @@ export default {
this.agentDblClickAction = r.data.dbl_click_action;
this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
this.clientTreeSort = r.data.client_tree_sort;
this.loading_bar_color = r.data.loading_bar_color;
});
},
editUserPrefs() {
@@ -138,6 +154,7 @@ export default {
agent_dblclick_action: this.agentDblClickAction,
default_agent_tbl_tab: this.defaultAgentTblTab,
client_tree_sort: this.clientTreeSort,
loading_bar_color: this.loading_bar_color,
};
this.$axios.patch("/accounts/users/ui/", data).then(r => {
this.notifySuccess("Preferences were saved!");

View File

@@ -59,4 +59,6 @@ const monthDays = [
"31"
]
export { scheduledTimes, monthDays };
const loadingBarColors = ["red", "pink", "purple", "deep-purple", "indigo", "blue", "light-blue", "cyan", "teal", "green", "light-green", "lime", "yellow", "amber", "orange", "deep-orange", "brown", "grey", "blue-grey"]
export { scheduledTimes, monthDays, loadingBarColors };

View File

@@ -33,8 +33,12 @@ export default function () {
agentDblClickAction: "",
defaultAgentTblTab: "server",
clientTreeSort: "alphafail",
clientTreeSplitter: 11,
},
getters: {
clientTreeSplitterModel(state) {
return state.clientTreeSplitter;
},
loggedIn(state) {
return state.token !== null;
},
@@ -132,6 +136,9 @@ export default function () {
agentHeight <= 15.0 ? state.tableHeight = "15vh" : state.tableHeight = `${agentHeight}vh`;
tabsHeight <= 15.0 ? state.tabHeight = "15vh" : state.tabHeight = `${tabsHeight}vh`;
},
SET_CLIENT_SPLITTER(state, val) {
state.clientTreeSplitter = val;
},
SET_NOTES(state, notes) {
state.notes = notes;
},
@@ -149,6 +156,11 @@ export default function () {
}
},
actions: {
setClientTreeSplitter(context, val) {
axios.patch("/accounts/users/ui/", { client_tree_splitter: Math.trunc(val) }).then(r => {
context.commit("SET_CLIENT_SPLITTER", val)
})
},
setShowCommunityScripts(context, data) {
axios.patch("/accounts/users/ui/", { show_community_scripts: data }).then(r => {
context.commit("setShowCommunityScripts", data)

View File

@@ -90,7 +90,7 @@
<q-page-container>
<FileBar />
<q-splitter v-model="outsideModel">
<q-splitter v-model="clientTreeSplitter">
<template v-slot:before>
<div v-if="!treeReady" class="q-pa-sm q-gutter-sm text-center" style="height: 30vh">
<q-spinner size="40px" color="primary" />
@@ -397,7 +397,6 @@ export default {
serverOfflineCount: 0,
workstationCount: 0,
workstationOfflineCount: 0,
outsideModel: 11,
selectedTree: "",
innerModel: 50,
clientActive: "",
@@ -712,8 +711,10 @@ export default {
getDashInfo(edited = true) {
this.$store.dispatch("getDashInfo").then(r => {
if (edited) {
this.$q.loadingBar.setDefaults({ color: r.data.loading_bar_color });
this.$store.commit("SET_DEFAULT_AGENT_TBL_TAB", r.data.default_agent_tbl_tab);
this.$store.commit("SET_CLIENT_TREE_SORT", r.data.client_tree_sort);
this.$store.commit("SET_CLIENT_SPLITTER", r.data.client_tree_splitter);
}
this.darkMode = r.data.dark_mode;
this.$q.dark.set(this.darkMode);
@@ -802,13 +803,21 @@ export default {
treeReady: state => state.treeReady,
clients: state => state.clients,
}),
...mapGetters(["selectedAgentPk", "needRefresh"]),
...mapGetters(["selectedAgentPk", "needRefresh", "clientTreeSplitterModel"]),
wsUrl() {
return getBaseUrl().split("://")[1];
},
token() {
return this.$store.state.token;
},
clientTreeSplitter: {
get: function () {
return this.clientTreeSplitterModel;
},
set: function (newVal) {
this.$store.dispatch("setClientTreeSplitter", newVal);
},
},
tab: {
get: function () {
return this.$store.state.defaultAgentTblTab;

View File

@@ -72,10 +72,11 @@ export default {
this.title = `${r.data.hostname} - ${r.data.client} - ${r.data.site} | Remote Background`;
});
},
getDark() {
getUI() {
this.$store.dispatch("getDashInfo").then(r => {
this.darkMode = r.data.dark_mode;
this.$q.dark.set(this.darkMode);
this.$q.loadingBar.setDefaults({ color: r.data.loading_bar_color });
});
},
},
@@ -90,7 +91,7 @@ export default {
},
},
created() {
this.getDark();
this.getUI();
this.genURLS();
},
};

View File

@@ -54,6 +54,12 @@ export default {
};
},
methods: {
getUI() {
this.$store.dispatch("getDashInfo").then(r => {
this.$q.dark.set(r.data.dark_mode);
this.$q.loadingBar.setDefaults({ color: r.data.loading_bar_color });
});
},
genURL() {
this.$q.loading.show();
this.visible = false;
@@ -117,6 +123,7 @@ export default {
},
},
created() {
this.getUI();
this.genURL();
},
};