Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0da1950427 | ||
|
|
e590b921be | ||
|
|
09462692f5 | ||
|
|
c1d1b5f762 | ||
|
|
6b9c87b858 | ||
|
|
485b6eb904 | ||
|
|
057630bdb5 | ||
|
|
6b02873b30 | ||
|
|
0fa0fc6d6b | ||
|
|
339ec07465 | ||
|
|
cd2e798fea | ||
|
|
d5cadbeae2 |
@@ -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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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",
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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": {
|
||||||
|
|||||||
@@ -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) + "";
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user