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"), | ||||
| ] | ||||
|  | ||||
| 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 | ||||
|  | ||||
|   | ||||
| @@ -111,9 +111,12 @@ def send_agent_update_task(pks: List[int], version: str) -> None: | ||||
|     agents: List[int] = [ | ||||
|         i.pk for i in q if pyver.parse(i.version) < pyver.parse(version) | ||||
|     ] | ||||
|  | ||||
|     for pk in agents: | ||||
|     chunks = (agents[i : i + 30] for i in range(0, len(agents), 30)) | ||||
|     for chunk in chunks: | ||||
|         for pk in chunk: | ||||
|             agent_update(pk) | ||||
|             sleep(0.05) | ||||
|         sleep(4) | ||||
|  | ||||
|  | ||||
| @app.task | ||||
| @@ -129,8 +132,12 @@ def auto_self_agent_update_task() -> None: | ||||
|         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) | ||||
|             sleep(0.05) | ||||
|         sleep(4) | ||||
|  | ||||
|  | ||||
| @app.task | ||||
|   | ||||
| @@ -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,17 +15,17 @@ EXE_DIR = os.path.join(BASE_DIR, "tacticalrmm/private/exe") | ||||
| AUTH_USER_MODEL = "accounts.User" | ||||
|  | ||||
| # latest release | ||||
| TRMM_VERSION = "0.3.0" | ||||
| 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" | ||||
|  | ||||
| # https://github.com/wh1te909/rmmagent | ||||
| LATEST_AGENT_VER = "1.2.0" | ||||
| LATEST_AGENT_VER = "1.2.1" | ||||
|  | ||||
| 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": { | ||||
|   | ||||
| @@ -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