Compare commits

...

12 Commits

Author SHA1 Message Date
wh1te909
0da1950427 Release 0.3.3 2021-01-18 11:01:25 +00:00
wh1te909
e590b921be fix #252 2021-01-18 11:00:50 +00:00
wh1te909
09462692f5 Release 0.3.2 2021-01-18 10:00:45 +00:00
wh1te909
c1d1b5f762 bump version 2021-01-18 10:00:26 +00:00
wh1te909
6b9c87b858 feat: set agent table tab default #249 2021-01-18 09:57:50 +00:00
wh1te909
485b6eb904 Merge branch 'develop' of https://github.com/wh1te909/tacticalrmm into develop 2021-01-18 09:32:00 +00:00
wh1te909
057630bdb5 fix agent table sort #250 2021-01-18 09:31:28 +00:00
wh1te909
6b02873b30 fix agent table sort #250 2021-01-18 09:12:01 +00:00
wh1te909
0fa0fc6d6b add json linter to migration docs 2021-01-17 18:09:47 +00:00
wh1te909
339ec07465 Release 0.3.1 2021-01-17 05:48:27 +00:00
wh1te909
cd2e798fea bump versions 2021-01-17 05:43:34 +00:00
wh1te909
d5cadbeae2 split agent update into chunks 2021-01-17 05:42:38 +00:00
12 changed files with 126 additions and 40 deletions

View File

@@ -0,0 +1,26 @@
# Generated by Django 3.1.5 on 2021-01-18 09:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("accounts", "0010_user_agent_dblclick_action"),
]
operations = [
migrations.AddField(
model_name="user",
name="default_agent_tbl_tab",
field=models.CharField(
choices=[
("server", "Servers"),
("workstation", "Workstations"),
("mixed", "Mixed"),
],
default="server",
max_length=50,
),
),
]

View File

