Compare commits
	
		
			5 Commits
		
	
	
		
			v0.101.23-
			...
			v0.100.7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f518043d8d | ||
| 
						 | 
					cc2335558d | ||
| 
						 | 
					a8a171ba2c | ||
| 
						 | 
					24a63f477e | ||
| 
						 | 
					ddeb6293a1 | 
@@ -1,7 +0,0 @@
 | 
				
			|||||||
COMPOSE_PROJECT_NAME=trmm
 | 
					 | 
				
			||||||
IMAGE_REPO=tacticalrmm/
 | 
					 | 
				
			||||||
VERSION=latest
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# DEV SETTINGS
 | 
					 | 
				
			||||||
APP_PORT=443
 | 
					 | 
				
			||||||
DOCKER_NETWORK=172.21.0.0/24
 | 
					 | 
				
			||||||
@@ -1,26 +0,0 @@
 | 
				
			|||||||
version: '3.4'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
services:
 | 
					 | 
				
			||||||
  app-dev:
 | 
					 | 
				
			||||||
    container_name: trmm-app-dev
 | 
					 | 
				
			||||||
    image: node:16-alpine
 | 
					 | 
				
			||||||
    restart: always
 | 
					 | 
				
			||||||
    command: /bin/sh -c "npm install --cache ~/.npm && npm run serve"
 | 
					 | 
				
			||||||
    user: 1000:1000
 | 
					 | 
				
			||||||
    working_dir: /workspace/web
 | 
					 | 
				
			||||||
    volumes:
 | 
					 | 
				
			||||||
      - ..:/workspace:cached
 | 
					 | 
				
			||||||
    ports:
 | 
					 | 
				
			||||||
      - "8080:443"
 | 
					 | 
				
			||||||
    networks:
 | 
					 | 
				
			||||||
      dev:
 | 
					 | 
				
			||||||
        aliases:
 | 
					 | 
				
			||||||
          - tactical-frontend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
networks:
 | 
					 | 
				
			||||||
  dev:
 | 
					 | 
				
			||||||
    driver: bridge
 | 
					 | 
				
			||||||
    ipam:
 | 
					 | 
				
			||||||
      driver: default
 | 
					 | 
				
			||||||
      config:
 | 
					 | 
				
			||||||
        - subnet: ${DOCKER_NETWORK}
 | 
					 | 
				
			||||||
							
								
								
									
										3
									
								
								.github/workflows/build-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/build-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -15,7 +15,7 @@ jobs:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      - uses: actions/setup-node@v3
 | 
					      - uses: actions/setup-node@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          node-version: 18
 | 
					          node-version: 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - run: touch env-config.js
 | 
					      - run: touch env-config.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,3 +32,4 @@ jobs:
 | 
				
			|||||||
        uses: softprops/action-gh-release@v1
 | 
					        uses: softprops/action-gh-release@v1
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          files: trmm-web-${{github.ref_name}}.tar.gz
 | 
					          files: trmm-web-${{github.ref_name}}.tar.gz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -33,4 +33,3 @@ yarn-error.log*
 | 
				
			|||||||
*.sln
 | 
					*.sln
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.env
 | 
					.env
 | 
				
			||||||
