Compare commits
	
		
			9 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0da1950427 | ||
| 
						 | 
					e590b921be | ||
| 
						 | 
					09462692f5 | ||
| 
						 | 
					c1d1b5f762 | ||
| 
						 | 
					6b9c87b858 | ||
| 
						 | 
					485b6eb904 | ||
| 
						 | 
					057630bdb5 | ||
| 
						 | 
					6b02873b30 | ||
| 
						 | 
					0fa0fc6d6b | 
@@ -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"),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
AGENT_TBL_TAB_CHOICES = [
 | 
			
		||||
    ("server", "Servers"),
 | 
			
		||||
    ("workstation", "Workstations"),
 | 
			
		||||
    ("mixed", "Mixed"),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class User(AbstractUser, BaseAuditModel):
 | 
			
		||||
    is_active = models.BooleanField(default=True)
 | 
			
		||||
@@ -18,6 +24,9 @@ class User(AbstractUser, BaseAuditModel):
 | 
			
		||||
    agent_dblclick_action = models.CharField(
 | 
			
		||||
        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(
 | 
			
		||||
        "agents.Agent",
 | 
			
		||||
 
 | 
			
		||||
@@ -189,16 +189,17 @@ class UserUI(APIView):
 | 
			
		||||
    def patch(self, request):
 | 
			
		||||
        user = request.user
 | 
			
		||||
 | 
			
		||||
        if "dark_mode" in request.data:
 | 
			
		||||
        if "dark_mode" in request.data.keys():
 | 
			
		||||
            user.dark_mode = request.data["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.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.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")
 | 
			
		||||
 
 | 
			
		||||
@@ -42,11 +42,13 @@ class AgentTableSerializer(serializers.ModelSerializer):
 | 
			
		||||
    last_seen = serializers.SerializerMethodField()
 | 
			
		||||
    client_name = serializers.ReadOnlyField(source="client.name")
 | 
			
		||||
    site_name = serializers.ReadOnlyField(source="site.name")
 | 
			
		||||
    logged_username = serializers.SerializerMethodField()
 | 
			
		||||
    italic = serializers.SerializerMethodField()
 | 
			
		||||
 | 
			
		||||
    def get_pending_actions(self, obj):
 | 
			
		||||
        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:
 | 
			
		||||
            agent_tz = pytz.timezone(obj.time_zone)
 | 
			
		||||
        else:
 | 
			
		||||
@@ -54,6 +56,17 @@ class AgentTableSerializer(serializers.ModelSerializer):
 | 
			
		||||
 | 
			
		||||
        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:
 | 
			
		||||
        model = Agent
 | 
			
		||||
        fields = [
 | 
			
		||||
@@ -73,9 +86,9 @@ class AgentTableSerializer(serializers.ModelSerializer):
 | 
			
		||||
            "last_seen",
 | 
			
		||||
            "boot_time",
 | 
			
		||||
            "checks",
 | 
			
		||||
            "logged_in_username",
 | 
			
		||||
            "last_logged_in_user",
 | 
			
		||||
            "maintenance_mode",
 | 
			
		||||
            "logged_username",
 | 
			
		||||
            "italic",
 | 
			
		||||
        ]
 | 
			
		||||
        depth = 2
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,7 @@ def dashboard_info(request):
 | 
			
		||||
            "dark_mode": request.user.dark_mode,
 | 
			
		||||
            "show_community_scripts": request.user.show_community_scripts,
 | 
			
		||||
            "dbl_click_action": request.user.agent_dblclick_action,
 | 
			
		||||
            "default_agent_tbl_tab": request.user.default_agent_tbl_tab,
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,11 +15,11 @@ EXE_DIR = os.path.join(BASE_DIR, "tacticalrmm/private/exe")
 | 
			
		||||
AUTH_USER_MODEL = "accounts.User"
 | 
			
		||||
 | 
			
		||||
# latest release
 | 
			
		||||
TRMM_VERSION = "0.3.1"
 | 
			
		||||
TRMM_VERSION = "0.3.3"
 | 
			
		||||
 | 
			
		||||
# bump this version everytime vue code is changed
 | 
			
		||||
# 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
 | 
			
		||||
LATEST_SALT_VER = "1.1.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -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": {
 | 
			
		||||
 
 | 
			
		||||
@@ -53,12 +53,6 @@
 | 
			
		||||
          </q-icon>
 | 
			
		||||
        </q-th>
 | 
			
		||||
      </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">
 | 
			
		||||
        <q-th auto-width :props="props">
 | 
			
		||||
          <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="description" :props="props">{{ props.row.description }}</q-td>
 | 
			
		||||
          <q-td key="user" :props="props">
 | 
			
		||||
            <span class="text-italic" v-if="props.row.logged_in_username === 'None' && props.row.status === 'online'">{{
 | 
			
		||||
              props.row.last_logged_in_user
 | 
			
		||||
            }}</span>
 | 
			
		||||
            <span v-else-if="props.row.logged_in_username !== 'None'">{{ props.row.logged_in_username }}</span>
 | 
			
		||||
            <span v-else>-</span>
 | 
			
		||||
            <span class="text-italic" v-if="props.row.italic">{{ props.row.logged_username }}</span>
 | 
			
		||||
            <span v-else>{{ props.row.logged_username }}</span>
 | 
			
		||||
          </q-td>
 | 
			
		||||
          <q-td :props="props" key="patchespending">
 | 
			
		||||
            <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
 | 
			
		||||
        return cols.some(col => {
 | 
			
		||||
          const val = cellValue(col, row) + "";
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,20 @@
 | 
			
		||||
                  class="col-4"
 | 
			
		||||
                />
 | 
			
		||||
              </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-panels>
 | 
			
		||||
 | 
			
		||||
@@ -54,6 +68,7 @@ export default {
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      agentDblClickAction: "",
 | 
			
		||||
      defaultAgentTblTab: "",
 | 
			
		||||
      tab: "ui",
 | 
			
		||||
      splitterModel: 20,
 | 
			
		||||
      agentDblClickOptions: [
 | 
			
		||||
@@ -70,16 +85,35 @@ export default {
 | 
			
		||||
          value: "remotebg",
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
      defaultAgentTblTabOptions: [
 | 
			
		||||
        {
 | 
			
		||||
          label: "Servers",
 | 
			
		||||
          value: "server",
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          label: "Workstations",
 | 
			
		||||
          value: "workstation",
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          label: "Mixed",
 | 
			
		||||
          value: "mixed",
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    getUserPrefs() {
 | 
			
		||||
      this.$axios.get("/core/dashinfo/").then(r => {
 | 
			
		||||
        this.agentDblClickAction = r.data.dbl_click_action;
 | 
			
		||||
        this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    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.notifySuccess("Preferences were saved!");
 | 
			
		||||
        this.$emit("edited");
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@ export default function () {
 | 
			
		||||
      tabHeight: "35vh",
 | 
			
		||||
      showCommunityScripts: false,
 | 
			
		||||
      agentDblClickAction: "",
 | 
			
		||||
      defaultAgentTblTab: "server",
 | 
			
		||||
    },
 | 
			
		||||
    getters: {
 | 
			
		||||
      loggedIn(state) {
 | 
			
		||||
@@ -139,6 +140,9 @@ export default function () {
 | 
			
		||||
      },
 | 
			
		||||
      SET_AGENT_DBLCLICK_ACTION(state, action) {
 | 
			
		||||
        state.agentDblClickAction = action
 | 
			
		||||
      },
 | 
			
		||||
      SET_DEFAULT_AGENT_TBL_TABd(state, tab) {
 | 
			
		||||
        state.defaultAgentTblTab = tab
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    actions: {
 | 
			
		||||
 
 | 
			
		||||
@@ -195,7 +195,6 @@
 | 
			
		||||
                </q-tabs>
 | 
			
		||||
                <q-space />
 | 
			
		||||
                <q-input
 | 
			
		||||
                  autogrow
 | 
			
		||||
                  v-model="search"
 | 
			
		||||
                  style="width: 450px"
 | 
			
		||||
                  label="Search"
 | 
			
		||||
@@ -411,7 +410,6 @@ export default {
 | 
			
		||||
      outsideModel: 11,
 | 
			
		||||
      selectedTree: "",
 | 
			
		||||
      innerModel: 50,
 | 
			
		||||
      tab: "server",
 | 
			
		||||
      clientActive: "",
 | 
			
		||||
      siteActive: "",
 | 
			
		||||
      frame: [],
 | 
			
		||||
@@ -472,16 +470,13 @@ export default {
 | 
			
		||||
        {
 | 
			
		||||
          name: "user",
 | 
			
		||||
          label: "User",
 | 
			
		||||
          field: "logged_in_username",
 | 
			
		||||
          field: "logged_username",
 | 
			
		||||
          sortable: true,
 | 
			
		||||
          align: "left",
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: "lastuser",
 | 
			
		||||
          label: "Last User",
 | 
			
		||||
          field: "last_logged_in_user",
 | 
			
		||||
          sortable: true,
 | 
			
		||||
          align: "left",
 | 
			
		||||
          name: "italic",
 | 
			
		||||
          field: "italic",
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: "patchespending",
 | 
			
		||||
@@ -686,6 +681,7 @@ export default {
 | 
			
		||||
        this.$q.dark.set(this.darkMode);
 | 
			
		||||
        this.currentTRMMVersion = r.data.trmm_version;
 | 
			
		||||
        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);
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
@@ -770,6 +766,14 @@ export default {
 | 
			
		||||
      clients: state => state.clients,
 | 
			
		||||
    }),
 | 
			
		||||
    ...mapGetters(["selectedAgentPk", "needRefresh"]),
 | 
			
		||||
    tab: {
 | 
			
		||||
      get: function () {
 | 
			
		||||
        return this.$store.state.defaultAgentTblTab;
 | 
			
		||||
      },
 | 
			
		||||
      set: function (newVal) {
 | 
			
		||||
        this.$store.commit("SET_DEFAULT_AGENT_TBL_TABd", newVal);
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    allClientsActive() {
 | 
			
		||||
      return this.selectedTree === "" ? true : false;
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user