@@ -9,6 +9,12 @@ AGENT_DBLCLICK_CHOICES = [
("remotebg", "Remote Background"), ("remotebg", "Remote Background"),
] ]
AGENT_TBL_TAB_CHOICES = [
("server", "Servers"),
("workstation", "Workstations"),
("mixed", "Mixed"),
]
class User(AbstractUser, BaseAuditModel): class User(AbstractUser, BaseAuditModel):
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
@@ -18,6 +24,9 @@ class User(AbstractUser, BaseAuditModel):
agent_dblclick_action = models.CharField( agent_dblclick_action = models.CharField(
max_length=50, choices=AGENT_DBLCLICK_CHOICES, default="editagent" max_length=50, choices=AGENT_DBLCLICK_CHOICES, default="editagent"
) )
default_agent_tbl_tab = models.CharField(
max_length=50, choices=AGENT_TBL_TAB_CHOICES, default="server"
)
agent = models.OneToOneField( agent = models.OneToOneField(
"agents.Agent", "agents.Agent",

View File

@@ -189,16 +189,17 @@ class UserUI(APIView):
def patch(self, request): def patch(self, request):
user = request.user user = request.user
if "dark_mode" in request.data: if "dark_mode" in request.data.keys():
user.dark_mode = request.data["dark_mode"] user.dark_mode = request.data["dark_mode"]
user.save(update_fields=["dark_mode"]) user.save(update_fields=["dark_mode"])
if "show_community_scripts" in request.data: if "show_community_scripts" in request.data.keys():
user.show_community_scripts = request.data["show_community_scripts"] user.show_community_scripts = request.data["show_community_scripts"]
user.save(update_fields=["show_community_scripts"]) user.save(update_fields=["show_community_scripts"])
if "agent_dblclick_action" in request.data: if "userui" in request.data.keys():
user.agent_dblclick_action = request.data["agent_dblclick_action"] user.agent_dblclick_action = request.data["agent_dblclick_action"]
user.save(update_fields=["agent_dblclick_action"]) user.default_agent_tbl_tab = request.data["default_agent_tbl_tab"]
user.save(update_fields=["agent_dblclick_action", "default_agent_tbl_tab"])
return Response("ok") return Response("ok")

View File

@@ -42,11 +42,13 @@ class AgentTableSerializer(serializers.ModelSerializer):
last_seen = serializers.SerializerMethodField() last_seen = serializers.SerializerMethodField()
client_name = serializers.ReadOnlyField(source="client.name") client_name = serializers.ReadOnlyField(source="client.name")
site_name = serializers.ReadOnlyField(source="site.name") site_name = serializers.ReadOnlyField(source="site.name")
logged_username = serializers.SerializerMethodField()
italic = serializers.SerializerMethodField()
def get_pending_actions(self, obj): def get_pending_actions(self, obj):
return obj.pendingactions.filter(status="pending").count() return obj.pendingactions.filter(status="pending").count()
def get_last_seen(self, obj): def get_last_seen(self, obj) -> str:
if obj.time_zone is not None: if obj.time_zone is not None:
agent_tz = pytz.timezone(obj.time_zone) agent_tz = pytz.timezone(obj.time_zone)
else: else:
@@ -54,6 +56,17 @@ class AgentTableSerializer(serializers.ModelSerializer):
return obj.last_seen.astimezone(agent_tz).strftime("%m %d %Y %H:%M:%S") return obj.last_seen.astimezone(agent_tz).strftime("%m %d %Y %H:%M:%S")
def get_logged_username(self, obj) -> str:
if obj.logged_in_username == "None" and obj.status == "online":
return obj.last_logged_in_user
elif obj.logged_in_username != "None":
return obj.logged_in_username
else:
return "-"
def get_italic(self, obj) -> bool:
return obj.logged_in_username == "None" and obj.status == "online"
class Meta: class Meta:
model = Agent model = Agent
fields = [ fields = [
@@ -73,9 +86,9 @@ class AgentTableSerializer(serializers.ModelSerializer):
"last_seen", "last_seen",
"boot_time", "boot_time",
"checks", "checks",
"logged_in_username",
"last_logged_in_user",
"maintenance_mode", "maintenance_mode",
"logged_username",
"italic",
] ]
depth = 2 depth = 2

View File

@@ -111,9 +111,12 @@ def send_agent_update_task(pks: List[int], version: str) -> None:
agents: List[int] = [ agents: List[int] = [
i.pk for i in q if pyver.parse(i.version) < pyver.parse(version) i.pk for i in q if pyver.parse(i.version) < pyver.parse(version)
] ]
chunks = (agents[i : i + 30] for i in range(0, len(agents), 30))
for pk in agents: for chunk in chunks:
for pk in chunk:
agent_update(pk) agent_update(pk)
sleep(0.05)
sleep(4)
@app.task @app.task
@@ -129,8 +132,12 @@ def auto_self_agent_update_task() -> None:
if pyver.parse(i.version) < pyver.parse(settings.LATEST_AGENT_VER) if pyver.parse(i.version) < pyver.parse(settings.LATEST_AGENT_VER)
] ]
for pk in pks: chunks = (pks[i : i + 30] for i in range(0, len(pks), 30))
for chunk in chunks:
for pk in chunk:
agent_update(pk) agent_update(pk)
sleep(0.05)
sleep(4)
@app.task @app.task

View File

@@ -72,6 +72,7 @@ def dashboard_info(request):
"dark_mode": request.user.dark_mode, "dark_mode": request.user.dark_mode,
"show_community_scripts": request.user.show_community_scripts, "show_community_scripts": request.user.show_community_scripts,
"dbl_click_action": request.user.agent_dblclick_action, "dbl_click_action": request.user.agent_dblclick_action,
"default_agent_tbl_tab": request.user.default_agent_tbl_tab,
} }
) )

View File

@@ -15,17 +15,17 @@ 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.3.0" TRMM_VERSION = "0.3.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.104" APP_VER = "0.0.106"
# https://github.com/wh1te909/salt # https://github.com/wh1te909/salt
LATEST_SALT_VER = "1.1.0" LATEST_SALT_VER = "1.1.0"
# https://github.com/wh1te909/rmmagent # https://github.com/wh1te909/rmmagent
LATEST_AGENT_VER = "1.2.0" LATEST_AGENT_VER = "1.2.1"
MESH_VER = "0.7.45" MESH_VER = "0.7.45"

