Skip to content

Commit

Permalink
Release 0.15.7
Browse files Browse the repository at this point in the history
  • Loading branch information
wh1te909 committed Jan 18, 2023
2 parents 0663969 + a0e1783 commit 074f898
Show file tree
Hide file tree
Showing 40 changed files with 621 additions and 364 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ daphne.sock.lock
.pytest_cache
coverage.xml
setup_dev.yml
11env/
22 changes: 4 additions & 18 deletions api/tacticalrmm/accounts/management/commands/reset_2fa.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
import subprocess
from contextlib import suppress

import pyotp
from django.core.management.base import BaseCommand

from accounts.models import User
from tacticalrmm.helpers import get_webdomain


class Command(BaseCommand):
Expand All @@ -22,26 +21,13 @@ def handle(self, *args, **kwargs):
self.stdout.write(self.style.ERROR(f"User {username} doesn't exist"))
return

domain = "Tactical RMM"
nginx = "/etc/nginx/sites-available/frontend.conf"
found = None
if os.path.exists(nginx):
with suppress(Exception):
with open(nginx, "r") as f:
for line in f:
if "server_name" in line:
found = line
break

if found:
rep = found.replace("server_name", "").replace(";", "")
domain = "".join(rep.split())

code = pyotp.random_base32()
user.totp_key = code
user.save(update_fields=["totp_key"])

url = pyotp.totp.TOTP(code).provisioning_uri(username, issuer_name=domain)
url = pyotp.totp.TOTP(code).provisioning_uri(
username, issuer_name=get_webdomain()
)
subprocess.run(f'qr "{url}"', shell=True)
self.stdout.write(
self.style.WARNING("Scan the barcode above with your authenticator app")
Expand Down
12 changes: 10 additions & 2 deletions api/tacticalrmm/accounts/management/commands/reset_password.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from getpass import getpass

from django.core.management.base import BaseCommand

from accounts.models import User
Expand All @@ -17,7 +19,13 @@ def handle(self, *args, **kwargs):
self.stdout.write(self.style.ERROR(f"User {username} doesn't exist"))
return

passwd = input("Enter new password: ")
user.set_password(passwd)
pass1, pass2 = "foo", "bar"
while pass1 != pass2:
pass1 = getpass()
pass2 = getpass(prompt="Confirm Password:")
if pass1 != pass2:
self.stdout.write(self.style.ERROR("Passwords don't match"))

user.set_password(pass1)
user.save()
self.stdout.write(self.style.SUCCESS(f"Password for {username} was reset!"))
27 changes: 13 additions & 14 deletions api/tacticalrmm/accounts/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@ class AccountsPerms(permissions.BasePermission):
def has_permission(self, r, view) -> bool:
if r.method == "GET":
return _has_perm(r, "can_list_accounts")
else:

# allow users to reset their own password/2fa see issue #686
base_path = "/accounts/users/"
paths = ["reset/", "reset_totp/"]
# allow users to reset their own password/2fa see issue #686
base_path = "/accounts/users/"
paths = ("reset/", "reset_totp/")

if r.path in [base_path + i for i in paths]:
from accounts.models import User
if r.path in [base_path + i for i in paths]:
from accounts.models import User

try:
user = User.objects.get(pk=r.data["id"])
except User.DoesNotExist:
pass
else:
if user == r.user:
return True
try:
user = User.objects.get(pk=r.data["id"])
except User.DoesNotExist:
pass
else:
if user == r.user:
return True

return _has_perm(r, "can_manage_accounts")
return _has_perm(r, "can_manage_accounts")


class RolesPerms(permissions.BasePermission):
Expand Down
3 changes: 1 addition & 2 deletions api/tacticalrmm/agents/management/commands/demo_cron.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.utils import timezone as djangotime

from agents.models import Agent
from core.tasks import cache_db_fields_task, handle_resolved_stuff
from core.tasks import cache_db_fields_task


class Command(BaseCommand):
Expand All @@ -30,4 +30,3 @@ def handle(self, *args, **kwargs):
agent.save(update_fields=["last_seen"])

cache_db_fields_task()
handle_resolved_stuff()
14 changes: 3 additions & 11 deletions api/tacticalrmm/agents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
PAAction,
PAStatus,
)
from tacticalrmm.helpers import get_nats_ports
from tacticalrmm.helpers import setup_nats_options
from tacticalrmm.models import PermissionQuerySet

if TYPE_CHECKING:
Expand Down Expand Up @@ -799,18 +799,10 @@ def _do_nats_debug(self, agent: "Agent", message: str) -> None:
async def nats_cmd(
self, data: Dict[Any, Any], timeout: int = 30, wait: bool = True
) -> Any:
nats_std_port, _ = get_nats_ports()
options = {
"servers": f"tls://{settings.ALLOWED_HOSTS[0]}:{nats_std_port}",
"user": "tacticalrmm",
"name": "trmm-django",
"password": settings.SECRET_KEY,
"connect_timeout": 3,
"max_reconnect_attempts": 2,
}

