improve typing support
This commit is contained in:
@@ -44,3 +44,4 @@ model_bakery
|
|||||||
mkdocs
|
mkdocs
|
||||||
mkdocs-material
|
mkdocs-material
|
||||||
pymdown-extensions
|
pymdown-extensions
|
||||||
|
mypy
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -45,3 +45,4 @@ htmlcov/
|
|||||||
docker-compose.dev.yml
|
docker-compose.dev.yml
|
||||||
docs/.vuepress/dist
|
docs/.vuepress/dist
|
||||||
nats-rmm.conf
|
nats-rmm.conf
|
||||||
|
.mypy_cache
|
||||||
|
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -3,7 +3,14 @@
|
|||||||
"python.languageServer": "Pylance",
|
"python.languageServer": "Pylance",
|
||||||
"python.analysis.extraPaths": [
|
"python.analysis.extraPaths": [
|
||||||
"api/tacticalrmm",
|
"api/tacticalrmm",
|
||||||
|
"api/env",
|
||||||
],
|
],
|
||||||
|
"python.analysis.diagnosticSeverityOverrides": {
|
||||||
|
"reportUnusedImport": "error",
|
||||||
|
"reportDuplicateImport": "error",
|
||||||
|
},
|
||||||
|
"python.analysis.memory.keepLibraryAst": true,
|
||||||
|
"python.linting.mypyEnabled": true,
|
||||||
"python.analysis.typeCheckingMode": "basic",
|
"python.analysis.typeCheckingMode": "basic",
|
||||||
"python.formatting.provider": "black",
|
"python.formatting.provider": "black",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
|
@@ -78,7 +78,7 @@ class GetAddUsers(APIView):
|
|||||||
def post(self, request):
|
def post(self, request):
|
||||||
# add new user
|
# add new user
|
||||||
try:
|
try:
|
||||||
user = User.objects.create_user(
|
user = User.objects.create_user( # type: ignore
|
||||||
request.data["username"],
|
request.data["username"],
|
||||||
request.data["email"],
|
request.data["email"],
|
||||||
request.data["password"],
|
request.data["password"],
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from agents.models import Agent
|
from agents.models import Agent
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
@@ -164,14 +164,14 @@ class Agent(BaseAuditModel):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def has_patches_pending(self):
|
def has_patches_pending(self):
|
||||||
return self.winupdates.filter(action="approve").filter(installed=False).exists()
|
return self.winupdates.filter(action="approve").filter(installed=False).exists() # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def checks(self):
|
def checks(self):
|
||||||
total, passing, failing = 0, 0, 0
|
total, passing, failing = 0, 0, 0
|
||||||
|
|
||||||
if self.agentchecks.exists():
|
if self.agentchecks.exists(): # type: ignore
|
||||||
for i in self.agentchecks.all():
|
for i in self.agentchecks.all(): # type: ignore
|
||||||
total += 1
|
total += 1
|
||||||
if i.status == "passing":
|
if i.status == "passing":
|
||||||
passing += 1
|
passing += 1
|
||||||
@@ -333,27 +333,27 @@ class Agent(BaseAuditModel):
|
|||||||
|
|
||||||
updates = list()
|
updates = list()
|
||||||
if patch_policy.critical == "approve":
|
if patch_policy.critical == "approve":
|
||||||
updates += self.winupdates.filter(
|
updates += self.winupdates.filter( # type: ignore
|
||||||
severity="Critical", installed=False
|
severity="Critical", installed=False
|
||||||
).exclude(action="approve")
|
).exclude(action="approve")
|
||||||
|
|
||||||
if patch_policy.important == "approve":
|
if patch_policy.important == "approve":
|
||||||
updates += self.winupdates.filter(
|
updates += self.winupdates.filter( # type: ignore
|
||||||
severity="Important", installed=False
|
severity="Important", installed=False
|
||||||
).exclude(action="approve")
|
).exclude(action="approve")
|
||||||
|
|
||||||
if patch_policy.moderate == "approve":
|
if patch_policy.moderate == "approve":
|
||||||
updates += self.winupdates.filter(
|
updates += self.winupdates.filter( # type: ignore
|
||||||
severity="Moderate", installed=False
|
severity="Moderate", installed=False
|
||||||
).exclude(action="approve")
|
).exclude(action="approve")
|
||||||
|
|
||||||
if patch_policy.low == "approve":
|
if patch_policy.low == "approve":
|
||||||
updates += self.winupdates.filter(severity="Low", installed=False).exclude(
|
updates += self.winupdates.filter(severity="Low", installed=False).exclude( # type: ignore
|
||||||
action="approve"
|
action="approve"
|
||||||
)
|
)
|
||||||
|
|
||||||
if patch_policy.other == "approve":
|
if patch_policy.other == "approve":
|
||||||
updates += self.winupdates.filter(severity="", installed=False).exclude(
|
updates += self.winupdates.filter(severity="", installed=False).exclude( # type: ignore
|
||||||
action="approve"
|
action="approve"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ class Agent(BaseAuditModel):
|
|||||||
site = self.site
|
site = self.site
|
||||||
core_settings = CoreSettings.objects.first()
|
core_settings = CoreSettings.objects.first()
|
||||||
patch_policy = None
|
patch_policy = None
|
||||||
agent_policy = self.winupdatepolicy.get()
|
agent_policy = self.winupdatepolicy.get() # type: ignore
|
||||||
|
|
||||||
if self.monitoring_type == "server":
|
if self.monitoring_type == "server":
|
||||||
# check agent policy first which should override client or site policy
|
# check agent policy first which should override client or site policy
|
||||||
@@ -455,7 +455,7 @@ class Agent(BaseAuditModel):
|
|||||||
|
|
||||||
def get_approved_update_guids(self) -> list[str]:
|
def get_approved_update_guids(self) -> list[str]:
|
||||||
return list(
|
return list(
|
||||||
self.winupdates.filter(action="approve", installed=False).values_list(
|
self.winupdates.filter(action="approve", installed=False).values_list( # type: ignore
|
||||||
"guid", flat=True
|
"guid", flat=True
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -571,7 +571,7 @@ class Agent(BaseAuditModel):
|
|||||||
from automation.models import Policy
|
from automation.models import Policy
|
||||||
|
|
||||||
# Clear agent checks that have overriden_by_policy set
|
# Clear agent checks that have overriden_by_policy set
|
||||||
self.agentchecks.update(overriden_by_policy=False)
|
self.agentchecks.update(overriden_by_policy=False) # type: ignore
|
||||||
|
|
||||||
# Generate checks based on policies
|
# Generate checks based on policies
|
||||||
Policy.generate_policy_checks(self)
|
Policy.generate_policy_checks(self)
|
||||||
@@ -606,7 +606,7 @@ class Agent(BaseAuditModel):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return "err"
|
return "err"
|
||||||
|
|
||||||
async def nats_cmd(self, data, timeout=30, wait=True):
|
async def nats_cmd(self, data: dict, timeout: int = 30, wait: bool = True):
|
||||||
nc = NATS()
|
nc = NATS()
|
||||||
options = {
|
options = {
|
||||||
"servers": f"tls://{settings.ALLOWED_HOSTS[0]}:4222",
|
"servers": f"tls://{settings.ALLOWED_HOSTS[0]}:4222",
|
||||||
@@ -628,7 +628,7 @@ class Agent(BaseAuditModel):
|
|||||||
except ErrTimeout:
|
except ErrTimeout:
|
||||||
ret = "timeout"
|
ret = "timeout"
|
||||||
else:
|
else:
|
||||||
ret = msgpack.loads(msg.data)
|
ret = msgpack.loads(msg.data) # type: ignore
|
||||||
|
|
||||||
await nc.close()
|
await nc.close()
|
||||||
return ret
|
return ret
|
||||||
@@ -650,12 +650,12 @@ class Agent(BaseAuditModel):
|
|||||||
def delete_superseded_updates(self):
|
def delete_superseded_updates(self):
|
||||||
try:
|
try:
|
||||||
pks = [] # list of pks to delete
|
pks = [] # list of pks to delete
|
||||||
kbs = list(self.winupdates.values_list("kb", flat=True))
|
kbs = list(self.winupdates.values_list("kb", flat=True)) # type: ignore
|
||||||
d = Counter(kbs)
|
d = Counter(kbs)
|
||||||
dupes = [k for k, v in d.items() if v > 1]
|
dupes = [k for k, v in d.items() if v > 1]
|
||||||
|
|
||||||
for dupe in dupes:
|
for dupe in dupes:
|
||||||
titles = self.winupdates.filter(kb=dupe).values_list("title", flat=True)
|
titles = self.winupdates.filter(kb=dupe).values_list("title", flat=True) # type: ignore
|
||||||
# extract the version from the title and sort from oldest to newest
|
# extract the version from the title and sort from oldest to newest
|
||||||
# skip if no version info is available therefore nothing to parse
|
# skip if no version info is available therefore nothing to parse
|
||||||
try:
|
try:
|
||||||
@@ -668,17 +668,17 @@ class Agent(BaseAuditModel):
|
|||||||
continue
|
continue
|
||||||
# append all but the latest version to our list of pks to delete
|
# append all but the latest version to our list of pks to delete
|
||||||
for ver in sorted_vers[:-1]:
|
for ver in sorted_vers[:-1]:
|
||||||
q = self.winupdates.filter(kb=dupe).filter(title__contains=ver)
|
q = self.winupdates.filter(kb=dupe).filter(title__contains=ver) # type: ignore
|
||||||
pks.append(q.first().pk)
|
pks.append(q.first().pk)
|
||||||
|
|
||||||
pks = list(set(pks))
|
pks = list(set(pks))
|
||||||
self.winupdates.filter(pk__in=pks).delete()
|
self.winupdates.filter(pk__in=pks).delete() # type: ignore
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# define how the agent should handle pending actions
|
# define how the agent should handle pending actions
|
||||||
def handle_pending_actions(self):
|
def handle_pending_actions(self):
|
||||||
pending_actions = self.pendingactions.filter(status="pending")
|
pending_actions = self.pendingactions.filter(status="pending") # type: ignore
|
||||||
|
|
||||||
for action in pending_actions:
|
for action in pending_actions:
|
||||||
if action.action_type == "taskaction":
|
if action.action_type == "taskaction":
|
||||||
@@ -702,7 +702,7 @@ class Agent(BaseAuditModel):
|
|||||||
# for clearing duplicate pending actions on agent
|
# for clearing duplicate pending actions on agent
|
||||||
def remove_matching_pending_task_actions(self, task_id):
|
def remove_matching_pending_task_actions(self, task_id):
|
||||||
# remove any other pending actions on agent with same task_id
|
# remove any other pending actions on agent with same task_id
|
||||||
for action in self.pendingactions.exclude(status="completed"):
|
for action in self.pendingactions.exclude(status="completed"): # type: ignore
|
||||||
if action.details["task_id"] == task_id:
|
if action.details["task_id"] == task_id:
|
||||||
action.delete()
|
action.delete()
|
||||||
|
|
||||||
@@ -798,7 +798,7 @@ class Agent(BaseAuditModel):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# add a null check history to allow gaps in graph
|
# add a null check history to allow gaps in graph
|
||||||
for check in self.agentchecks.all():
|
for check in self.agentchecks.all(): # type: ignore
|
||||||
check.add_check_history(None)
|
check.add_check_history(None)
|
||||||
else:
|
else:
|
||||||
alert = Alert.objects.get(agent=self, resolved=False)
|
alert = Alert.objects.get(agent=self, resolved=False)
|
||||||
|
@@ -3,7 +3,6 @@ import datetime as dt
|
|||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
@@ -99,7 +98,7 @@ def edit_agent(request):
|
|||||||
a_serializer.save()
|
a_serializer.save()
|
||||||
|
|
||||||
if "winupdatepolicy" in request.data.keys():
|
if "winupdatepolicy" in request.data.keys():
|
||||||
policy = agent.winupdatepolicy.get()
|
policy = agent.winupdatepolicy.get() # type: ignore
|
||||||
p_serializer = WinUpdatePolicySerializer(
|
p_serializer = WinUpdatePolicySerializer(
|
||||||
instance=policy, data=request.data["winupdatepolicy"][0]
|
instance=policy, data=request.data["winupdatepolicy"][0]
|
||||||
)
|
)
|
||||||
@@ -553,7 +552,7 @@ def recover(request):
|
|||||||
if r == "ok":
|
if r == "ok":
|
||||||
return Response("Successfully completed recovery")
|
return Response("Successfully completed recovery")
|
||||||
|
|
||||||
if agent.recoveryactions.filter(last_run=None).exists():
|
if agent.recoveryactions.filter(last_run=None).exists(): # type: ignore
|
||||||
return notify_error(
|
return notify_error(
|
||||||
"A recovery action is currently pending. Please wait for the next agent check-in."
|
"A recovery action is currently pending. Please wait for the next agent check-in."
|
||||||
)
|
)
|
||||||
|
@@ -283,4 +283,4 @@ class AlertTemplate(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_default_template(self) -> bool:
|
def is_default_template(self) -> bool:
|
||||||
return self.default_alert_template.exists()
|
return self.default_alert_template.exists() # type: ignore
|
||||||
|
@@ -50,26 +50,26 @@ class CheckIn(APIView):
|
|||||||
# change agent update pending status to completed if agent has just updated
|
# change agent update pending status to completed if agent has just updated
|
||||||
if (
|
if (
|
||||||
updated
|
updated
|
||||||
and agent.pendingactions.filter(
|
and agent.pendingactions.filter( # type: ignore
|
||||||
action_type="agentupdate", status="pending"
|
action_type="agentupdate", status="pending"
|
||||||
).exists()
|
).exists()
|
||||||
):
|
):
|
||||||
agent.pendingactions.filter(
|
agent.pendingactions.filter( # type: ignore
|
||||||
action_type="agentupdate", status="pending"
|
action_type="agentupdate", status="pending"
|
||||||
).update(status="completed")
|
).update(status="completed")
|
||||||
|
|
||||||
# handles any alerting actions
|
# handles any alerting actions
|
||||||
agent.handle_alert(checkin=True)
|
agent.handle_alert(checkin=True)
|
||||||
|
|
||||||
recovery = agent.recoveryactions.filter(last_run=None).last()
|
recovery = agent.recoveryactions.filter(last_run=None).last() # type: ignore
|
||||||
if recovery is not None:
|
if recovery is not None:
|
||||||
recovery.last_run = djangotime.now()
|
recovery.last_run = djangotime.now()
|
||||||
recovery.save(update_fields=["last_run"])
|
recovery.save(update_fields=["last_run"])
|
||||||
handle_agent_recovery_task.delay(pk=recovery.pk)
|
handle_agent_recovery_task.delay(pk=recovery.pk) # type: ignore
|
||||||
return Response("ok")
|
return Response("ok")
|
||||||
|
|
||||||
# get any pending actions
|
# get any pending actions
|
||||||
if agent.pendingactions.filter(status="pending").exists():
|
if agent.pendingactions.filter(status="pending").exists(): # type: ignore
|
||||||
agent.handle_pending_actions()
|
agent.handle_pending_actions()
|
||||||
|
|
||||||
return Response("ok")
|
return Response("ok")
|
||||||
@@ -111,7 +111,7 @@ class CheckIn(APIView):
|
|||||||
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
||||||
InstalledSoftware(agent=agent, software=sw).save()
|
InstalledSoftware(agent=agent, software=sw).save()
|
||||||
else:
|
else:
|
||||||
s = agent.installedsoftware_set.first()
|
s = agent.installedsoftware_set.first() # type: ignore
|
||||||
s.software = sw
|
s.software = sw
|
||||||
s.save(update_fields=["software"])
|
s.save(update_fields=["software"])
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ class WinUpdates(APIView):
|
|||||||
|
|
||||||
def patch(self, request):
|
def patch(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
u = agent.winupdates.filter(guid=request.data["guid"]).last()
|
u = agent.winupdates.filter(guid=request.data["guid"]).last() # type: ignore
|
||||||
success: bool = request.data["success"]
|
success: bool = request.data["success"]
|
||||||
if success:
|
if success:
|
||||||
u.result = "success"
|
u.result = "success"
|
||||||
@@ -210,8 +210,8 @@ class WinUpdates(APIView):
|
|||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
updates = request.data["wua_updates"]
|
updates = request.data["wua_updates"]
|
||||||
for update in updates:
|
for update in updates:
|
||||||
if agent.winupdates.filter(guid=update["guid"]).exists():
|
if agent.winupdates.filter(guid=update["guid"]).exists(): # type: ignore
|
||||||
u = agent.winupdates.filter(guid=update["guid"]).last()
|
u = agent.winupdates.filter(guid=update["guid"]).last() # type: ignore
|
||||||
u.downloaded = update["downloaded"]
|
u.downloaded = update["downloaded"]
|
||||||
u.installed = update["installed"]
|
u.installed = update["installed"]
|
||||||
u.save(update_fields=["downloaded", "installed"])
|
u.save(update_fields=["downloaded", "installed"])
|
||||||
@@ -242,7 +242,7 @@ class WinUpdates(APIView):
|
|||||||
|
|
||||||
# more superseded updates cleanup
|
# more superseded updates cleanup
|
||||||
if pyver.parse(agent.version) <= pyver.parse("1.4.2"):
|
if pyver.parse(agent.version) <= pyver.parse("1.4.2"):
|
||||||
for u in agent.winupdates.filter(
|
for u in agent.winupdates.filter( # type: ignore
|
||||||
date_installed__isnull=True, result="failed"
|
date_installed__isnull=True, result="failed"
|
||||||
).exclude(installed=True):
|
).exclude(installed=True):
|
||||||
u.delete()
|
u.delete()
|
||||||
@@ -256,7 +256,7 @@ class SupersededWinUpdate(APIView):
|
|||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
updates = agent.winupdates.filter(guid=request.data["guid"])
|
updates = agent.winupdates.filter(guid=request.data["guid"]) # type: ignore
|
||||||
for u in updates:
|
for u in updates:
|
||||||
u.delete()
|
u.delete()
|
||||||
|
|
||||||
@@ -404,10 +404,10 @@ class NewAgent(APIView):
|
|||||||
agent.salt_id = f"{agent.hostname}-{agent.pk}"
|
agent.salt_id = f"{agent.hostname}-{agent.pk}"
|
||||||
agent.save(update_fields=["salt_id"])
|
agent.save(update_fields=["salt_id"])
|
||||||
|
|
||||||
user = User.objects.create_user(
|
user = User.objects.create_user( # type: ignore
|
||||||
username=request.data["agent_id"],
|
username=request.data["agent_id"],
|
||||||
agent=agent,
|
agent=agent,
|
||||||
password=User.objects.make_random_password(60),
|
password=User.objects.make_random_password(60), # type: ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
token = Token.objects.create(user=user)
|
token = Token.objects.create(user=user)
|
||||||
@@ -452,7 +452,7 @@ class Software(APIView):
|
|||||||
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
||||||
InstalledSoftware(agent=agent, software=sw).save()
|
InstalledSoftware(agent=agent, software=sw).save()
|
||||||
else:
|
else:
|
||||||
s = agent.installedsoftware_set.first()
|
s = agent.installedsoftware_set.first() # type: ignore
|
||||||
s.software = sw
|
s.software = sw
|
||||||
s.save(update_fields=["software"])
|
s.save(update_fields=["software"])
|
||||||
|
|
||||||
|
@@ -43,11 +43,11 @@ class Policy(BaseAuditModel):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_default_server_policy(self):
|
def is_default_server_policy(self):
|
||||||
return self.default_server_policy.exists()
|
return self.default_server_policy.exists() # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_default_workstation_policy(self):
|
def is_default_workstation_policy(self):
|
||||||
return self.default_workstation_policy.exists()
|
return self.default_workstation_policy.exists() # type: ignore
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -56,7 +56,7 @@ class Policy(BaseAuditModel):
|
|||||||
return self.get_related("server") | self.get_related("workstation")
|
return self.get_related("server") | self.get_related("workstation")
|
||||||
|
|
||||||
def get_related(self, mon_type):
|
def get_related(self, mon_type):
|
||||||
explicit_agents = self.agents.filter(monitoring_type=mon_type)
|
explicit_agents = self.agents.filter(monitoring_type=mon_type) # type: ignore
|
||||||
explicit_clients = getattr(self, f"{mon_type}_clients").all()
|
explicit_clients = getattr(self, f"{mon_type}_clients").all()
|
||||||
explicit_sites = getattr(self, f"{mon_type}_sites").all()
|
explicit_sites = getattr(self, f"{mon_type}_sites").all()
|
||||||
|
|
||||||
|
@@ -171,7 +171,7 @@ class UpdatePatchPolicy(APIView):
|
|||||||
|
|
||||||
serializer = WinUpdatePolicySerializer(data=request.data, partial=True)
|
serializer = WinUpdatePolicySerializer(data=request.data, partial=True)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
serializer.policy = policy
|
serializer.policy = policy # type: ignore
|
||||||
serializer.save()
|
serializer.save()
|
||||||
|
|
||||||
return Response("ok")
|
return Response("ok")
|
||||||
|
@@ -205,9 +205,9 @@ class Check(BaseAuditModel):
|
|||||||
if self.error_threshold:
|
if self.error_threshold:
|
||||||
text += f" Error Threshold: {self.error_threshold}%"
|
text += f" Error Threshold: {self.error_threshold}%"
|
||||||
|
|
||||||
return f"{self.get_check_type_display()}: Drive {self.disk} < {text}"
|
return f"{self.get_check_type_display()}: Drive {self.disk} < {text}" # type: ignore
|
||||||
elif self.check_type == "ping":
|
elif self.check_type == "ping":
|
||||||
return f"{self.get_check_type_display()}: {self.name}"
|
return f"{self.get_check_type_display()}: {self.name}" # type: ignore
|
||||||
elif self.check_type == "cpuload" or self.check_type == "memory":
|
elif self.check_type == "cpuload" or self.check_type == "memory":
|
||||||
|
|
||||||
text = ""
|
text = ""
|
||||||
@@ -216,13 +216,13 @@ class Check(BaseAuditModel):
|
|||||||
if self.error_threshold:
|
if self.error_threshold:
|
||||||
text += f" Error Threshold: {self.error_threshold}%"
|
text += f" Error Threshold: {self.error_threshold}%"
|
||||||
|
|
||||||
return f"{self.get_check_type_display()} > {text}"
|
return f"{self.get_check_type_display()} > {text}" # type: ignore
|
||||||
elif self.check_type == "winsvc":
|
elif self.check_type == "winsvc":
|
||||||
return f"{self.get_check_type_display()}: {self.svc_display_name}"
|
return f"{self.get_check_type_display()}: {self.svc_display_name}" # type: ignore
|
||||||
elif self.check_type == "eventlog":
|
elif self.check_type == "eventlog":
|
||||||
return f"{self.get_check_type_display()}: {self.name}"
|
return f"{self.get_check_type_display()}: {self.name}" # type: ignore
|
||||||
elif self.check_type == "script":
|
elif self.check_type == "script":
|
||||||
return f"{self.get_check_type_display()}: {self.script.name}"
|
return f"{self.get_check_type_display()}: {self.script.name}" # type: ignore
|
||||||
else:
|
else:
|
||||||
return "n/a"
|
return "n/a"
|
||||||
|
|
||||||
|
@@ -59,7 +59,7 @@ class AddCheck(APIView):
|
|||||||
if policy:
|
if policy:
|
||||||
generate_agent_checks_from_policies_task.delay(policypk=policy.pk)
|
generate_agent_checks_from_policies_task.delay(policypk=policy.pk)
|
||||||
elif agent:
|
elif agent:
|
||||||
checks = agent.agentchecks.filter(
|
checks = agent.agentchecks.filter( # type: ignore
|
||||||
check_type=obj.check_type, managed_by_policy=True
|
check_type=obj.check_type, managed_by_policy=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ class CheckHistory(APIView):
|
|||||||
- djangotime.timedelta(days=request.data["timeFilter"]),
|
- djangotime.timedelta(days=request.data["timeFilter"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
check_history = check.check_history.filter(timeFilter).order_by("-x")
|
check_history = check.check_history.filter(timeFilter).order_by("-x") # type: ignore
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
CheckHistorySerializer(
|
CheckHistorySerializer(
|
||||||
|
@@ -16,11 +16,7 @@ from rest_framework.views import APIView
|
|||||||
|
|
||||||
from agents.models import Agent
|
from agents.models import Agent
|
||||||
from agents.serializers import WinAgentSerializer
|
from agents.serializers import WinAgentSerializer
|
||||||
from agents.tasks import (
|
from agents.tasks import handle_agent_recovery_task
|
||||||
agent_recovery_email_task,
|
|
||||||
agent_recovery_sms_task,
|
|
||||||
handle_agent_recovery_task,
|
|
||||||
)
|
|
||||||
from checks.utils import bytes2human
|
from checks.utils import bytes2human
|
||||||
from software.models import InstalledSoftware
|
from software.models import InstalledSoftware
|
||||||
from tacticalrmm.utils import SoftwareList, filter_software, notify_error
|
from tacticalrmm.utils import SoftwareList, filter_software, notify_error
|
||||||
@@ -38,8 +34,8 @@ def nats_info(request):
|
|||||||
|
|
||||||
class NatsCheckIn(APIView):
|
class NatsCheckIn(APIView):
|
||||||
|
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def patch(self, request):
|
def patch(self, request):
|
||||||
updated = False
|
updated = False
|
||||||
@@ -57,18 +53,18 @@ class NatsCheckIn(APIView):
|
|||||||
# change agent update pending status to completed if agent has just updated
|
# change agent update pending status to completed if agent has just updated
|
||||||
if (
|
if (
|
||||||
updated
|
updated
|
||||||
and agent.pendingactions.filter(
|
and agent.pendingactions.filter( # type: ignore
|
||||||
action_type="agentupdate", status="pending"
|
action_type="agentupdate", status="pending"
|
||||||
).exists()
|
).exists()
|
||||||
):
|
):
|
||||||
agent.pendingactions.filter(
|
agent.pendingactions.filter( # type: ignore
|
||||||
action_type="agentupdate", status="pending"
|
action_type="agentupdate", status="pending"
|
||||||
).update(status="completed")
|
).update(status="completed")
|
||||||
|
|
||||||
# handles any alerting actions
|
# handles any alerting actions
|
||||||
agent.handle_alert(checkin=True)
|
agent.handle_alert(checkin=True)
|
||||||
|
|
||||||
recovery = agent.recoveryactions.filter(last_run=None).last()
|
recovery = agent.recoveryactions.filter(last_run=None).last() # type: ignore
|
||||||
if recovery is not None:
|
if recovery is not None:
|
||||||
recovery.last_run = djangotime.now()
|
recovery.last_run = djangotime.now()
|
||||||
recovery.save(update_fields=["last_run"])
|
recovery.save(update_fields=["last_run"])
|
||||||
@@ -76,7 +72,7 @@ class NatsCheckIn(APIView):
|
|||||||
return Response("ok")
|
return Response("ok")
|
||||||
|
|
||||||
# get any pending actions
|
# get any pending actions
|
||||||
if agent.pendingactions.filter(status="pending").exists():
|
if agent.pendingactions.filter(status="pending").exists(): # type: ignore
|
||||||
agent.handle_pending_actions()
|
agent.handle_pending_actions()
|
||||||
|
|
||||||
return Response("ok")
|
return Response("ok")
|
||||||
@@ -118,7 +114,7 @@ class NatsCheckIn(APIView):
|
|||||||
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
||||||
InstalledSoftware(agent=agent, software=sw).save()
|
InstalledSoftware(agent=agent, software=sw).save()
|
||||||
else:
|
else:
|
||||||
s = agent.installedsoftware_set.first()
|
s = agent.installedsoftware_set.first() # type: ignore
|
||||||
s.software = sw
|
s.software = sw
|
||||||
s.save(update_fields=["software"])
|
s.save(update_fields=["software"])
|
||||||
|
|
||||||
@@ -140,8 +136,8 @@ class NatsCheckIn(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class SyncMeshNodeID(APIView):
|
class SyncMeshNodeID(APIView):
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
@@ -153,8 +149,8 @@ class SyncMeshNodeID(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class NatsChoco(APIView):
|
class NatsChoco(APIView):
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
@@ -164,8 +160,8 @@ class NatsChoco(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class NatsWinUpdates(APIView):
|
class NatsWinUpdates(APIView):
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
@@ -191,7 +187,7 @@ class NatsWinUpdates(APIView):
|
|||||||
|
|
||||||
def patch(self, request):
|
def patch(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
u = agent.winupdates.filter(guid=request.data["guid"]).last()
|
u = agent.winupdates.filter(guid=request.data["guid"]).last() # type: ignore
|
||||||
success: bool = request.data["success"]
|
success: bool = request.data["success"]
|
||||||
if success:
|
if success:
|
||||||
u.result = "success"
|
u.result = "success"
|
||||||
@@ -217,8 +213,8 @@ class NatsWinUpdates(APIView):
|
|||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
updates = request.data["wua_updates"]
|
updates = request.data["wua_updates"]
|
||||||
for update in updates:
|
for update in updates:
|
||||||
if agent.winupdates.filter(guid=update["guid"]).exists():
|
if agent.winupdates.filter(guid=update["guid"]).exists(): # type: ignore
|
||||||
u = agent.winupdates.filter(guid=update["guid"]).last()
|
u = agent.winupdates.filter(guid=update["guid"]).last() # type: ignore
|
||||||
u.downloaded = update["downloaded"]
|
u.downloaded = update["downloaded"]
|
||||||
u.installed = update["installed"]
|
u.installed = update["installed"]
|
||||||
u.save(update_fields=["downloaded", "installed"])
|
u.save(update_fields=["downloaded", "installed"])
|
||||||
@@ -249,7 +245,7 @@ class NatsWinUpdates(APIView):
|
|||||||
|
|
||||||
# more superseded updates cleanup
|
# more superseded updates cleanup
|
||||||
if pyver.parse(agent.version) <= pyver.parse("1.4.2"):
|
if pyver.parse(agent.version) <= pyver.parse("1.4.2"):
|
||||||
for u in agent.winupdates.filter(
|
for u in agent.winupdates.filter( # type: ignore
|
||||||
date_installed__isnull=True, result="failed"
|
date_installed__isnull=True, result="failed"
|
||||||
).exclude(installed=True):
|
).exclude(installed=True):
|
||||||
u.delete()
|
u.delete()
|
||||||
@@ -258,12 +254,12 @@ class NatsWinUpdates(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class SupersededWinUpdate(APIView):
|
class SupersededWinUpdate(APIView):
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agent_id"])
|
||||||
updates = agent.winupdates.filter(guid=request.data["guid"])
|
updates = agent.winupdates.filter(guid=request.data["guid"]) # type: ignore
|
||||||
for u in updates:
|
for u in updates:
|
||||||
u.delete()
|
u.delete()
|
||||||
|
|
||||||
@@ -272,8 +268,8 @@ class SupersededWinUpdate(APIView):
|
|||||||
|
|
||||||
class NatsWMI(APIView):
|
class NatsWMI(APIView):
|
||||||
|
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
agents = Agent.objects.only(
|
agents = Agent.objects.only(
|
||||||
@@ -288,8 +284,8 @@ class NatsWMI(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class OfflineAgents(APIView):
|
class OfflineAgents(APIView):
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
agents = Agent.objects.only(
|
agents = Agent.objects.only(
|
||||||
@@ -302,8 +298,8 @@ class OfflineAgents(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class LogCrash(APIView):
|
class LogCrash(APIView):
|
||||||
authentication_classes = []
|
authentication_classes = [] # type: ignore
|
||||||
permission_classes = []
|
permission_classes = [] # type: ignore
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
agent = get_object_or_404(Agent, agent_id=request.data["agentid"])
|
agent = get_object_or_404(Agent, agent_id=request.data["agentid"])
|
||||||
|
@@ -4,4 +4,5 @@ django-extensions
|
|||||||
mkdocs
|
mkdocs
|
||||||
mkdocs-material
|
mkdocs-material
|
||||||
pymdown-extensions
|
pymdown-extensions
|
||||||
isort
|
isort
|
||||||
|
mypy
|
@@ -55,7 +55,7 @@ def refresh_installed(request, pk):
|
|||||||
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
if not InstalledSoftware.objects.filter(agent=agent).exists():
|
||||||
InstalledSoftware(agent=agent, software=sw).save()
|
InstalledSoftware(agent=agent, software=sw).save()
|
||||||
else:
|
else:
|
||||||
s = agent.installedsoftware_set.first()
|
s = agent.installedsoftware_set.first() # type: ignore
|
||||||
s.software = sw
|
s.software = sw
|
||||||
s.save(update_fields=["software"])
|
s.save(update_fields=["software"])
|
||||||
|
|
||||||
|
@@ -14,11 +14,11 @@ app = Celery(
|
|||||||
broker="redis://" + settings.REDIS_HOST,
|
broker="redis://" + settings.REDIS_HOST,
|
||||||
)
|
)
|
||||||
# app.config_from_object('django.conf:settings', namespace='CELERY')
|
# app.config_from_object('django.conf:settings', namespace='CELERY')
|
||||||
app.broker_url = "redis://" + settings.REDIS_HOST + ":6379"
|
app.broker_url = "redis://" + settings.REDIS_HOST + ":6379" # type: ignore
|
||||||
app.result_backend = "redis://" + settings.REDIS_HOST + ":6379"
|
app.result_backend = "redis://" + settings.REDIS_HOST + ":6379" # type: ignore
|
||||||
app.accept_content = ["application/json"]
|
app.accept_content = ["application/json"] # type: ignore
|
||||||
app.result_serializer = "json"
|
app.result_serializer = "json" # type: ignore
|
||||||
app.task_serializer = "json"
|
app.task_serializer = "json" # type: ignore
|
||||||
app.conf.task_track_started = True
|
app.conf.task_track_started = True
|
||||||
app.autodiscover_tasks()
|
app.autodiscover_tasks()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user