Compare commits

..

11 Commits

Author SHA1 Message Date
wh1te909
99490bf859 Release 0.101.7 2022-11-13 01:20:33 +00:00
wh1te909
72cdeeaa6a Release 0.101.5 2022-10-25 22:02:34 +00:00
wh1te909
1eca4d605b Release 0.101.3 2022-10-19 22:35:54 +00:00
wh1te909
52ee98f6f8 Release 0.101.0 2022-09-24 02:43:53 +00:00
wh1te909
d270b877c9 Release 0.100.9 2022-08-23 05:04:57 +00:00
wh1te909
fd8b2a1d98 Release 0.100.8 2022-08-09 20:40:48 +00:00
wh1te909
f518043d8d Release 0.100.7 2022-08-01 17:36:11 +00:00
wh1te909
cc2335558d Release 0.100.6 2022-07-27 06:15:49 +00:00
wh1te909
a8a171ba2c Release 0.100.5 2022-07-10 00:00:08 +00:00
wh1te909
24a63f477e Release 0.100.4 2022-07-07 16:38:14 +00:00
wh1te909
ddeb6293a1 init 2022-05-17 20:46:22 +00:00
52 changed files with 4528 additions and 4324 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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,
} }
} }
} }

View File

@@ -1,22 +1,24 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<title><%= productName %></title> <head>
<title>
<%= productName %>
</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="robots" content="noindex" /> <meta name="robots" content="noindex" />
<meta name="description" content="<%= productDescription %>" /> <meta name="description" content="<%= productDescription %>" />
<meta name="format-detection" content="telephone=no" /> <meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" /> <meta name="msapplication-tap-highlight" content="no" />
<meta <meta name="viewport"
name="viewport" 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<% } %>" />
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" /> <link rel="icon" type="image/ico" href="favicon.ico" />
<script src="/env-config.js"></script> <script src="/env-config.js"></script>
</head> </head>
<body> <body>
<!-- quasar:entry-point --> <!-- quasar:entry-point -->
</body> </body>
</html> </html>

7042
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "web", "name": "web",
"version": "0.101.23-dev", "version": "0.101.7",
"private": true, "private": true,
"productName": "Tactical RMM", "productName": "Tactical RMM",
"scripts": { "scripts": {
@@ -10,13 +10,13 @@
"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.5",
"apexcharts": "3.41.0", "apexcharts": "3.35.5",
"axios": "1.4.0", "axios": "0.27.2",
"dotenv": "16.3.1", "dotenv": "16.0.3",
"qrcode.vue": "3.4.0", "qrcode.vue": "3.3.3",
"quasar": "2.12.1", "quasar": "2.10.1",
"vue": "3.2.47", "vue": "3.2.41",
"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",
@@ -24,17 +24,17 @@
"vuex": "4.1.0" "vuex": "4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@quasar/cli": "^2.2.1", "@quasar/cli": "^1.3.2",
"@intlify/unplugin-vue-i18n": "^0.10.0", "@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@quasar/app-vite": "^1.4.3", "@quasar/app-vite": "^1.1.3",
"@types/node": "^20.3.2", "@types/node": "^18.11.9",
"@typescript-eslint/eslint-plugin": "^5.60.1", "@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.60.1", "@typescript-eslint/parser": "^5.42.1",
"autoprefixer": "10.4.14", "autoprefixer": "^10.4.12",
"eslint": "8.43.0", "eslint": "^8.27.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.8.4"
} }
} }

View File

@@ -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')
], ]
}; }

View File

@@ -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

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -211,7 +211,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 +219,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 +227,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 +235,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 +243,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 +279,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 +303,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 +311,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>
@@ -378,13 +373,17 @@ export default {
"local_ips", "local_ips",
"make_model", "make_model",
"physical_disks", "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 // 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 for (const elem of hiddenFields) {
// https://github.com/amidaware/tacticalrmm/issues/1264 if (!cols.find((o) => o.name === elem)) {
const allColumns = [...cols, ...hiddenFields.map((field) => ({ field }))]; cols.push({
name: elem,
field: elem,
});
}
}
const lowerTerms = terms ? terms.toLowerCase() : ""; const lowerTerms = terms ? terms.toLowerCase() : "";
let advancedFilter = false; let advancedFilter = false;
@@ -438,12 +437,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 +489,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 +533,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;
}, },

View File

@@ -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+";

View File

@@ -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>

View File

@@ -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,

View File

@@ -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,
}; };
}, },
}; };

View File

@@ -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,

View File

@@ -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,

View File

