Skip to content

Commit

Permalink
Release 0.5.3
Browse files Browse the repository at this point in the history
  • Loading branch information
wh1te909 committed Apr 11, 2021
2 parents aa8b84a + 0f9872a commit 28edc31
Show file tree
Hide file tree
Showing 31 changed files with 311 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -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),
),
]
18 changes: 18 additions & 0 deletions api/tacticalrmm/accounts/migrations/0015_user_loading_bar_color.py
Original file line number Diff line number Diff line change
@@ -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),
),
]
2 changes: 2 additions & 0 deletions api/tacticalrmm/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/accounts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class Meta:
"agent_dblclick_action",
"default_agent_tbl_tab",
"client_tree_sort",
"client_tree_splitter",
"loading_bar_color",
]


Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/accounts/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ def test_user_ui(self):
"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)
Expand Down
29 changes: 22 additions & 7 deletions api/tacticalrmm/agents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,27 @@ def cpu_model(self):
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 = []
Expand Down Expand Up @@ -322,7 +343,7 @@ def run_script(
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"
]
Expand Down Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions api/tacticalrmm/agents/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
39 changes: 5 additions & 34 deletions api/tacticalrmm/agents/tasks.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -17,6 +14,7 @@
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)

Expand Down Expand Up @@ -257,46 +255,19 @@ 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
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)
2 changes: 1 addition & 1 deletion api/tacticalrmm/agents/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

@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],
Expand Down
27 changes: 17 additions & 10 deletions api/tacticalrmm/checks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,12 +633,15 @@ def send_email(self):
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":

Expand Down Expand Up @@ -710,11 +713,15 @@ def send_sms(self):
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":
Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
)

Expand Down
37 changes: 37 additions & 0 deletions api/tacticalrmm/scripts/community_scripts.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
6 changes: 3 additions & 3 deletions api/tacticalrmm/tacticalrmm/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
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"

Expand Down
7 changes: 7 additions & 0 deletions api/tacticalrmm/tacticalrmm/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
generate_winagent_exe,
get_bit_days,
reload_nats,
run_nats_api_cmd,
)


Expand Down Expand Up @@ -74,6 +75,12 @@ def test_reload_nats(self, mock_subprocess):

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 = [
Expand Down
17 changes: 17 additions & 0 deletions api/tacticalrmm/tacticalrmm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,20 @@ async def __call__(self, scope, receive, send):
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)
Loading

0 comments on commit 28edc31

Please sign in to comment.