Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31830dc67d | ||
|
|
d0ce2a46ac | ||
|
|
7e5bc4e1ce | ||
|
|
d2b6d0a0ff | ||
|
|
542b0658b8 | ||
|
|
e73c7e19b5 | ||
|
|
6a32ed7d7b | ||
|
|
a63001f17c | ||
|
|
4d1ad9c832 |
@@ -430,14 +430,22 @@ class TestAgentViews(TacticalTestCase):
|
|||||||
"func": "schedtask",
|
"func": "schedtask",
|
||||||
"schedtaskpayload": {
|
"schedtaskpayload": {
|
||||||
"type": "schedreboot",
|
"type": "schedreboot",
|
||||||
"deleteafter": True,
|
"enabled": True,
|
||||||
"trigger": "once",
|
"delete_expired_task_after": True,
|
||||||
|
"start_when_available": False,
|
||||||
|
"multiple_instances": 2,
|
||||||
|
"trigger": "runonce",
|
||||||
"name": r.data["task_name"], # type: ignore
|
"name": r.data["task_name"], # type: ignore
|
||||||
"year": 2025,
|
"start_year": 2025,
|
||||||
"month": "August",
|
"start_month": 8,
|
||||||
"day": 29,
|
"start_day": 29,
|
||||||
"hour": 18,
|
"start_hour": 18,
|
||||||
"min": 41,
|
"start_min": 41,
|
||||||
|
"expire_year": 2025,
|
||||||
|
"expire_month": 8,
|
||||||
|
"expire_day": 29,
|
||||||
|
"expire_hour": 18,
|
||||||
|
"expire_min": 46,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
nats_cmd.assert_called_with(nats_data, timeout=10)
|
nats_cmd.assert_called_with(nats_data, timeout=10)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from django.conf import settings
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.utils import timezone as djangotime
|
||||||
from packaging import version as pyver
|
from packaging import version as pyver
|
||||||
from rest_framework.decorators import api_view, permission_classes
|
from rest_framework.decorators import api_view, permission_classes
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
@@ -383,18 +384,28 @@ class Reboot(APIView):
|
|||||||
random.choice(string.ascii_letters) for _ in range(10)
|
random.choice(string.ascii_letters) for _ in range(10)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
expire_date = obj + djangotime.timedelta(minutes=5)
|
||||||
|
|
||||||
nats_data = {
|
nats_data = {
|
||||||
"func": "schedtask",
|
"func": "schedtask",
|
||||||
"schedtaskpayload": {
|
"schedtaskpayload": {
|
||||||
"type": "schedreboot",
|
"type": "schedreboot",
|
||||||
"deleteafter": True,
|
"enabled": True,
|
||||||
"trigger": "once",
|
"delete_expired_task_after": True,
|
||||||
|
"start_when_available": False,
|
||||||
|
"multiple_instances": 2,
|
||||||
|
"trigger": "runonce",
|
||||||
"name": task_name,
|
"name": task_name,
|
||||||
"year": int(dt.datetime.strftime(obj, "%Y")),
|
"start_year": int(dt.datetime.strftime(obj, "%Y")),
|
||||||
"month": dt.datetime.strftime(obj, "%B"),
|
"start_month": int(dt.datetime.strftime(obj, "%-m")),
|
||||||
"day": int(dt.datetime.strftime(obj, "%d")),
|
"start_day": int(dt.datetime.strftime(obj, "%-d")),
|
||||||
"hour": int(dt.datetime.strftime(obj, "%H")),
|
"start_hour": int(dt.datetime.strftime(obj, "%-H")),
|
||||||
"min": int(dt.datetime.strftime(obj, "%M")),
|
"start_min": int(dt.datetime.strftime(obj, "%-M")),
|
||||||
|
"expire_year": int(expire_date.strftime("%Y")),
|
||||||
|
"expire_month": int(expire_date.strftime("%-m")),
|
||||||
|
"expire_day": int(expire_date.strftime("%-d")),
|
||||||
|
"expire_hour": int(expire_date.strftime("%-H")),
|
||||||
|
"expire_min": int(expire_date.strftime("%-M")),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ EXE_DIR = os.path.join(BASE_DIR, "tacticalrmm/private/exe")
|
|||||||
AUTH_USER_MODEL = "accounts.User"
|
AUTH_USER_MODEL = "accounts.User"
|
||||||
|
|
||||||
# latest release
|
# latest release
|
||||||
TRMM_VERSION = "0.11.2"
|
TRMM_VERSION = "0.11.3"
|
||||||
|
|
||||||
# bump this version everytime vue code is changed
|
# bump this version everytime vue code is changed
|
||||||
# to alert user they need to manually refresh their browser
|
# to alert user they need to manually refresh their browser
|
||||||
APP_VER = "0.0.156"
|
APP_VER = "0.0.157"
|
||||||
|
|
||||||
# https://github.com/wh1te909/rmmagent
|
# https://github.com/wh1te909/rmmagent
|
||||||
LATEST_AGENT_VER = "1.8.0"
|
LATEST_AGENT_VER = "1.8.0"
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ If you're running low, shrink you database
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo -u postgres psql -d tacticalrmm -c "vacuum full logs_auditlog"
|
sudo -u postgres psql -d tacticalrmm -c "vacuum full logs_auditlog"
|
||||||
sudo -u postgres psql -d tacticalrmm -c "vacuum full logs_auditlog"
|
sudo -u postgres psql -d tacticalrmm -c "vacuum full logs_pendingaction"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Video Walkthru
|
## Video Walkthru
|
||||||
|
|||||||
@@ -4,13 +4,25 @@
|
|||||||
#BurntToast Module Source and Examples: https://github.com/Windos/BurntToast
|
#BurntToast Module Source and Examples: https://github.com/Windos/BurntToast
|
||||||
#RunAsUser Module Source and Examples: https://github.com/KelvinTegelaar/RunAsUser
|
#RunAsUser Module Source and Examples: https://github.com/KelvinTegelaar/RunAsUser
|
||||||
|
|
||||||
# Assign last logged in user from TRMM to variable
|
|
||||||
|
# Set parameters
|
||||||
param (
|
param (
|
||||||
[string] $lastLoggedIn
|
[int[]] $expiryDaysToAlert=@(1,2,3,7)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Will exit when a user is not logged in
|
||||||
|
try{
|
||||||
|
$loggedInUser = ((Get-WMIObject -ClassName Win32_ComputerSystem).Username).Split('\')[1]
|
||||||
|
}catch{
|
||||||
|
Write-Host "No logged in user. Exiting"
|
||||||
|
Exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
|
||||||
# Check for, and install pre-reqs if not found.
|
# Check for, and install pre-reqs if not found.
|
||||||
if (Get-PackageProvider -Name NuGet) {
|
if (Get-PackageProvider -Name NuGet) {
|
||||||
#Write-Host "NuGet Already Added"
|
#Write-Host "NuGet Already Added"
|
||||||
@@ -36,26 +48,23 @@ else {
|
|||||||
Install-Module -Name RunAsUser -Force
|
Install-Module -Name RunAsUser -Force
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check to confirm temporary directory is present, and if not, create.
|
|
||||||
$directoryPath = "C:\ProgramData\TRMM\temp"
|
|
||||||
if(!(test-path $directoryPath))
|
|
||||||
{
|
|
||||||
New-Item -ItemType Directory -Force -Path $directoryPath
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get password expiration date with NET USER command. If returned output is null, then run command again for local user.
|
# Get password expiration date with NET USER command. If returned output is null, then run command again for local user.
|
||||||
$output = net user $lastLoggedIn /domain | find 'Password expires'
|
$output = net user $LoggedInUser /domain | find 'Password expires'
|
||||||
if ($output -eq $null)
|
if ($output -eq $null)
|
||||||
{
|
{
|
||||||
$output = net user $lastLoggedIn | find 'Password expires'
|
$output = net user $LoggedInUser | find 'Password expires'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Parse output to only show expiration date
|
# Parse output to only show expiration date
|
||||||
$passwordExpiry = $output -replace ".* "
|
$passwordExpiry = $output -replace ".* "
|
||||||
|
|
||||||
|
|
||||||
# TESTING - UNCOMMENT AND MANUALLY SET PASSWORD EXPIRY TO TEST SCRIPT AND ALERTS
|
# TESTING - UNCOMMENT AND MANUALLY SET PASSWORD EXPIRY TO TEST SCRIPT AND ALERTS
|
||||||
# $passwordExpiry = "1/14/2022 12:00:00"
|
# $passwordExpiry = "1/14/2022 12:00:00"
|
||||||
|
|
||||||
|
|
||||||
# Check if password is set to never expire.
|
# Check if password is set to never expire.
|
||||||
if ($passwordExpiry -eq "Never")
|
if ($passwordExpiry -eq "Never")
|
||||||
{
|
{
|
||||||
@@ -63,7 +72,7 @@ if ($passwordExpiry -eq "Never")
|
|||||||
Start-Sleep -Seconds 1
|
Start-Sleep -Seconds 1
|
||||||
Exit
|
Exit
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
# Calculate time until password expires
|
# Calculate time until password expires
|
||||||
$expiryDetails = ((get-date $passwordExpiry) - (get-date))
|
$expiryDetails = ((get-date $passwordExpiry) - (get-date))
|
||||||
@@ -72,77 +81,74 @@ if ($passwordExpiry -eq "Never")
|
|||||||
$expiryDays = $expiryDetails.Days
|
$expiryDays = $expiryDetails.Days
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Set messagetext variable depending on how soon the password expires.
|
# Set messagetext variable depending on how soon the password expires.
|
||||||
if ($expiryDays -eq 7)
|
if ($expiryDays -le 1)
|
||||||
|
{
|
||||||
|
$messagetext = "Your password is going to expire! To ensure you are not blocked from logging into your PC or online services, you must update your password immediately."
|
||||||
|
$urgentFlag = 1
|
||||||
|
}
|
||||||
|
elseif ($expiryDays -le 2)
|
||||||
|
{
|
||||||
|
$messagetext = "Your password will expire in 2 days or less. It is important that you change your password as soon as possible."
|
||||||
|
$urgentFlag = 0
|
||||||
|
}
|
||||||
|
elseif ($expiryDays -le 3)
|
||||||
|
{
|
||||||
|
$messagetext = "Your password will expire in 3 days or less. Please change your password."
|
||||||
|
$urgentFlag = 0
|
||||||
|
}
|
||||||
|
elseif ($expiryDays -le 7)
|
||||||
{
|
{
|
||||||
$messagetext = "Your password will expire in 7 days or less. You should consider changing your password."
|
$messagetext = "Your password will expire in 7 days or less. You should consider changing your password."
|
||||||
$urgentFlag = 0
|
$urgentFlag = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($expiryDays -eq 3)
|
|
||||||
{
|
|
||||||
$messagetext = "Your password will expire in 3 days or less. Please change your password."
|
|
||||||
$urgentFlag = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($expiryDays -eq 2)
|
# Download Regular and Urgent Image files
|
||||||
{
|
$regDownloadPath = "https://YOURDOMAIN.COM/BurntToastLogo.png"
|
||||||
$messagetext = "Your password will expire in 2 days or less. It is important that you change your password as soon as possible."
|
Invoke-WebRequest $regDownloadPath -OutFile "C:\Program Files\TacticalAgent\BurntToastLogo.png"
|
||||||
$urgentFlag = 0
|
$urgentDownloadPath = "https://YOURDOMAIN.COM/BurntToastLogoUrgent.png"
|
||||||
}
|
Invoke-WebRequest $urgentDownloadPath -OutFile "C:\Program Files\TacticalAgent\BurntToastLogoUrgent.png"
|
||||||
|
|
||||||
if ($expiryDays -eq 1)
|
|
||||||
{
|
|
||||||
$messagetext = "Your password is going to expire! To ensure you are not blocked from logging into your PC or online services, you must update your password immediately."
|
|
||||||
$urgentFlag = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Check if URGENT BurntToastLogo.png file is required and download appropriate image.
|
# Check if URGENT BurntToastLogo.png file is required and set variable path
|
||||||
if ($urgentFlag -eq 1)
|
if ($urgentFlag -eq 1)
|
||||||
{
|
{
|
||||||
Write-Output "Downloading URGENT Logo"
|
$popupImage = "C:\Program Files\TacticalAgent\BurntToastLogoUrgent.png"
|
||||||
$urgentDownloadPath = "https://YOURDOMAIN.COM/BurntToastLogoUrgent.png"
|
|
||||||
Invoke-WebRequest $urgentDownloadPath -OutFile "C:\Program Files\TacticalAgent\BurntToastLogo.png"
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Write-Output "Downloading Regular Logo"
|
$popupImage = "C:\Program Files\TacticalAgent\BurntToastLogo.png"
|
||||||
$regDownloadPath = "https://YOURDOMAIN.COM/BurntToastLogo.png"
|
|
||||||
Invoke-WebRequest $regDownloadPath -OutFile "C:\Program Files\TacticalAgent\BurntToastLogo.png"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Write message text to file on disk
|
|
||||||
Set-Content -Path c:\ProgramData\TRMM\temp\message.txt -Value $messagetext
|
|
||||||
|
|
||||||
# If password expires within either 7, 3, 2, or 1 days, send popup to user.
|
# If password expires is in $expiryDaystAlert days, send popup to user.
|
||||||
if ($expiryDays -eq 7 -or $expiryDays -eq 3 -or $expiryDays -eq 2 -or $expiryDays -eq 1)
|
if ($expiryDays -in $expiryDaysToAlert)
|
||||||
{
|
{
|
||||||
|
$command = @"
|
||||||
|
`$HeroImage = New-BTImage -Source "${popupImage}" -HeroImage
|
||||||
|
`$Text1 = New-BTText -Content "*** IMPORTANT Alert from IT Department ***"
|
||||||
|
`$Text2 = New-BTText -Content "${messagetext}"
|
||||||
|
`$Button = New-BTButton -Content "Snooze" -snooze -id 'SnoozeTime'
|
||||||
|
`$Button2 = New-BTButton -Content "Dismiss" -dismiss
|
||||||
|
`$5Min = New-BTSelectionBoxItem -Id 5 -Content '5 minutes'
|
||||||
|
`$10Min = New-BTSelectionBoxItem -Id 10 -Content '10 minutes'
|
||||||
|
`$1Hour = New-BTSelectionBoxItem -Id 60 -Content '1 hour'
|
||||||
|
`$4Hour = New-BTSelectionBoxItem -Id 240 -Content '4 hours'
|
||||||
|
`$1Day = New-BTSelectionBoxItem -Id 1440 -Content '1 day'
|
||||||
|
`$Items = `$5Min, `$10Min, `$1Hour, `$4Hour, `$1Day
|
||||||
|
`$SelectionBox = New-BTInput -Id 'SnoozeTime' -DefaultSelectionBoxItemId 10 -Items `$Items
|
||||||
|
`$Action = New-BTAction -Buttons `$Button, `$Button2 -inputs `$SelectionBox
|
||||||
|
`$Binding = New-BTBinding -Children `$Text1, `$Text2 -HeroImage `$HeroImage
|
||||||
|
`$Visual = New-BTVisual -BindingGeneric `$Binding
|
||||||
|
`$Audio = New-BTAudio -Source ms-winsoundevent:Notification.Looping.Alarm4
|
||||||
|
`$Content = New-BTContent -Visual `$Visual -Actions `$Action -Audio `$Audio
|
||||||
|
Submit-BTNotification -Content `$Content
|
||||||
|
"@
|
||||||
|
|
||||||
Invoke-AsCurrentUser -scriptblock {
|
$scriptblock = [scriptblock]::Create($command)
|
||||||
|
Invoke-AsCurrentUser -ScriptBlock $scriptblock
|
||||||
$messageContent = Get-Content -Path c:\ProgramData\TRMM\temp\message.txt
|
|
||||||
$heroimage = New-BTImage -Source 'C:\Program Files\TacticalAgent\BurntToastLogo.png' -HeroImage
|
|
||||||
$Text1 = New-BTText -Content "*** IMPORTANT Alert from IT Department ***"
|
|
||||||
$Text2 = New-BTText -Content "$messageContent"
|
|
||||||
$Button = New-BTButton -Content "Snooze" -snooze -id 'SnoozeTime'
|
|
||||||
$Button2 = New-BTButton -Content "Dismiss" -dismiss
|
|
||||||
$5Min = New-BTSelectionBoxItem -Id 5 -Content '5 minutes'
|
|
||||||
$10Min = New-BTSelectionBoxItem -Id 10 -Content '10 minutes'
|
|
||||||
$1Hour = New-BTSelectionBoxItem -Id 60 -Content '1 hour'
|
|
||||||
$4Hour = New-BTSelectionBoxItem -Id 240 -Content '4 hours'
|
|
||||||
$1Day = New-BTSelectionBoxItem -Id 1440 -Content '1 day'
|
|
||||||
$Items = $5Min, $10Min, $1Hour, $4Hour, $1Day
|
|
||||||
$SelectionBox = New-BTInput -Id 'SnoozeTime' -DefaultSelectionBoxItemId 10 -Items $Items
|
|
||||||
$action = New-BTAction -Buttons $Button, $Button2 -inputs $SelectionBox
|
|
||||||
$Binding = New-BTBinding -Children $Text1, $Text2 -HeroImage $heroimage
|
|
||||||
$Visual = New-BTVisual -BindingGeneric $Binding
|
|
||||||
$Content = New-BTContent -Visual $Visual -Actions $action
|
|
||||||
Submit-BTNotification -Content $Content
|
|
||||||
}
|
|
||||||
|
|
||||||
# Cleanup temp file for message variables
|
|
||||||
Remove-Item -Path C:\ProgramData\TRMM\temp\message.txt
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ export async function scheduleAgentReboot(agent_id, payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function agentRebootNow(agent_id) {
|
export async function agentRebootNow(agent_id) {
|
||||||
const { data } = await axios.post(`${baseUrl}/${agent_id}/reboot/`, payload)
|
const { data } = await axios.post(`${baseUrl}/${agent_id}/reboot/`)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
activeTabs: {
|
activeTabs: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: ["summary", "checks", "tasks", "patches", "software", "history", "notes", "assets", "audit"],
|
default: ["summary", "checks", "tasks", "patches", "software", "history", "notes", "assets", "debug", "audit"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
|||||||
@@ -360,10 +360,13 @@ export default {
|
|||||||
cancel: true,
|
cancel: true,
|
||||||
persistent: true,
|
persistent: true,
|
||||||
}).onOk(async () => {
|
}).onOk(async () => {
|
||||||
|
$q.loading.show();
|
||||||
try {
|
try {
|
||||||
const result = await agentRebootNow(agent.agent_id);
|
const result = await agentRebootNow(agent.agent_id);
|
||||||
notifySuccess(`${agent.hostname} will now be restarted`);
|
notifySuccess(`${agent.hostname} will now be restarted`);
|
||||||
|
$q.loading.hide();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
$q.loading.hide();
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,15 @@
|
|||||||
<q-form @submit.prevent="submit(onDialogOK)">
|
<q-form @submit.prevent="submit(onDialogOK)">
|
||||||
<div style="max-height: 70vh" class="scroll">
|
<div style="max-height: 70vh" class="scroll">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-select dense :disable="!!check" outlined v-model="state.disk" :options="diskOptions" label="Disk" />
|
<q-select
|
||||||
|
dense
|
||||||
|
:disable="!!check"
|
||||||
|
outlined
|
||||||
|
v-model="state.disk"
|
||||||
|
:options="diskOptions"
|
||||||
|
label="Disk"
|
||||||
|
:rules="[val => !!val || '*Required']"
|
||||||
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
|
|||||||
Reference in New Issue
Block a user