@@ -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) => {

View File

@@ -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">
&bull; <q-badge color="green"> Maintenance Mode </q-badge> &bull; <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,

View File

@@ -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();
@@ -355,9 +348,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,

View File

@@ -42,9 +42,10 @@ export default {
const tabHeight = computed(() => store.state.tabHeight); const tabHeight = computed(() => store.state.tabHeight);
function copyValueToClip(val) { function copyValueToClip(val) {
copyToClipboard(val).then(() => { copyToClipboard(val)
.then(() => {
notifySuccess("Copied to clipboard"); notifySuccess("Copied to clipboard");
}); })
} }
return { return {

View File

@@ -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(() => {

View File

@@ -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"

View File

@@ -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,13 +132,8 @@ 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,
defaultTimeout,
defaultArgs,
defaultEnvVars,
} = useScriptDropdown(props.check ? props.check.script : undefined, {
onMount: true, onMount: true,
}); });
@@ -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,

View File

@@ -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);

View File

@@ -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

View File

@@ -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,

View File

@@ -89,8 +89,7 @@
<p class="text-italic"> <p class="text-italic">
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'"
v-if="info.plat === 'windows'"
type="a" type="a"
:href="info.data.url" :href="info.data.url"
color="primary" color="primary"

View File

@@ -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";
@@ -296,7 +284,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 +307,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 +404,6 @@ export default {
targetOptions, targetOptions,
patchModeOptions, patchModeOptions,
runAsUserToolTip, runAsUserToolTip,
envVarsLabel,
//computed //computed
modalTitle, modalTitle,

View File

@@ -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";
@@ -550,9 +549,6 @@ export default {
return result.trimEnd(","); return result.trimEnd(",");
}, },
}, },
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) => {

View File

@@ -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,15 +209,8 @@ 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,
defaultTimeout,
defaultArgs,
defaultEnvVars,
syntax,
link,
} = useScriptDropdown(props.script, {
onMount: true, onMount: true,
filterByPlatform: props.agent.plat, filterByPlatform: props.agent.plat,
}); });
@@ -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,

View File

@@ -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() {

View File

@@ -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">

View File

@@ -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,
}; };

View File

@@ -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,23 +57,7 @@
><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="{
right: '4px',
borderRadius: '5px',
width: '5px',
opacity: 0.75,
}"
:bar-style="{
right: '2px',
borderRadius: '9px',
width: '9px',
opacity: 0.2,
}"
class="col-4 q-mb-none q-pb-none"
:style="{ height: `${maximized ? '82vh' : '64vh'}` }"
>
<div class="q-gutter-sm q-pr-sm">
<q-input <q-input
filled filled
dense dense
@@ -144,17 +118,6 @@
new-value-mode="add" new-value-mode="add"
:readonly="readonly" :readonly="readonly"
/> />
<tactical-dropdown
v-model="formScript.env_vars"
:label="envVarsLabel"
filled
use-input
multiple
hide-dropdown-icon
input-debounce="0"
new-value-mode="add"
:readonly="readonly"
/>
<q-input <q-input
type="number" type="number"
filled filled
@@ -170,11 +133,11 @@
label="Run As User (Windows only)" label="Run As User (Windows only)"
> >
<q-tooltip <q-tooltip
>Setting this value on the script model will always override >Setting this value on the script model will always override any
any 'Run As User' checkboxes in the UI and force this script 'Run As User' checkboxes in the UI and force this script to
to always be run in the context of the logged in user. If no always be run in the context of the logged in user. If no user
user is logged in, the script will not run and an error will is logged in, the script will not run and an error will be
be returned. returned. Not supported on Windows Server.
</q-tooltip> </q-tooltip>
</q-checkbox> </q-checkbox>
<q-input <q-input
@@ -187,13 +150,12 @@
:readonly="readonly" :readonly="readonly"
/> />
</div> </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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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"

View File

@@ -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);

View File

@@ -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,13 +817,8 @@ 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,
defaultTimeout,
defaultArgs,
defaultEnvVars,
} = useScriptDropdown(undefined, {
onMount: true, onMount: true,
}); });
@@ -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,

View File

@@ -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>

View File

@@ -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,12 +28,10 @@ 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 = [

View File

@@ -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,

View File

@@ -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,
};

View File

@@ -20,14 +20,9 @@
class="bg-yellow text-black text-center" class="bg-yellow text-black text-center"
> >
<q-icon size="xl" name="warning" /> <q-icon size="xl" name="warning" />
<span <span><br />Your code signing token is no longer valid.<br/><br/>
><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/>
If you have downgraded or cancelled your sponsorship, please delete For any issues or to renew your sponsorship please email support@amidaware.com<br/><br/></span>
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 <q-btn
color="dark" color="dark"
icon="refresh" icon="refresh"
@@ -56,27 +51,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"
class="text-overline q-ml-sm"
:color="dash_warning_color"
icon="update"
dense
><a :href="latestReleaseURL" target="_blank" ><a :href="latestReleaseURL" target="_blank"
>v{{ latestTRMMVersion }} available</a >v{{ latestTRMMVersion }} available</a
></q-chip ></q-badge
> ></span
<!-- 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 +89,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 +108,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 +135,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 +156,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",
@@ -238,8 +184,6 @@ export default {
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 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 +197,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 +208,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 +220,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 +243,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,7 +270,6 @@ export default {
serverOfflineCount, serverOfflineCount,
workstationCount, workstationCount,
workstationOfflineCount, workstationOfflineCount,
daysUntilCertExpires,
latestReleaseURL, latestReleaseURL,
currentTRMMVersion, currentTRMMVersion,
latestTRMMVersion, latestTRMMVersion,
@@ -369,13 +278,9 @@ export default {
darkMode, darkMode,
hosted, hosted,
tokenExpired, tokenExpired,
dash_warning_color,
dash_negative_color,
// methods // methods
showUserPreferences, showUserPreferences,
resetPassword,
reset2FA,
updateAvailable, updateAvailable,
}; };
}, },

View File

@@ -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,
}); });
} }
}); });

View File

@@ -33,16 +33,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: {
@@ -146,24 +136,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 +160,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,38 +194,35 @@ 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); context.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) => {
@@ -326,7 +295,6 @@ export default function () {
.catch(() => { .catch(() => {
state.treeReady = true; state.treeReady = true;
}); });
}, 150);
}, },
checkVer(context) { checkVer(context) {
axios.get("/core/version/").then((r) => { axios.get("/core/version/").then((r) => {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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>

View File

@@ -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,