View File

@@ -139,7 +139,7 @@ server {
} }
``` ```
4. Edit `/meshcentral/meshcentral-data/config.json` and change to match the example below. Replace `mesh.example.com` with your mesh domain. 4. Edit `/meshcentral/meshcentral-data/config.json` and change to match the example below. Replace `mesh.example.com` with your mesh domain. After editing, use a json linter like `https://jsonlint.com/` to verify no syntax errors, otherwise meshcentral will fail to start.
``` ```
{ {
"settings": { "settings": {

View File

@@ -53,12 +53,6 @@
</q-icon> </q-icon>
</q-th> </q-th>
</template> </template>
<!--
<template v-slot:header-cell-antivirus="props">
<q-th auto-width :props="props">
<q-icon name="fas fa-shield-alt" size="1.2em" color="primary"><q-tooltip>Anti Virus</q-tooltip></q-icon>
</q-th>
</template>-->
<template v-slot:header-cell-agentstatus="props"> <template v-slot:header-cell-agentstatus="props">
<q-th auto-width :props="props"> <q-th auto-width :props="props">
<q-icon name="fas fa-signal" size="1.2em"> <q-icon name="fas fa-signal" size="1.2em">
@@ -286,11 +280,8 @@
<q-td key="hostname" :props="props">{{ props.row.hostname }}</q-td> <q-td key="hostname" :props="props">{{ props.row.hostname }}</q-td>
<q-td key="description" :props="props">{{ props.row.description }}</q-td> <q-td key="description" :props="props">{{ props.row.description }}</q-td>
<q-td key="user" :props="props"> <q-td key="user" :props="props">
<span class="text-italic" v-if="props.row.logged_in_username === 'None' && props.row.status === 'online'">{{ <span class="text-italic" v-if="props.row.italic">{{ props.row.logged_username }}</span>
props.row.last_logged_in_user <span v-else>{{ props.row.logged_username }}</span>
}}</span>
<span v-else-if="props.row.logged_in_username !== 'None'">{{ props.row.logged_in_username }}</span>
<span v-else>-</span>
</q-td> </q-td>
<q-td :props="props" key="patchespending"> <q-td :props="props" key="patchespending">
<q-icon v-if="props.row.patches_pending" name="far fa-clock" color="primary"> <q-icon v-if="props.row.patches_pending" name="far fa-clock" color="primary">
@@ -455,10 +446,6 @@ export default {
} }
} }
// fix for last_logged_in_user not filtering
if (row.logged_in_username === "None" && row.status === "online" && !!row.last_logged_in_user)
return row.last_logged_in_user.toLowerCase().indexOf(search) !== -1;
// Normal text filter // Normal text filter
return cols.some(col => { return cols.some(col => {
const val = cellValue(col, row) + ""; const val = cellValue(col, row) + "";

View File

@@ -32,6 +32,20 @@
class="col-4" class="col-4"
/> />
</q-card-section> </q-card-section>
<q-card-section class="row">
<div class="col-6">Agent table default tab:</div>
<div class="col-2"></div>
<q-select
map-options
emit-value
outlined
dense
options-dense
v-model="defaultAgentTblTab"
:options="defaultAgentTblTabOptions"
class="col-4"
/>
</q-card-section>
</q-tab-panel> </q-tab-panel>
</q-tab-panels> </q-tab-panels>
@@ -54,6 +68,7 @@ export default {
data() { data() {
return { return {
agentDblClickAction: "", agentDblClickAction: "",
defaultAgentTblTab: "",
tab: "ui", tab: "ui",
splitterModel: 20, splitterModel: 20,
agentDblClickOptions: [ agentDblClickOptions: [
@@ -70,16 +85,35 @@ export default {
value: "remotebg", value: "remotebg",
}, },
], ],
defaultAgentTblTabOptions: [
{
label: "Servers",
value: "server",
},
{
label: "Workstations",
value: "workstation",
},
{
label: "Mixed",
value: "mixed",
},
],
}; };
}, },
methods: { methods: {
getUserPrefs() { getUserPrefs() {
this.$axios.get("/core/dashinfo/").then(r => { this.$axios.get("/core/dashinfo/").then(r => {
this.agentDblClickAction = r.data.dbl_click_action; this.agentDblClickAction = r.data.dbl_click_action;
this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
}); });
}, },
editUserPrefs() { editUserPrefs() {
const data = { agent_dblclick_action: this.agentDblClickAction }; const data = {
userui: true,
agent_dblclick_action: this.agentDblClickAction,
default_agent_tbl_tab: this.defaultAgentTblTab,
};
this.$axios.patch("/accounts/users/ui/", data).then(r => { this.$axios.patch("/accounts/users/ui/", data).then(r => {
this.notifySuccess("Preferences were saved!"); this.notifySuccess("Preferences were saved!");
this.$emit("edited"); this.$emit("edited");

View File

@@ -35,6 +35,7 @@ export default function () {
tabHeight: "35vh", tabHeight: "35vh",
showCommunityScripts: false, showCommunityScripts: false,
agentDblClickAction: "", agentDblClickAction: "",
defaultAgentTblTab: "server",
}, },
getters: { getters: {
loggedIn(state) { loggedIn(state) {
@@ -139,6 +140,9 @@ export default function () {
}, },
SET_AGENT_DBLCLICK_ACTION(state, action) { SET_AGENT_DBLCLICK_ACTION(state, action) {
state.agentDblClickAction = action state.agentDblClickAction = action
},
SET_DEFAULT_AGENT_TBL_TABd(state, tab) {
state.defaultAgentTblTab = tab
} }
}, },
actions: { actions: {

View File

@@ -195,7 +195,6 @@
</q-tabs> </q-tabs>
<q-space /> <q-space />
<q-input <q-input
autogrow
v-model="search" v-model="search"
style="width: 450px" style="width: 450px"
label="Search" label="Search"
@@ -411,7 +410,6 @@ export default {
outsideModel: 11, outsideModel: 11,
selectedTree: "", selectedTree: "",
innerModel: 50, innerModel: 50,
tab: "server",
clientActive: "", clientActive: "",
siteActive: "", siteActive: "",
frame: [], frame: [],
@@ -472,16 +470,13 @@ export default {
{ {
name: "user", name: "user",
label: "User", label: "User",
field: "logged_in_username", field: "logged_username",
sortable: true, sortable: true,
align: "left", align: "left",
}, },
{ {
name: "lastuser", name: "italic",
label: "Last User", field: "italic",
field: "last_logged_in_user",
sortable: true,
align: "left",
}, },
{ {
name: "patchespending", name: "patchespending",
@@ -686,6 +681,7 @@ export default {
this.$q.dark.set(this.darkMode); this.$q.dark.set(this.darkMode);
this.currentTRMMVersion = r.data.trmm_version; this.currentTRMMVersion = r.data.trmm_version;
this.$store.commit("SET_AGENT_DBLCLICK_ACTION", r.data.dbl_click_action); this.$store.commit("SET_AGENT_DBLCLICK_ACTION", r.data.dbl_click_action);
this.$store.commit("SET_DEFAULT_AGENT_TBL_TABd", r.data.default_agent_tbl_tab);
this.$store.commit("setShowCommunityScripts", r.data.show_community_scripts); this.$store.commit("setShowCommunityScripts", r.data.show_community_scripts);
}); });
}, },
@@ -770,6 +766,14 @@ export default {
clients: state => state.clients, clients: state => state.clients,
}), }),
...mapGetters(["selectedAgentPk", "needRefresh"]), ...mapGetters(["selectedAgentPk", "needRefresh"]),
tab: {
get: function () {
return this.$store.state.defaultAgentTblTab;
},
set: function (newVal) {
this.$store.commit("SET_DEFAULT_AGENT_TBL_TABd", newVal);
},
},
allClientsActive() { allClientsActive() {
return this.selectedTree === "" ? true : false; return this.selectedTree === "" ? true : false;
}, },