/public/env-config.js
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
								
							@@ -5,7 +5,7 @@
 | 
				
			|||||||
    "esbenp.prettier-vscode",
 | 
					    "esbenp.prettier-vscode",
 | 
				
			||||||
    "editorconfig.editorconfig",
 | 
					    "editorconfig.editorconfig",
 | 
				
			||||||
    "vue.volar",
 | 
					    "vue.volar",
 | 
				
			||||||
    "wayou.vscode-todo-highlight"
 | 
					    "wayou.vscode-todo-highlight",
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "unwantedRecommendations": [
 | 
					  "unwantedRecommendations": [
 | 
				
			||||||
    "octref.vetur",
 | 
					    "octref.vetur",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@
 | 
				
			|||||||
  "editor.formatOnSave": true,
 | 
					  "editor.formatOnSave": true,
 | 
				
			||||||
  "[vue][javascript][typescript][javascriptreact]": {
 | 
					  "[vue][javascript][typescript][javascriptreact]": {
 | 
				
			||||||
    "editor.defaultFormatter": "esbenp.prettier-vscode",
 | 
					    "editor.defaultFormatter": "esbenp.prettier-vscode",
 | 
				
			||||||
    "editor.codeActionsOnSave": ["source.fixAll.eslint"]
 | 
					    "editor.codeActionsOnSave": ["source.fixAll.eslint"],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"],
 | 
					  "eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"],
 | 
				
			||||||
  "typescript.tsdk": "node_modules/typescript/lib",
 | 
					  "typescript.tsdk": "node_modules/typescript/lib",
 | 
				
			||||||
@@ -15,7 +15,7 @@
 | 
				
			|||||||
      "**/node_modules/": true,
 | 
					      "**/node_modules/": true,
 | 
				
			||||||
      "/node_modules/**": true,
 | 
					      "/node_modules/**": true,
 | 
				
			||||||
      "**/env/": true,
 | 
					      "**/env/": true,
 | 
				
			||||||
      "/env/**": true
 | 
					      "/env/**": true,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								index.html
									
									
									
									
									
								
							@@ -1,22 +1,24 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html>
 | 
					<html>
 | 
				
			||||||
  <head>
 | 
					 | 
				
			||||||
    <title><%= productName %></title>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <meta charset="utf-8" />
 | 
					<head>
 | 
				
			||||||
    <meta name="robots" content="noindex" />
 | 
					  <title>
 | 
				
			||||||
    <meta name="description" content="<%= productDescription %>" />
 | 
					    <%= productName %>
 | 
				
			||||||
    <meta name="format-detection" content="telephone=no" />
 | 
					  </title>
 | 
				
			||||||
    <meta name="msapplication-tap-highlight" content="no" />
 | 
					
 | 
				
			||||||
    <meta
 | 
					  <meta charset="utf-8" />
 | 
				
			||||||
      name="viewport"
 | 
					  <meta name="robots" content="noindex" />
 | 
				
			||||||
      content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>"
 | 
					  <meta name="description" content="<%= productDescription %>" />
 | 
				
			||||||
    />
 | 
					  <meta name="format-detection" content="telephone=no" />
 | 
				
			||||||
    <link rel="icon" type="image/ico" href="favicon.ico" />
 | 
					  <meta name="msapplication-tap-highlight" content="no" />
 | 
				
			||||||
    <script src="/env-config.js"></script>
 | 
					  <meta name="viewport"
 | 
				
			||||||
  </head>
 | 
					    content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>" />
 | 
				
			||||||
 | 
					  <link rel="icon" type="image/ico" href="favicon.ico" />
 | 
				
			||||||
 | 
					  <script src="/env-config.js"></script>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					  <!-- quasar:entry-point -->
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <body>
 | 
					 | 
				
			||||||
    <!-- quasar:entry-point -->
 | 
					 | 
				
			||||||
  </body>
 | 
					 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7706
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7706
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										46
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								package.json
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "web",
 | 
					  "name": "web",
 | 
				
			||||||
  "version": "0.101.23-dev",
 | 
					  "version": "0.100.7",
 | 
				
			||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "productName": "Tactical RMM",
 | 
					  "productName": "Tactical RMM",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
@@ -10,31 +10,31 @@
 | 
				
			|||||||
    "format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
 | 
					    "format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@quasar/extras": "1.16.4",
 | 
					    "@quasar/extras": "1.15.0",
 | 
				
			||||||
    "apexcharts": "3.41.0",
 | 
					    "apexcharts": "3.35.4",
 | 
				
			||||||
    "axios": "1.4.0",
 | 
					    "axios": "0.27.2",
 | 
				
			||||||
    "dotenv": "16.3.1",
 | 
					    "dotenv": "16.0.1",
 | 
				
			||||||
    "qrcode.vue": "3.4.0",
 | 
					    "qrcode.vue": "3.3.3",
 | 
				
			||||||
    "quasar": "2.12.1",
 | 
					    "quasar": "2.7.5",
 | 
				
			||||||
    "vue": "3.2.47",
 | 
					    "vue": "3.2.37",
 | 
				
			||||||
    "vue3-ace-editor": "2.2.2",
 | 
					    "vue3-ace-editor": "2.2.2",
 | 
				
			||||||
    "vue3-apexcharts": "1.4.1",
 | 
					    "vue3-apexcharts": "1.4.1",
 | 
				
			||||||
    "vuedraggable": "4.1.0",
 | 
					    "vuedraggable": "4.1.0",
 | 
				
			||||||
    "vue-router": "4.1.6",
 | 
					    "vue-router": "4.1.2",
 | 
				
			||||||
    "vuex": "4.1.0"
 | 
					    "vuex": "4.0.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@quasar/cli": "^2.2.1",
 | 
					    "@quasar/cli": "^1.3.2",
 | 
				
			||||||
    "@intlify/unplugin-vue-i18n": "^0.10.0",
 | 
					    "@intlify/vite-plugin-vue-i18n": "^5.0.1",
 | 
				
			||||||
    "@quasar/app-vite": "^1.4.3",
 | 
					    "@quasar/app-vite": "^1.0.5",
 | 
				
			||||||
    "@types/node": "^20.3.2",
 | 
					    "@types/node": "^18.6.1",
 | 
				
			||||||
    "@typescript-eslint/eslint-plugin": "^5.60.1",
 | 
					    "@typescript-eslint/eslint-plugin": "^5.30.5",
 | 
				
			||||||
    "@typescript-eslint/parser": "^5.60.1",
 | 
					    "@typescript-eslint/parser": "^5.30.5",
 | 
				
			||||||
    "autoprefixer": "10.4.14",
 | 
					    "autoprefixer": "^10.4.7",
 | 
				
			||||||
    "eslint": "8.43.0",
 | 
					    "eslint": "^8.20.0",
 | 
				
			||||||
    "eslint-config-prettier": "8.8.0",
 | 
					    "eslint-config-prettier": "^8.5.0",
 | 
				
			||||||
    "eslint-plugin-vue": "8.7.1",
 | 
					    "eslint-plugin-vue": "^8.5.0",
 | 
				
			||||||
    "prettier": "2.8.8",
 | 
					    "prettier": "^2.7.1",
 | 
				
			||||||
    "typescript": "5.1.6"
 | 
					    "typescript": "^4.7.4"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,18 +4,18 @@
 | 
				
			|||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  plugins: [
 | 
					  plugins: [
 | 
				
			||||||
    // https://github.com/postcss/autoprefixer
 | 
					    // https://github.com/postcss/autoprefixer
 | 
				
			||||||
    require("autoprefixer")({
 | 
					    require('autoprefixer')({
 | 
				
			||||||
      overrideBrowserslist: [
 | 
					      overrideBrowserslist: [
 | 
				
			||||||
        "last 4 Chrome versions",
 | 
					        'last 4 Chrome versions',
 | 
				
			||||||
        "last 4 Firefox versions",
 | 
					        'last 4 Firefox versions',
 | 
				
			||||||
        "last 4 Edge versions",
 | 
					        'last 4 Edge versions',
 | 
				
			||||||
        "last 4 Safari versions",
 | 
					        'last 4 Safari versions',
 | 
				
			||||||
        "last 4 Android versions",
 | 
					        'last 4 Android versions',
 | 
				
			||||||
        "last 4 ChromeAndroid versions",
 | 
					        'last 4 ChromeAndroid versions',
 | 
				
			||||||
        "last 4 FirefoxAndroid versions",
 | 
					        'last 4 FirefoxAndroid versions',
 | 
				
			||||||
        "last 4 iOS versions",
 | 
					        'last 4 iOS versions'
 | 
				
			||||||
      ],
 | 
					      ]
 | 
				
			||||||
    }),
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // https://github.com/elchininet/postcss-rtlcss
 | 
					    // https://github.com/elchininet/postcss-rtlcss
 | 
				
			||||||
    // If you want to support RTL css, then
 | 
					    // If you want to support RTL css, then
 | 
				
			||||||
@@ -23,5 +23,5 @@ module.exports = {
 | 
				
			|||||||
    // 2. optionally set quasar.config.js > framework > lang to an RTL language
 | 
					    // 2. optionally set quasar.config.js > framework > lang to an RTL language
 | 
				
			||||||
    // 3. uncomment the following line:
 | 
					    // 3. uncomment the following line:
 | 
				
			||||||
    // require('postcss-rtlcss')
 | 
					    // require('postcss-rtlcss')
 | 
				
			||||||
  ],
 | 
					  ]
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,9 +12,6 @@ export default {
 | 
				
			|||||||
body
 | 
					body
 | 
				
			||||||
  overflow-y: hidden
 | 
					  overflow-y: hidden
 | 
				
			||||||
 | 
					
 | 
				
			||||||
a
 | 
					 | 
				
			||||||
  color: #1976D2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.tbl-sticky
 | 
					.tbl-sticky
 | 
				
			||||||
  thead tr th
 | 
					  thead tr th
 | 
				
			||||||
    position: sticky
 | 
					    position: sticky
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,25 +12,6 @@ export async function fetchUsers(params = {}) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function resetPass(pass) {
 | 
					 | 
				
			||||||
  const payload = { password: pass };
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const { data } = await axios.put(`${baseUrl}/resetpw/`, payload);
 | 
					 | 
				
			||||||
    return data;
 | 
					 | 
				
			||||||
  } catch (e) {
 | 
					 | 
				
			||||||
    console.error(e);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function resetTwoFactor() {
 | 
					 | 
				
			||||||
  try {
 | 
					 | 
				
			||||||
    const { data } = await axios.put(`${baseUrl}/reset2fa/`);
 | 
					 | 
				
			||||||
    return data;
 | 
					 | 
				
			||||||
  } catch (e) {
 | 
					 | 
				
			||||||
    console.error(e);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// role api function
 | 
					// role api function
 | 
				
			||||||
export async function fetchRoles(params = {}) {
 | 
					export async function fetchRoles(params = {}) {
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,8 +232,3 @@ export async function removeAgentNote(pk) {
 | 
				
			|||||||
  const { data } = await axios.delete(`${baseUrl}/notes/${pk}/`);
 | 
					  const { data } = await axios.delete(`${baseUrl}/notes/${pk}/`);
 | 
				
			||||||
  return data;
 | 
					  return data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function wakeUpWOL(agent_id) {
 | 
					 | 
				
			||||||
  const { data } = await axios.post(`${baseUrl}/${agent_id}/wol/`);
 | 
					 | 
				
			||||||
  return data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,8 +38,3 @@ export async function runURLAction(payload) {
 | 
				
			|||||||
    console.error(e);
 | 
					    console.error(e);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function generateScript(payload) {
 | 
					 | 
				
			||||||
  const { data } = await axios.post(`${baseUrl}/openai/generate/`, payload);
 | 
					 | 
				
			||||||
  return data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -196,14 +196,6 @@
 | 
				
			|||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Linux</q-tooltip>
 | 
					              <q-tooltip>Linux</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
            <q-icon
 | 
					 | 
				
			||||||
              v-else-if="props.row.plat === 'darwin'"
 | 
					 | 
				
			||||||
              name="mdi-apple"
 | 
					 | 
				
			||||||
              size="sm"
 | 
					 | 
				
			||||||
              color="primary"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
              <q-tooltip>macOS</q-tooltip>
 | 
					 | 
				
			||||||
            </q-icon>
 | 
					 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <q-td key="checks-status" :props="props">
 | 
					          <q-td key="checks-status" :props="props">
 | 
				
			||||||
@@ -211,7 +203,7 @@
 | 
				
			|||||||
              v-if="props.row.maintenance_mode"
 | 
					              v-if="props.row.maintenance_mode"
 | 
				
			||||||
              name="construction"
 | 
					              name="construction"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_positive_color"
 | 
					              color="green"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Maintenance Mode Enabled</q-tooltip>
 | 
					              <q-tooltip>Maintenance Mode Enabled</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -219,7 +211,7 @@
 | 
				
			|||||||
              v-else-if="props.row.checks.failing > 0"
 | 
					              v-else-if="props.row.checks.failing > 0"
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="negative"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks failing</q-tooltip>
 | 
					              <q-tooltip>Checks failing</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -227,7 +219,7 @@
 | 
				
			|||||||
              v-else-if="props.row.checks.warning > 0"
 | 
					              v-else-if="props.row.checks.warning > 0"
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_warning_color"
 | 
					              color="warning"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks warning</q-tooltip>
 | 
					              <q-tooltip>Checks warning</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -235,7 +227,7 @@
 | 
				
			|||||||
              v-else-if="props.row.checks.info > 0"
 | 
					              v-else-if="props.row.checks.info > 0"
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_info_color"
 | 
					              color="info"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks info</q-tooltip>
 | 
					              <q-tooltip>Checks info</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -243,7 +235,7 @@
 | 
				
			|||||||
              v-else
 | 
					              v-else
 | 
				
			||||||
              name="fas fa-check-double"
 | 
					              name="fas fa-check-double"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_positive_color"
 | 
					              color="positive"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Checks passing</q-tooltip>
 | 
					              <q-tooltip>Checks passing</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -279,7 +271,7 @@
 | 
				
			|||||||
              @click="showPendingActionsModal(props.row)"
 | 
					              @click="showPendingActionsModal(props.row)"
 | 
				
			||||||
              name="far fa-clock"
 | 
					              name="far fa-clock"
 | 
				
			||||||
              size="1.4em"
 | 
					              size="1.4em"
 | 
				
			||||||
              :color="dash_warning_color"
 | 
					              color="warning"
 | 
				
			||||||
              class="cursor-pointer"
 | 
					              class="cursor-pointer"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip
 | 
					              <q-tooltip
 | 
				
			||||||
@@ -303,7 +295,7 @@
 | 
				
			|||||||
              v-if="props.row.status === 'overdue'"
 | 
					              v-if="props.row.status === 'overdue'"
 | 
				
			||||||
              name="fas fa-signal"
 | 
					              name="fas fa-signal"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="negative"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Agent overdue</q-tooltip>
 | 
					              <q-tooltip>Agent overdue</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -311,16 +303,11 @@
 | 
				
			|||||||
              v-else-if="props.row.status === 'offline'"
 | 
					              v-else-if="props.row.status === 'offline'"
 | 
				
			||||||
              name="fas fa-signal"
 | 
					              name="fas fa-signal"
 | 
				
			||||||
              size="1.2em"
 | 
					              size="1.2em"
 | 
				
			||||||
              :color="dash_warning_color"
 | 
					              color="warning"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Agent offline</q-tooltip>
 | 
					              <q-tooltip>Agent offline</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
            <q-icon
 | 
					            <q-icon v-else name="fas fa-signal" size="1.2em" color="positive">
 | 
				
			||||||
              v-else
 | 
					 | 
				
			||||||
              name="fas fa-signal"
 | 
					 | 
				
			||||||
              size="1.2em"
 | 
					 | 
				
			||||||
              :color="dash_positive_color"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
              <q-tooltip>Agent online</q-tooltip>
 | 
					              <q-tooltip>Agent online</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
@@ -369,23 +356,6 @@ export default {
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    filterTable(rows, terms, cols, cellValue) {
 | 
					    filterTable(rows, terms, cols, cellValue) {
 | 
				
			||||||
      const hiddenFields = [
 | 
					 | 
				
			||||||
        "version",
 | 
					 | 
				
			||||||
        "operating_system",
 | 
					 | 
				
			||||||
        "public_ip",
 | 
					 | 
				
			||||||
        "cpu_model",
 | 
					 | 
				
			||||||
        "graphics",
 | 
					 | 
				
			||||||
        "local_ips",
 | 
					 | 
				
			||||||
        "make_model",
 | 
					 | 
				
			||||||
        "physical_disks",
 | 
					 | 
				
			||||||
        "custom_fields",
 | 
					 | 
				
			||||||
        "serial_number",
 | 
					 | 
				
			||||||
      ];
 | 
					 | 
				
			||||||
      // quasar filter only does visible columns so this is a hack to add hidden columns we want to filter
 | 
					 | 
				
			||||||
      // originally I was modifying cols directly but this led to phantom colum so doing it this way now
 | 
					 | 
				
			||||||
      // https://github.com/amidaware/tacticalrmm/issues/1264
 | 
					 | 
				
			||||||
      const allColumns = [...cols, ...hiddenFields.map((field) => ({ field }))];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const lowerTerms = terms ? terms.toLowerCase() : "";
 | 
					      const lowerTerms = terms ? terms.toLowerCase() : "";
 | 
				
			||||||
      let advancedFilter = false;
 | 
					      let advancedFilter = false;
 | 
				
			||||||
      let availability = null;
 | 
					      let availability = null;
 | 
				
			||||||
@@ -438,12 +408,8 @@ export default {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Normal text filter
 | 
					        // Normal text filter
 | 
				
			||||||
        return allColumns.some((col) => {
 | 
					        return cols.some((col) => {
 | 
				
			||||||
          let valObj = cellValue(col, row);
 | 
					          const val = cellValue(col, row) + "";
 | 
				
			||||||
          if (Array.isArray(valObj)) {
 | 
					 | 
				
			||||||
            valObj = valObj.map((item) => (item.value ? item.value : item));
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          const val = valObj + "";
 | 
					 | 
				
			||||||
          const haystack =
 | 
					          const haystack =
 | 
				
			||||||
            val === "undefined" || val === "null" ? "" : val.toLowerCase();
 | 
					            val === "undefined" || val === "null" ? "" : val.toLowerCase();
 | 
				
			||||||
          return haystack.indexOf(search) !== -1;
 | 
					          return haystack.indexOf(search) !== -1;
 | 
				
			||||||
@@ -494,9 +460,7 @@ export default {
 | 
				
			|||||||
      const data = {
 | 
					      const data = {
 | 
				
			||||||
        [db_field]: !alert_action,
 | 
					        [db_field]: !alert_action,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      const alertColor = !alert_action
 | 
					      const alertColor = !alert_action ? "positive" : "info";
 | 
				
			||||||
        ? this.dash_positive_color
 | 
					 | 
				
			||||||
        : this.dash_info_color;
 | 
					 | 
				
			||||||
      this.$axios.put(`/agents/${agent.agent_id}/`, data).then(() => {
 | 
					      this.$axios.put(`/agents/${agent.agent_id}/`, data).then(() => {
 | 
				
			||||||
        this.$q.notify({
 | 
					        this.$q.notify({
 | 
				
			||||||
          color: alertColor,
 | 
					          color: alertColor,
 | 
				
			||||||
@@ -540,13 +504,7 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    ...mapState([
 | 
					    ...mapState(["tableHeight"]),
 | 
				
			||||||
      "tableHeight",
 | 
					 | 
				
			||||||
      "dash_info_color",
 | 
					 | 
				
			||||||
      "dash_positive_color",
 | 
					 | 
				
			||||||
      "dash_negative_color",
 | 
					 | 
				
			||||||
      "dash_warning_color",
 | 
					 | 
				
			||||||
    ]),
 | 
					 | 
				
			||||||
    agentDblClickAction() {
 | 
					    agentDblClickAction() {
 | 
				
			||||||
      return this.$store.state.agentDblClickAction;
 | 
					      return this.$store.state.agentDblClickAction;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@
 | 
				
			|||||||
    <q-badge v-if="alertsCount > 0" :color="badgeColor" floating transparent>{{
 | 
					    <q-badge v-if="alertsCount > 0" :color="badgeColor" floating transparent>{{
 | 
				
			||||||
      alertsCountText()
 | 
					      alertsCountText()
 | 
				
			||||||
    }}</q-badge>
 | 
					    }}</q-badge>
 | 
				
			||||||
    <q-menu :style="{ 'max-height': `${$q.screen.height - 100}px` }">
 | 
					    <q-menu style="max-height: 30vh">
 | 
				
			||||||
      <q-list separator>
 | 
					      <q-list separator>
 | 
				
			||||||
        <q-item v-if="alertsCount === 0">No New Alerts</q-item>
 | 
					        <q-item v-if="alertsCount === 0">No New Alerts</q-item>
 | 
				
			||||||
        <q-item v-for="alert in topAlerts" :key="alert.id">
 | 
					        <q-item v-for="alert in topAlerts" :key="alert.id">
 | 
				
			||||||
@@ -59,7 +59,6 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { mapState } from "vuex";
 | 
					 | 
				
			||||||
import mixins from "@/mixins/mixins";
 | 
					import mixins from "@/mixins/mixins";
 | 
				
			||||||
import AlertsOverview from "@/components/modals/alerts/AlertsOverview.vue";
 | 
					import AlertsOverview from "@/components/modals/alerts/AlertsOverview.vue";
 | 
				
			||||||
import { getTimeLapse } from "@/utils/format";
 | 
					import { getTimeLapse } from "@/utils/format";
 | 
				
			||||||
@@ -76,21 +75,19 @@ export default {
 | 
				
			|||||||
    return {
 | 
					    return {
 | 
				
			||||||
      alertsCount: 0,
 | 
					      alertsCount: 0,
 | 
				
			||||||
      topAlerts: [],
 | 
					      topAlerts: [],
 | 
				
			||||||
 | 
					      errorColor: "red",
 | 
				
			||||||
 | 
					      warningColor: "orange",
 | 
				
			||||||
 | 
					      infoColor: "blue",
 | 
				
			||||||
      poll: null,
 | 
					      poll: null,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    ...mapState([
 | 
					 | 
				
			||||||
      "dash_info_color",
 | 
					 | 
				
			||||||
      "dash_warning_color",
 | 
					 | 
				
			||||||
      "dash_negative_color",
 | 
					 | 
				
			||||||
    ]),
 | 
					 | 
				
			||||||
    badgeColor() {
 | 
					    badgeColor() {
 | 
				
			||||||
      const severities = this.topAlerts.map((alert) => alert.severity);
 | 
					      const severities = this.topAlerts.map((alert) => alert.severity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (severities.includes("error")) return this.dash_negative_color;
 | 
					      if (severities.includes("error")) return this.errorColor;
 | 
				
			||||||
      else if (severities.includes("warning")) return this.dash_warning_color;
 | 
					      else if (severities.includes("warning")) return this.warningColor;
 | 
				
			||||||
      else return this.dash_info_color;
 | 
					      else return this.infoColor;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
@@ -162,9 +159,9 @@ export default {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    alertIconColor(severity) {
 | 
					    alertIconColor(severity) {
 | 
				
			||||||
      if (severity === "error") return this.dash_negative_color;
 | 
					      if (severity === "error") return this.errorColor;
 | 
				
			||||||
      else if (severity === "warning") return this.dash_warning_color;
 | 
					      else if (severity === "warning") return this.warningColor;
 | 
				
			||||||
      else return this.dash_info_color;
 | 
					      else return this.infoColor;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    alertsCountText() {
 | 
					    alertsCountText() {
 | 
				
			||||||
      if (this.alertsCount > 99) return "99+";
 | 
					      if (this.alertsCount > 99) return "99+";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,75 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
  <q-dialog ref="dialogRef" @hide="onDialogHide">
 | 
					 | 
				
			||||||
    <q-card class="q-dialog-plugin" style="width: 60vw">
 | 
					 | 
				
			||||||
      <q-card-section class="row">
 | 
					 | 
				
			||||||
        <div class="col-3">New password:</div>
 | 
					 | 
				
			||||||
        <div class="col-9">
 | 
					 | 
				
			||||||
          <q-input
 | 
					 | 
				
			||||||
            outlined
 | 
					 | 
				
			||||||
            dense
 | 
					 | 
				
			||||||
            v-model="pass"
 | 
					 | 
				
			||||||
            :type="isPwd ? 'password' : 'text'"
 | 
					 | 
				
			||||||
            :rules="[(val) => !!val || '*Required']"
 | 
					 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
            <template v-slot:append>
 | 
					 | 
				
			||||||
              <q-icon
 | 
					 | 
				
			||||||
                :name="isPwd ? 'visibility_off' : 'visibility'"
 | 
					 | 
				
			||||||
                class="cursor-pointer"
 | 
					 | 
				
			||||||
                @click="isPwd = !isPwd"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
          </q-input>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="col-3">Confirm password:</div>
 | 
					 | 
				
			||||||
        <div class="col-9">
 | 
					 | 
				
			||||||
          <q-input
 | 
					 | 
				
			||||||
            outlined
 | 
					 | 
				
			||||||
            dense
 | 
					 | 
				
			||||||
            v-model="pass2"
 | 
					 | 
				
			||||||
            :type="isPwd ? 'password' : 'text'"
 | 
					 | 
				
			||||||
            :rules="[(val) => val === pass || 'Passwords do not match']"
 | 
					 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
            <template v-slot:append>
 | 
					 | 
				
			||||||
              <q-icon
 | 
					 | 
				
			||||||
                :name="isPwd ? 'visibility_off' : 'visibility'"
 | 
					 | 
				
			||||||
                class="cursor-pointer"
 | 
					 | 
				
			||||||
                @click="isPwd = !isPwd"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
          </q-input>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </q-card-section>
 | 
					 | 
				
			||||||
      <q-card-actions align="right">
 | 
					 | 
				
			||||||
        <q-btn
 | 
					 | 
				
			||||||
          color="primary"
 | 
					 | 
				
			||||||
          label="Reset"
 | 
					 | 
				
			||||||
          @click="onOKClick"
 | 
					 | 
				
			||||||
          :disable="!pass || pass !== pass2"
 | 
					 | 
				
			||||||
        />
 | 
					 | 
				
			||||||
        <q-btn color="negative" label="Cancel" @click="onDialogCancel" />
 | 
					 | 
				
			||||||
      </q-card-actions>
 | 
					 | 
				
			||||||
    </q-card>
 | 
					 | 
				
			||||||
  </q-dialog>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script setup>
 | 
					 | 
				
			||||||
import { ref } from "vue";
 | 
					 | 
				
			||||||
import { useDialogPluginComponent } from "quasar";
 | 
					 | 
				
			||||||
import { resetPass } from "@/api/accounts";
 | 
					 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const pass = ref("");
 | 
					 | 
				
			||||||
const pass2 = ref("");
 | 
					 | 
				
			||||||
const isPwd = ref(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
defineEmits([...useDialogPluginComponent.emits]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
 | 
					 | 
				
			||||||
  useDialogPluginComponent();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function onOKClick() {
 | 
					 | 
				
			||||||
  const ret = await resetPass(pass.value);
 | 
					 | 
				
			||||||
  notifySuccess(ret);
 | 
					 | 
				
			||||||
  onDialogOK();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
@@ -98,10 +98,6 @@
 | 
				
			|||||||
                v-model="localRole.can_reboot_agents"
 | 
					                v-model="localRole.can_reboot_agents"
 | 
				
			||||||
                label="Reboot Agents"
 | 
					                label="Reboot Agents"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
              <q-checkbox
 | 
					 | 
				
			||||||
                v-model="localRole.can_send_wol"
 | 
					 | 
				
			||||||
                label="Wake-Up (WoL) Agents"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
              <q-checkbox
 | 
					              <q-checkbox
 | 
				
			||||||
                v-model="localRole.can_install_agents"
 | 
					                v-model="localRole.can_install_agents"
 | 
				
			||||||
                label="Install Agents"
 | 
					                label="Install Agents"
 | 
				
			||||||
@@ -441,8 +437,8 @@ export default {
 | 
				
			|||||||
          can_run_scripts: false,
 | 
					          can_run_scripts: false,
 | 
				
			||||||
          can_run_bulk: false,
 | 
					          can_run_bulk: false,
 | 
				
			||||||
          can_manage_winsvcs: false,
 | 
					          can_manage_winsvcs: false,
 | 
				
			||||||
 | 
					          can_recover_agents: false,
 | 
				
			||||||
          can_list_agent_history: false,
 | 
					          can_list_agent_history: false,
 | 
				
			||||||
          can_send_wol: false,
 | 
					 | 
				
			||||||
          // software perms
 | 
					          // software perms
 | 
				
			||||||
          can_list_software: false,
 | 
					          can_list_software: false,
 | 
				
			||||||
          can_manage_software: false,
 | 
					          can_manage_software: false,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -146,13 +146,6 @@
 | 
				
			|||||||
      <q-item-section>Run Checks</q-item-section>
 | 
					      <q-item-section>Run Checks</q-item-section>
 | 
				
			||||||
    </q-item>
 | 
					    </q-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <q-item clickable v-close-popup @click="wakeUp(agent)">
 | 
					 | 
				
			||||||
      <q-item-section side>
 | 
					 | 
				
			||||||
        <q-icon size="xs" name="offline_bolt" />
 | 
					 | 
				
			||||||
      </q-item-section>
 | 
					 | 
				
			||||||
      <q-item-section>Wake-Up (WoL)</q-item-section>
 | 
					 | 
				
			||||||
    </q-item>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <q-item clickable>
 | 
					    <q-item clickable>
 | 
				
			||||||
      <q-item-section side>
 | 
					      <q-item-section side>
 | 
				
			||||||
        <q-icon size="xs" name="power_settings_new" />
 | 
					        <q-icon size="xs" name="power_settings_new" />
 | 
				
			||||||
@@ -217,7 +210,6 @@ import {
 | 
				
			|||||||
  removeAgent,
 | 
					  removeAgent,
 | 
				
			||||||
  runRemoteBackground,
 | 
					  runRemoteBackground,
 | 
				
			||||||
  runTakeControl,
 | 
					  runTakeControl,
 | 
				
			||||||
  wakeUpWOL,
 | 
					 | 
				
			||||||
} from "@/api/agents";
 | 
					} from "@/api/agents";
 | 
				
			||||||
import { runAgentUpdateScan, runAgentUpdateInstall } from "@/api/winupdates";
 | 
					import { runAgentUpdateScan, runAgentUpdateInstall } from "@/api/winupdates";
 | 
				
			||||||
import { runAgentChecks } from "@/api/checks";
 | 
					import { runAgentChecks } from "@/api/checks";
 | 
				
			||||||
@@ -378,15 +370,6 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function wakeUp(agent) {
 | 
					 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        const data = await wakeUpWOL(agent.agent_id);
 | 
					 | 
				
			||||||
        notifySuccess(data);
 | 
					 | 
				
			||||||
      } catch (e) {
 | 
					 | 
				
			||||||
        console.error(e);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function showRebootLaterModal(agent) {
 | 
					    function showRebootLaterModal(agent) {
 | 
				
			||||||
      $q.dialog({
 | 
					      $q.dialog({
 | 
				
			||||||
        component: RebootLater,
 | 
					        component: RebootLater,
 | 
				
			||||||
@@ -515,7 +498,6 @@ export default {
 | 
				
			|||||||
      showPolicyAdd,
 | 
					      showPolicyAdd,
 | 
				
			||||||
      showAgentRecovery,
 | 
					      showAgentRecovery,
 | 
				
			||||||
      pingAgent,
 | 
					      pingAgent,
 | 
				
			||||||
      wakeUp,
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -261,7 +261,7 @@
 | 
				
			|||||||
          <q-td v-else-if="props.row.task_result.status === 'passing'">
 | 
					          <q-td v-else-if="props.row.task_result.status === 'passing'">
 | 
				
			||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_positive_color"
 | 
					              color="positive"
 | 
				
			||||||
              name="check_circle"
 | 
					              name="check_circle"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Passing</q-tooltip>
 | 
					              <q-tooltip>Passing</q-tooltip>
 | 
				
			||||||
@@ -271,7 +271,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-if="props.row.alert_severity === 'info'"
 | 
					              v-if="props.row.alert_severity === 'info'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_info_color"
 | 
					              color="info"
 | 
				
			||||||
              name="info"
 | 
					              name="info"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Informational</q-tooltip>
 | 
					              <q-tooltip>Informational</q-tooltip>
 | 
				
			||||||
@@ -279,7 +279,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="props.row.alert_severity === 'warning'"
 | 
					              v-else-if="props.row.alert_severity === 'warning'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_warning_color"
 | 
					              color="warning"
 | 
				
			||||||
              name="warning"
 | 
					              name="warning"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Warning</q-tooltip>
 | 
					              <q-tooltip>Warning</q-tooltip>
 | 
				
			||||||
@@ -287,7 +287,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else
 | 
					              v-else
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="negative"
 | 
				
			||||||
              name="error"
 | 
					              name="error"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Error</q-tooltip>
 | 
					              <q-tooltip>Error</q-tooltip>
 | 
				
			||||||
@@ -418,10 +418,6 @@ export default {
 | 
				
			|||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
					    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
    const dash_info_color = computed(() => store.state.dash_info_color);
 | 
					 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup quasar
 | 
					    // setup quasar
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
@@ -556,10 +552,6 @@ export default {
 | 
				
			|||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      agentPlatform,
 | 
					      agentPlatform,
 | 
				
			||||||
      dash_info_color,
 | 
					 | 
				
			||||||
      dash_positive_color,
 | 
					 | 
				
			||||||
      dash_warning_color,
 | 
					 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,7 +301,7 @@
 | 
				
			|||||||
          <q-td v-else-if="props.row.check_result.status === 'passing'">
 | 
					          <q-td v-else-if="props.row.check_result.status === 'passing'">
 | 
				
			||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_positive_color"
 | 
					              color="positive"
 | 
				
			||||||
              name="check_circle"
 | 
					              name="check_circle"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Passing</q-tooltip>
 | 
					              <q-tooltip>Passing</q-tooltip>
 | 
				
			||||||
@@ -311,7 +311,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-if="getAlertSeverity(props.row) === 'info'"
 | 
					              v-if="getAlertSeverity(props.row) === 'info'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_info_color"
 | 
					              color="info"
 | 
				
			||||||
              name="info"
 | 
					              name="info"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Informational</q-tooltip>
 | 
					              <q-tooltip>Informational</q-tooltip>
 | 
				
			||||||
@@ -319,7 +319,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="getAlertSeverity(props.row) === 'warning'"
 | 
					              v-else-if="getAlertSeverity(props.row) === 'warning'"
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_warning_color"
 | 
					              color="warning"
 | 
				
			||||||
              name="warning"
 | 
					              name="warning"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Warning</q-tooltip>
 | 
					              <q-tooltip>Warning</q-tooltip>
 | 
				
			||||||
@@ -327,7 +327,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else
 | 
					              v-else
 | 
				
			||||||
              style="font-size: 1.3rem"
 | 
					              style="font-size: 1.3rem"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="negative"
 | 
				
			||||||
              name="error"
 | 
					              name="error"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Error</q-tooltip>
 | 
					              <q-tooltip>Error</q-tooltip>
 | 
				
			||||||
@@ -479,10 +479,6 @@ export default {
 | 
				
			|||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
					    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
    const dash_info_color = computed(() => store.state.dash_info_color);
 | 
					 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup quasar
 | 
					    // setup quasar
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
@@ -657,10 +653,6 @@ export default {
 | 
				
			|||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      agentPlatform,
 | 
					      agentPlatform,
 | 
				
			||||||
      dash_info_color,
 | 
					 | 
				
			||||||
      dash_positive_color,
 | 
					 | 
				
			||||||
      dash_warning_color,
 | 
					 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,7 +166,7 @@ export default {
 | 
				
			|||||||
          type: "textarea",
 | 
					          type: "textarea",
 | 
				
			||||||
          isValid: (val) => !!val,
 | 
					          isValid: (val) => !!val,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        style: "width: 90vw; max-width: 90vw",
 | 
					        style: "width: 30vw; max-width: 50vw;",
 | 
				
			||||||
        ok: { label: "Add" },
 | 
					        ok: { label: "Add" },
 | 
				
			||||||
        cancel: true,
 | 
					        cancel: true,
 | 
				
			||||||
      }).onOk(async () => {
 | 
					      }).onOk(async () => {
 | 
				
			||||||
@@ -193,7 +193,7 @@ export default {
 | 
				
			|||||||
          type: "textarea",
 | 
					          type: "textarea",
 | 
				
			||||||
          isValid: (val) => !!val,
 | 
					          isValid: (val) => !!val,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        style: "width: 90vw; max-width: 90vw",
 | 
					        style: "width: 30vw; max-width: 50vw;",
 | 
				
			||||||
        ok: { label: "Save" },
 | 
					        ok: { label: "Save" },
 | 
				
			||||||
        cancel: true,
 | 
					        cancel: true,
 | 
				
			||||||
      }).onOk(async (data) => {
 | 
					      }).onOk(async (data) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,33 +18,6 @@
 | 
				
			|||||||
        icon="refresh"
 | 
					        icon="refresh"
 | 
				
			||||||
        @click="refreshSummary"
 | 
					        @click="refreshSummary"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
      <q-icon
 | 
					 | 
				
			||||||
        v-if="summary.status === 'overdue'"
 | 
					 | 
				
			||||||
        name="fas fa-signal"
 | 
					 | 
				
			||||||
        size="1.2em"
 | 
					 | 
				
			||||||
        :color="dash_negative_color"
 | 
					 | 
				
			||||||
        class="q-mr-sm"
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <q-tooltip>Agent overdue</q-tooltip>
 | 
					 | 
				
			||||||
      </q-icon>
 | 
					 | 
				
			||||||
      <q-icon
 | 
					 | 
				
			||||||
        v-else-if="summary.status === 'offline'"
 | 
					 | 
				
			||||||
        name="fas fa-signal"
 | 
					 | 
				
			||||||
        size="1.2em"
 | 
					 | 
				
			||||||
        :color="dash_warning_color"
 | 
					 | 
				
			||||||
        class="q-mr-sm"
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <q-tooltip>Agent offline</q-tooltip>
 | 
					 | 
				
			||||||
      </q-icon>
 | 
					 | 
				
			||||||
      <q-icon
 | 
					 | 
				
			||||||
        v-else
 | 
					 | 
				
			||||||
        name="fas fa-signal"
 | 
					 | 
				
			||||||
        size="1.2em"
 | 
					 | 
				
			||||||
        :color="dash_positive_color"
 | 
					 | 
				
			||||||
        class="q-mr-sm"
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <q-tooltip>Agent online</q-tooltip>
 | 
					 | 
				
			||||||
      </q-icon>
 | 
					 | 
				
			||||||
      <b>{{ summary.hostname }}</b>
 | 
					      <b>{{ summary.hostname }}</b>
 | 
				
			||||||
      <span v-if="summary.maintenance_mode">
 | 
					      <span v-if="summary.maintenance_mode">
 | 
				
			||||||
        • <q-badge color="green"> Maintenance Mode </q-badge>
 | 
					        • <q-badge color="green"> Maintenance Mode </q-badge>
 | 
				
			||||||
@@ -87,7 +60,7 @@
 | 
				
			|||||||
            </q-item-section>
 | 
					            </q-item-section>
 | 
				
			||||||
            <q-item-section>{{ summary.make_model }}</q-item-section>
 | 
					            <q-item-section>{{ summary.make_model }}</q-item-section>
 | 
				
			||||||
          </q-item>
 | 
					          </q-item>
 | 
				
			||||||
          <q-item>
 | 
					          <q-item v-for="(cpu, i) in summary.cpu_model" :key="cpu + i">
 | 
				
			||||||
            <q-item-section avatar>
 | 
					            <q-item-section avatar>
 | 
				
			||||||
              <q-icon name="fas fa-microchip" />
 | 
					              <q-icon name="fas fa-microchip" />
 | 
				
			||||||
            </q-item-section>
 | 
					            </q-item-section>
 | 
				
			||||||
@@ -114,13 +87,6 @@
 | 
				
			|||||||
            </q-item-section>
 | 
					            </q-item-section>
 | 
				
			||||||
            <q-item-section>{{ summary.graphics }}</q-item-section>
 | 
					            <q-item-section>{{ summary.graphics }}</q-item-section>
 | 
				
			||||||
          </q-item>
 | 
					          </q-item>
 | 
				
			||||||
          <!-- serial -->
 | 
					 | 
				
			||||||
          <q-item v-if="serial_number">
 | 
					 | 
				
			||||||
            <q-item-section avatar>
 | 
					 | 
				
			||||||
              <q-icon name="fa-solid fa-barcode" />
 | 
					 | 
				
			||||||
            </q-item-section>
 | 
					 | 
				
			||||||
            <q-item-section>{{ serial_number }}</q-item-section>
 | 
					 | 
				
			||||||
          </q-item>
 | 
					 | 
				
			||||||
          <q-item>
 | 
					          <q-item>
 | 
				
			||||||
            <q-item-section avatar>
 | 
					            <q-item-section avatar>
 | 
				
			||||||
              <q-icon name="fas fa-globe-americas" />
 | 
					              <q-icon name="fas fa-globe-americas" />
 | 
				
			||||||
@@ -144,7 +110,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="done"
 | 
					              icon="done"
 | 
				
			||||||
              :color="dash_positive_color"
 | 
					              color="green"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.passing }} checks passing</small>
 | 
					            <small>{{ summary.checks.passing }} checks passing</small>
 | 
				
			||||||
@@ -154,7 +120,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="cancel"
 | 
					              icon="cancel"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="red"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.failing }} checks failing</small>
 | 
					            <small>{{ summary.checks.failing }} checks failing</small>
 | 
				
			||||||
@@ -164,7 +130,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="warning"
 | 
					              icon="warning"
 | 
				
			||||||
              :color="dash_warning_color"
 | 
					              color="warning"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.warning }} checks warning</small>
 | 
					            <small>{{ summary.checks.warning }} checks warning</small>
 | 
				
			||||||
@@ -174,7 +140,7 @@
 | 
				
			|||||||
              size="lg"
 | 
					              size="lg"
 | 
				
			||||||
              square
 | 
					              square
 | 
				
			||||||
              icon="info"
 | 
					              icon="info"
 | 
				
			||||||
              :color="dash_info_color"
 | 
					              color="info"
 | 
				
			||||||
              text-color="white"
 | 
					              text-color="white"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <small>{{ summary.checks.info }} checks info</small>
 | 
					            <small>{{ summary.checks.info }} checks info</small>
 | 
				
			||||||
@@ -192,20 +158,6 @@
 | 
				
			|||||||
          >
 | 
					          >
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-else>No checks</div>
 | 
					        <div v-else>No checks</div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
        <span
 | 
					 | 
				
			||||||
          v-if="customFields.length > 0"
 | 
					 | 
				
			||||||
          class="text-subtitle2 text-bold block q-mt-xl"
 | 
					 | 
				
			||||||
          >Custom Fields</span
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
        <q-list dense>
 | 
					 | 
				
			||||||
          <q-item v-for="(field, i) in customFields" :key="field + i">
 | 
					 | 
				
			||||||
            <q-item-section thumbnail>
 | 
					 | 
				
			||||||
              <q-icon name="fas fa-user" size="xs" />
 | 
					 | 
				
			||||||
            </q-item-section>
 | 
					 | 
				
			||||||
            <q-item-section>{{ field.name }}: {{ field.value }}</q-item-section>
 | 
					 | 
				
			||||||
          </q-item>
 | 
					 | 
				
			||||||
        </q-list>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="col-1"></div>
 | 
					      <div class="col-1"></div>
 | 
				
			||||||
      <!-- right -->
 | 
					      <!-- right -->
 | 
				
			||||||
@@ -241,7 +193,6 @@ import {
 | 
				
			|||||||
  openAgentWindow,
 | 
					  openAgentWindow,
 | 
				
			||||||
} from "@/api/agents";
 | 
					} from "@/api/agents";
 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
import { fetchCustomFields } from "@/api/core";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
import AgentActionMenu from "@/components/agents/AgentActionMenu.vue";
 | 
					import AgentActionMenu from "@/components/agents/AgentActionMenu.vue";
 | 
				
			||||||
@@ -256,34 +207,18 @@ export default {
 | 
				
			|||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
    const selectedAgent = computed(() => store.state.selectedRow);
 | 
					    const selectedAgent = computed(() => store.state.selectedRow);
 | 
				
			||||||
    const refreshSummaryTab = computed(() => store.state.refreshSummaryTab);
 | 
					    const refreshSummaryTab = computed(() => store.state.refreshSummaryTab);
 | 
				
			||||||
    const dash_info_color = computed(() => store.state.dash_info_color);
 | 
					 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // summary tab logic
 | 
					    // summary tab logic
 | 
				
			||||||
    const summary = ref(null);
 | 
					    const summary = ref(null);
 | 
				
			||||||
    const customFieldsDefinitions = ref(null);
 | 
					 | 
				
			||||||
    const loading = ref(false);
 | 
					    const loading = ref(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const serial_number = computed(() => {
 | 
					 | 
				
			||||||
      return summary.value.wmi_detail.bios?.[0]?.[0]?.SerialNumber;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const cpu = computed(() => {
 | 
					 | 
				
			||||||
      if (summary.value.cpu_model?.length > 1) {
 | 
					 | 
				
			||||||
        return `${summary.value.cpu_model.length}x ${summary.value.cpu_model[0]}`;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return summary.value.cpu_model[0];
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function diskBarColor(percent) {
 | 
					    function diskBarColor(percent) {
 | 
				
			||||||
      if (percent < 80) {
 | 
					      if (percent < 80) {
 | 
				
			||||||
        return dash_positive_color.value;
 | 
					        return "positive";
 | 
				
			||||||
      } else if (percent > 80 && percent < 95) {
 | 
					      } else if (percent > 80 && percent < 95) {
 | 
				
			||||||
        return dash_warning_color.value;
 | 
					        return "warning";
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        return dash_negative_color.value;
 | 
					        return "negative";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -301,37 +236,9 @@ export default {
 | 
				
			|||||||
      return ret;
 | 
					      return ret;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const customFields = computed(() => {
 | 
					 | 
				
			||||||
      if (!summary.value.custom_fields) {
 | 
					 | 
				
			||||||
        return [];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (!customFieldsDefinitions.value) {
 | 
					 | 
				
			||||||
        return [];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      const ret = [];
 | 
					 | 
				
			||||||
      for (const customField of summary.value.custom_fields) {
 | 
					 | 
				
			||||||
        const definition = customFieldsDefinitions.value.find(
 | 
					 | 
				
			||||||
          (def) => def.id === customField.field
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        if (
 | 
					 | 
				
			||||||
          definition &&
 | 
					 | 
				
			||||||
          !definition.hide_in_ui &&
 | 
					 | 
				
			||||||
          customField.value?.length > 0
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
          ret.push({
 | 
					 | 
				
			||||||
            name: definition.name,
 | 
					 | 
				
			||||||
            value: customField.value,
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return ret;
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async function getSummary() {
 | 
					    async function getSummary() {
 | 
				
			||||||
      loading.value = true;
 | 
					      loading.value = true;
 | 
				
			||||||
      summary.value = await fetchAgent(selectedAgent.value);
 | 
					      summary.value = await fetchAgent(selectedAgent.value);
 | 
				
			||||||
      customFieldsDefinitions.value = await fetchCustomFields();
 | 
					 | 
				
			||||||
      store.commit("setRefreshSummaryTab", false);
 | 
					      store.commit("setRefreshSummaryTab", false);
 | 
				
			||||||
      store.commit("setAgentPlatform", summary.value.plat);
 | 
					      store.commit("setAgentPlatform", summary.value.plat);
 | 
				
			||||||
      loading.value = false;
 | 
					      loading.value = false;
 | 
				
			||||||
@@ -339,7 +246,6 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    async function refreshSummary() {
 | 
					    async function refreshSummary() {
 | 
				
			||||||
      loading.value = true;
 | 
					      loading.value = true;
 | 
				
			||||||
      summary.value = await fetchAgent(selectedAgent.value);
 | 
					 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        const result = await refreshAgentWMI(selectedAgent.value);
 | 
					        const result = await refreshAgentWMI(selectedAgent.value);
 | 
				
			||||||
        await getSummary();
 | 
					        await getSummary();
 | 
				
			||||||
@@ -371,16 +277,9 @@ export default {
 | 
				
			|||||||
    return {
 | 
					    return {
 | 
				
			||||||
      // reactive data
 | 
					      // reactive data
 | 
				
			||||||
      summary,
 | 
					      summary,
 | 
				
			||||||
      customFields,
 | 
					 | 
				
			||||||
      loading,
 | 
					      loading,
 | 
				
			||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      disks,
 | 
					      disks,
 | 
				
			||||||
      dash_info_color,
 | 
					 | 
				
			||||||
      dash_positive_color,
 | 
					 | 
				
			||||||
      dash_warning_color,
 | 
					 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
      serial_number,
 | 
					 | 
				
			||||||
      cpu,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      getSummary,
 | 
					      getSummary,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,7 +128,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="props.row.action === 'ignore'"
 | 
					              v-else-if="props.row.action === 'ignore'"
 | 
				
			||||||
              name="fas fa-check"
 | 
					              name="fas fa-check"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="negative"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Ignore</q-tooltip>
 | 
					              <q-tooltip>Ignore</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -144,7 +144,7 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-if="props.row.installed"
 | 
					              v-if="props.row.installed"
 | 
				
			||||||
              name="fas fa-check"
 | 
					              name="fas fa-check"
 | 
				
			||||||
              :color="dash_positive_color"
 | 
					              color="positive"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Installed</q-tooltip>
 | 
					              <q-tooltip>Installed</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
@@ -158,15 +158,11 @@
 | 
				
			|||||||
            <q-icon
 | 
					            <q-icon
 | 
				
			||||||
              v-else-if="props.row.action == 'ignore'"
 | 
					              v-else-if="props.row.action == 'ignore'"
 | 
				
			||||||
              name="fas fa-ban"
 | 
					              name="fas fa-ban"
 | 
				
			||||||
              :color="dash_negative_color"
 | 
					              color="negative"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <q-tooltip>Ignored</q-tooltip>
 | 
					              <q-tooltip>Ignored</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
            <q-icon
 | 
					            <q-icon v-else name="fas fa-exclamation" color="warning">
 | 
				
			||||||
              v-else
 | 
					 | 
				
			||||||
              name="fas fa-exclamation"
 | 
					 | 
				
			||||||
              :color="dash_warning_color"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
              <q-tooltip>Missing</q-tooltip>
 | 
					              <q-tooltip>Missing</q-tooltip>
 | 
				
			||||||
            </q-icon>
 | 
					            </q-icon>
 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
@@ -255,9 +251,6 @@ export default {
 | 
				
			|||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
					    const agentPlatform = computed(() => store.state.agentPlatform);
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup quasar
 | 
					    // setup quasar
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
@@ -317,10 +310,9 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function showUpdateDetails(update) {
 | 
					    function showUpdateDetails(update) {
 | 
				
			||||||
      const color = $q.dark.isActive ? "white" : "";
 | 
					 | 
				
			||||||
      let support_urls = "";
 | 
					      let support_urls = "";
 | 
				
			||||||
      update.more_info_urls.forEach((u) => {
 | 
					      update.more_info_urls.forEach((u) => {
 | 
				
			||||||
        support_urls += `<a style='color: ${color}' href='${u}' target='_blank'>${u}</a><br/>`;
 | 
					        support_urls += `<a href='${u}' target='_blank'>${u}</a><br/>`;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      let cats = update.categories.join(", ");
 | 
					      let cats = update.categories.join(", ");
 | 
				
			||||||
      $q.dialog({
 | 
					      $q.dialog({
 | 
				
			||||||
@@ -355,9 +347,6 @@ export default {
 | 
				
			|||||||
      selectedAgent,
 | 
					      selectedAgent,
 | 
				
			||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      agentPlatform,
 | 
					      agentPlatform,
 | 
				
			||||||
      dash_positive_color,
 | 
					 | 
				
			||||||
      dash_warning_color,
 | 
					 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,17 +7,6 @@
 | 
				
			|||||||
          <q-badge color="primary" class="q-ml-sm text-caption">{{
 | 
					          <q-badge color="primary" class="q-ml-sm text-caption">{{
 | 
				
			||||||
            v
 | 
					            v
 | 
				
			||||||
          }}</q-badge>
 | 
					          }}</q-badge>
 | 
				
			||||||
          <q-btn
 | 
					 | 
				
			||||||
            v-if="!!v"
 | 
					 | 
				
			||||||
            size="sm"
 | 
					 | 
				
			||||||
            class="q-ml-xs"
 | 
					 | 
				
			||||||
            flat
 | 
					 | 
				
			||||||
            round
 | 
					 | 
				
			||||||
            icon="content_copy"
 | 
					 | 
				
			||||||
            @click="copyValueToClip(v)"
 | 
					 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
            <q-tooltip>Copy to Clipboard</q-tooltip>
 | 
					 | 
				
			||||||
          </q-btn>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <q-separator v-if="info.length > 1" />
 | 
					      <q-separator v-if="info.length > 1" />
 | 
				
			||||||
@@ -26,8 +15,6 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { copyToClipboard } from "quasar";
 | 
					 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					 | 
				
			||||||
// composition imports
 | 
					// composition imports
 | 
				
			||||||
import { computed } from "vue";
 | 
					import { computed } from "vue";
 | 
				
			||||||
import { useStore } from "vuex";
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
@@ -41,16 +28,9 @@ export default {
 | 
				
			|||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
    const tabHeight = computed(() => store.state.tabHeight);
 | 
					    const tabHeight = computed(() => store.state.tabHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function copyValueToClip(val) {
 | 
					 | 
				
			||||||
      copyToClipboard(val).then(() => {
 | 
					 | 
				
			||||||
        notifySuccess("Copied to clipboard");
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      tabHeight,
 | 
					      tabHeight,
 | 
				
			||||||
      uid,
 | 
					      uid,
 | 
				
			||||||
      copyValueToClip,
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -217,7 +217,6 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { mapState } from "vuex";
 | 
					 | 
				
			||||||
import mixins from "@/mixins/mixins";
 | 
					import mixins from "@/mixins/mixins";
 | 
				
			||||||
import PolicyStatus from "@/components/automation/modals/PolicyStatus.vue";
 | 
					import PolicyStatus from "@/components/automation/modals/PolicyStatus.vue";
 | 
				
			||||||
import DiskSpaceCheck from "@/components/checks/DiskSpaceCheck.vue";
 | 
					import DiskSpaceCheck from "@/components/checks/DiskSpaceCheck.vue";
 | 
				
			||||||
@@ -269,9 +268,6 @@ export default {
 | 
				
			|||||||
      if (newValue !== oldValue) this.getChecks();
 | 
					      if (newValue !== oldValue) this.getChecks();
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					 | 
				
			||||||
    ...mapState(["dash_positive_color", "dash_warning_color"]),
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    getChecks() {
 | 
					    getChecks() {
 | 
				
			||||||
      this.$q.loading.show();
 | 
					      this.$q.loading.show();
 | 
				
			||||||
@@ -299,9 +295,7 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      data.check_alert = true;
 | 
					      data.check_alert = true;
 | 
				
			||||||
      const act = !action ? "enabled" : "disabled";
 | 
					      const act = !action ? "enabled" : "disabled";
 | 
				
			||||||
      const color = !action
 | 
					      const color = !action ? "positive" : "warning";
 | 
				
			||||||
        ? this.dash_positive_color
 | 
					 | 
				
			||||||
        : this.dash_warning_color;
 | 
					 | 
				
			||||||
      this.$axios
 | 
					      this.$axios
 | 
				
			||||||
        .put(`/checks/${id}/`, data)
 | 
					        .put(`/checks/${id}/`, data)
 | 
				
			||||||
        .then(() => {
 | 
					        .then(() => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@
 | 
				
			|||||||
              <q-td v-if="props.row.status === 'passing'">
 | 
					              <q-td v-if="props.row.status === 'passing'">
 | 
				
			||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  :color="dash_positive_color"
 | 
					                  color="positive"
 | 
				
			||||||
                  name="check_circle"
 | 
					                  name="check_circle"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Passing</q-tooltip>
 | 
					                  <q-tooltip>Passing</q-tooltip>
 | 
				
			||||||
@@ -51,7 +51,7 @@
 | 
				
			|||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  v-if="props.row.alert_severity === 'info'"
 | 
					                  v-if="props.row.alert_severity === 'info'"
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  :color="dash_info_color"
 | 
					                  color="info"
 | 
				
			||||||
                  name="info"
 | 
					                  name="info"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Informational</q-tooltip>
 | 
					                  <q-tooltip>Informational</q-tooltip>
 | 
				
			||||||
@@ -59,7 +59,7 @@
 | 
				
			|||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  v-else-if="props.row.alert_severity === 'warning'"
 | 
					                  v-else-if="props.row.alert_severity === 'warning'"
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  :color="dash_warning_color"
 | 
					                  color="warning"
 | 
				
			||||||
                  name="warning"
 | 
					                  name="warning"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Warning</q-tooltip>
 | 
					                  <q-tooltip>Warning</q-tooltip>
 | 
				
			||||||
@@ -67,7 +67,7 @@
 | 
				
			|||||||
                <q-icon
 | 
					                <q-icon
 | 
				
			||||||
                  v-else
 | 
					                  v-else
 | 
				
			||||||
                  style="font-size: 1.3rem"
 | 
					                  style="font-size: 1.3rem"
 | 
				
			||||||
                  :color="dash_negative_color"
 | 
					                  color="negative"
 | 
				
			||||||
                  name="error"
 | 
					                  name="error"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  <q-tooltip>Error</q-tooltip>
 | 
					                  <q-tooltip>Error</q-tooltip>
 | 
				
			||||||
@@ -148,7 +148,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { computed } from "vue";
 | 
					import { computed } from "vue";
 | 
				
			||||||
import { useStore, mapState } from "vuex";
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
import ScriptOutput from "@/components/checks/ScriptOutput.vue";
 | 
					import ScriptOutput from "@/components/checks/ScriptOutput.vue";
 | 
				
			||||||
import EventLogCheckOutput from "@/components/checks/EventLogCheckOutput.vue";
 | 
					import EventLogCheckOutput from "@/components/checks/EventLogCheckOutput.vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -220,12 +220,6 @@ export default {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    ...mapState([
 | 
					 | 
				
			||||||
      "dash_info_color",
 | 
					 | 
				
			||||||
      "dash_positive_color",
 | 
					 | 
				
			||||||
      "dash_negative_color",
 | 
					 | 
				
			||||||
      "dash_warning_color",
 | 
					 | 
				
			||||||
    ]),
 | 
					 | 
				
			||||||
    title() {
 | 
					    title() {
 | 
				
			||||||
      return !!this.item.readable_desc
 | 
					      return !!this.item.readable_desc
 | 
				
			||||||
        ? this.item.readable_desc + " Status"
 | 
					        ? this.item.readable_desc + " Status"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,19 +39,6 @@
 | 
				
			|||||||
            new-value-mode="add"
 | 
					            new-value-mode="add"
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </q-card-section>
 | 
					        </q-card-section>
 | 
				
			||||||
        <q-card-section>
 | 
					 | 
				
			||||||
          <q-select
 | 
					 | 
				
			||||||
            dense
 | 
					 | 
				
			||||||
            :label="envVarsLabel"
 | 
					 | 
				
			||||||
            filled
 | 
					 | 
				
			||||||
            v-model="state.env_vars"
 | 
					 | 
				
			||||||
            use-input
 | 
					 | 
				
			||||||
            use-chips
 | 
					 | 
				
			||||||
            multiple
 | 
					 | 
				
			||||||
            hide-dropdown-icon
 | 
					 | 
				
			||||||
            new-value-mode="add"
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        </q-card-section>
 | 
					 | 
				
			||||||
        <q-card-section>
 | 
					        <q-card-section>
 | 
				
			||||||
          <tactical-dropdown
 | 
					          <tactical-dropdown
 | 
				
			||||||
            label="Informational return codes (press Enter after typing each code)"
 | 
					            label="Informational return codes (press Enter after typing each code)"
 | 
				
			||||||
@@ -128,7 +115,6 @@ import { useDialogPluginComponent } from "quasar";
 | 
				
			|||||||
import { useCheckModal } from "@/composables/checks";
 | 
					import { useCheckModal } from "@/composables/checks";
 | 
				
			||||||
import { useScriptDropdown } from "@/composables/scripts";
 | 
					import { useScriptDropdown } from "@/composables/scripts";
 | 
				
			||||||
import { validateRetcode } from "@/utils/validation";
 | 
					import { validateRetcode } from "@/utils/validation";
 | 
				
			||||||
import { envVarsLabel } from "@/constants/constants";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
 | 
					import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
 | 
				
			||||||
@@ -146,15 +132,10 @@ export default {
 | 
				
			|||||||
    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup script dropdown
 | 
					    // setup script dropdown
 | 
				
			||||||
    const {
 | 
					    const { script, scriptOptions, defaultTimeout, defaultArgs } =
 | 
				
			||||||
      script,
 | 
					      useScriptDropdown(props.check ? props.check.script : undefined, {
 | 
				
			||||||
      scriptOptions,
 | 
					        onMount: true,
 | 
				
			||||||
      defaultTimeout,
 | 
					      });
 | 
				
			||||||
      defaultArgs,
 | 
					 | 
				
			||||||
      defaultEnvVars,
 | 
					 | 
				
			||||||
    } = useScriptDropdown(props.check ? props.check.script : undefined, {
 | 
					 | 
				
			||||||
      onMount: true,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // check logic
 | 
					    // check logic
 | 
				
			||||||
    const { state, loading, submit, failOptions, severityOptions } =
 | 
					    const { state, loading, submit, failOptions, severityOptions } =
 | 
				
			||||||
@@ -164,7 +145,6 @@ export default {
 | 
				
			|||||||
          ...props.parent,
 | 
					          ...props.parent,
 | 
				
			||||||
          script,
 | 
					          script,
 | 
				
			||||||
          script_args: defaultArgs,
 | 
					          script_args: defaultArgs,
 | 
				
			||||||
          env_vars: defaultEnvVars,
 | 
					 | 
				
			||||||
          timeout: defaultTimeout,
 | 
					          timeout: defaultTimeout,
 | 
				
			||||||
          check_type: "script",
 | 
					          check_type: "script",
 | 
				
			||||||
          fails_b4_alert: 1,
 | 
					          fails_b4_alert: 1,
 | 
				
			||||||
@@ -183,7 +163,6 @@ export default {
 | 
				
			|||||||
      failOptions,
 | 
					      failOptions,
 | 
				
			||||||
      scriptOptions,
 | 
					      scriptOptions,
 | 
				
			||||||
      severityOptions,
 | 
					      severityOptions,
 | 
				
			||||||
      envVarsLabel,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      submit,
 | 
					      submit,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,7 +122,7 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        const result = props.APIKey
 | 
					        const result = props.APIKey
 | 
				
			||||||
          ? await editAPIKey(data.id, data)
 | 
					          ? await editAPIKey(data)
 | 
				
			||||||
          : await saveAPIKey(data);
 | 
					          : await saveAPIKey(data);
 | 
				
			||||||
        onDialogOK();
 | 
					        onDialogOK();
 | 
				
			||||||
        notifySuccess(result);
 | 
					        notifySuccess(result);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -208,7 +208,7 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // component lifecycle hooks
 | 
					    // component lifecycle hooks
 | 
				
			||||||
    onMounted(getAPIKeys);
 | 
					    onMounted(getAPIKeys());
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      // reactive data
 | 
					      // reactive data
 | 
				
			||||||
      keys,
 | 
					      keys,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -304,9 +304,6 @@ export default {
 | 
				
			|||||||
    // setup vuex
 | 
					    // setup vuex
 | 
				
			||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup dropdowns
 | 
					    // setup dropdowns
 | 
				
			||||||
    const { clientOptions, getClientOptions } = useClientDropdown();
 | 
					    const { clientOptions, getClientOptions } = useClientDropdown();
 | 
				
			||||||
@@ -384,18 +381,12 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function formatActionColor(action) {
 | 
					    function formatActionColor(action) {
 | 
				
			||||||
      switch (action.toLowerCase()) {
 | 
					      if (action === "add") return "success";
 | 
				
			||||||
        case "modify":
 | 
					      else if (action === "agent_install") return "success";
 | 
				
			||||||
          return dash_warning_color.value;
 | 
					      else if (action === "modify") return "warning";
 | 
				
			||||||
        case "add":
 | 
					      else if (action === "delete") return "negative";
 | 
				
			||||||
        case "agent_install":
 | 
					      else if (action === "failed_login") return "negative";
 | 
				
			||||||
          return dash_positive_color.value;
 | 
					      else return "primary";
 | 
				
			||||||
        case "delete":
 | 
					 | 
				
			||||||
        case "failed_login":
 | 
					 | 
				
			||||||
          return dash_negative_color.value;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
          return "primary";
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // watchers
 | 
					    // watchers
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,25 +68,25 @@
 | 
				
			|||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          :color="dash_info_color"
 | 
					          color="cyan"
 | 
				
			||||||
          val="info"
 | 
					          val="info"
 | 
				
			||||||
          label="Info"
 | 
					          label="Info"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          :color="dash_negative_color"
 | 
					          color="red"
 | 
				
			||||||
          val="critical"
 | 
					          val="critical"
 | 
				
			||||||
          label="Critical"
 | 
					          label="Critical"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          :color="dash_negative_color"
 | 
					          color="red"
 | 
				
			||||||
          val="error"
 | 
					          val="error"
 | 
				
			||||||
          label="Error"
 | 
					          label="Error"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
        <q-radio
 | 
					        <q-radio
 | 
				
			||||||
          v-model="logLevelFilter"
 | 
					          v-model="logLevelFilter"
 | 
				
			||||||
          :color="dash_warning_color"
 | 
					          color="yellow"
 | 
				
			||||||
          val="warning"
 | 
					          val="warning"
 | 
				
			||||||
          label="Warning"
 | 
					          label="Warning"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
@@ -109,7 +109,7 @@
 | 
				
			|||||||
      <template v-slot:top-row>
 | 
					      <template v-slot:top-row>
 | 
				
			||||||
        <q-tr v-if="Array.isArray(debugLog) && debugLog.length === 1000">
 | 
					        <q-tr v-if="Array.isArray(debugLog) && debugLog.length === 1000">
 | 
				
			||||||
          <q-td colspan="100%">
 | 
					          <q-td colspan="100%">
 | 
				
			||||||
            <q-icon name="warning" :color="dash_warning_color" />
 | 
					            <q-icon name="warning" color="warning" />
 | 
				
			||||||
            Results are limited to 1000 rows.
 | 
					            Results are limited to 1000 rows.
 | 
				
			||||||
          </q-td>
 | 
					          </q-td>
 | 
				
			||||||
        </q-tr>
 | 
					        </q-tr>
 | 
				
			||||||
@@ -203,10 +203,6 @@ export default {
 | 
				
			|||||||
    const store = useStore();
 | 
					    const store = useStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const formatDate = computed(() => store.getters.formatDate);
 | 
					    const formatDate = computed(() => store.getters.formatDate);
 | 
				
			||||||
    const dash_info_color = computed(() => store.state.dash_info_color);
 | 
					 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup dropdowns
 | 
					    // setup dropdowns
 | 
				
			||||||
    const { agentOptions, getAgentOptions } = useAgentDropdown();
 | 
					    const { agentOptions, getAgentOptions } = useAgentDropdown();
 | 
				
			||||||
@@ -265,10 +261,6 @@ export default {
 | 
				
			|||||||
      agentOptions,
 | 
					      agentOptions,
 | 
				
			||||||
      loading,
 | 
					      loading,
 | 
				
			||||||
      filter,
 | 
					      filter,
 | 
				
			||||||
      dash_info_color,
 | 
					 | 
				
			||||||
      dash_positive_color,
 | 
					 | 
				
			||||||
      dash_warning_color,
 | 
					 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      columns,
 | 
					      columns,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,13 +10,10 @@
 | 
				
			|||||||
      </q-card-actions>
 | 
					      </q-card-actions>
 | 
				
			||||||
    </q-card-section>
 | 
					    </q-card-section>
 | 
				
			||||||
    <q-card-section>
 | 
					    <q-card-section>
 | 
				
			||||||
      <p v-if="info.plat === 'windows'" class="text-subtitle1">
 | 
					      <p class="text-subtitle1">
 | 
				
			||||||
        Download the agent then run the following command from an elevated
 | 
					        Download the agent then run the following command from an elevated
 | 
				
			||||||
        command prompt on the device you want to add.
 | 
					        command prompt on the device you want to add.
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <p v-else-if="info.plat === 'darwin'" class="text-subtitle1">
 | 
					 | 
				
			||||||
        Run the following command from a terminal
 | 
					 | 
				
			||||||
      </p>
 | 
					 | 
				
			||||||
      <p>
 | 
					      <p>
 | 
				
			||||||
        <q-field outlined :color="$q.dark.isActive ? 'white' : 'black'">
 | 
					        <q-field outlined :color="$q.dark.isActive ? 'white' : 'black'">
 | 
				
			||||||
          <code>{{ info.data.cmd }}</code>
 | 
					          <code>{{ info.data.cmd }}</code>
 | 
				
			||||||
@@ -40,7 +37,7 @@
 | 
				
			|||||||
          </q-badge>
 | 
					          </q-badge>
 | 
				
			||||||
          <span>Do not popup any message boxes during install</span>
 | 
					          <span>Do not popup any message boxes during install</span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-if="info.plat === 'windows'" class="q-pa-xs q-gutter-xs">
 | 
					        <div class="q-pa-xs q-gutter-xs">
 | 
				
			||||||
          <q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
 | 
					          <q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
 | 
				
			||||||
            <code
 | 
					            <code
 | 
				
			||||||
              >-local-mesh "C:\\<some folder or
 | 
					              >-local-mesh "C:\\<some folder or
 | 
				
			||||||
@@ -49,7 +46,7 @@
 | 
				
			|||||||
          </q-badge>
 | 
					          </q-badge>
 | 
				
			||||||
          <span> To skip downloading the Mesh Agent during the install.</span>
 | 
					          <span> To skip downloading the Mesh Agent during the install.</span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-if="info.plat === 'windows'" class="q-pa-xs q-gutter-xs">
 | 
					        <div class="q-pa-xs q-gutter-xs">
 | 
				
			||||||
          <q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
 | 
					          <q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
 | 
				
			||||||
            <code
 | 
					            <code
 | 
				
			||||||
              >-meshdir "C:\Program Files\Your Company Name\Mesh Agent"</code
 | 
					              >-meshdir "C:\Program Files\Your Company Name\Mesh Agent"</code
 | 
				
			||||||
@@ -66,7 +63,7 @@
 | 
				
			|||||||
          </q-badge>
 | 
					          </q-badge>
 | 
				
			||||||
          <span>Don't install the mesh agent</span>
 | 
					          <span>Don't install the mesh agent</span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-if="info.plat === 'windows'" class="q-pa-xs q-gutter-xs">
 | 
					        <div class="q-pa-xs q-gutter-xs">
 | 
				
			||||||
          <q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
 | 
					          <q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
 | 
				
			||||||
            <code>-cert "C:\\<some folder or path>\\ca.pem"</code>
 | 
					            <code>-cert "C:\\<some folder or path>\\ca.pem"</code>
 | 
				
			||||||
          </q-badge>
 | 
					          </q-badge>
 | 
				
			||||||
@@ -90,12 +87,11 @@
 | 
				
			|||||||
        Note: the auth token above will be valid for {{ info.expires }} hours.
 | 
					        Note: the auth token above will be valid for {{ info.expires }} hours.
 | 
				
			||||||
      </p>
 | 
					      </p>
 | 
				
			||||||
      <q-btn
 | 
					      <q-btn
 | 
				
			||||||
        v-if="info.plat === 'windows'"
 | 
					 | 
				
			||||||
        type="a"
 | 
					        type="a"
 | 
				
			||||||
        :href="info.data.url"
 | 
					        :href="info.data.url"
 | 
				
			||||||
        color="primary"
 | 
					        color="primary"
 | 
				
			||||||
        label="Download Agent"
 | 
					        label="Download Agent"
 | 
				
			||||||
      ></q-btn>
 | 
					      />
 | 
				
			||||||
    </q-card-section>
 | 
					    </q-card-section>
 | 
				
			||||||
  </q-card>
 | 
					  </q-card>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,18 +102,6 @@
 | 
				
			|||||||
            new-value-mode="add"
 | 
					            new-value-mode="add"
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </q-card-section>
 | 
					        </q-card-section>
 | 
				
			||||||
        <q-card-section v-if="mode === 'script'" class="q-pt-none">
 | 
					 | 
				
			||||||
          <tactical-dropdown
 | 
					 | 
				
			||||||
            v-model="state.env_vars"
 | 
					 | 
				
			||||||
            :label="envVarsLabel"
 | 
					 | 
				
			||||||
            filled
 | 
					 | 
				
			||||||
            use-input
 | 
					 | 
				
			||||||
            multiple
 | 
					 | 
				
			||||||
            hide-dropdown-icon
 | 
					 | 
				
			||||||
            input-debounce="0"
 | 
					 | 
				
			||||||
            new-value-mode="add"
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        </q-card-section>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <q-card-section v-if="mode === 'command'">
 | 
					        <q-card-section v-if="mode === 'command'">
 | 
				
			||||||
          <p>Shell</p>
 | 
					          <p>Shell</p>
 | 
				
			||||||
@@ -220,7 +208,7 @@ import { runBulkAction } from "@/api/agents";
 | 
				
			|||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
import { cmdPlaceholder } from "@/composables/agents";
 | 
					import { cmdPlaceholder } from "@/composables/agents";
 | 
				
			||||||
import { removeExtraOptionCategories } from "@/utils/format";
 | 
					import { removeExtraOptionCategories } from "@/utils/format";
 | 
				
			||||||
import { envVarsLabel, runAsUserToolTip } from "@/constants/constants";
 | 
					import { runAsUserToolTip } from "@/constants/constants";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
 | 
					import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
 | 
				
			||||||
@@ -235,7 +223,6 @@ const monTypeOptions = [
 | 
				
			|||||||
const osTypeOptions = [
 | 
					const osTypeOptions = [
 | 
				
			||||||
  { label: "Windows", value: "windows" },
 | 
					  { label: "Windows", value: "windows" },
 | 
				
			||||||
  { label: "Linux", value: "linux" },
 | 
					  { label: "Linux", value: "linux" },
 | 
				
			||||||
  { label: "macOS", value: "darwin" },
 | 
					 | 
				
			||||||
  { label: "All", value: "all" },
 | 
					  { label: "All", value: "all" },
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -296,7 +283,6 @@ export default {
 | 
				
			|||||||
      scriptOptions,
 | 
					      scriptOptions,
 | 
				
			||||||
      defaultTimeout,
 | 
					      defaultTimeout,
 | 
				
			||||||
      defaultArgs,
 | 
					      defaultArgs,
 | 
				
			||||||
      defaultEnvVars,
 | 
					 | 
				
			||||||
      getScriptOptions,
 | 
					      getScriptOptions,
 | 
				
			||||||
    } = useScriptDropdown();
 | 
					    } = useScriptDropdown();
 | 
				
			||||||
    const { agents, agentOptions, getAgentOptions } = useAgentDropdown();
 | 
					    const { agents, agentOptions, getAgentOptions } = useAgentDropdown();
 | 
				
			||||||
@@ -320,7 +306,6 @@ export default {
 | 
				
			|||||||
      script,
 | 
					      script,
 | 
				
			||||||
      timeout: defaultTimeout,
 | 
					      timeout: defaultTimeout,
 | 
				
			||||||
      args: defaultArgs,
 | 
					      args: defaultArgs,
 | 
				
			||||||
      env_vars: defaultEnvVars,
 | 
					 | 
				
			||||||
      run_as_user: false,
 | 
					      run_as_user: false,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    const loading = ref(false);
 | 
					    const loading = ref(false);
 | 
				
			||||||
@@ -418,7 +403,6 @@ export default {
 | 
				
			|||||||
      targetOptions,
 | 
					      targetOptions,
 | 
				
			||||||
      patchModeOptions,
 | 
					      patchModeOptions,
 | 
				
			||||||
      runAsUserToolTip,
 | 
					      runAsUserToolTip,
 | 
				
			||||||
      envVarsLabel,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //computed
 | 
					      //computed
 | 
				
			||||||
      modalTitle,
 | 
					      modalTitle,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,7 +94,7 @@
 | 
				
			|||||||
                        class="q-pr-sm"
 | 
					                        class="q-pr-sm"
 | 
				
			||||||
                        name="fas fa-signal"
 | 
					                        name="fas fa-signal"
 | 
				
			||||||
                        size="1.2em"
 | 
					                        size="1.2em"
 | 
				
			||||||
                        :color="dash_warning_color"
 | 
					                        color="warning"
 | 
				
			||||||
                      />
 | 
					                      />
 | 
				
			||||||
                      Mark an agent as
 | 
					                      Mark an agent as
 | 
				
			||||||
                      <span class="text-weight-bold">offline</span> if it has
 | 
					                      <span class="text-weight-bold">offline</span> if it has
 | 
				
			||||||
@@ -120,7 +120,7 @@
 | 
				
			|||||||
                        class="q-pr-sm"
 | 
					                        class="q-pr-sm"
 | 
				
			||||||
                        name="fas fa-signal"
 | 
					                        name="fas fa-signal"
 | 
				
			||||||
                        size="1.2em"
 | 
					                        size="1.2em"
 | 
				
			||||||
                        :color="dash_negative_color"
 | 
					                        color="negative"
 | 
				
			||||||
                      />
 | 
					                      />
 | 
				
			||||||
                      Mark an agent as
 | 
					                      Mark an agent as
 | 
				
			||||||
                      <span class="text-weight-bold">overdue</span> if it has
 | 
					                      <span class="text-weight-bold">overdue</span> if it has
 | 
				
			||||||
@@ -373,7 +373,6 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
import { mapState } from "vuex";
 | 
					 | 
				
			||||||
import { useDialogPluginComponent } from "quasar";
 | 
					import { useDialogPluginComponent } from "quasar";
 | 
				
			||||||
import mixins from "@/mixins/mixins";
 | 
					import mixins from "@/mixins/mixins";
 | 
				
			||||||
import PatchPolicyForm from "@/components/modals/agents/PatchPolicyForm.vue";
 | 
					import PatchPolicyForm from "@/components/modals/agents/PatchPolicyForm.vue";
 | 
				
			||||||
@@ -466,51 +465,8 @@ export default {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    editAgent() {
 | 
					    editAgent() {
 | 
				
			||||||
      // TODO we need to fix the serializer to not send this stuff
 | 
					      delete this.agent.all_timezones;
 | 
				
			||||||
      const toRemove = [
 | 
					      delete this.agent.timezone;
 | 
				
			||||||
        "created_by",
 | 
					 | 
				
			||||||
        "created_time",
 | 
					 | 
				
			||||||
        "modified_by",
 | 
					 | 
				
			||||||
        "modified_time",
 | 
					 | 
				
			||||||
        "all_timezones",
 | 
					 | 
				
			||||||
        "timezone",
 | 
					 | 
				
			||||||
        "wmi_detail",
 | 
					 | 
				
			||||||
        "services",
 | 
					 | 
				
			||||||
        "status",
 | 
					 | 
				
			||||||
        "cpu_model",
 | 
					 | 
				
			||||||
        "local_ips",
 | 
					 | 
				
			||||||
        "make_model",
 | 
					 | 
				
			||||||
        "physical_disks",
 | 
					 | 
				
			||||||
        "graphics",
 | 
					 | 
				
			||||||
        "checks",
 | 
					 | 
				
			||||||
        "patches_last_installed",
 | 
					 | 
				
			||||||
        "last_seen",
 | 
					 | 
				
			||||||
        "applied_policies",
 | 
					 | 
				
			||||||
        "effective_patch_policy",
 | 
					 | 
				
			||||||
        "version",
 | 
					 | 
				
			||||||
        "operating_system",
 | 
					 | 
				
			||||||
        "plat",
 | 
					 | 
				
			||||||
        "goarch",
 | 
					 | 
				
			||||||
        "hostname",
 | 
					 | 
				
			||||||
        "public_ip",
 | 
					 | 
				
			||||||
        "total_ram",
 | 
					 | 
				
			||||||
        "disks",
 | 
					 | 
				
			||||||
        "boot_time",
 | 
					 | 
				
			||||||
        "logged_in_username",
 | 
					 | 
				
			||||||
        "last_logged_in_user",
 | 
					 | 
				
			||||||
        "needs_reboot",
 | 
					 | 
				
			||||||
        "choco_installed",
 | 
					 | 
				
			||||||
        "policy",
 | 
					 | 
				
			||||||
        "mesh_node_id",
 | 
					 | 
				
			||||||
        "block_policy_inheritance",
 | 
					 | 
				
			||||||
        "maintenance_mode",
 | 
					 | 
				
			||||||
        "alert_template",
 | 
					 | 
				
			||||||
        "client",
 | 
					 | 
				
			||||||
        "site_name",
 | 
					 | 
				
			||||||
      ];
 | 
					 | 
				
			||||||
      for (const elem of toRemove) {
 | 
					 | 
				
			||||||
        delete this.agent[elem];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // only send the timezone data if it has changed
 | 
					      // only send the timezone data if it has changed
 | 
				
			||||||
      // this way django will keep the db column as null and inherit from the global setting
 | 
					      // this way django will keep the db column as null and inherit from the global setting
 | 
				
			||||||
@@ -547,12 +503,9 @@ export default {
 | 
				
			|||||||
        else if (day === 0) result += "Sun, ";
 | 
					        else if (day === 0) result += "Sun, ";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return result.trimEnd(",");
 | 
					      return result.trimRight(",");
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					 | 
				
			||||||
    ...mapState(["dash_warning_color", "dash_negative_color"]),
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  mounted() {
 | 
					  mounted() {
 | 
				
			||||||
    // Get custom fields
 | 
					    // Get custom fields
 | 
				
			||||||
    this.getCustomFields("agent").then((r) => {
 | 
					    this.getCustomFields("agent").then((r) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,15 +52,6 @@
 | 
				
			|||||||
                goarch = GOARCH_AMD64;
 | 
					                goarch = GOARCH_AMD64;
 | 
				
			||||||
              "
 | 
					              "
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <q-radio
 | 
					 | 
				
			||||||
              v-model="agentOS"
 | 
					 | 
				
			||||||
              val="darwin"
 | 
					 | 
				
			||||||
              label="macOS"
 | 
					 | 
				
			||||||
              @update:model-value="
 | 
					 | 
				
			||||||
                installMethod = 'mac';
 | 
					 | 
				
			||||||
                goarch = GOARCH_AMD64;
 | 
					 | 
				
			||||||
              "
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </q-card-section>
 | 
					        </q-card-section>
 | 
				
			||||||
        <q-card-section>
 | 
					        <q-card-section>
 | 
				
			||||||
@@ -114,37 +105,37 @@
 | 
				
			|||||||
              v-model="goarch"
 | 
					              v-model="goarch"
 | 
				
			||||||
              :val="GOARCH_AMD64"
 | 
					              :val="GOARCH_AMD64"
 | 
				
			||||||
              label="64 bit"
 | 
					              label="64 bit"
 | 
				
			||||||
              v-show="agentOS === 'windows' || agentOS === 'linux'"
 | 
					              v-show="agentOS === 'windows'"
 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
            <q-radio
 | 
					 | 
				
			||||||
              v-model="goarch"
 | 
					 | 
				
			||||||
              :val="GOARCH_AMD64"
 | 
					 | 
				
			||||||
              label="Intel 64 bit"
 | 
					 | 
				
			||||||
              v-show="agentOS === 'darwin'"
 | 
					 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <q-radio
 | 
					            <q-radio
 | 
				
			||||||
              v-model="goarch"
 | 
					              v-model="goarch"
 | 
				
			||||||
              :val="GOARCH_i386"
 | 
					              :val="GOARCH_i386"
 | 
				
			||||||
              label="32 bit"
 | 
					              label="32 bit"
 | 
				
			||||||
              v-show="agentOS !== 'darwin'"
 | 
					              v-show="agentOS === 'windows'"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <q-radio
 | 
				
			||||||
 | 
					              v-model="goarch"
 | 
				
			||||||
 | 
					              :val="GOARCH_AMD64"
 | 
				
			||||||
 | 
					              label="64 bit"
 | 
				
			||||||
 | 
					              v-show="agentOS !== 'windows'"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <q-radio
 | 
				
			||||||
 | 
					              v-model="goarch"
 | 
				
			||||||
 | 
					              :val="GOARCH_i386"
 | 
				
			||||||
 | 
					              label="32 bit"
 | 
				
			||||||
 | 
					              v-show="agentOS !== 'windows'"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <q-radio
 | 
					            <q-radio
 | 
				
			||||||
              v-model="goarch"
 | 
					              v-model="goarch"
 | 
				
			||||||
              :val="GOARCH_ARM64"
 | 
					              :val="GOARCH_ARM64"
 | 
				
			||||||
              label="ARM 64 bit"
 | 
					              label="ARM 64 bit"
 | 
				
			||||||
              v-show="agentOS === 'linux'"
 | 
					              v-show="agentOS !== 'windows'"
 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
            <q-radio
 | 
					 | 
				
			||||||
              v-model="goarch"
 | 
					 | 
				
			||||||
              :val="GOARCH_ARM64"
 | 
					 | 
				
			||||||
              label="Apple Silicon (M1, M2)"
 | 
					 | 
				
			||||||
              v-show="agentOS === 'darwin'"
 | 
					 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <q-radio
 | 
					            <q-radio
 | 
				
			||||||
              v-model="goarch"
 | 
					              v-model="goarch"
 | 
				
			||||||
              :val="GOARCH_ARM32"
 | 
					              :val="GOARCH_ARM32"
 | 
				
			||||||
              label="ARM 32 bit (Rasp Pi)"
 | 
					              label="ARM 32 bit (Rasp Pi)"
 | 
				
			||||||
              v-show="agentOS === 'linux'"
 | 
					              v-show="agentOS !== 'windows'"
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </q-card-section>
 | 
					        </q-card-section>
 | 
				
			||||||
@@ -275,13 +266,12 @@ export default {
 | 
				
			|||||||
        plat: this.agentOS,
 | 
					        plat: this.agentOS,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (this.installMethod === "manual" || this.installMethod === "mac") {
 | 
					      if (this.installMethod === "manual") {
 | 
				
			||||||
        this.$axios.post("/agents/installer/", data).then((r) => {
 | 
					        this.$axios.post("/agents/installer/", data).then((r) => {
 | 
				
			||||||
          this.info = {
 | 
					          this.info = {
 | 
				
			||||||
            expires: this.expires,
 | 
					            expires: this.expires,
 | 
				
			||||||
            data: r.data,
 | 
					            data: r.data,
 | 
				
			||||||
            goarch: this.goarch,
 | 
					            goarch: this.goarch,
 | 
				
			||||||
            plat: this.agentOS,
 | 
					 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
          this.showAgentDownload = true;
 | 
					          this.showAgentDownload = true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
@@ -353,9 +343,6 @@ export default {
 | 
				
			|||||||
        case "bash":
 | 
					        case "bash":
 | 
				
			||||||
          text = "Download linux install script";
 | 
					          text = "Download linux install script";
 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
        case "mac":
 | 
					 | 
				
			||||||
          text = "Show installation instructions";
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return text;
 | 
					      return text;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,18 +77,6 @@
 | 
				
			|||||||
            new-value-mode="add"
 | 
					            new-value-mode="add"
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        </q-card-section>
 | 
					        </q-card-section>
 | 
				
			||||||
        <q-card-section>
 | 
					 | 
				
			||||||
          <tactical-dropdown
 | 
					 | 
				
			||||||
            v-model="state.env_vars"
 | 
					 | 
				
			||||||
            :label="envVarsLabel"
 | 
					 | 
				
			||||||
            filled
 | 
					 | 
				
			||||||
            use-input
 | 
					 | 
				
			||||||
            multiple
 | 
					 | 
				
			||||||
            hide-dropdown-icon
 | 
					 | 
				
			||||||
            input-debounce="0"
 | 
					 | 
				
			||||||
            new-value-mode="add"
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        </q-card-section>
 | 
					 | 
				
			||||||
        <q-card-section>
 | 
					        <q-card-section>
 | 
				
			||||||
          <q-option-group
 | 
					          <q-option-group
 | 
				
			||||||
            v-model="state.output"
 | 
					            v-model="state.output"
 | 
				
			||||||
@@ -190,7 +178,7 @@ import { useScriptDropdown } from "@/composables/scripts";
 | 
				
			|||||||
import { useCustomFieldDropdown } from "@/composables/core";
 | 
					import { useCustomFieldDropdown } from "@/composables/core";
 | 
				
			||||||
import { runScript } from "@/api/agents";
 | 
					import { runScript } from "@/api/agents";
 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
import { envVarsLabel, runAsUserToolTip } from "@/constants/constants";
 | 
					import { runAsUserToolTip } from "@/constants/constants";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  formatScriptSyntax,
 | 
					  formatScriptSyntax,
 | 
				
			||||||
  removeExtraOptionCategories,
 | 
					  removeExtraOptionCategories,
 | 
				
			||||||
@@ -221,18 +209,11 @@ export default {
 | 
				
			|||||||
    const { dialogRef, onDialogHide } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide } = useDialogPluginComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup dropdowns
 | 
					    // setup dropdowns
 | 
				
			||||||
    const {
 | 
					    const { script, scriptOptions, defaultTimeout, defaultArgs, syntax, link } =
 | 
				
			||||||
      script,
 | 
					      useScriptDropdown(props.script, {
 | 
				
			||||||
      scriptOptions,
 | 
					        onMount: true,
 | 
				
			||||||
      defaultTimeout,
 | 
					        filterByPlatform: props.agent.plat,
 | 
				
			||||||
      defaultArgs,
 | 
					      });
 | 
				
			||||||
      defaultEnvVars,
 | 
					 | 
				
			||||||
      syntax,
 | 
					 | 
				
			||||||
      link,
 | 
					 | 
				
			||||||
    } = useScriptDropdown(props.script, {
 | 
					 | 
				
			||||||
      onMount: true,
 | 
					 | 
				
			||||||
      filterByPlatform: props.agent.plat,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    const { customFieldOptions } = useCustomFieldDropdown({ onMount: true });
 | 
					    const { customFieldOptions } = useCustomFieldDropdown({ onMount: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // main run script functionaity
 | 
					    // main run script functionaity
 | 
				
			||||||
@@ -244,7 +225,6 @@ export default {
 | 
				
			|||||||
      save_all_output: false,
 | 
					      save_all_output: false,
 | 
				
			||||||
      script,
 | 
					      script,
 | 
				
			||||||
      args: defaultArgs,
 | 
					      args: defaultArgs,
 | 
				
			||||||
      env_vars: defaultEnvVars,
 | 
					 | 
				
			||||||
      timeout: defaultTimeout,
 | 
					      timeout: defaultTimeout,
 | 
				
			||||||
      run_as_user: false,
 | 
					      run_as_user: false,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -301,7 +281,6 @@ export default {
 | 
				
			|||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      outputOptions,
 | 
					      outputOptions,
 | 
				
			||||||
      runAsUserToolTip,
 | 
					      runAsUserToolTip,
 | 
				
			||||||
      envVarsLabel,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //methods
 | 
					      //methods
 | 
				
			||||||
      formatScriptSyntax,
 | 
					      formatScriptSyntax,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,20 +204,6 @@
 | 
				
			|||||||
                new-value-mode="add"
 | 
					                new-value-mode="add"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <q-select
 | 
					 | 
				
			||||||
                class="q-mb-sm"
 | 
					 | 
				
			||||||
                dense
 | 
					 | 
				
			||||||
                label="Failure action environment vars (press Enter after typing each key=value pair)"
 | 
					 | 
				
			||||||
                filled
 | 
					 | 
				
			||||||
                v-model="template.action_env_vars"
 | 
					 | 
				
			||||||
                use-input
 | 
					 | 
				
			||||||
                use-chips
 | 
					 | 
				
			||||||
                multiple
 | 
					 | 
				
			||||||
                hide-dropdown-icon
 | 
					 | 
				
			||||||
                input-debounce="0"
 | 
					 | 
				
			||||||
                new-value-mode="add"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <q-input
 | 
					              <q-input
 | 
				
			||||||
                class="q-mb-sm"
 | 
					                class="q-mb-sm"
 | 
				
			||||||
                label="Failure action timeout (seconds)"
 | 
					                label="Failure action timeout (seconds)"
 | 
				
			||||||
@@ -291,20 +277,6 @@
 | 
				
			|||||||
                new-value-mode="add"
 | 
					                new-value-mode="add"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <q-select
 | 
					 | 
				
			||||||
                class="q-mb-sm"
 | 
					 | 
				
			||||||
                dense
 | 
					 | 
				
			||||||
                label="Resolved action environment vars (press Enter after typing each key=value pair)"
 | 
					 | 
				
			||||||
                filled
 | 
					 | 
				
			||||||
                v-model="template.resolved_action_env_vars"
 | 
					 | 
				
			||||||
                use-input
 | 
					 | 
				
			||||||
                use-chips
 | 
					 | 
				
			||||||
                multiple
 | 
					 | 
				
			||||||
                hide-dropdown-icon
 | 
					 | 
				
			||||||
                input-debounce="0"
 | 
					 | 
				
			||||||
                new-value-mode="add"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <q-input
 | 
					              <q-input
 | 
				
			||||||
                class="q-mb-sm"
 | 
					                class="q-mb-sm"
 | 
				
			||||||
                label="Resolved action timeout (seconds)"
 | 
					                label="Resolved action timeout (seconds)"
 | 
				
			||||||
@@ -724,11 +696,9 @@ export default {
 | 
				
			|||||||
        is_active: true,
 | 
					        is_active: true,
 | 
				
			||||||
        action: null,
 | 
					        action: null,
 | 
				
			||||||
        action_args: [],
 | 
					        action_args: [],
 | 
				
			||||||
        action_env_vars: [],
 | 
					 | 
				
			||||||
        action_timeout: 15,
 | 
					        action_timeout: 15,
 | 
				
			||||||
        resolved_action: null,
 | 
					        resolved_action: null,
 | 
				
			||||||
        resolved_action_args: [],
 | 
					        resolved_action_args: [],
 | 
				
			||||||
        resolved_action_env_vars: [],
 | 
					 | 
				
			||||||
        resolved_action_timeout: 15,
 | 
					        resolved_action_timeout: 15,
 | 
				
			||||||
        email_recipients: [],
 | 
					        email_recipients: [],
 | 
				
			||||||
        email_from: "",
 | 
					        email_from: "",
 | 
				
			||||||
@@ -792,13 +762,11 @@ export default {
 | 
				
			|||||||
          (i) => i.value === this.template.action
 | 
					          (i) => i.value === this.template.action
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        this.template.action_args = script.args;
 | 
					        this.template.action_args = script.args;
 | 
				
			||||||
        this.template.action_env_vars = script.env_vars;
 | 
					 | 
				
			||||||
      } else if (type === "resolved") {
 | 
					      } else if (type === "resolved") {
 | 
				
			||||||
        const script = this.scriptOptions.find(
 | 
					        const script = this.scriptOptions.find(
 | 
				
			||||||
          (i) => i.value === this.template.resolved_action
 | 
					          (i) => i.value === this.template.resolved_action
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        this.template.resolved_action_args = script.args;
 | 
					        this.template.resolved_action_args = script.args;
 | 
				
			||||||
        this.template.resolved_action_env_vars = script.env_vars;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    toggleAddEmail() {
 | 
					    toggleAddEmail() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,6 @@
 | 
				
			|||||||
          <q-tab name="urlactions" label="URL Actions" />
 | 
					          <q-tab name="urlactions" label="URL Actions" />
 | 
				
			||||||
          <q-tab name="retention" label="Retention" />
 | 
					          <q-tab name="retention" label="Retention" />
 | 
				
			||||||
          <q-tab name="apikeys" label="API Keys" />
 | 
					          <q-tab name="apikeys" label="API Keys" />
 | 
				
			||||||
          <!-- <q-tab name="openai" label="Open AI" /> -->
 | 
					 | 
				
			||||||
        </q-tabs>
 | 
					        </q-tabs>
 | 
				
			||||||
      </template>
 | 
					      </template>
 | 
				
			||||||
      <template v-slot:after>
 | 
					      <template v-slot:after>
 | 
				
			||||||
@@ -509,49 +508,6 @@
 | 
				
			|||||||
              <q-tab-panel name="apikeys">
 | 
					              <q-tab-panel name="apikeys">
 | 
				
			||||||
                <APIKeysTable />
 | 
					                <APIKeysTable />
 | 
				
			||||||
              </q-tab-panel>
 | 
					              </q-tab-panel>
 | 
				
			||||||
 | 
					 | 
				
			||||||
              <!-- Open AI -->
 | 
					 | 
				
			||||||
              <!-- <q-tab-panel name="openai">
 | 
					 | 
				
			||||||
                <div class="text-subtitle2">Open AI</div>
 | 
					 | 
				
			||||||
                <q-separator />
 | 
					 | 
				
			||||||
                <q-card-section class="row">
 | 
					 | 
				
			||||||
                  <div class="col-4">API Key:</div>
 | 
					 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					 | 
				
			||||||
                  <q-input
 | 
					 | 
				
			||||||
                    dense
 | 
					 | 
				
			||||||
                    outlined
 | 
					 | 
				
			||||||
                    v-model="settings.open_ai_token"
 | 
					 | 
				
			||||||
                    class="col-6"
 | 
					 | 
				
			||||||
                  />
 | 
					 | 
				
			||||||
                </q-card-section>
 | 
					 | 
				
			||||||
                <q-card-section class="row">
 | 
					 | 
				
			||||||
                  <div class="col-4">Open AI Model:</div>
 | 
					 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					 | 
				
			||||||
                  <q-input
 | 
					 | 
				
			||||||
                    dense
 | 
					 | 
				
			||||||
                    outlined
 | 
					 | 
				
			||||||
                    v-model="settings.open_ai_model"
 | 
					 | 
				
			||||||
                    class="col-6"
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    <template v-slot:after>
 | 
					 | 
				
			||||||
                      <q-btn
 | 
					 | 
				
			||||||
                        round
 | 
					 | 
				
			||||||
                        dense
 | 
					 | 
				
			||||||
                        flat
 | 
					 | 
				
			||||||
                        icon="info"
 | 
					 | 
				
			||||||
                        size="sm"
 | 
					 | 
				
			||||||
                        @click="
 | 
					 | 
				
			||||||
                          openURL(
 | 
					 | 
				
			||||||
                            'https://platform.openai.com/docs/models/overview'
 | 
					 | 
				
			||||||
                          )
 | 
					 | 
				
			||||||
                        "
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                        <q-tooltip>Click to see available options</q-tooltip>
 | 
					 | 
				
			||||||
                      </q-btn>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                  </q-input>
 | 
					 | 
				
			||||||
                </q-card-section>
 | 
					 | 
				
			||||||
              </q-tab-panel> -->
 | 
					 | 
				
			||||||
            </q-tab-panels>
 | 
					            </q-tab-panels>
 | 
				
			||||||
          </q-scroll-area>
 | 
					          </q-scroll-area>
 | 
				
			||||||
          <q-card-section class="row items-center">
 | 
					          <q-card-section class="row items-center">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,98 +82,6 @@
 | 
				
			|||||||
                    class="col-4"
 | 
					                    class="col-4"
 | 
				
			||||||
                  />
 | 
					                  />
 | 
				
			||||||
                </q-card-section>
 | 
					                </q-card-section>
 | 
				
			||||||
                <q-card-section class="row">
 | 
					 | 
				
			||||||
                  <div class="col-2">Dashboard Info Color:</div>
 | 
					 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					 | 
				
			||||||
                  <q-input
 | 
					 | 
				
			||||||
                    outlined
 | 
					 | 
				
			||||||
                    dense
 | 
					 | 
				
			||||||
                    v-model="dash_info_color"
 | 
					 | 
				
			||||||
                    class="col-8"
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    <template v-slot:after>
 | 
					 | 
				
			||||||
                      <q-btn
 | 
					 | 
				
			||||||
                        round
 | 
					 | 
				
			||||||
                        dense
 | 
					 | 
				
			||||||
                        flat
 | 
					 | 
				
			||||||
                        size="sm"
 | 
					 | 
				
			||||||
                        icon="info"
 | 
					 | 
				
			||||||
                        @click="openURL(quasar_color_url)"
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                        <q-tooltip>Click to see color options</q-tooltip>
 | 
					 | 
				
			||||||
                      </q-btn>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                  </q-input>
 | 
					 | 
				
			||||||
                </q-card-section>
 | 
					 | 
				
			||||||
                <q-card-section class="row">
 | 
					 | 
				
			||||||
                  <div class="col-2">Dashboard Positive Color:</div>
 | 
					 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					 | 
				
			||||||
                  <q-input
 | 
					 | 
				
			||||||
                    outlined
 | 
					 | 
				
			||||||
                    dense
 | 
					 | 
				
			||||||
                    v-model="dash_positive_color"
 | 
					 | 
				
			||||||
                    class="col-8"
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    <template v-slot:after>
 | 
					 | 
				
			||||||
                      <q-btn
 | 
					 | 
				
			||||||
                        round
 | 
					 | 
				
			||||||
                        dense
 | 
					 | 
				
			||||||
                        flat
 | 
					 | 
				
			||||||
                        size="sm"
 | 
					 | 
				
			||||||
                        icon="info"
 | 
					 | 
				
			||||||
                        @click="openURL(quasar_color_url)"
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                        <q-tooltip>Click to see color options</q-tooltip>
 | 
					 | 
				
			||||||
                      </q-btn>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                  </q-input>
 | 
					 | 
				
			||||||
                </q-card-section>
 | 
					 | 
				
			||||||
                <q-card-section class="row">
 | 
					 | 
				
			||||||
                  <div class="col-2">Dashboard Negative Color:</div>
 | 
					 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					 | 
				
			||||||
                  <q-input
 | 
					 | 
				
			||||||
                    outlined
 | 
					 | 
				
			||||||
                    dense
 | 
					 | 
				
			||||||
                    v-model="dash_negative_color"
 | 
					 | 
				
			||||||
                    class="col-8"
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    <template v-slot:after>
 | 
					 | 
				
			||||||
                      <q-btn
 | 
					 | 
				
			||||||
                        round
 | 
					 | 
				
			||||||
                        dense
 | 
					 | 
				
			||||||
                        flat
 | 
					 | 
				
			||||||
                        size="sm"
 | 
					 | 
				
			||||||
                        icon="info"
 | 
					 | 
				
			||||||
                        @click="openURL(quasar_color_url)"
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                        <q-tooltip>Click to see color options</q-tooltip>
 | 
					 | 
				
			||||||
                      </q-btn>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                  </q-input>
 | 
					 | 
				
			||||||
                </q-card-section>
 | 
					 | 
				
			||||||
                <q-card-section class="row">
 | 
					 | 
				
			||||||
                  <div class="col-2">Dashboard Warning Color:</div>
 | 
					 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					 | 
				
			||||||
                  <q-input
 | 
					 | 
				
			||||||
                    outlined
 | 
					 | 
				
			||||||
                    dense
 | 
					 | 
				
			||||||
                    v-model="dash_warning_color"
 | 
					 | 
				
			||||||
                    class="col-8"
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    <template v-slot:after>
 | 
					 | 
				
			||||||
                      <q-btn
 | 
					 | 
				
			||||||
                        round
 | 
					 | 
				
			||||||
                        dense
 | 
					 | 
				
			||||||
                        flat
 | 
					 | 
				
			||||||
                        size="sm"
 | 
					 | 
				
			||||||
                        icon="info"
 | 
					 | 
				
			||||||
                        @click="openURL(quasar_color_url)"
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                        <q-tooltip>Click to see color options</q-tooltip>
 | 
					 | 
				
			||||||
                      </q-btn>
 | 
					 | 
				
			||||||
                    </template>
 | 
					 | 
				
			||||||
                  </q-input>
 | 
					 | 
				
			||||||
                </q-card-section>
 | 
					 | 
				
			||||||
                <q-card-section class="row">
 | 
					                <q-card-section class="row">
 | 
				
			||||||
                  <div class="col-2">Client Sort:</div>
 | 
					                  <div class="col-2">Client Sort:</div>
 | 
				
			||||||
                  <div class="col-2"></div>
 | 
					                  <div class="col-2"></div>
 | 
				
			||||||
@@ -248,14 +156,9 @@ export default {
 | 
				
			|||||||
      tab: "ui",
 | 
					      tab: "ui",
 | 
				
			||||||
      splitterModel: 20,
 | 
					      splitterModel: 20,
 | 
				
			||||||
      loading_bar_color: "",
 | 
					      loading_bar_color: "",
 | 
				
			||||||
      dash_info_color: "",
 | 
					 | 
				
			||||||
      dash_positive_color: "",
 | 
					 | 
				
			||||||
      dash_negative_color: "",
 | 
					 | 
				
			||||||
      dash_warning_color: "",
 | 
					 | 
				
			||||||
      urlActions: [],
 | 
					      urlActions: [],
 | 
				
			||||||
      clear_search_when_switching: true,
 | 
					      clear_search_when_switching: true,
 | 
				
			||||||
      date_format: "",
 | 
					      date_format: "",
 | 
				
			||||||
      quasar_color_url: "https://quasar.dev/style/color-palette",
 | 
					 | 
				
			||||||
      clientTreeSortOptions: [
 | 
					      clientTreeSortOptions: [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          label: "Sort alphabetically, moving failing clients to the top",
 | 
					          label: "Sort alphabetically, moving failing clients to the top",
 | 
				
			||||||
@@ -332,10 +235,6 @@ export default {
 | 
				
			|||||||
        this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
 | 
					        this.defaultAgentTblTab = r.data.default_agent_tbl_tab;
 | 
				
			||||||
        this.clientTreeSort = r.data.client_tree_sort;
 | 
					        this.clientTreeSort = r.data.client_tree_sort;
 | 
				
			||||||
        this.loading_bar_color = r.data.loading_bar_color;
 | 
					        this.loading_bar_color = r.data.loading_bar_color;
 | 
				
			||||||
        this.dash_info_color = r.data.dash_info_color;
 | 
					 | 
				
			||||||
        this.dash_positive_color = r.data.dash_positive_color;
 | 
					 | 
				
			||||||
        this.dash_negative_color = r.data.dash_negative_color;
 | 
					 | 
				
			||||||
        this.dash_warning_color = r.data.dash_warning_color;
 | 
					 | 
				
			||||||
        this.clear_search_when_switching = r.data.clear_search_when_switching;
 | 
					        this.clear_search_when_switching = r.data.clear_search_when_switching;
 | 
				
			||||||
        this.date_format = r.data.date_format;
 | 
					        this.date_format = r.data.date_format;
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -354,10 +253,6 @@ export default {
 | 
				
			|||||||
        default_agent_tbl_tab: this.defaultAgentTblTab,
 | 
					        default_agent_tbl_tab: this.defaultAgentTblTab,
 | 
				
			||||||
        client_tree_sort: this.clientTreeSort,
 | 
					        client_tree_sort: this.clientTreeSort,
 | 
				
			||||||
        loading_bar_color: this.loading_bar_color,
 | 
					        loading_bar_color: this.loading_bar_color,
 | 
				
			||||||
        dash_info_color: this.dash_info_color,
 | 
					 | 
				
			||||||
        dash_positive_color: this.dash_positive_color,
 | 
					 | 
				
			||||||
        dash_negative_color: this.dash_negative_color,
 | 
					 | 
				
			||||||
        dash_warning_color: this.dash_warning_color,
 | 
					 | 
				
			||||||
        clear_search_when_switching: this.clear_search_when_switching,
 | 
					        clear_search_when_switching: this.clear_search_when_switching,
 | 
				
			||||||
        date_format: this.date_format,
 | 
					        date_format: this.date_format,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,17 +11,7 @@
 | 
				
			|||||||
      :style="maximized ? '' : 'width: 90vw; max-width: 90vw'"
 | 
					      :style="maximized ? '' : 'width: 90vw; max-width: 90vw'"
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <q-bar>
 | 
					      <q-bar>
 | 
				
			||||||
        <span class="q-pr-sm">{{ title }}</span>
 | 
					        {{ title }}
 | 
				
			||||||
        <q-btn
 | 
					 | 
				
			||||||
          v-if="!script && openAIEnabled"
 | 
					 | 
				
			||||||
          size="xs"
 | 
					 | 
				
			||||||
          :disable="loading"
 | 
					 | 
				
			||||||
          dense
 | 
					 | 
				
			||||||
          label="Generate Script"
 | 
					 | 
				
			||||||
          color="primary"
 | 
					 | 
				
			||||||
          no-caps
 | 
					 | 
				
			||||||
          @click="generateScriptOpenAI"
 | 
					 | 
				
			||||||
        />
 | 
					 | 
				
			||||||
        <q-space />
 | 
					        <q-space />
 | 
				
			||||||
        <q-btn
 | 
					        <q-btn
 | 
				
			||||||
          dense
 | 
					          dense
 | 
				
			||||||
@@ -67,133 +57,105 @@
 | 
				
			|||||||
          ><br />Add one to get rid of this warning. Ignore if windows.
 | 
					          ><br />Add one to get rid of this warning. Ignore if windows.
 | 
				
			||||||
        </q-banner>
 | 
					        </q-banner>
 | 
				
			||||||
        <div class="row q-pa-sm">
 | 
					        <div class="row q-pa-sm">
 | 
				
			||||||
          <q-scroll-area
 | 
					          <div class="col-4 q-gutter-sm q-pr-sm">
 | 
				
			||||||
            :thumb-style="{
 | 
					            <q-input
 | 
				
			||||||
              right: '4px',
 | 
					              filled
 | 
				
			||||||
              borderRadius: '5px',
 | 
					              dense
 | 
				
			||||||
              width: '5px',
 | 
					              :readonly="readonly"
 | 
				
			||||||
              opacity: 0.75,
 | 
					              v-model="formScript.name"
 | 
				
			||||||
            }"
 | 
					              label="Name"
 | 
				
			||||||
            :bar-style="{
 | 
					              :rules="[(val) => !!val || '*Required']"
 | 
				
			||||||
              right: '2px',
 | 
					              hide-bottom-space
 | 
				
			||||||
              borderRadius: '9px',
 | 
					            />
 | 
				
			||||||
              width: '9px',
 | 
					            <q-input
 | 
				
			||||||
              opacity: 0.2,
 | 
					              filled
 | 
				
			||||||
            }"
 | 
					              dense
 | 
				
			||||||
            class="col-4 q-mb-none q-pb-none"
 | 
					              :readonly="readonly"
 | 
				
			||||||
            :style="{ height: `${maximized ? '82vh' : '64vh'}` }"
 | 
					              v-model="formScript.description"
 | 
				
			||||||
          >
 | 
					              label="Description"
 | 
				
			||||||
            <div class="q-gutter-sm q-pr-sm">
 | 
					            />
 | 
				
			||||||
              <q-input
 | 
					            <q-select
 | 
				
			||||||
                filled
 | 
					              :readonly="readonly"
 | 
				
			||||||
                dense
 | 
					              options-dense
 | 
				
			||||||
                :readonly="readonly"
 | 
					              filled
 | 
				
			||||||
                v-model="formScript.name"
 | 
					              dense
 | 
				
			||||||
                label="Name"
 | 
					              v-model="formScript.shell"
 | 
				
			||||||
                :rules="[(val) => !!val || '*Required']"
 | 
					              :options="shellOptions"
 | 
				
			||||||
                hide-bottom-space
 | 
					              emit-value
 | 
				
			||||||
              />
 | 
					              map-options
 | 
				
			||||||
              <q-input
 | 
					              label="Shell Type"
 | 
				
			||||||
                filled
 | 
					            />
 | 
				
			||||||
                dense
 | 
					            <tactical-dropdown
 | 
				
			||||||
                :readonly="readonly"
 | 
					              v-model="formScript.supported_platforms"
 | 
				
			||||||
                v-model="formScript.description"
 | 
					              :options="agentPlatformOptions"
 | 
				
			||||||
                label="Description"
 | 
					              label="Supported Platforms (All supported if blank)"
 | 
				
			||||||
              />
 | 
					              clearable
 | 
				
			||||||
              <q-select
 | 
					              mapOptions
 | 
				
			||||||
                :readonly="readonly"
 | 
					              filled
 | 
				
			||||||
                options-dense
 | 
					              multiple
 | 
				
			||||||
                filled
 | 
					              :readonly="readonly"
 | 
				
			||||||
                dense
 | 
					            />
 | 
				
			||||||
                v-model="formScript.shell"
 | 
					            <tactical-dropdown
 | 
				
			||||||
                :options="shellOptions"
 | 
					              filled
 | 
				
			||||||
                emit-value
 | 
					              v-model="formScript.category"
 | 
				
			||||||
                map-options
 | 
					              :options="categories"
 | 
				
			||||||
                label="Shell Type"
 | 
					              use-input
 | 
				
			||||||
              />
 | 
					              clearable
 | 
				
			||||||
              <tactical-dropdown
 | 
					              new-value-mode="add-unique"
 | 
				
			||||||
                v-model="formScript.supported_platforms"
 | 
					              filterable
 | 
				
			||||||
                :options="agentPlatformOptions"
 | 
					              label="Category"
 | 
				
			||||||
                label="Supported Platforms (All supported if blank)"
 | 
					              :readonly="readonly"
 | 
				
			||||||
                clearable
 | 
					              hide-bottom-space
 | 
				
			||||||
                mapOptions
 | 
					            />
 | 
				
			||||||
                filled
 | 
					            <tactical-dropdown
 | 
				
			||||||
                multiple
 | 
					              v-model="formScript.args"
 | 
				
			||||||
                :readonly="readonly"
 | 
					              label="Script Arguments (press Enter after typing each argument)"
 | 
				
			||||||
              />
 | 
					              filled
 | 
				
			||||||
              <tactical-dropdown
 | 
					              use-input
 | 
				
			||||||
                filled
 | 
					              multiple
 | 
				
			||||||
                v-model="formScript.category"
 | 
					              hide-dropdown-icon
 | 
				
			||||||
                :options="categories"
 | 
					              input-debounce="0"
 | 
				
			||||||
                use-input
 | 
					              new-value-mode="add"
 | 
				
			||||||
                clearable
 | 
					              :readonly="readonly"
 | 
				
			||||||
                new-value-mode="add-unique"
 | 
					            />
 | 
				
			||||||
                filterable
 | 
					            <q-input
 | 
				
			||||||
                label="Category"
 | 
					              type="number"
 | 
				
			||||||
                :readonly="readonly"
 | 
					              filled
 | 
				
			||||||
                hide-bottom-space
 | 
					              dense
 | 
				
			||||||
              />
 | 
					              :readonly="readonly"
 | 
				
			||||||
              <tactical-dropdown
 | 
					              v-model.number="formScript.default_timeout"
 | 
				
			||||||
                v-model="formScript.args"
 | 
					              label="Timeout (seconds)"
 | 
				
			||||||
                label="Script Arguments (press Enter after typing each argument)"
 | 
					              :rules="[(val) => val >= 5 || 'Minimum is 5']"
 | 
				
			||||||
                filled
 | 
					              hide-bottom-space
 | 
				
			||||||
                use-input
 | 
					            />
 | 
				
			||||||
                multiple
 | 
					            <q-checkbox
 | 
				
			||||||
                hide-dropdown-icon
 | 
					              v-model="formScript.run_as_user"
 | 
				
			||||||
                input-debounce="0"
 | 
					              label="Run As User (Windows only)"
 | 
				
			||||||
                new-value-mode="add"
 | 
					            >
 | 
				
			||||||
                :readonly="readonly"
 | 
					              <q-tooltip
 | 
				
			||||||
              />
 | 
					                >Setting this value on the script model will always override any
 | 
				
			||||||
              <tactical-dropdown
 | 
					                'Run As User' checkboxes in the UI and force this script to
 | 
				
			||||||
                v-model="formScript.env_vars"
 | 
					                always be run in the context of the logged in user. If no user
 | 
				
			||||||
                :label="envVarsLabel"
 | 
					                is logged in, the script will not run and an error will be
 | 
				
			||||||
                filled
 | 
					                returned. Not supported on Windows Server.
 | 
				
			||||||
                use-input
 | 
					              </q-tooltip>
 | 
				
			||||||
                multiple
 | 
					            </q-checkbox>
 | 
				
			||||||
                hide-dropdown-icon
 | 
					            <q-input
 | 
				
			||||||
                input-debounce="0"
 | 
					              label="Syntax"
 | 
				
			||||||
                new-value-mode="add"
 | 
					              type="textarea"
 | 
				
			||||||
                :readonly="readonly"
 | 
					              style="height: 150px; overflow-y: auto; resize: none"
 | 
				
			||||||
              />
 | 
					              v-model="formScript.syntax"
 | 
				
			||||||
              <q-input
 | 
					              dense
 | 
				
			||||||
                type="number"
 | 
					              filled
 | 
				
			||||||
                filled
 | 
					              :readonly="readonly"
 | 
				
			||||||
                dense
 | 
					            />
 | 
				
			||||||
                :readonly="readonly"
 | 
					          </div>
 | 
				
			||||||
                v-model.number="formScript.default_timeout"
 | 
					 | 
				
			||||||
                label="Timeout (seconds)"
 | 
					 | 
				
			||||||
                :rules="[(val) => val >= 5 || 'Minimum is 5']"
 | 
					 | 
				
			||||||
                hide-bottom-space
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
              <q-checkbox
 | 
					 | 
				
			||||||
                v-model="formScript.run_as_user"
 | 
					 | 
				
			||||||
                label="Run As User (Windows only)"
 | 
					 | 
				
			||||||
              >
 | 
					 | 
				
			||||||
                <q-tooltip
 | 
					 | 
				
			||||||
                  >Setting this value on the script model will always override
 | 
					 | 
				
			||||||
                  any 'Run As User' checkboxes in the UI and force this script
 | 
					 | 
				
			||||||
                  to always be run in the context of the logged in user. If no
 | 
					 | 
				
			||||||
                  user is logged in, the script will not run and an error will
 | 
					 | 
				
			||||||
                  be returned.
 | 
					 | 
				
			||||||
                </q-tooltip>
 | 
					 | 
				
			||||||
              </q-checkbox>
 | 
					 | 
				
			||||||
              <q-input
 | 
					 | 
				
			||||||
                label="Syntax"
 | 
					 | 
				
			||||||
                type="textarea"
 | 
					 | 
				
			||||||
                style="height: 150px; overflow-y: auto; resize: none"
 | 
					 | 
				
			||||||
                v-model="formScript.syntax"
 | 
					 | 
				
			||||||
                dense
 | 
					 | 
				
			||||||
                filled
 | 
					 | 
				
			||||||
                :readonly="readonly"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </q-scroll-area>
 | 
					 | 
				
			||||||
          <v-ace-editor
 | 
					          <v-ace-editor
 | 
				
			||||||
            v-model:value="formScript.script_body"
 | 
					            v-model:value="formScript.script_body"
 | 
				
			||||||
            class="col-8"
 | 
					            class="col-8"
 | 
				
			||||||
            :lang="lang"
 | 
					            :lang="lang"
 | 
				
			||||||
            :theme="$q.dark.isActive ? 'tomorrow_night_eighties' : 'tomorrow'"
 | 
					            :theme="$q.dark.isActive ? 'tomorrow_night_eighties' : 'tomorrow'"
 | 
				
			||||||
            :style="{ height: `${maximized ? '82vh' : '64vh'}` }"
 | 
					            :style="{ height: `${maximized ? '87vh' : '64vh'}` }"
 | 
				
			||||||
            wrap
 | 
					            wrap
 | 
				
			||||||
            :printMargin="false"
 | 
					            :printMargin="false"
 | 
				
			||||||
            :options="{ fontSize: '14px' }"
 | 
					            :options="{ fontSize: '14px' }"
 | 
				
			||||||
@@ -247,11 +209,9 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
// composable imports
 | 
					// composable imports
 | 
				
			||||||
import { ref, computed, onMounted } from "vue";
 | 
					import { ref, computed, onMounted } from "vue";
 | 
				
			||||||
import { useStore } from "vuex";
 | 
					 | 
				
			||||||
import { useQuasar, useDialogPluginComponent } from "quasar";
 | 
					import { useQuasar, useDialogPluginComponent } from "quasar";
 | 
				
			||||||
import { saveScript, editScript, downloadScript } from "@/api/scripts";
 | 
					import { saveScript, editScript, downloadScript } from "@/api/scripts";
 | 
				
			||||||
import { useAgentDropdown, agentPlatformOptions } from "@/composables/agents";
 | 
					import { useAgentDropdown, agentPlatformOptions } from "@/composables/agents";
 | 
				
			||||||
import { generateScript } from "@/api/core";
 | 
					 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
@@ -269,7 +229,6 @@ import "ace-builds/src-noconflict/theme-tomorrow";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// static data
 | 
					// static data
 | 
				
			||||||
import { shellOptions } from "@/composables/scripts";
 | 
					import { shellOptions } from "@/composables/scripts";
 | 
				
			||||||
import { envVarsLabel } from "@/constants/constants";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  name: "ScriptFormModal",
 | 
					  name: "ScriptFormModal",
 | 
				
			||||||
@@ -295,10 +254,6 @@ export default {
 | 
				
			|||||||
    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup store
 | 
					 | 
				
			||||||
    const store = useStore();
 | 
					 | 
				
			||||||
    const openAIEnabled = computed(() => store.state.openAIIntegrationEnabled);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // setup agent dropdown
 | 
					    // setup agent dropdown
 | 
				
			||||||
    const { agent, agentOptions, getAgentOptions } = useAgentDropdown();
 | 
					    const { agent, agentOptions, getAgentOptions } = useAgentDropdown();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -311,7 +266,6 @@ export default {
 | 
				
			|||||||
          args: [],
 | 
					          args: [],
 | 
				
			||||||
          script_body: "",
 | 
					          script_body: "",
 | 
				
			||||||
          run_as_user: false,
 | 
					          run_as_user: false,
 | 
				
			||||||
          env_vars: [],
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (props.clone) script.value.name = `(Copy) ${script.value.name}`;
 | 
					    if (props.clone) script.value.name = `(Copy) ${script.value.name}`;
 | 
				
			||||||
@@ -388,23 +342,6 @@ export default {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function generateScriptOpenAI() {
 | 
					 | 
				
			||||||
      $q.dialog({
 | 
					 | 
				
			||||||
        title: "Ask ChatGPT what you need!",
 | 
					 | 
				
			||||||
        prompt: {
 | 
					 | 
				
			||||||
          model: `${lang.value} code that `,
 | 
					 | 
				
			||||||
          type: "text",
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        cancel: true,
 | 
					 | 
				
			||||||
        persistent: true,
 | 
					 | 
				
			||||||
      }).onOk(async (data) => {
 | 
					 | 
				
			||||||
        const completion = await generateScript({
 | 
					 | 
				
			||||||
          prompt: data,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        script.value.script_body = completion;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // component life cycle hooks
 | 
					    // component life cycle hooks
 | 
				
			||||||
    onMounted(async () => {
 | 
					    onMounted(async () => {
 | 
				
			||||||
      agentLoading.value = true;
 | 
					      agentLoading.value = true;
 | 
				
			||||||
@@ -426,16 +363,13 @@ export default {
 | 
				
			|||||||
      // non-reactive data
 | 
					      // non-reactive data
 | 
				
			||||||
      shellOptions,
 | 
					      shellOptions,
 | 
				
			||||||
      agentPlatformOptions,
 | 
					      agentPlatformOptions,
 | 
				
			||||||
      envVarsLabel,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //computed
 | 
					      //computed
 | 
				
			||||||
      title,
 | 
					      title,
 | 
				
			||||||
      openAIEnabled,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //methods
 | 
					      //methods
 | 
				
			||||||
      submitForm,
 | 
					      submitForm,
 | 
				
			||||||
      openTestScriptModal,
 | 
					      openTestScriptModal,
 | 
				
			||||||
      generateScriptOpenAI,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // quasar dialog plugin
 | 
					      // quasar dialog plugin
 | 
				
			||||||
      dialogRef,
 | 
					      dialogRef,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -286,10 +286,15 @@
 | 
				
			|||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
        </q-tree>
 | 
					        </q-tree>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <tactical-table
 | 
					      <q-table
 | 
				
			||||||
        v-if="tableView"
 | 
					        v-if="tableView"
 | 
				
			||||||
        dense
 | 
					        dense
 | 
				
			||||||
 | 
					        :table-class="{
 | 
				
			||||||
 | 
					          'table-bgcolor': !$q.dark.isActive,
 | 
				
			||||||
 | 
					          'table-bgcolor-dark': $q.dark.isActive,
 | 
				
			||||||
 | 
					        }"
 | 
				
			||||||
        :style="{ 'max-height': `${$q.screen.height - 182}px` }"
 | 
					        :style="{ 'max-height': `${$q.screen.height - 182}px` }"
 | 
				
			||||||
 | 
					        class="tbl-sticky"
 | 
				
			||||||
        :rows="visibleScripts"
 | 
					        :rows="visibleScripts"
 | 
				
			||||||
        :columns="columns"
 | 
					        :columns="columns"
 | 
				
			||||||
        :loading="loading"
 | 
					        :loading="loading"
 | 
				
			||||||
@@ -299,7 +304,6 @@
 | 
				
			|||||||
        binary-state-sort
 | 
					        binary-state-sort
 | 
				
			||||||
        virtual-scroll
 | 
					        virtual-scroll
 | 
				
			||||||
        :rows-per-page-options="[0]"
 | 
					        :rows-per-page-options="[0]"
 | 
				
			||||||
        column-select
 | 
					 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        <template v-slot:header-cell-favorite="props">
 | 
					        <template v-slot:header-cell-favorite="props">
 | 
				
			||||||
          <q-th :props="props" auto-width>
 | 
					          <q-th :props="props" auto-width>
 | 
				
			||||||
@@ -421,7 +425,7 @@
 | 
				
			|||||||
              </q-list>
 | 
					              </q-list>
 | 
				
			||||||
            </q-menu>
 | 
					            </q-menu>
 | 
				
			||||||
            <!-- favorite -->
 | 
					            <!-- favorite -->
 | 
				
			||||||
            <q-td key="favorite" :props="props">
 | 
					            <q-td>
 | 
				
			||||||
              <q-icon
 | 
					              <q-icon
 | 
				
			||||||
                v-if="props.row.favorite"
 | 
					                v-if="props.row.favorite"
 | 
				
			||||||
                color="yellow-8"
 | 
					                color="yellow-8"
 | 
				
			||||||
@@ -430,7 +434,7 @@
 | 
				
			|||||||
              />
 | 
					              />
 | 
				
			||||||
            </q-td>
 | 
					            </q-td>
 | 
				
			||||||
            <!-- shell icon -->
 | 
					            <!-- shell icon -->
 | 
				
			||||||
            <q-td key="shell" :props="props">
 | 
					            <q-td>
 | 
				
			||||||
              <q-icon
 | 
					              <q-icon
 | 
				
			||||||
                v-if="props.row.shell === 'powershell'"
 | 
					                v-if="props.row.shell === 'powershell'"
 | 
				
			||||||
                name="mdi-powershell"
 | 
					                name="mdi-powershell"
 | 
				
			||||||
@@ -465,7 +469,7 @@
 | 
				
			|||||||
              </q-icon>
 | 
					              </q-icon>
 | 
				
			||||||
            </q-td>
 | 
					            </q-td>
 | 
				
			||||||
            <!-- supported platforms -->
 | 
					            <!-- supported platforms -->
 | 
				
			||||||
            <q-td key="supported_platforms" :props="props">
 | 
					            <q-td>
 | 
				
			||||||
              <q-badge
 | 
					              <q-badge
 | 
				
			||||||
                v-if="
 | 
					                v-if="
 | 
				
			||||||
                  !props.row.supported_platforms ||
 | 
					                  !props.row.supported_platforms ||
 | 
				
			||||||
@@ -483,11 +487,7 @@
 | 
				
			|||||||
              >
 | 
					              >
 | 
				
			||||||
            </q-td>
 | 
					            </q-td>
 | 
				
			||||||
            <!-- name -->
 | 
					            <!-- name -->
 | 
				
			||||||
            <q-td
 | 
					            <q-td :style="{ color: props.row.hidden ? 'grey' : '' }">
 | 
				
			||||||
              key="name"
 | 
					 | 
				
			||||||
              :props="props"
 | 
					 | 
				
			||||||
              :style="{ color: props.row.hidden ? 'grey' : '' }"
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
              {{ truncateText(props.row.name, 50) }}
 | 
					              {{ truncateText(props.row.name, 50) }}
 | 
				
			||||||
              <q-tooltip
 | 
					              <q-tooltip
 | 
				
			||||||
                v-if="props.row.name.length >= 50"
 | 
					                v-if="props.row.name.length >= 50"
 | 
				
			||||||
@@ -497,7 +497,7 @@
 | 
				
			|||||||
              </q-tooltip>
 | 
					              </q-tooltip>
 | 
				
			||||||
            </q-td>
 | 
					            </q-td>
 | 
				
			||||||
            <!-- args -->
 | 
					            <!-- args -->
 | 
				
			||||||
            <q-td key="args" :props="props">
 | 
					            <q-td>
 | 
				
			||||||
              <span v-if="props.row.args.length > 0">
 | 
					              <span v-if="props.row.args.length > 0">
 | 
				
			||||||
                {{ truncateText(props.row.args.toString(), 30) }}
 | 
					                {{ truncateText(props.row.args.toString(), 30) }}
 | 
				
			||||||
                <q-tooltip
 | 
					                <q-tooltip
 | 
				
			||||||
@@ -509,8 +509,8 @@
 | 
				
			|||||||
              </span>
 | 
					              </span>
 | 
				
			||||||
            </q-td>
 | 
					            </q-td>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <q-td key="category" :props="props">{{ props.row.category }}</q-td>
 | 
					            <q-td>{{ props.row.category }}</q-td>
 | 
				
			||||||
            <q-td key="desc" :props="props">
 | 
					            <q-td>
 | 
				
			||||||
              {{ truncateText(props.row.description, 30) }}
 | 
					              {{ truncateText(props.row.description, 30) }}
 | 
				
			||||||
              <q-tooltip
 | 
					              <q-tooltip
 | 
				
			||||||
                v-if="props.row.description.length >= 30"
 | 
					                v-if="props.row.description.length >= 30"
 | 
				
			||||||
@@ -518,13 +518,10 @@
 | 
				
			|||||||
                >{{ props.row.description }}</q-tooltip
 | 
					                >{{ props.row.description }}</q-tooltip
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
            </q-td>
 | 
					            </q-td>
 | 
				
			||||||
            <q-td key="default_timeout" :props="props">{{
 | 
					            <q-td>{{ props.row.default_timeout }}</q-td>
 | 
				
			||||||
              props.row.default_timeout
 | 
					 | 
				
			||||||
            }}</q-td>
 | 
					 | 
				
			||||||
            <q-td></q-td>
 | 
					 | 
				
			||||||
          </q-tr>
 | 
					          </q-tr>
 | 
				
			||||||
        </template>
 | 
					        </template>
 | 
				
			||||||
      </tactical-table>
 | 
					      </q-table>
 | 
				
			||||||
    </q-card>
 | 
					    </q-card>
 | 
				
			||||||
  </q-dialog>
 | 
					  </q-dialog>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
@@ -548,13 +545,12 @@ import { notifySuccess } from "@/utils/notify";
 | 
				
			|||||||
import ScriptUploadModal from "@/components/scripts/ScriptUploadModal.vue";
 | 
					import ScriptUploadModal from "@/components/scripts/ScriptUploadModal.vue";
 | 
				
			||||||
import ScriptFormModal from "@/components/scripts/ScriptFormModal.vue";
 | 
					import ScriptFormModal from "@/components/scripts/ScriptFormModal.vue";
 | 
				
			||||||
import ScriptSnippets from "@/components/scripts/ScriptSnippets.vue";
 | 
					import ScriptSnippets from "@/components/scripts/ScriptSnippets.vue";
 | 
				
			||||||
import TacticalTable from "@/components/ui/TacticalTable.vue";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// static data
 | 
					// static data
 | 
				
			||||||
const columns = [
 | 
					const columns = [
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    name: "favorite",
 | 
					    name: "favorite",
 | 
				
			||||||
    label: "Favorites",
 | 
					    label: "",
 | 
				
			||||||
    field: "favorite",
 | 
					    field: "favorite",
 | 
				
			||||||
    align: "left",
 | 
					    align: "left",
 | 
				
			||||||
    sortable: true,
 | 
					    sortable: true,
 | 
				
			||||||
@@ -612,9 +608,6 @@ const columns = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  name: "ScriptManager",
 | 
					  name: "ScriptManager",
 | 
				
			||||||
  components: {
 | 
					 | 
				
			||||||
    TacticalTable,
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  emits: [...useDialogPluginComponent.emits],
 | 
					  emits: [...useDialogPluginComponent.emits],
 | 
				
			||||||
  setup() {
 | 
					  setup() {
 | 
				
			||||||
    // setup vuex store
 | 
					    // setup vuex store
 | 
				
			||||||
@@ -874,7 +867,7 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // component life cycle hooks
 | 
					    // component life cycle hooks
 | 
				
			||||||
    onMounted(getScripts);
 | 
					    onMounted(getScripts());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      // reactive data
 | 
					      // reactive data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,17 +11,7 @@
 | 
				
			|||||||
      :style="maximized ? '' : 'width: 70vw; max-width: 90vw'"
 | 
					      :style="maximized ? '' : 'width: 70vw; max-width: 90vw'"
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <q-bar>
 | 
					      <q-bar>
 | 
				
			||||||
        <span class="q-pr-sm">{{ title }}</span>
 | 
					        {{ title }}
 | 
				
			||||||
        <q-btn
 | 
					 | 
				
			||||||
          v-if="!snippet && openAIEnabled"
 | 
					 | 
				
			||||||
          :disable="loading"
 | 
					 | 
				
			||||||
          dense
 | 
					 | 
				
			||||||
          size="xs"
 | 
					 | 
				
			||||||
          label="Generate Script"
 | 
					 | 
				
			||||||
          color="primary"
 | 
					 | 
				
			||||||
          no-caps
 | 
					 | 
				
			||||||
          @click="generateScriptOpenAI"
 | 
					 | 
				
			||||||
        />
 | 
					 | 
				
			||||||
        <q-space />
 | 
					        <q-space />
 | 
				
			||||||
        <q-btn
 | 
					        <q-btn
 | 
				
			||||||
          dense
 | 
					          dense
 | 
				
			||||||
@@ -107,9 +97,6 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
// composable imports
 | 
					// composable imports
 | 
				
			||||||
import { ref, computed } from "vue";
 | 
					import { ref, computed } from "vue";
 | 
				
			||||||
import { useStore } from "vuex";
 | 
					 | 
				
			||||||
import { useQuasar } from "quasar";
 | 
					 | 
				
			||||||
import { generateScript } from "@/api/core";
 | 
					 | 
				
			||||||
import { useDialogPluginComponent } from "quasar";
 | 
					import { useDialogPluginComponent } from "quasar";
 | 
				
			||||||
import { saveScriptSnippet, editScriptSnippet } from "@/api/scripts";
 | 
					import { saveScriptSnippet, editScriptSnippet } from "@/api/scripts";
 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					import { notifySuccess } from "@/utils/notify";
 | 
				
			||||||
@@ -141,13 +128,6 @@ export default {
 | 
				
			|||||||
    // setup quasar plugins
 | 
					    // setup quasar plugins
 | 
				
			||||||
    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup quasar
 | 
					 | 
				
			||||||
    const $q = useQuasar();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // setup store
 | 
					 | 
				
			||||||
    const store = useStore();
 | 
					 | 
				
			||||||
    const openAIEnabled = computed(() => store.state.openAIIntegrationEnabled);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // snippet form logic
 | 
					    // snippet form logic
 | 
				
			||||||
    const snippet = props.snippet
 | 
					    const snippet = props.snippet
 | 
				
			||||||
      ? ref(Object.assign({}, props.snippet))
 | 
					      ? ref(Object.assign({}, props.snippet))
 | 
				
			||||||
@@ -187,23 +167,6 @@ export default {
 | 
				
			|||||||
      loading.value = false;
 | 
					      loading.value = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function generateScriptOpenAI() {
 | 
					 | 
				
			||||||
      $q.dialog({
 | 
					 | 
				
			||||||
        title: "Ask ChatGPT what you need!",
 | 
					 | 
				
			||||||
        prompt: {
 | 
					 | 
				
			||||||
          model: `${lang.value} code that `,
 | 
					 | 
				
			||||||
          type: "text",
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        cancel: true,
 | 
					 | 
				
			||||||
        persistent: true,
 | 
					 | 
				
			||||||
      }).onOk(async (data) => {
 | 
					 | 
				
			||||||
        const completion = await generateScript({
 | 
					 | 
				
			||||||
          prompt: data,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        snippet.value.code = completion;
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      // reactive data
 | 
					      // reactive data
 | 
				
			||||||
      formSnippet: snippet.value,
 | 
					      formSnippet: snippet.value,
 | 
				
			||||||
@@ -216,11 +179,9 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      //computed
 | 
					      //computed
 | 
				
			||||||
      title,
 | 
					      title,
 | 
				
			||||||
      openAIEnabled,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      //methods
 | 
					      //methods
 | 
				
			||||||
      submitForm,
 | 
					      submitForm,
 | 
				
			||||||
      generateScriptOpenAI,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // quasar dialog plugin
 | 
					      // quasar dialog plugin
 | 
				
			||||||
      dialogRef,
 | 
					      dialogRef,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,20 +93,6 @@
 | 
				
			|||||||
          />
 | 
					          />
 | 
				
			||||||
        </q-card-section>
 | 
					        </q-card-section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <q-card-section>
 | 
					 | 
				
			||||||
          <tactical-dropdown
 | 
					 | 
				
			||||||
            v-model="script.env_vars"
 | 
					 | 
				
			||||||
            label="Environment Variables"
 | 
					 | 
				
			||||||
            placeholder="(press Enter after typing each key=value pair)"
 | 
					 | 
				
			||||||
            filled
 | 
					 | 
				
			||||||
            use-input
 | 
					 | 
				
			||||||
            multiple
 | 
					 | 
				
			||||||
            hide-dropdown-icon
 | 
					 | 
				
			||||||
            input-debounce="0"
 | 
					 | 
				
			||||||
            new-value-mode="add"
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        </q-card-section>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <q-card-section>
 | 
					        <q-card-section>
 | 
				
			||||||
          <q-input
 | 
					          <q-input
 | 
				
			||||||
            label="Default Timeout"
 | 
					            label="Default Timeout"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,7 +45,6 @@ export default {
 | 
				
			|||||||
        args: props.script.args,
 | 
					        args: props.script.args,
 | 
				
			||||||
        shell: props.script.shell,
 | 
					        shell: props.script.shell,
 | 
				
			||||||
        run_as_user: props.script.run_as_user,
 | 
					        run_as_user: props.script.run_as_user,
 | 
				
			||||||
        env_vars: props.script.env_vars,
 | 
					 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
        ret.value = await testScript(props.agent, data);
 | 
					        ret.value = await testScript(props.agent, data);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,7 +102,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
              <tactical-dropdown
 | 
					              <tactical-dropdown
 | 
				
			||||||
                v-if="actionType === 'script'"
 | 
					                v-if="actionType === 'script'"
 | 
				
			||||||
                class="col-3"
 | 
					                class="col-4"
 | 
				
			||||||
                label="Select script"
 | 
					                label="Select script"
 | 
				
			||||||
                v-model="script"
 | 
					                v-model="script"
 | 
				
			||||||
                :options="scriptOptions"
 | 
					                :options="scriptOptions"
 | 
				
			||||||
@@ -113,7 +113,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
              <q-select
 | 
					              <q-select
 | 
				
			||||||
                v-if="actionType === 'script'"
 | 
					                v-if="actionType === 'script'"
 | 
				
			||||||
                class="col-3"
 | 
					                class="col-5"
 | 
				
			||||||
                dense
 | 
					                dense
 | 
				
			||||||
                label="Script Arguments (press Enter after typing each argument)"
 | 
					                label="Script Arguments (press Enter after typing each argument)"
 | 
				
			||||||
                filled
 | 
					                filled
 | 
				
			||||||
@@ -126,21 +126,6 @@
 | 
				
			|||||||
                new-value-mode="add"
 | 
					                new-value-mode="add"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <q-select
 | 
					 | 
				
			||||||
                v-if="actionType === 'script'"
 | 
					 | 
				
			||||||
                class="col-3"
 | 
					 | 
				
			||||||
                dense
 | 
					 | 
				
			||||||
                :label="envVarsLabel"
 | 
					 | 
				
			||||||
                filled
 | 
					 | 
				
			||||||
                v-model="defaultEnvVars"
 | 
					 | 
				
			||||||
                use-input
 | 
					 | 
				
			||||||
                use-chips
 | 
					 | 
				
			||||||
                multiple
 | 
					 | 
				
			||||||
                hide-dropdown-icon
 | 
					 | 
				
			||||||
                input-debounce="0"
 | 
					 | 
				
			||||||
                new-value-mode="add"
 | 
					 | 
				
			||||||
              />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <q-input
 | 
					              <q-input
 | 
				
			||||||
                v-if="actionType === 'script'"
 | 
					                v-if="actionType === 'script'"
 | 
				
			||||||
                class="col-2"
 | 
					                class="col-2"
 | 
				
			||||||
@@ -225,9 +210,6 @@
 | 
				
			|||||||
                    <q-item-label caption>
 | 
					                    <q-item-label caption>
 | 
				
			||||||
                      Arguments: {{ element.script_args }}
 | 
					                      Arguments: {{ element.script_args }}
 | 
				
			||||||
                    </q-item-label>
 | 
					                    </q-item-label>
 | 
				
			||||||
                    <q-item-label caption>
 | 
					 | 
				
			||||||
                      Env Vars: {{ element.env_vars }}
 | 
					 | 
				
			||||||
                    </q-item-label>
 | 
					 | 
				
			||||||
                    <q-item-label caption>
 | 
					                    <q-item-label caption>
 | 
				
			||||||
                      Timeout: {{ element.timeout }}
 | 
					                      Timeout: {{ element.timeout }}
 | 
				
			||||||
                    </q-item-label>
 | 
					                    </q-item-label>
 | 
				
			||||||
@@ -745,7 +727,6 @@ import { useCheckDropdown } from "@/composables/checks";
 | 
				
			|||||||
import { useCustomFieldDropdown } from "@/composables/core";
 | 
					import { useCustomFieldDropdown } from "@/composables/core";
 | 
				
			||||||
import { notifySuccess, notifyError } from "@/utils/notify";
 | 
					import { notifySuccess, notifyError } from "@/utils/notify";
 | 
				
			||||||
import { validateTimePeriod } from "@/utils/validation";
 | 
					import { validateTimePeriod } from "@/utils/validation";
 | 
				
			||||||
import { envVarsLabel } from "@/constants/constants";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  convertPeriodToSeconds,
 | 
					  convertPeriodToSeconds,
 | 
				
			||||||
  convertToBitArray,
 | 
					  convertToBitArray,
 | 
				
			||||||
@@ -836,15 +817,10 @@ export default {
 | 
				
			|||||||
    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
					    const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // setup dropdowns
 | 
					    // setup dropdowns
 | 
				
			||||||
    const {
 | 
					    const { script, scriptOptions, defaultTimeout, defaultArgs } =
 | 
				
			||||||
      script,
 | 
					      useScriptDropdown(undefined, {
 | 
				
			||||||
      scriptOptions,
 | 
					        onMount: true,
 | 
				
			||||||
      defaultTimeout,
 | 
					      });
 | 
				
			||||||
      defaultArgs,
 | 
					 | 
				
			||||||
      defaultEnvVars,
 | 
					 | 
				
			||||||
    } = useScriptDropdown(undefined, {
 | 
					 | 
				
			||||||
      onMount: true,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // set defaultTimeout to 30
 | 
					    // set defaultTimeout to 30
 | 
				
			||||||
    defaultTimeout.value = 30;
 | 
					    defaultTimeout.value = 30;
 | 
				
			||||||
@@ -938,7 +914,6 @@ export default {
 | 
				
			|||||||
          script: script.value,
 | 
					          script: script.value,
 | 
				
			||||||
          timeout: defaultTimeout.value,
 | 
					          timeout: defaultTimeout.value,
 | 
				
			||||||
          script_args: defaultArgs.value,
 | 
					          script_args: defaultArgs.value,
 | 
				
			||||||
          env_vars: defaultEnvVars.value,
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      } else if (actionType.value === "cmd") {
 | 
					      } else if (actionType.value === "cmd") {
 | 
				
			||||||
        task.value.actions.push({
 | 
					        task.value.actions.push({
 | 
				
			||||||
@@ -952,7 +927,6 @@ export default {
 | 
				
			|||||||
      // clear fields after add
 | 
					      // clear fields after add
 | 
				
			||||||
      script.value = null;
 | 
					      script.value = null;
 | 
				
			||||||
      defaultArgs.value = [];
 | 
					      defaultArgs.value = [];
 | 
				
			||||||
      defaultEnvVars.value = [];
 | 
					 | 
				
			||||||
      defaultTimeout.value = 30;
 | 
					      defaultTimeout.value = 30;
 | 
				
			||||||
      command.value = "";
 | 
					      command.value = "";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -1115,7 +1089,6 @@ export default {
 | 
				
			|||||||
      script,
 | 
					      script,
 | 
				
			||||||
      defaultTimeout,
 | 
					      defaultTimeout,
 | 
				
			||||||
      defaultArgs,
 | 
					      defaultArgs,
 | 
				
			||||||
      defaultEnvVars,
 | 
					 | 
				
			||||||
      actionType,
 | 
					      actionType,
 | 
				
			||||||
      command,
 | 
					      command,
 | 
				
			||||||
      shell,
 | 
					      shell,
 | 
				
			||||||
@@ -1143,7 +1116,6 @@ export default {
 | 
				
			|||||||
      monthOptions,
 | 
					      monthOptions,
 | 
				
			||||||
      taskTypeOptions,
 | 
					      taskTypeOptions,
 | 
				
			||||||
      taskInstancePolicyOptions,
 | 
					      taskInstancePolicyOptions,
 | 
				
			||||||
      envVarsLabel,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      submit,
 | 
					      submit,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,107 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
  <q-table
 | 
					 | 
				
			||||||
    :columns="localColumns"
 | 
					 | 
				
			||||||
    :visible-columns="visibleColumns"
 | 
					 | 
				
			||||||
    :table-class="{
 | 
					 | 
				
			||||||
      'table-bgcolor': !$q.dark.isActive,
 | 
					 | 
				
			||||||
      'table-bgcolor-dark': $q.dark.isActive,
 | 
					 | 
				
			||||||
      'column-bgcolor-dark': $q.dark.isActive && columnSelect,
 | 
					 | 
				
			||||||
      'column-bgcolor': !$q.dark.isActive && columnSelect,
 | 
					 | 
				
			||||||
      'sticky-header-right-column': columnSelect,
 | 
					 | 
				
			||||||
      'tbl-sticky': !columnSelect,
 | 
					 | 
				
			||||||
    }"
 | 
					 | 
				
			||||||
    v-bind="$attrs"
 | 
					 | 
				
			||||||
  >
 | 
					 | 
				
			||||||
    <template v-for="(_, slot) in $slots" v-slot:[slot]="scope">
 | 
					 | 
				
			||||||
      <slot :name="slot" v-bind="scope || {}" />
 | 
					 | 
				
			||||||
    </template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <template v-slot:header-cell-columnSelect="props">
 | 
					 | 
				
			||||||
      <q-th :props="props" auto-width>
 | 
					 | 
				
			||||||
        <q-btn dense flat icon="more_horiz">
 | 
					 | 
				
			||||||
          <q-menu>
 | 
					 | 
				
			||||||
            <q-option-group
 | 
					 | 
				
			||||||
              v-model="visibleColumns"
 | 
					 | 
				
			||||||
              :options="columnOptions"
 | 
					 | 
				
			||||||
              type="checkbox"
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </q-menu>
 | 
					 | 
				
			||||||
        </q-btn>
 | 
					 | 
				
			||||||
      </q-th>
 | 
					 | 
				
			||||||
    </template>
 | 
					 | 
				
			||||||
  </q-table>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script lang="ts">
 | 
					 | 
				
			||||||
import { defineComponent } from "vue";
 | 
					 | 
				
			||||||
export default defineComponent({
 | 
					 | 
				
			||||||
  inheritAttrs: false,
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script setup lang="ts">
 | 
					 | 
				
			||||||
import { ref } from "vue";
 | 
					 | 
				
			||||||
import { type QTableColumn } from "quasar";
 | 
					 | 
				
			||||||
const props = withDefaults(
 | 
					 | 
				
			||||||
  defineProps<{
 | 
					 | 
				
			||||||
    columns: QTableColumn[];
 | 
					 | 
				
			||||||
    columnSelect?: boolean;
 | 
					 | 
				
			||||||
    excludeColumns?: string[];
 | 
					 | 
				
			||||||
  }>(),
 | 
					 | 
				
			||||||
  { columnSelect: false, excludeColumns: () => ["columnSelect"] }
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
// save a non-reactive copy of columns to modify
 | 
					 | 
				
			||||||
const localColumns: QTableColumn[] = Object.assign([], props.columns);
 | 
					 | 
				
			||||||
if (props.columnSelect)
 | 
					 | 
				
			||||||
  localColumns.push({
 | 
					 | 
				
			||||||
    name: "columnSelect",
 | 
					 | 
				
			||||||
    label: "Column Select",
 | 
					 | 
				
			||||||
    field: "columnSelect",
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
const visibleColumns = ref(localColumns.map((column) => column.name));
 | 
					 | 
				
			||||||
const columnOptions = ref(
 | 
					 | 
				
			||||||
  localColumns
 | 
					 | 
				
			||||||
    .filter((column) => !props.excludeColumns.includes(column.name))
 | 
					 | 
				
			||||||
    .map((column) => ({ label: column.label, value: column.name }))
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style lang="sass">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.column-bgcolor-dark
 | 
					 | 
				
			||||||
  td:last-child
 | 
					 | 
				
			||||||
    /* bg color is important for td; just specify one */
 | 
					 | 
				
			||||||
    background-color: #1d1d1d
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.column-bgcolor
 | 
					 | 
				
			||||||
  td:last-child
 | 
					 | 
				
			||||||
    /* bg color is important for td; just specify one */
 | 
					 | 
				
			||||||
    background-color: #ffffff
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.sticky-header-right-column
 | 
					 | 
				
			||||||
  tr th
 | 
					 | 
				
			||||||
    position: sticky
 | 
					 | 
				
			||||||
    /* higher than z-index for td below */
 | 
					 | 
				
			||||||
    z-index: 2
 | 
					 | 
				
			||||||
  /* this will be the loading indicator */
 | 
					 | 
				
			||||||
  thead tr:last-child th
 | 
					 | 
				
			||||||
    /* height of all previous header rows */
 | 
					 | 
				
			||||||
    top: 48px
 | 
					 | 
				
			||||||
    /* highest z-index */
 | 
					 | 
				
			||||||
    z-index: 3
 | 
					 | 
				
			||||||
  thead tr:last-child th
 | 
					 | 
				
			||||||
    top: 0
 | 
					 | 
				
			||||||
    z-index: 1
 | 
					 | 
				
			||||||
  tr:last-child th:last-child
 | 
					 | 
				
			||||||
    /* highest z-index */
 | 
					 | 
				
			||||||
    z-index: 3
 | 
					 | 
				
			||||||
  td:last-child
 | 
					 | 
				
			||||||
    z-index: 1
 | 
					 | 
				
			||||||
  td:last-child, th:last-child
 | 
					 | 
				
			||||||
    position: sticky
 | 
					 | 
				
			||||||
    right: 0
 | 
					 | 
				
			||||||
  /* prevent scrolling behind sticky top row on focus */
 | 
					 | 
				
			||||||
  tbody
 | 
					 | 
				
			||||||
    /* height of all previous header rows */
 | 
					 | 
				
			||||||
    scroll-margin-top: 48px
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@@ -31,7 +31,7 @@ export function useUserDropdown(onMount = false) {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (onMount) {
 | 
					  if (onMount) {
 | 
				
			||||||
    onMounted(getUserOptions);
 | 
					    onMounted(getUserOptions());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
import { computed, ref } from "vue";
 | 
					import { ref } from "vue";
 | 
				
			||||||
import { useStore } from "vuex";
 | 
					 | 
				
			||||||
import { fetchAgents } from "@/api/agents";
 | 
					import { fetchAgents } from "@/api/agents";
 | 
				
			||||||
import { formatAgentOptions } from "@/utils/format";
 | 
					import { formatAgentOptions } from "@/utils/format";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,16 +28,13 @@ export function useAgentDropdown() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function cmdPlaceholder(shell) {
 | 
					export function cmdPlaceholder(shell) {
 | 
				
			||||||
  const store = useStore();
 | 
					  if (shell === "cmd") return "rmdir /S /Q C:\\Windows\\System32";
 | 
				
			||||||
  const placeholders = computed(() => store.state.run_cmd_placeholder_text);
 | 
					  else if (shell === "powershell")
 | 
				
			||||||
 | 
					    return "Remove-Item -Recurse -Force C:\\Windows\\System32";
 | 
				
			||||||
  if (shell === "cmd") return placeholders.value.cmd;
 | 
					  else return "rm -rf --no-preserve-root /";
 | 
				
			||||||
  else if (shell === "powershell") return placeholders.value.powershell;
 | 
					 | 
				
			||||||
  else return placeholders.value.shell;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const agentPlatformOptions = [
 | 
					export const agentPlatformOptions = [
 | 
				
			||||||
  { value: "windows", label: "Windows" },
 | 
					  { value: "windows", label: "Windows" },
 | 
				
			||||||
  { value: "linux", label: "Linux" },
 | 
					  { value: "linux", label: "Linux" },
 | 
				
			||||||
  { value: "darwin", label: "macOS" },
 | 
					 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,6 @@ export function useScriptDropdown(setScript = null, { onMount = false } = {}) {
 | 
				
			|||||||
  const scriptOptions = ref([]);
 | 
					  const scriptOptions = ref([]);
 | 
				
			||||||
  const defaultTimeout = ref(30);
 | 
					  const defaultTimeout = ref(30);
 | 
				
			||||||
  const defaultArgs = ref([]);
 | 
					  const defaultArgs = ref([]);
 | 
				
			||||||
  const defaultEnvVars = ref([]);
 | 
					 | 
				
			||||||
  const script = ref(setScript);
 | 
					  const script = ref(setScript);
 | 
				
			||||||
  const syntax = ref("");
 | 
					  const syntax = ref("");
 | 
				
			||||||
  const link = ref("");
 | 
					  const link = ref("");
 | 
				
			||||||
@@ -30,7 +29,6 @@ export function useScriptDropdown(setScript = null, { onMount = false } = {}) {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
      defaultTimeout.value = tmpScript.timeout;
 | 
					      defaultTimeout.value = tmpScript.timeout;
 | 
				
			||||||
      defaultArgs.value = tmpScript.args;
 | 
					      defaultArgs.value = tmpScript.args;
 | 
				
			||||||
      defaultEnvVars.value = tmpScript.env_vars;
 | 
					 | 
				
			||||||
      syntax.value = tmpScript.syntax;
 | 
					      syntax.value = tmpScript.syntax;
 | 
				
			||||||
      link.value =
 | 
					      link.value =
 | 
				
			||||||
        tmpScript.script_type === "builtin"
 | 
					        tmpScript.script_type === "builtin"
 | 
				
			||||||
@@ -51,7 +49,6 @@ export function useScriptDropdown(setScript = null, { onMount = false } = {}) {
 | 
				
			|||||||
    scriptOptions,
 | 
					    scriptOptions,
 | 
				
			||||||
    defaultTimeout,
 | 
					    defaultTimeout,
 | 
				
			||||||
    defaultArgs,
 | 
					    defaultArgs,
 | 
				
			||||||
    defaultEnvVars,
 | 
					 | 
				
			||||||
    syntax,
 | 
					    syntax,
 | 
				
			||||||
    link,
 | 
					    link,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,15 @@
 | 
				
			|||||||
export const GOARCH_AMD64 = "amd64";
 | 
					const GOARCH_AMD64 = "amd64";
 | 
				
			||||||
export const GOARCH_i386 = "386";
 | 
					const GOARCH_i386 = "386";
 | 
				
			||||||
export const GOARCH_ARM64 = "arm64";
 | 
					const GOARCH_ARM64 = "arm64";
 | 
				
			||||||
export const GOARCH_ARM32 = "arm";
 | 
					const GOARCH_ARM32 = "arm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const runAsUserToolTip =
 | 
					const runAsUserToolTip =
 | 
				
			||||||
  "Run in the context of the logged in user. If no user is logged in, the script will not run and an error will be returned.";
 | 
					  "Run in the context of the logged in user. If no user is logged in, the script will not run and an error will be returned. Not supported on Windows Server.";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const envVarsLabel =
 | 
					export {
 | 
				
			||||||
  "Environment vars (press Enter after typing each key=value pair)";
 | 
					  GOARCH_AMD64,
 | 
				
			||||||
 | 
					  GOARCH_i386,
 | 
				
			||||||
 | 
					  GOARCH_ARM64,
 | 
				
			||||||
 | 
					  GOARCH_ARM32,
 | 
				
			||||||
 | 
					  runAsUserToolTip,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,27 +14,6 @@
 | 
				
			|||||||
          @click="$store.dispatch('reload')"
 | 
					          @click="$store.dispatch('reload')"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </q-banner>
 | 
					      </q-banner>
 | 
				
			||||||
      <q-banner
 | 
					 | 
				
			||||||
        v-if="!hosted && tokenExpired"
 | 
					 | 
				
			||||||
        inline-actions
 | 
					 | 
				
			||||||
        class="bg-yellow text-black text-center"
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        <q-icon size="xl" name="warning" />
 | 
					 | 
				
			||||||
        <span
 | 
					 | 
				
			||||||
          ><br />Your code signing token is no longer valid.<br /><br />
 | 
					 | 
				
			||||||
          If you have downgraded or cancelled your sponsorship, please delete
 | 
					 | 
				
			||||||
          your token from the Code Signing modal and refresh to get rid of this
 | 
					 | 
				
			||||||
          banner.<br /><br />
 | 
					 | 
				
			||||||
          For any issues or to renew your sponsorship please email
 | 
					 | 
				
			||||||
          support@amidaware.com<br /><br
 | 
					 | 
				
			||||||
        /></span>
 | 
					 | 
				
			||||||
        <q-btn
 | 
					 | 
				
			||||||
          color="dark"
 | 
					 | 
				
			||||||
          icon="refresh"
 | 
					 | 
				
			||||||
          label="Refresh"
 | 
					 | 
				
			||||||
          @click="$store.dispatch('reload')"
 | 
					 | 
				
			||||||
        />
 | 
					 | 
				
			||||||
      </q-banner>
 | 
					 | 
				
			||||||
      <q-toolbar>
 | 
					      <q-toolbar>
 | 
				
			||||||
        <q-btn
 | 
					        <q-btn
 | 
				
			||||||
          dense
 | 
					          dense
 | 
				
			||||||
@@ -56,27 +35,15 @@
 | 
				
			|||||||
          Tactical RMM<span class="text-overline q-ml-sm"
 | 
					          Tactical RMM<span class="text-overline q-ml-sm"
 | 
				
			||||||
            >v{{ currentTRMMVersion }}</span
 | 
					            >v{{ currentTRMMVersion }}</span
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
          <!-- update check -->
 | 
					          <span class="text-overline q-ml-md" v-if="updateAvailable()"
 | 
				
			||||||
          <q-chip
 | 
					            ><q-badge color="warning"
 | 
				
			||||||
            v-if="updateAvailable"
 | 
					              ><a :href="latestReleaseURL" target="_blank"
 | 
				
			||||||
            class="text-overline q-ml-sm"
 | 
					                >v{{ latestTRMMVersion }} available</a
 | 
				
			||||||
            :color="dash_warning_color"
 | 
					              ></q-badge
 | 
				
			||||||
            icon="update"
 | 
					            ></span
 | 
				
			||||||
            dense
 | 
					 | 
				
			||||||
            ><a :href="latestReleaseURL" target="_blank"
 | 
					 | 
				
			||||||
              >v{{ latestTRMMVersion }} available</a
 | 
					 | 
				
			||||||
            ></q-chip
 | 
					 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
          <!-- cert expiring soon check -->
 | 
					 | 
				
			||||||
          <q-chip
 | 
					 | 
				
			||||||
            v-if="daysUntilCertExpires <= 15"
 | 
					 | 
				
			||||||
            dense
 | 
					 | 
				
			||||||
            :color="dash_negative_color"
 | 
					 | 
				
			||||||
            text-color="black"
 | 
					 | 
				
			||||||
            icon="warning"
 | 
					 | 
				
			||||||
            >Certificate expires in {{ daysUntilCertExpires }} days</q-chip
 | 
					 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
        </q-toolbar-title>
 | 
					        </q-toolbar-title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- temp dark mode toggle -->
 | 
					        <!-- temp dark mode toggle -->
 | 
				
			||||||
        <q-toggle
 | 
					        <q-toggle
 | 
				
			||||||
          v-model="darkMode"
 | 
					          v-model="darkMode"
 | 
				
			||||||
@@ -106,11 +73,7 @@
 | 
				
			|||||||
              </q-item>
 | 
					              </q-item>
 | 
				
			||||||
              <q-item>
 | 
					              <q-item>
 | 
				
			||||||
                <q-item-section avatar>
 | 
					                <q-item-section avatar>
 | 
				
			||||||
                  <q-icon
 | 
					                  <q-icon name="power_off" size="sm" color="negative" />
 | 
				
			||||||
                    name="power_off"
 | 
					 | 
				
			||||||
                    size="sm"
 | 
					 | 
				
			||||||
                    :color="dash_negative_color"
 | 
					 | 
				
			||||||
                  />
 | 
					 | 
				
			||||||
                </q-item-section>
 | 
					                </q-item-section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <q-item-section no-wrap>
 | 
					                <q-item-section no-wrap>
 | 
				
			||||||
@@ -129,11 +92,7 @@
 | 
				
			|||||||
              </q-item>
 | 
					              </q-item>
 | 
				
			||||||
              <q-item>
 | 
					              <q-item>
 | 
				
			||||||
                <q-item-section avatar>
 | 
					                <q-item-section avatar>
 | 
				
			||||||
                  <q-icon
 | 
					                  <q-icon name="power_off" size="sm" color="negative" />
 | 
				
			||||||
                    name="power_off"
 | 
					 | 
				
			||||||
                    size="sm"
 | 
					 | 
				
			||||||
                    :color="dash_negative_color"
 | 
					 | 
				
			||||||
                  />
 | 
					 | 
				
			||||||
                </q-item-section>
 | 
					                </q-item-section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <q-item-section no-wrap>
 | 
					                <q-item-section no-wrap>
 | 
				
			||||||
@@ -160,32 +119,6 @@
 | 
				
			|||||||
                <q-item-label>Preferences</q-item-label>
 | 
					                <q-item-label>Preferences</q-item-label>
 | 
				
			||||||
              </q-item-section>
 | 
					              </q-item-section>
 | 
				
			||||||
            </q-item>
 | 
					            </q-item>
 | 
				
			||||||
            <q-item clickable>
 | 
					 | 
				
			||||||
              <q-item-section>Account</q-item-section>
 | 
					 | 
				
			||||||
              <q-item-section side>
 | 
					 | 
				
			||||||
                <q-icon name="keyboard_arrow_right" />
 | 
					 | 
				
			||||||
              </q-item-section>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              <q-menu anchor="top end" self="top start">
 | 
					 | 
				
			||||||
                <q-list>
 | 
					 | 
				
			||||||
                  <q-item
 | 
					 | 
				
			||||||
                    clickable
 | 
					 | 
				
			||||||
                    v-ripple
 | 
					 | 
				
			||||||
                    @click="resetPassword"
 | 
					 | 
				
			||||||
                    v-close-popup
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    <q-item-section>
 | 
					 | 
				
			||||||
                      <q-item-label>Reset Password</q-item-label>
 | 
					 | 
				
			||||||
                    </q-item-section>
 | 
					 | 
				
			||||||
                  </q-item>
 | 
					 | 
				
			||||||
                  <q-item clickable v-ripple @click="reset2FA" v-close-popup>
 | 
					 | 
				
			||||||
                    <q-item-section>
 | 
					 | 
				
			||||||
                      <q-item-label>Reset 2FA</q-item-label>
 | 
					 | 
				
			||||||
                    </q-item-section>
 | 
					 | 
				
			||||||
                  </q-item>
 | 
					 | 
				
			||||||
                </q-list>
 | 
					 | 
				
			||||||
              </q-menu>
 | 
					 | 
				
			||||||
            </q-item>
 | 
					 | 
				
			||||||
            <q-item to="/expired" exact>
 | 
					            <q-item to="/expired" exact>
 | 
				
			||||||
              <q-item-section>
 | 
					              <q-item-section>
 | 
				
			||||||
                <q-item-label>Logout</q-item-label>
 | 
					                <q-item-label>Logout</q-item-label>
 | 
				
			||||||
@@ -207,13 +140,10 @@ import { useQuasar } from "quasar";
 | 
				
			|||||||
import { useStore } from "vuex";
 | 
					import { useStore } from "vuex";
 | 
				
			||||||
import axios from "axios";
 | 
					import axios from "axios";
 | 
				
			||||||
import { getWSUrl } from "@/websocket/channels";
 | 
					import { getWSUrl } from "@/websocket/channels";
 | 
				
			||||||
import { resetTwoFactor } from "@/api/accounts";
 | 
					 | 
				
			||||||
import { notifySuccess } from "@/utils/notify";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ui imports
 | 
					// ui imports
 | 
				
			||||||
import AlertsIcon from "@/components/AlertsIcon.vue";
 | 
					import AlertsIcon from "@/components/AlertsIcon.vue";
 | 
				
			||||||
import UserPreferences from "@/components/modals/coresettings/UserPreferences.vue";
 | 
					import UserPreferences from "@/components/modals/coresettings/UserPreferences.vue";
 | 
				
			||||||
import ResetPass from "@/components/accounts/ResetPass.vue";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  name: "MainLayout",
 | 
					  name: "MainLayout",
 | 
				
			||||||
@@ -237,9 +167,6 @@ export default {
 | 
				
			|||||||
    const needRefresh = computed(() => store.state.needrefresh);
 | 
					    const needRefresh = computed(() => store.state.needrefresh);
 | 
				
			||||||
    const user = computed(() => store.state.username);
 | 
					    const user = computed(() => store.state.username);
 | 
				
			||||||
    const hosted = computed(() => store.state.hosted);
 | 
					    const hosted = computed(() => store.state.hosted);
 | 
				
			||||||
    const tokenExpired = computed(() => store.state.tokenExpired);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const latestReleaseURL = computed(() => {
 | 
					    const latestReleaseURL = computed(() => {
 | 
				
			||||||
      return latestTRMMVersion.value
 | 
					      return latestTRMMVersion.value
 | 
				
			||||||
@@ -253,31 +180,10 @@ export default {
 | 
				
			|||||||
      }).onOk(() => store.dispatch("getDashInfo"));
 | 
					      }).onOk(() => store.dispatch("getDashInfo"));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function resetPassword() {
 | 
					 | 
				
			||||||
      $q.dialog({
 | 
					 | 
				
			||||||
        component: ResetPass,
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function reset2FA() {
 | 
					 | 
				
			||||||
      $q.dialog({
 | 
					 | 
				
			||||||
        title: "Reset 2FA",
 | 
					 | 
				
			||||||
        message: "Are you sure you would like to reset your 2FA token?",
 | 
					 | 
				
			||||||
        cancel: true,
 | 
					 | 
				
			||||||
        persistent: true,
 | 
					 | 
				
			||||||
      }).onOk(async () => {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
          const ret = await resetTwoFactor();
 | 
					 | 
				
			||||||
          notifySuccess(ret, 3000);
 | 
					 | 
				
			||||||
        } catch {}
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const serverCount = ref(0);
 | 
					    const serverCount = ref(0);
 | 
				
			||||||
    const serverOfflineCount = ref(0);
 | 
					    const serverOfflineCount = ref(0);
 | 
				
			||||||
    const workstationCount = ref(0);
 | 
					    const workstationCount = ref(0);
 | 
				
			||||||
    const workstationOfflineCount = ref(0);
 | 
					    const workstationOfflineCount = ref(0);
 | 
				
			||||||
    const daysUntilCertExpires = ref(100);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const ws = ref(null);
 | 
					    const ws = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -285,13 +191,6 @@ export default {
 | 
				
			|||||||
      // moved computed token inside the function since it is not refreshing
 | 
					      // moved computed token inside the function since it is not refreshing
 | 
				
			||||||
      // when ws is closed causing ws to connect with expired token
 | 
					      // when ws is closed causing ws to connect with expired token
 | 
				
			||||||
      const token = computed(() => store.state.token);
 | 
					      const token = computed(() => store.state.token);
 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!token.value) {
 | 
					 | 
				
			||||||
        console.log(
 | 
					 | 
				
			||||||
          "Access token is null or invalid, not setting up WebSocket"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      console.log("Starting websocket");
 | 
					      console.log("Starting websocket");
 | 
				
			||||||
      let url = getWSUrl("dashinfo", token.value);
 | 
					      let url = getWSUrl("dashinfo", token.value);
 | 
				
			||||||
      ws.value = new WebSocket(url);
 | 
					      ws.value = new WebSocket(url);
 | 
				
			||||||
@@ -304,7 +203,6 @@ export default {
 | 
				
			|||||||
        serverOfflineCount.value = data.total_server_offline_count;
 | 
					        serverOfflineCount.value = data.total_server_offline_count;
 | 
				
			||||||
        workstationCount.value = data.total_workstation_count;
 | 
					        workstationCount.value = data.total_workstation_count;
 | 
				
			||||||
        workstationOfflineCount.value = data.total_workstation_offline_count;
 | 
					        workstationOfflineCount.value = data.total_workstation_offline_count;
 | 
				
			||||||
        daysUntilCertExpires.value = data.days_until_cert_expires;
 | 
					 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      ws.value.onclose = (e) => {
 | 
					      ws.value.onclose = (e) => {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
@@ -328,18 +226,13 @@ export default {
 | 
				
			|||||||
      poll.value = setInterval(() => {
 | 
					      poll.value = setInterval(() => {
 | 
				
			||||||
        store.dispatch("checkVer");
 | 
					        store.dispatch("checkVer");
 | 
				
			||||||
        store.dispatch("getDashInfo", false);
 | 
					        store.dispatch("getDashInfo", false);
 | 
				
			||||||
      }, 60 * 4 * 1000);
 | 
					      }, 60 * 5 * 1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const updateAvailable = computed(() => {
 | 
					    function updateAvailable() {
 | 
				
			||||||
      if (
 | 
					      if (latestTRMMVersion.value === "error" || hosted.value) return false;
 | 
				
			||||||
        latestTRMMVersion.value === "error" ||
 | 
					 | 
				
			||||||
        hosted.value ||
 | 
					 | 
				
			||||||
        currentTRMMVersion.value?.includes("-dev")
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
      return currentTRMMVersion.value !== latestTRMMVersion.value;
 | 
					      return currentTRMMVersion.value !== latestTRMMVersion.value;
 | 
				
			||||||
    });
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onMounted(() => {
 | 
					    onMounted(() => {
 | 
				
			||||||
      setupWS();
 | 
					      setupWS();
 | 
				
			||||||
@@ -360,22 +253,15 @@ export default {
 | 
				
			|||||||
      serverOfflineCount,
 | 
					      serverOfflineCount,
 | 
				
			||||||
      workstationCount,
 | 
					      workstationCount,
 | 
				
			||||||
      workstationOfflineCount,
 | 
					      workstationOfflineCount,
 | 
				
			||||||
      daysUntilCertExpires,
 | 
					 | 
				
			||||||
      latestReleaseURL,
 | 
					      latestReleaseURL,
 | 
				
			||||||
      currentTRMMVersion,
 | 
					      currentTRMMVersion,
 | 
				
			||||||
      latestTRMMVersion,
 | 
					      latestTRMMVersion,
 | 
				
			||||||
      user,
 | 
					      user,
 | 
				
			||||||
      needRefresh,
 | 
					      needRefresh,
 | 
				
			||||||
      darkMode,
 | 
					      darkMode,
 | 
				
			||||||
      hosted,
 | 
					 | 
				
			||||||
      tokenExpired,
 | 
					 | 
				
			||||||
      dash_warning_color,
 | 
					 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      showUserPreferences,
 | 
					      showUserPreferences,
 | 
				
			||||||
      resetPassword,
 | 
					 | 
				
			||||||
      reset2FA,
 | 
					 | 
				
			||||||
      updateAvailable,
 | 
					      updateAvailable,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -193,7 +193,6 @@ export default {
 | 
				
			|||||||
              value: script.id,
 | 
					              value: script.id,
 | 
				
			||||||
              timeout: script.default_timeout,
 | 
					              timeout: script.default_timeout,
 | 
				
			||||||
              args: script.args,
 | 
					              args: script.args,
 | 
				
			||||||
              env_vars: script.env_vars,
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
          } else if (cat === "Unassigned" && !script.category) {
 | 
					          } else if (cat === "Unassigned" && !script.category) {
 | 
				
			||||||
            tmp.push({
 | 
					            tmp.push({
 | 
				
			||||||
@@ -201,7 +200,6 @@ export default {
 | 
				
			|||||||
              value: script.id,
 | 
					              value: script.id,
 | 
				
			||||||
              timeout: script.default_timeout,
 | 
					              timeout: script.default_timeout,
 | 
				
			||||||
              args: script.args,
 | 
					              args: script.args,
 | 
				
			||||||
              env_vars: script.env_vars,
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,6 @@ export default function () {
 | 
				
			|||||||
        agentPlatform: "windows",
 | 
					        agentPlatform: "windows",
 | 
				
			||||||
        agentTableLoading: false,
 | 
					        agentTableLoading: false,
 | 
				
			||||||
        needrefresh: false,
 | 
					        needrefresh: false,
 | 
				
			||||||
        tokenExpired: false,
 | 
					 | 
				
			||||||
        refreshSummaryTab: false,
 | 
					        refreshSummaryTab: false,
 | 
				
			||||||
        tableHeight: "300px",
 | 
					        tableHeight: "300px",
 | 
				
			||||||
        tabHeight: "300px",
 | 
					        tabHeight: "300px",
 | 
				
			||||||
@@ -33,16 +32,6 @@ export default function () {
 | 
				
			|||||||
        currentTRMMVersion: null,
 | 
					        currentTRMMVersion: null,
 | 
				
			||||||
        latestTRMMVersion: null,
 | 
					        latestTRMMVersion: null,
 | 
				
			||||||
        dateFormat: "MMM-DD-YYYY - HH:mm",
 | 
					        dateFormat: "MMM-DD-YYYY - HH:mm",
 | 
				
			||||||
        openAIIntegrationEnabled: false,
 | 
					 | 
				
			||||||
        dash_info_color: "info",
 | 
					 | 
				
			||||||
        dash_positive_color: "positive",
 | 
					 | 
				
			||||||
        dash_negative_color: "negative",
 | 
					 | 
				
			||||||
        dash_warning_color: "warning",
 | 
					 | 
				
			||||||
        run_cmd_placeholder_text: {
 | 
					 | 
				
			||||||
          cmd: "rmdir /S /Q C:\\Windows\\System32",
 | 
					 | 
				
			||||||
          powershell: "Remove-Item -Recurse -Force C:\\Windows\\System32",
 | 
					 | 
				
			||||||
          shell: "rm -rf --no-preserve-root /",
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    getters: {
 | 
					    getters: {
 | 
				
			||||||
@@ -94,9 +83,6 @@ export default function () {
 | 
				
			|||||||
      SET_REFRESH_NEEDED(state, action) {
 | 
					      SET_REFRESH_NEEDED(state, action) {
 | 
				
			||||||
        state.needrefresh = action;
 | 
					        state.needrefresh = action;
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      SET_TOKEN_EXPIRED(state, action) {
 | 
					 | 
				
			||||||
        state.tokenExpired = action;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      SET_SPLITTER(state, val) {
 | 
					      SET_SPLITTER(state, val) {
 | 
				
			||||||
        // top toolbar is 50px. Filebar is 40px and agent filter tabs are 44px
 | 
					        // top toolbar is 50px. Filebar is 40px and agent filter tabs are 44px
 | 
				
			||||||
        state.tableHeight = `${Screen.height - 50 - 40 - 78 - val}px`;
 | 
					        state.tableHeight = `${Screen.height - 50 - 40 - 78 - val}px`;
 | 
				
			||||||
@@ -146,24 +132,6 @@ export default function () {
 | 
				
			|||||||
      setDateFormat(state, val) {
 | 
					      setDateFormat(state, val) {
 | 
				
			||||||
        state.dateFormat = val;
 | 
					        state.dateFormat = val;
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      setOpenAIIntegrationStatus(state, val) {
 | 
					 | 
				
			||||||
        state.openAIIntegrationEnabled = val;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      setDashInfoColor(state, val) {
 | 
					 | 
				
			||||||
        state.dash_info_color = val;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      setDashPositiveColor(state, val) {
 | 
					 | 
				
			||||||
        state.dash_positive_color = val;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      setDashNegativeColor(state, val) {
 | 
					 | 
				
			||||||
        state.dash_negative_color = val;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      setDashWarningColor(state, val) {
 | 
					 | 
				
			||||||
        state.dash_warning_color = val;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      setRunCmdPlaceholders(state, obj) {
 | 
					 | 
				
			||||||
        state.run_cmd_placeholder_text = obj;
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    actions: {
 | 
					    actions: {
 | 
				
			||||||
      setClientTreeSplitter(context, val) {
 | 
					      setClientTreeSplitter(context, val) {
 | 
				
			||||||
@@ -188,9 +156,9 @@ export default function () {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (clearTreeSelected) commit("destroySubTable");
 | 
					        if (clearTreeSelected) commit("destroySubTable");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dispatch("getDashInfo", false);
 | 
					 | 
				
			||||||
        dispatch("loadAgents");
 | 
					        dispatch("loadAgents");
 | 
				
			||||||
        dispatch("loadTree");
 | 
					        dispatch("loadTree");
 | 
				
			||||||
 | 
					        dispatch("getDashInfo", false);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      async loadAgents({ state, commit }) {
 | 
					      async loadAgents({ state, commit }) {
 | 
				
			||||||
        commit("AGENT_TABLE_LOADING", true);
 | 
					        commit("AGENT_TABLE_LOADING", true);
 | 
				
			||||||
@@ -222,111 +190,106 @@ export default function () {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        commit("AGENT_TABLE_LOADING", false);
 | 
					        commit("AGENT_TABLE_LOADING", false);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      async getDashInfo({ commit }, edited = true) {
 | 
					      async getDashInfo(context, edited = true) {
 | 
				
			||||||
        const { data } = await axios.get("/core/dashinfo/");
 | 
					        const { data } = await axios.get("/core/dashinfo/");
 | 
				
			||||||
        commit("setDashInfoColor", data.dash_info_color);
 | 
					 | 
				
			||||||
        commit("setDashPositiveColor", data.dash_positive_color);
 | 
					 | 
				
			||||||
        commit("setDashNegativeColor", data.dash_negative_color);
 | 
					 | 
				
			||||||
        commit("setDashWarningColor", data.dash_warning_color);
 | 
					 | 
				
			||||||
        if (edited) {
 | 
					        if (edited) {
 | 
				
			||||||
          LoadingBar.setDefaults({ color: data.loading_bar_color });
 | 
					          LoadingBar.setDefaults({ color: data.loading_bar_color });
 | 
				
			||||||
          commit(
 | 
					          context.commit(
 | 
				
			||||||
            "setClearSearchWhenSwitching",
 | 
					            "setClearSearchWhenSwitching",
 | 
				
			||||||
            data.clear_search_when_switching
 | 
					            data.clear_search_when_switching
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          commit("SET_DEFAULT_AGENT_TBL_TAB", data.default_agent_tbl_tab);
 | 
					          context.commit(
 | 
				
			||||||
          commit("SET_CLIENT_TREE_SORT", data.client_tree_sort);
 | 
					            "SET_DEFAULT_AGENT_TBL_TAB",
 | 
				
			||||||
          commit("SET_CLIENT_SPLITTER", data.client_tree_splitter);
 | 
					            data.default_agent_tbl_tab
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					          context.commit("SET_CLIENT_TREE_SORT", data.client_tree_sort);
 | 
				
			||||||
 | 
					          context.commit("SET_CLIENT_SPLITTER", data.client_tree_splitter);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Dark.set(data.dark_mode);
 | 
					        Dark.set(data.dark_mode);
 | 
				
			||||||
        commit("setCurrentTRMMVersion", data.trmm_version);
 | 
					        context.commit("setCurrentTRMMVersion", data.trmm_version);
 | 
				
			||||||
        commit("setLatestTRMMVersion", data.latest_trmm_ver);
 | 
					        context.commit("setLatestTRMMVersion", data.latest_trmm_ver);
 | 
				
			||||||
        commit("SET_AGENT_DBLCLICK_ACTION", data.dbl_click_action);
 | 
					        context.commit("SET_AGENT_DBLCLICK_ACTION", data.dbl_click_action);
 | 
				
			||||||
        commit("SET_URL_ACTION", data.url_action);
 | 
					        context.commit("SET_URL_ACTION", data.url_action);
 | 
				
			||||||
        commit("setShowCommunityScripts", data.show_community_scripts);
 | 
					        context.commit("setShowCommunityScripts", data.show_community_scripts);
 | 
				
			||||||
        commit("SET_HOSTED", data.hosted);
 | 
					        context.commit("SET_HOSTED", data.hosted);
 | 
				
			||||||
        commit("SET_TOKEN_EXPIRED", data.token_is_expired);
 | 
					 | 
				
			||||||
        commit("setOpenAIIntegrationStatus", data.open_ai_integration_enabled);
 | 
					 | 
				
			||||||
        commit("setRunCmdPlaceholders", data.run_cmd_placeholder_text);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (data?.date_format !== "") commit("setDateFormat", data.date_format);
 | 
					        if (data.date_format && data.date_format !== "")
 | 
				
			||||||
        else commit("setDateFormat", data.default_date_format);
 | 
					          context.commit("setDateFormat", data.date_format);
 | 
				
			||||||
 | 
					        else context.commit("setDateFormat", data.default_date_format);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      loadTree({ commit, state }) {
 | 
					      loadTree({ commit, state }) {
 | 
				
			||||||
        setTimeout(() => {
 | 
					        axios
 | 
				
			||||||
          axios
 | 
					          .get("/clients/")
 | 
				
			||||||
            .get("/clients/")
 | 
					          .then((r) => {
 | 
				
			||||||
            .then((r) => {
 | 
					            if (r.data.length === 0) {
 | 
				
			||||||
              if (r.data.length === 0) {
 | 
					              this.$router.push({ name: "InitialSetup" });
 | 
				
			||||||
                this.$router.push({ name: "InitialSetup" });
 | 
					            }
 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
              let output = [];
 | 
					            let output = [];
 | 
				
			||||||
              for (let client of r.data) {
 | 
					            for (let client of r.data) {
 | 
				
			||||||
                let childSites = [];
 | 
					              let childSites = [];
 | 
				
			||||||
                for (let site of client.sites) {
 | 
					              for (let site of client.sites) {
 | 
				
			||||||
                  let siteNode = {
 | 
					                let siteNode = {
 | 
				
			||||||
                    label: site.name,
 | 
					                  label: site.name,
 | 
				
			||||||
                    id: site.id,
 | 
					                  id: site.id,
 | 
				
			||||||
                    raw: `Site|${site.id}`,
 | 
					                  raw: `Site|${site.id}`,
 | 
				
			||||||
                    header: "generic",
 | 
					                  header: "generic",
 | 
				
			||||||
                    icon: "apartment",
 | 
					                  icon: "apartment",
 | 
				
			||||||
                    selectable: true,
 | 
					                  selectable: true,
 | 
				
			||||||
                    site: site,
 | 
					                  site: site,
 | 
				
			||||||
                  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                  if (site.maintenance_mode) {
 | 
					 | 
				
			||||||
                    siteNode["color"] = "green";
 | 
					 | 
				
			||||||
                  } else if (site.failing_checks.error) {
 | 
					 | 
				
			||||||
                    siteNode["color"] = "negative";
 | 
					 | 
				
			||||||
                  } else if (site.failing_checks.warning) {
 | 
					 | 
				
			||||||
                    siteNode["color"] = "warning";
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                  childSites.push(siteNode);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let clientNode = {
 | 
					 | 
				
			||||||
                  label: client.name,
 | 
					 | 
				
			||||||
                  id: client.id,
 | 
					 | 
				
			||||||
                  raw: `Client|${client.id}`,
 | 
					 | 
				
			||||||
                  header: "root",
 | 
					 | 
				
			||||||
                  icon: "business",
 | 
					 | 
				
			||||||
                  children: childSites,
 | 
					 | 
				
			||||||
                  client: client,
 | 
					 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (client.maintenance_mode) clientNode["color"] = "green";
 | 
					                if (site.maintenance_mode) {
 | 
				
			||||||
                else if (client.failing_checks.error) {
 | 
					                  siteNode["color"] = "green";
 | 
				
			||||||
                  clientNode["color"] = "negative";
 | 
					                } else if (site.failing_checks.error) {
 | 
				
			||||||
                } else if (client.failing_checks.warning) {
 | 
					                  siteNode["color"] = "negative";
 | 
				
			||||||
                  clientNode["color"] = "warning";
 | 
					                } else if (site.failing_checks.warning) {
 | 
				
			||||||
 | 
					                  siteNode["color"] = "warning";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                output.push(clientNode);
 | 
					                childSites.push(siteNode);
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              const sorted = output.sort((a, b) =>
 | 
					              let clientNode = {
 | 
				
			||||||
                a.label.localeCompare(b.label)
 | 
					                label: client.name,
 | 
				
			||||||
              );
 | 
					                id: client.id,
 | 
				
			||||||
              if (state.clientTreeSort === "alphafail") {
 | 
					                raw: `Client|${client.id}`,
 | 
				
			||||||
                // move failing clients to the top
 | 
					                header: "root",
 | 
				
			||||||
                const failing = sorted.filter(
 | 
					                icon: "business",
 | 
				
			||||||
                  (i) => i.color === "negative" || i.color === "warning"
 | 
					                children: childSites,
 | 
				
			||||||
                );
 | 
					                client: client,
 | 
				
			||||||
                const ok = sorted.filter(
 | 
					              };
 | 
				
			||||||
                  (i) => i.color !== "negative" && i.color !== "warning"
 | 
					
 | 
				
			||||||
                );
 | 
					              if (client.maintenance_mode) clientNode["color"] = "green";
 | 
				
			||||||
                const sortedByFailing = [...failing, ...ok];
 | 
					              else if (client.failing_checks.error) {
 | 
				
			||||||
                commit("loadTree", sortedByFailing);
 | 
					                clientNode["color"] = "negative";
 | 
				
			||||||
              } else {
 | 
					              } else if (client.failing_checks.warning) {
 | 
				
			||||||
                commit("loadTree", sorted);
 | 
					                clientNode["color"] = "warning";
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            })
 | 
					
 | 
				
			||||||
            .catch(() => {
 | 
					              output.push(clientNode);
 | 
				
			||||||
              state.treeReady = true;
 | 
					            }
 | 
				
			||||||
            });
 | 
					
 | 
				
			||||||
        }, 150);
 | 
					            const sorted = output.sort((a, b) =>
 | 
				
			||||||
 | 
					              a.label.localeCompare(b.label)
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            if (state.clientTreeSort === "alphafail") {
 | 
				
			||||||
 | 
					              // move failing clients to the top
 | 
				
			||||||
 | 
					              const failing = sorted.filter(
 | 
				
			||||||
 | 
					                (i) => i.color === "negative" || i.color === "warning"
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					              const ok = sorted.filter(
 | 
				
			||||||
 | 
					                (i) => i.color !== "negative" && i.color !== "warning"
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					              const sortedByFailing = [...failing, ...ok];
 | 
				
			||||||
 | 
					              commit("loadTree", sortedByFailing);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              commit("loadTree", sorted);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .catch(() => {
 | 
				
			||||||
 | 
					            state.treeReady = true;
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      checkVer(context) {
 | 
					      checkVer(context) {
 | 
				
			||||||
        axios.get("/core/version/").then((r) => {
 | 
					        axios.get("/core/version/").then((r) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,6 @@ export function formatScriptOptions(data) {
 | 
				
			|||||||
          value: script.id,
 | 
					          value: script.id,
 | 
				
			||||||
          timeout: script.default_timeout,
 | 
					          timeout: script.default_timeout,
 | 
				
			||||||
          args: script.args,
 | 
					          args: script.args,
 | 
				
			||||||
          env_vars: script.env_vars,
 | 
					 | 
				
			||||||
          filename: script.filename,
 | 
					          filename: script.filename,
 | 
				
			||||||
          syntax: script.syntax,
 | 
					          syntax: script.syntax,
 | 
				
			||||||
          script_type: script.script_type,
 | 
					          script_type: script.script_type,
 | 
				
			||||||
@@ -81,7 +80,6 @@ export function formatScriptOptions(data) {
 | 
				
			|||||||
          value: script.id,
 | 
					          value: script.id,
 | 
				
			||||||
          timeout: script.default_timeout,
 | 
					          timeout: script.default_timeout,
 | 
				
			||||||
          args: script.args,
 | 
					          args: script.args,
 | 
				
			||||||
          env_vars: script.env_vars,
 | 
					 | 
				
			||||||
          filename: script.filename,
 | 
					          filename: script.filename,
 | 
				
			||||||
          syntax: script.syntax,
 | 
					          syntax: script.syntax,
 | 
				
			||||||
          script_type: script.script_type,
 | 
					          script_type: script.script_type,
 | 
				
			||||||
@@ -287,7 +285,7 @@ export function formatDateInputField(isoDateString, noTimezone = false) {
 | 
				
			|||||||
  if (noTimezone) {
 | 
					  if (noTimezone) {
 | 
				
			||||||
    isoDateString = isoDateString.replace("Z", "");
 | 
					    isoDateString = isoDateString.replace("Z", "");
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return date.formatDate(isoDateString, "YYYY-MM-DDTHH:mm");
 | 
					  return date.formatDate(isoDateString, "YYYY-MM-DDTHH:mm:ss");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// converts a local date string "YYYY-MM-DDTHH:mm:ss" to an iso date string with the local timezone
 | 
					// converts a local date string "YYYY-MM-DDTHH:mm:ss" to an iso date string with the local timezone
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,18 +173,6 @@
 | 
				
			|||||||
                        </q-menu>
 | 
					                        </q-menu>
 | 
				
			||||||
                      </q-item>
 | 
					                      </q-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                      <!-- Bulk Run Checks -->
 | 
					 | 
				
			||||||
                      <q-item
 | 
					 | 
				
			||||||
                        clickable
 | 
					 | 
				
			||||||
                        v-close-popup
 | 
					 | 
				
			||||||
                        @click="runChecks(props.node)"
 | 
					 | 
				
			||||||
                      >
 | 
					 | 
				
			||||||
                        <q-item-section side>
 | 
					 | 
				
			||||||
                          <q-icon name="fas fa-check-double" />
 | 
					 | 
				
			||||||
                        </q-item-section>
 | 
					 | 
				
			||||||
                        <q-item-section>Run Checks</q-item-section>
 | 
					 | 
				
			||||||
                      </q-item>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                      <q-separator></q-separator>
 | 
					                      <q-separator></q-separator>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                      <q-item clickable v-close-popup>
 | 
					                      <q-item clickable v-close-popup>
 | 
				
			||||||
@@ -452,7 +440,7 @@ export default {
 | 
				
			|||||||
      showInstallAgentModal: false,
 | 
					      showInstallAgentModal: false,
 | 
				
			||||||
      sitePk: null,
 | 
					      sitePk: null,
 | 
				
			||||||
      innerModel: (this.$q.screen.height - 82) / 2,
 | 
					      innerModel: (this.$q.screen.height - 82) / 2,
 | 
				
			||||||
      search: this.$route.query.search ? this.$route.query.search : "",
 | 
					      search: "",
 | 
				
			||||||
      filterTextLength: 0,
 | 
					      filterTextLength: 0,
 | 
				
			||||||
      filterAvailability: "all",
 | 
					      filterAvailability: "all",
 | 
				
			||||||
      filterPatchesPending: false,
 | 
					      filterPatchesPending: false,
 | 
				
			||||||
@@ -702,17 +690,6 @@ export default {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
        .onOk(() => this.$store.dispatch("refreshDashboard"));
 | 
					        .onOk(() => this.$store.dispatch("refreshDashboard"));
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    runChecks(node) {
 | 
					 | 
				
			||||||
      const target = node.children ? "client" : "site";
 | 
					 | 
				
			||||||
      this.$axios
 | 
					 | 
				
			||||||
        .post(`/checks/${target}/${node.id}/csbulkrun/`)
 | 
					 | 
				
			||||||
        .then((r) => {
 | 
					 | 
				
			||||||
          this.notifySuccess(r.data);
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        .catch((e) => {
 | 
					 | 
				
			||||||
          console.error(e);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    showToggleMaintenance(node) {
 | 
					    showToggleMaintenance(node) {
 | 
				
			||||||
      let data = {
 | 
					      let data = {
 | 
				
			||||||
        id: node.id,
 | 
					        id: node.id,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,17 +4,8 @@
 | 
				
			|||||||
      <div class="col"></div>
 | 
					      <div class="col"></div>
 | 
				
			||||||
      <div class="col">
 | 
					      <div class="col">
 | 
				
			||||||
        <q-card>
 | 
					        <q-card>
 | 
				
			||||||
          <q-card-actions align="center">
 | 
					 | 
				
			||||||
            <q-btn
 | 
					 | 
				
			||||||
              label="Getting Started"
 | 
					 | 
				
			||||||
              color="info"
 | 
					 | 
				
			||||||
              class="full-width"
 | 
					 | 
				
			||||||
              href="https://docs.tacticalrmm.com/guide_gettingstarted/"
 | 
					 | 
				
			||||||
              target="_blank"
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </q-card-actions>
 | 
					 | 
				
			||||||
          <q-card-section class="row items-center">
 | 
					          <q-card-section class="row items-center">
 | 
				
			||||||
            <div class="text-h5 text-weight-bold">Initial Setup</div>
 | 
					            <div class="text-h6">Initial Setup</div>
 | 
				
			||||||
          </q-card-section>
 | 
					          </q-card-section>
 | 
				
			||||||
          <q-form @submit.prevent="finish">
 | 
					          <q-form @submit.prevent="finish">
 | 
				
			||||||
            <q-card-section>
 | 
					            <q-card-section>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@
 | 
				
			|||||||
        @click="restartMeshService"
 | 
					        @click="restartMeshService"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
      <q-btn
 | 
					      <q-btn
 | 
				
			||||||
        :color="dash_negative_color"
 | 
					        color="negative"
 | 
				
			||||||
        size="sm"
 | 
					        size="sm"
 | 
				
			||||||
        label="Recover Connection"
 | 
					        label="Recover Connection"
 | 
				
			||||||
        icon="fas fa-first-aid"
 | 
					        icon="fas fa-first-aid"
 | 
				
			||||||
@@ -35,7 +35,6 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
// composition imports
 | 
					// composition imports
 | 
				
			||||||
import { ref, computed, onMounted } from "vue";
 | 
					import { ref, computed, onMounted } from "vue";
 | 
				
			||||||
import { useStore } from "vuex";
 | 
					 | 
				
			||||||
import { useRoute } from "vue-router";
 | 
					import { useRoute } from "vue-router";
 | 
				
			||||||
import { useMeta, useQuasar } from "quasar";
 | 
					import { useMeta, useQuasar } from "quasar";
 | 
				
			||||||
import { fetchAgentMeshCentralURLs, sendAgentRecoverMesh } from "@/api/agents";
 | 
					import { fetchAgentMeshCentralURLs, sendAgentRecoverMesh } from "@/api/agents";
 | 
				
			||||||
@@ -48,17 +47,12 @@ export default {
 | 
				
			|||||||
  setup() {
 | 
					  setup() {
 | 
				
			||||||
    // vue lifecycle hooks
 | 
					    // vue lifecycle hooks
 | 
				
			||||||
    onMounted(() => {
 | 
					    onMounted(() => {
 | 
				
			||||||
      dashInfo();
 | 
					 | 
				
			||||||
      getDashInfo();
 | 
					      getDashInfo();
 | 
				
			||||||
      getMeshURLs();
 | 
					      getMeshURLs();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // quasar setup
 | 
					    // quasar setup
 | 
				
			||||||
    const $q = useQuasar();
 | 
					    const $q = useQuasar();
 | 
				
			||||||
    const store = useStore();
 | 
					 | 
				
			||||||
    const dash_positive_color = computed(() => store.state.dash_positive_color);
 | 
					 | 
				
			||||||
    const dash_negative_color = computed(() => store.state.dash_negative_color);
 | 
					 | 
				
			||||||
    const dash_warning_color = computed(() => store.state.dash_warning_color);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // vue router
 | 
					    // vue router
 | 
				
			||||||
    const { params } = useRoute();
 | 
					    const { params } = useRoute();
 | 
				
			||||||
@@ -70,19 +64,14 @@ export default {
 | 
				
			|||||||
    const statusColor = computed(() => {
 | 
					    const statusColor = computed(() => {
 | 
				
			||||||
      switch (status.value) {
 | 
					      switch (status.value) {
 | 
				
			||||||
        case "online":
 | 
					        case "online":
 | 
				
			||||||
          return dash_positive_color.value;
 | 
					          return "positive";
 | 
				
			||||||
        case "offline":
 | 
					        case "offline":
 | 
				
			||||||
          return dash_warning_color.value;
 | 
					          return "warning";
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
          return dash_negative_color.value;
 | 
					          return "negative";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO refactor this so we're not calling the api twice
 | 
					 | 
				
			||||||
    const dashInfo = () => {
 | 
					 | 
				
			||||||
      store.dispatch("getDashInfo", false);
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async function getMeshURLs() {
 | 
					    async function getMeshURLs() {
 | 
				
			||||||
      $q.loading.show();
 | 
					      $q.loading.show();
 | 
				
			||||||
      try {
 | 
					      try {
 | 
				
			||||||
@@ -142,7 +131,6 @@ export default {
 | 
				
			|||||||
      control,
 | 
					      control,
 | 
				
			||||||
      status,
 | 
					      status,
 | 
				
			||||||
      statusColor,
 | 
					      statusColor,
 | 
				
			||||||
      dash_negative_color,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // methods
 | 
					      // methods
 | 
				
			||||||
      repairMeshCentral,
 | 
					      repairMeshCentral,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user