opts = setup_nats_options()
try:
nc = await nats.connect(**options)
nc = await nats.connect(**opts)
except:
return "natsdown"

Expand Down
44 changes: 21 additions & 23 deletions api/tacticalrmm/agents/tasks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import datetime as dt
import random
from time import sleep
from typing import TYPE_CHECKING, Optional

Expand All @@ -13,10 +12,13 @@
from tacticalrmm.celery import app
from tacticalrmm.constants import (
AGENT_DEFER,
AGENT_OUTAGES_LOCK,
AGENT_STATUS_OVERDUE,
CheckStatus,
DebugLogType,
)
from tacticalrmm.helpers import rand_range
from tacticalrmm.utils import redis_lock

if TYPE_CHECKING:
from django.db.models.query import QuerySet
Expand Down Expand Up @@ -46,7 +48,7 @@ def agent_outage_email_task(pk: int, alert_interval: Optional[float] = None) ->
return "alert not found"

if not alert.email_sent:
sleep(random.randint(1, 5))
sleep(rand_range(100, 1500))
alert.agent.send_outage_email()
alert.email_sent = djangotime.now()
alert.save(update_fields=["email_sent"])
Expand All @@ -55,7 +57,7 @@ def agent_outage_email_task(pk: int, alert_interval: Optional[float] = None) ->
# send an email only if the last email sent is older than alert interval
delta = djangotime.now() - dt.timedelta(days=alert_interval)
if alert.email_sent < delta:
sleep(random.randint(1, 5))
sleep(rand_range(100, 1500))
alert.agent.send_outage_email()
alert.email_sent = djangotime.now()
alert.save(update_fields=["email_sent"])
Expand All @@ -67,7 +69,7 @@ def agent_outage_email_task(pk: int, alert_interval: Optional[float] = None) ->
def agent_recovery_email_task(pk: int) -> str:
from alerts.models import Alert

sleep(random.randint(1, 5))
sleep(rand_range(100, 1500))

try:
alert = Alert.objects.get(pk=pk)
Expand All @@ -91,7 +93,7 @@ def agent_outage_sms_task(pk: int, alert_interval: Optional[float] = None) -> st
return "alert not found"

if not alert.sms_sent:
sleep(random.randint(1, 3))
sleep(rand_range(100, 1500))
alert.agent.send_outage_sms()
alert.sms_sent = djangotime.now()
alert.save(update_fields=["sms_sent"])
Expand All @@ -100,7 +102,7 @@ def agent_outage_sms_task(pk: int, alert_interval: Optional[float] = None) -> st
# send an sms only if the last sms sent is older than alert interval
delta = djangotime.now() - dt.timedelta(days=alert_interval)
if alert.sms_sent < delta:
sleep(random.randint(1, 3))
sleep(rand_range(100, 1500))
alert.agent.send_outage_sms()
alert.sms_sent = djangotime.now()
alert.save(update_fields=["sms_sent"])
Expand All @@ -112,7 +114,7 @@ def agent_outage_sms_task(pk: int, alert_interval: Optional[float] = None) -> st
def agent_recovery_sms_task(pk: int) -> str:
from alerts.models import Alert

sleep(random.randint(1, 3))
sleep(rand_range(100, 1500))
try:
alert = Alert.objects.get(pk=pk)
except Alert.DoesNotExist:
Expand All @@ -125,24 +127,20 @@ def agent_recovery_sms_task(pk: int) -> str:
return "ok"


@app.task
def agent_outages_task() -> None:
from alerts.models import Alert
@app.task(bind=True)
def agent_outages_task(self) -> str:
with redis_lock(AGENT_OUTAGES_LOCK, self.app.oid) as acquired:
if not acquired:
return f"{self.app.oid} still running"

agents = Agent.objects.only(
"pk",
"agent_id",
"last_seen",
"offline_time",
"overdue_time",
"overdue_email_alert",
"overdue_text_alert",
"overdue_dashboard_alert",
)
from alerts.models import Alert
from core.tasks import _get_agent_qs

for agent in agents:
if agent.status == AGENT_STATUS_OVERDUE:
Alert.handle_alert_failure(agent)
for agent in _get_agent_qs():
if agent.status == AGENT_STATUS_OVERDUE:
Alert.handle_alert_failure(agent)

return "completed"


@app.task
Expand Down
1 change: 1 addition & 0 deletions api/tacticalrmm/agents/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@
path("update/", views.update_agents),
path("installer/", views.install_agent),
path("bulkrecovery/", views.bulk_agent_recovery),
path("scripthistory/", views.ScriptRunHistory.as_view()),
]
Loading

0 comments on commit 074f898

Please sign in to comment.