Compare commits
24 Commits
v0.100.6-d
...
v0.101.4-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17d960fca9 | ||
|
|
d2e0b8ad9b | ||
|
|
776c27ec26 | ||
|
|
41c61ce152 | ||
|
|
8e9de8b6b6 | ||
|
|
4cf5f7a3cb | ||
|
|
9729492d1c | ||
|
|
d6da8b4a96 | ||
|
|
9264cf4044 | ||
|
|
3a45c2a309 | ||
|
|
59de35c698 | ||
|
|
5b8ac2c809 | ||
|
|
83d0ff1c0a | ||
|
|
8a6ec6ceab | ||
|
|
93dbc74e33 | ||
|
|
5f2add48a9 | ||
|
|
b7369875af | ||
|
|
2eb6580fed | ||
|
|
9f85fbb330 | ||
|
|
ee9715a4cf | ||
|
|
76f330fb9c | ||
|
|
e67c1ff331 | ||
|
|
137a5648ce | ||
|
|
a944bc50d1 |
7
.devcontainer/.env.example
Normal file
7
.devcontainer/.env.example
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
COMPOSE_PROJECT_NAME=trmm
|
||||||
|
IMAGE_REPO=tacticalrmm/
|
||||||
|
VERSION=latest
|
||||||
|
|
||||||
|
# DEV SETTINGS
|
||||||
|
APP_PORT=443
|
||||||
|
DOCKER_NETWORK=172.21.0.0/24
|
||||||
26
.devcontainer/docker-compose.yml
Normal file
26
.devcontainer/docker-compose.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
version: '3.4'
|
||||||
|
|
||||||
|
services:
|
||||||
|
app-dev:
|
||||||
|
container_name: trmm-app-dev
|
||||||
|
image: node:16-alpine
|
||||||
|
restart: always
|
||||||
|
command: /bin/sh -c "npm install --cache ~/.npm && npm run serve"
|
||||||
|
user: 1000:1000
|
||||||
|
working_dir: /workspace/web
|
||||||
|
volumes:
|
||||||
|
- ..:/workspace:cached
|
||||||
|
ports:
|
||||||
|
- "8080:443"
|
||||||
|
networks:
|
||||||
|
dev:
|
||||||
|
aliases:
|
||||||
|
- tactical-frontend
|
||||||
|
|
||||||
|
networks:
|
||||||
|
dev:
|
||||||
|
driver: bridge
|
||||||
|
ipam:
|
||||||
|
driver: default
|
||||||
|
config:
|
||||||
|
- subnet: ${DOCKER_NETWORK}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,3 +33,4 @@ yarn-error.log*
|
|||||||
*.sln
|
*.sln
|
||||||
|
|
||||||
.env
|
.env
|
||||||
|
/public/env-config.js
|
||||||
|
|||||||
1496
package-lock.json
generated
1496
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "web",
|
"name": "web",
|
||||||
"version": "0.100.6-dev",
|
"version": "0.101.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"productName": "Tactical RMM",
|
"productName": "Tactical RMM",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -10,31 +10,31 @@
|
|||||||
"format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
|
"format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@quasar/extras": "1.15.0",
|
"@quasar/extras": "1.15.5",
|
||||||
"apexcharts": "3.35.4",
|
"apexcharts": "3.35.5",
|
||||||
"axios": "0.27.2",
|
"axios": "0.27.2",
|
||||||
"dotenv": "16.0.1",
|
"dotenv": "16.0.3",
|
||||||
"qrcode.vue": "3.3.3",
|
"qrcode.vue": "3.3.3",
|
||||||
"quasar": "2.7.5",
|
"quasar": "2.10.0",
|
||||||
"vue": "3.2.37",
|
"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",
|
||||||
"vue-router": "4.1.2",
|
"vue-router": "4.1.6",
|
||||||
"vuex": "4.0.2"
|
"vuex": "4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@quasar/cli": "^1.3.2",
|
"@quasar/cli": "^1.3.2",
|
||||||
"@intlify/vite-plugin-vue-i18n": "^5.0.1",
|
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
|
||||||
"@quasar/app-vite": "^1.0.5",
|
"@quasar/app-vite": "^1.1.3",
|
||||||
"@types/node": "^18.6.1",
|
"@types/node": "^18.11.5",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||||
"@typescript-eslint/parser": "^5.30.5",
|
"@typescript-eslint/parser": "^5.41.0",
|
||||||
"autoprefixer": "^10.4.7",
|
"autoprefixer": "^10.4.12",
|
||||||
"eslint": "^8.20.0",
|
"eslint": "^8.26.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-vue": "^8.5.0",
|
"eslint-plugin-vue": "^8.5.0",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"typescript": "^4.7.4"
|
"typescript": "^4.8.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,6 +196,14 @@
|
|||||||
>
|
>
|
||||||
<q-tooltip>Linux</q-tooltip>
|
<q-tooltip>Linux</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
|
<q-icon
|
||||||
|
v-else-if="props.row.plat === 'darwin'"
|
||||||
|
name="mdi-apple"
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<q-tooltip>macOS</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
</q-td>
|
</q-td>
|
||||||
|
|
||||||
<q-td key="checks-status" :props="props">
|
<q-td key="checks-status" :props="props">
|
||||||
@@ -356,6 +364,27 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
filterTable(rows, terms, cols, cellValue) {
|
filterTable(rows, terms, cols, cellValue) {
|
||||||
|
const hiddenFields = [
|
||||||
|
"version",
|
||||||
|
"operating_system",
|
||||||
|
"public_ip",
|
||||||
|
"cpu_model",
|
||||||
|
"graphics",
|
||||||
|
"local_ips",
|
||||||
|
"make_model",
|
||||||
|
"physical_disks",
|
||||||
|
];
|
||||||
|
|
||||||
|
// quasar filter only does visible columns so this is a hack to add hidden columns we want to filter
|
||||||
|
for (const elem of hiddenFields) {
|
||||||
|
if (!cols.find((o) => o.name === elem)) {
|
||||||
|
cols.push({
|
||||||
|
name: elem,
|
||||||
|
field: elem,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const lowerTerms = terms ? terms.toLowerCase() : "";
|
const lowerTerms = terms ? terms.toLowerCase() : "";
|
||||||
let advancedFilter = false;
|
let advancedFilter = false;
|
||||||
let availability = null;
|
let availability = null;
|
||||||
|
|||||||
@@ -310,9 +310,10 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showUpdateDetails(update) {
|
function showUpdateDetails(update) {
|
||||||
|
const color = $q.dark.isActive ? "white" : "";
|
||||||
let support_urls = "";
|
let support_urls = "";
|
||||||
update.more_info_urls.forEach((u) => {
|
update.more_info_urls.forEach((u) => {
|
||||||
support_urls += `<a href='${u}' target='_blank'>${u}</a><br/>`;
|
support_urls += `<a style='color: ${color}' href='${u}' target='_blank'>${u}</a><br/>`;
|
||||||
});
|
});
|
||||||
let cats = update.categories.join(", ");
|
let cats = update.categories.join(", ");
|
||||||
$q.dialog({
|
$q.dialog({
|
||||||
|
|||||||
@@ -7,6 +7,17 @@
|
|||||||
<q-badge color="primary" class="q-ml-sm text-caption">{{
|
<q-badge color="primary" class="q-ml-sm text-caption">{{
|
||||||
v
|
v
|
||||||
}}</q-badge>
|
}}</q-badge>
|
||||||
|
<q-btn
|
||||||
|
v-if="!!v"
|
||||||
|
size="sm"
|
||||||
|
class="q-ml-xs"
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="content_copy"
|
||||||
|
@click="copyValueToClip(v)"
|
||||||
|
>
|
||||||
|
<q-tooltip>Copy to Clipboard</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-separator v-if="info.length > 1" />
|
<q-separator v-if="info.length > 1" />
|
||||||
@@ -15,6 +26,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { copyToClipboard } from "quasar";
|
||||||
|
import { notifySuccess } from "@/utils/notify";
|
||||||
// composition imports
|
// composition imports
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { useStore } from "vuex";
|
import { useStore } from "vuex";
|
||||||
@@ -28,9 +41,17 @@ export default {
|
|||||||
const store = useStore();
|
const store = useStore();
|
||||||
const tabHeight = computed(() => store.state.tabHeight);
|
const tabHeight = computed(() => store.state.tabHeight);
|
||||||
|
|
||||||
|
function copyValueToClip(val) {
|
||||||
|
copyToClipboard(val)
|
||||||
|
.then(() => {
|
||||||
|
notifySuccess("Copied to clipboard");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tabHeight,
|
tabHeight,
|
||||||
uid,
|
uid,
|
||||||
|
copyValueToClip,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// component lifecycle hooks
|
// component lifecycle hooks
|
||||||
onMounted(getAPIKeys());
|
onMounted(getAPIKeys);
|
||||||
return {
|
return {
|
||||||
// reactive data
|
// reactive data
|
||||||
keys,
|
keys,
|
||||||
|
|||||||
@@ -10,10 +10,13 @@
|
|||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<p class="text-subtitle1">
|
<p v-if="info.plat === 'windows'" class="text-subtitle1">
|
||||||
Download the agent then run the following command from an elevated
|
Download the agent then run the following command from an elevated
|
||||||
command prompt on the device you want to add.
|
command prompt on the device you want to add.
|
||||||
</p>
|
</p>
|
||||||
|
<p v-else-if="info.plat === 'darwin'" class="text-subtitle1">
|
||||||
|
Run the following command from a terminal
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<q-field outlined :color="$q.dark.isActive ? 'white' : 'black'">
|
<q-field outlined :color="$q.dark.isActive ? 'white' : 'black'">
|
||||||
<code>{{ info.data.cmd }}</code>
|
<code>{{ info.data.cmd }}</code>
|
||||||
@@ -37,7 +40,7 @@
|
|||||||
</q-badge>
|
</q-badge>
|
||||||
<span>Do not popup any message boxes during install</span>
|
<span>Do not popup any message boxes during install</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pa-xs q-gutter-xs">
|
<div v-if="info.plat === 'windows'" class="q-pa-xs q-gutter-xs">
|
||||||
<q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
|
<q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
|
||||||
<code
|
<code
|
||||||
>-local-mesh "C:\\<some folder or
|
>-local-mesh "C:\\<some folder or
|
||||||
@@ -46,7 +49,7 @@
|
|||||||
</q-badge>
|
</q-badge>
|
||||||
<span> To skip downloading the Mesh Agent during the install.</span>
|
<span> To skip downloading the Mesh Agent during the install.</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pa-xs q-gutter-xs">
|
<div v-if="info.plat === 'windows'" class="q-pa-xs q-gutter-xs">
|
||||||
<q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
|
<q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
|
||||||
<code
|
<code
|
||||||
>-meshdir "C:\Program Files\Your Company Name\Mesh Agent"</code
|
>-meshdir "C:\Program Files\Your Company Name\Mesh Agent"</code
|
||||||
@@ -63,7 +66,7 @@
|
|||||||
</q-badge>
|
</q-badge>
|
||||||
<span>Don't install the mesh agent</span>
|
<span>Don't install the mesh agent</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pa-xs q-gutter-xs">
|
<div v-if="info.plat === 'windows'" class="q-pa-xs q-gutter-xs">
|
||||||
<q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
|
<q-badge class="text-caption q-mr-xs" color="grey" text-color="black">
|
||||||
<code>-cert "C:\\<some folder or path>\\ca.pem"</code>
|
<code>-cert "C:\\<some folder or path>\\ca.pem"</code>
|
||||||
</q-badge>
|
</q-badge>
|
||||||
@@ -86,12 +89,12 @@
|
|||||||
<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'"
|
||||||
type="a"
|
type="a"
|
||||||
:href="info.data.url"
|
:href="info.data.url"
|
||||||
color="primary"
|
color="primary"
|
||||||
label="Download Agent"
|
label="Download Agent"
|
||||||
/>
|
></q-btn>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -135,6 +135,11 @@
|
|||||||
:rules="[(val) => !!val || '*Required']"
|
:rules="[(val) => !!val || '*Required']"
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-card-section v-if="supportsRunAsUser()" class="q-pt-none">
|
||||||
|
<q-checkbox v-model="state.run_as_user" label="Run As User">
|
||||||
|
<q-tooltip>{{ runAsUserToolTip }}</q-tooltip>
|
||||||
|
</q-checkbox>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
<q-card-section v-if="mode === 'script' || mode === 'command'">
|
<q-card-section v-if="mode === 'script' || mode === 'command'">
|
||||||
<q-input
|
<q-input
|
||||||
@@ -203,6 +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 { runAsUserToolTip } from "@/constants/constants";
|
||||||
|
|
||||||
// ui imports
|
// ui imports
|
||||||
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
|
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
|
||||||
@@ -217,6 +223,7 @@ const monTypeOptions = [
|
|||||||
const osTypeOptions = [
|
const osTypeOptions = [
|
||||||
{ label: "Windows", value: "windows" },
|
{ label: "Windows", value: "windows" },
|
||||||
{ label: "Linux", value: "linux" },
|
{ label: "Linux", value: "linux" },
|
||||||
|
{ label: "macOS", value: "darwin" },
|
||||||
{ label: "All", value: "all" },
|
{ label: "All", value: "all" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -300,6 +307,7 @@ export default {
|
|||||||
script,
|
script,
|
||||||
timeout: defaultTimeout,
|
timeout: defaultTimeout,
|
||||||
args: defaultArgs,
|
args: defaultArgs,
|
||||||
|
run_as_user: false,
|
||||||
});
|
});
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
@@ -316,6 +324,7 @@ export default {
|
|||||||
() => state.value.osType,
|
() => state.value.osType,
|
||||||
(newValue) => {
|
(newValue) => {
|
||||||
state.value.custom_shell = null;
|
state.value.custom_shell = null;
|
||||||
|
state.value.run_as_user = false;
|
||||||
|
|
||||||
if (newValue === "windows") {
|
if (newValue === "windows") {
|
||||||
state.value.shell = "cmd";
|
state.value.shell = "cmd";
|
||||||
@@ -337,6 +346,13 @@ export default {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const supportsRunAsUser = () => {
|
||||||
|
const modes = ["script", "command"];
|
||||||
|
return (
|
||||||
|
state.value.osType === "windows" && modes.includes(state.value.mode)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// set modal title and caption
|
// set modal title and caption
|
||||||
const modalTitle = computed(() => {
|
const modalTitle = computed(() => {
|
||||||
return props.mode === "command"
|
return props.mode === "command"
|
||||||
@@ -387,6 +403,7 @@ export default {
|
|||||||
osTypeOptions,
|
osTypeOptions,
|
||||||
targetOptions,
|
targetOptions,
|
||||||
patchModeOptions,
|
patchModeOptions,
|
||||||
|
runAsUserToolTip,
|
||||||
|
|
||||||
//computed
|
//computed
|
||||||
modalTitle,
|
modalTitle,
|
||||||
@@ -394,6 +411,7 @@ export default {
|
|||||||
//methods
|
//methods
|
||||||
submit,
|
submit,
|
||||||
cmdPlaceholder,
|
cmdPlaceholder,
|
||||||
|
supportsRunAsUser,
|
||||||
|
|
||||||
// quasar dialog plugin
|
// quasar dialog plugin
|
||||||
dialogRef,
|
dialogRef,
|
||||||
|
|||||||
@@ -465,8 +465,51 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
editAgent() {
|
editAgent() {
|
||||||
delete this.agent.all_timezones;
|
// TODO we need to fix the serializer to not send this stuff
|
||||||
delete this.agent.timezone;
|
const toRemove = [
|
||||||
|
"created_by",
|
||||||
|
"created_time",
|
||||||
|
"modified_by",
|
||||||
|
"modified_time",
|
||||||
|
"all_timezones",
|
||||||
|
"timezone",
|
||||||
|
"wmi_detail",
|
||||||
|
"services",
|
||||||
|
"status",
|
||||||
|
"cpu_model",
|
||||||
|
"local_ips",
|
||||||
|
"make_model",
|
||||||
|
"physical_disks",
|
||||||
|
"graphics",
|
||||||
|
"checks",
|
||||||
|
"patches_last_installed",
|
||||||
|
"last_seen",
|
||||||
|
"applied_policies",
|
||||||
|
"effective_patch_policy",
|
||||||
|
"version",
|
||||||
|
"operating_system",
|
||||||
|
"plat",
|
||||||
|
"goarch",
|
||||||
|
"hostname",
|
||||||
|
"public_ip",
|
||||||
|
"total_ram",
|
||||||
|
"disks",
|
||||||
|
"boot_time",
|
||||||
|
"logged_in_username",
|
||||||
|
"last_logged_in_user",
|
||||||
|
"needs_reboot",
|
||||||
|
"choco_installed",
|
||||||
|
"policy",
|
||||||
|
"mesh_node_id",
|
||||||
|
"block_policy_inheritance",
|
||||||
|
"maintenance_mode",
|
||||||
|
"alert_template",
|
||||||
|
"client",
|
||||||
|
"site_name",
|
||||||
|
];
|
||||||
|
for (const elem of toRemove) {
|
||||||
|
delete this.agent[elem];
|
||||||
|
}
|
||||||
|
|
||||||
// only send the timezone data if it has changed
|
// only send the timezone data if it has changed
|
||||||
// this way django will keep the db column as null and inherit from the global setting
|
// this way django will keep the db column as null and inherit from the global setting
|
||||||
@@ -503,7 +546,7 @@ export default {
|
|||||||
else if (day === 0) result += "Sun, ";
|
else if (day === 0) result += "Sun, ";
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.trimRight(",");
|
return result.trimEnd(",");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@@ -52,6 +52,15 @@
|
|||||||
goarch = GOARCH_AMD64;
|
goarch = GOARCH_AMD64;
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
<q-radio
|
||||||
|
v-model="agentOS"
|
||||||
|
val="darwin"
|
||||||
|
label="macOS"
|
||||||
|
@update:model-value="
|
||||||
|
installMethod = 'mac';
|
||||||
|
goarch = GOARCH_AMD64;
|
||||||
|
"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
@@ -105,37 +114,37 @@
|
|||||||
v-model="goarch"
|
v-model="goarch"
|
||||||
:val="GOARCH_AMD64"
|
:val="GOARCH_AMD64"
|
||||||
label="64 bit"
|
label="64 bit"
|
||||||
v-show="agentOS === 'windows'"
|
v-show="agentOS === 'windows' || agentOS === 'linux'"
|
||||||
/>
|
|
||||||
<q-radio
|
|
||||||
v-model="goarch"
|
|
||||||
:val="GOARCH_i386"
|
|
||||||
label="32 bit"
|
|
||||||
v-show="agentOS === 'windows'"
|
|
||||||
/>
|
/>
|
||||||
<q-radio
|
<q-radio
|
||||||
v-model="goarch"
|
v-model="goarch"
|
||||||
:val="GOARCH_AMD64"
|
:val="GOARCH_AMD64"
|
||||||
label="64 bit"
|
label="Intel 64 bit"
|
||||||
v-show="agentOS !== 'windows'"
|
v-show="agentOS === 'darwin'"
|
||||||
/>
|
/>
|
||||||
<q-radio
|
<q-radio
|
||||||
v-model="goarch"
|
v-model="goarch"
|
||||||
:val="GOARCH_i386"
|
:val="GOARCH_i386"
|
||||||
label="32 bit"
|
label="32 bit"
|
||||||
v-show="agentOS !== 'windows'"
|
v-show="agentOS !== 'darwin'"
|
||||||
/>
|
/>
|
||||||
<q-radio
|
<q-radio
|
||||||
v-model="goarch"
|
v-model="goarch"
|
||||||
:val="GOARCH_ARM64"
|
:val="GOARCH_ARM64"
|
||||||
label="ARM 64 bit"
|
label="ARM 64 bit"
|
||||||
v-show="agentOS !== 'windows'"
|
v-show="agentOS === 'linux'"
|
||||||
|
/>
|
||||||
|
<q-radio
|
||||||
|
v-model="goarch"
|
||||||
|
:val="GOARCH_ARM64"
|
||||||
|
label="Apple Silicon (M1, M2)"
|
||||||
|
v-show="agentOS === 'darwin'"
|
||||||
/>
|
/>
|
||||||
<q-radio
|
<q-radio
|
||||||
v-model="goarch"
|
v-model="goarch"
|
||||||
:val="GOARCH_ARM32"
|
:val="GOARCH_ARM32"
|
||||||
label="ARM 32 bit (Rasp Pi)"
|
label="ARM 32 bit (Rasp Pi)"
|
||||||
v-show="agentOS !== 'windows'"
|
v-show="agentOS === 'linux'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
@@ -266,12 +275,13 @@ export default {
|
|||||||
plat: this.agentOS,
|
plat: this.agentOS,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.installMethod === "manual") {
|
if (this.installMethod === "manual" || this.installMethod === "mac") {
|
||||||
this.$axios.post("/agents/installer/", data).then((r) => {
|
this.$axios.post("/agents/installer/", data).then((r) => {
|
||||||
this.info = {
|
this.info = {
|
||||||
expires: this.expires,
|
expires: this.expires,
|
||||||
data: r.data,
|
data: r.data,
|
||||||
goarch: this.goarch,
|
goarch: this.goarch,
|
||||||
|
plat: this.agentOS,
|
||||||
};
|
};
|
||||||
this.showAgentDownload = true;
|
this.showAgentDownload = true;
|
||||||
});
|
});
|
||||||
@@ -343,6 +353,9 @@ export default {
|
|||||||
case "bash":
|
case "bash":
|
||||||
text = "Download linux install script";
|
text = "Download linux install script";
|
||||||
break;
|
break;
|
||||||
|
case "mac":
|
||||||
|
text = "Show installation instructions";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
|||||||
@@ -128,6 +128,11 @@
|
|||||||
/>
|
/>
|
||||||
<q-checkbox v-model="state.save_all_output" label="Save all output" />
|
<q-checkbox v-model="state.save_all_output" label="Save all output" />
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-card-section v-if="agent.plat === 'windows'">
|
||||||
|
<q-checkbox v-model="state.run_as_user" label="Run As User">
|
||||||
|
<q-tooltip>{{ runAsUserToolTip }}</q-tooltip>
|
||||||
|
</q-checkbox>
|
||||||
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-input
|
<q-input
|
||||||
v-model.number="state.timeout"
|
v-model.number="state.timeout"
|
||||||
@@ -173,6 +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 { runAsUserToolTip } from "@/constants/constants";
|
||||||
import {
|
import {
|
||||||
formatScriptSyntax,
|
formatScriptSyntax,
|
||||||
removeExtraOptionCategories,
|
removeExtraOptionCategories,
|
||||||
@@ -220,6 +226,7 @@ export default {
|
|||||||
script,
|
script,
|
||||||
args: defaultArgs,
|
args: defaultArgs,
|
||||||
timeout: defaultTimeout,
|
timeout: defaultTimeout,
|
||||||
|
run_as_user: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const ret = ref(null);
|
const ret = ref(null);
|
||||||
@@ -273,6 +280,7 @@ export default {
|
|||||||
|
|
||||||
// non-reactive data
|
// non-reactive data
|
||||||
outputOptions,
|
outputOptions,
|
||||||
|
runAsUserToolTip,
|
||||||
|
|
||||||
//methods
|
//methods
|
||||||
formatScriptSyntax,
|
formatScriptSyntax,
|
||||||
|
|||||||
@@ -51,6 +51,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-card-section v-if="agent.plat === 'windows'">
|
||||||
|
<q-checkbox v-model="state.run_as_user" label="Run As User">
|
||||||
|
<q-tooltip>{{ runAsUserToolTip }}</q-tooltip>
|
||||||
|
</q-checkbox>
|
||||||
|
</q-card-section>
|
||||||
<q-card-section v-if="state.shell === 'custom'">
|
<q-card-section v-if="state.shell === 'custom'">
|
||||||
<q-input
|
<q-input
|
||||||
v-model="state.custom_shell"
|
v-model="state.custom_shell"
|
||||||
@@ -117,6 +122,7 @@ import { ref } from "vue";
|
|||||||
import { useDialogPluginComponent } from "quasar";
|
import { useDialogPluginComponent } from "quasar";
|
||||||
import { sendAgentCommand } from "@/api/agents";
|
import { sendAgentCommand } from "@/api/agents";
|
||||||
import { cmdPlaceholder } from "@/composables/agents";
|
import { cmdPlaceholder } from "@/composables/agents";
|
||||||
|
import { runAsUserToolTip } from "@/constants/constants";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SendCommand",
|
name: "SendCommand",
|
||||||
@@ -134,6 +140,7 @@ export default {
|
|||||||
cmd: null,
|
cmd: null,
|
||||||
timeout: 30,
|
timeout: 30,
|
||||||
custom_shell: null,
|
custom_shell: null,
|
||||||
|
run_as_user: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@@ -156,6 +163,9 @@ export default {
|
|||||||
loading,
|
loading,
|
||||||
ret,
|
ret,
|
||||||
|
|
||||||
|
// non reactivete data
|
||||||
|
runAsUserToolTip,
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
submit,
|
submit,
|
||||||
cmdPlaceholder,
|
cmdPlaceholder,
|
||||||
|
|||||||
@@ -128,6 +128,18 @@
|
|||||||
:rules="[(val) => val >= 5 || 'Minimum is 5']"
|
:rules="[(val) => val >= 5 || 'Minimum is 5']"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
/>
|
/>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="formScript.run_as_user"
|
||||||
|
label="Run As User (Windows only)"
|
||||||
|
>
|
||||||
|
<q-tooltip
|
||||||
|
>Setting this value on the script model will always override any
|
||||||
|
'Run As User' checkboxes in the UI and force this script to
|
||||||
|
always be run in the context of the logged in user. If no user
|
||||||
|
is logged in, the script will not run and an error will be
|
||||||
|
returned. Not supported on Windows Server.
|
||||||
|
</q-tooltip>
|
||||||
|
</q-checkbox>
|
||||||
<q-input
|
<q-input
|
||||||
label="Syntax"
|
label="Syntax"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
@@ -253,6 +265,7 @@ export default {
|
|||||||
default_timeout: 90,
|
default_timeout: 90,
|
||||||
args: [],
|
args: [],
|
||||||
script_body: "",
|
script_body: "",
|
||||||
|
run_as_user: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (props.clone) script.value.name = `(Copy) ${script.value.name}`;
|
if (props.clone) script.value.name = `(Copy) ${script.value.name}`;
|
||||||
|
|||||||
@@ -867,7 +867,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// component life cycle hooks
|
// component life cycle hooks
|
||||||
onMounted(getScripts());
|
onMounted(getScripts);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// reactive data
|
// reactive data
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export default {
|
|||||||
timeout: props.script.default_timeout,
|
timeout: props.script.default_timeout,
|
||||||
args: props.script.args,
|
args: props.script.args,
|
||||||
shell: props.script.shell,
|
shell: props.script.shell,
|
||||||
|
run_as_user: props.script.run_as_user,
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
ret.value = await testScript(props.agent, data);
|
ret.value = await testScript(props.agent, data);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function useUserDropdown(onMount = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (onMount) {
|
if (onMount) {
|
||||||
onMounted(getUserOptions());
|
onMounted(getUserOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -37,4 +37,5 @@ export function cmdPlaceholder(shell) {
|
|||||||
export const agentPlatformOptions = [
|
export const agentPlatformOptions = [
|
||||||
{ value: "windows", label: "Windows" },
|
{ value: "windows", label: "Windows" },
|
||||||
{ value: "linux", label: "Linux" },
|
{ value: "linux", label: "Linux" },
|
||||||
|
{ value: "darwin", label: "macOS" },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,4 +3,13 @@ const GOARCH_i386 = "386";
|
|||||||
const GOARCH_ARM64 = "arm64";
|
const GOARCH_ARM64 = "arm64";
|
||||||
const GOARCH_ARM32 = "arm";
|
const GOARCH_ARM32 = "arm";
|
||||||
|
|
||||||
export { GOARCH_AMD64, GOARCH_i386, GOARCH_ARM64, GOARCH_ARM32 };
|
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. Not supported on Windows Server.";
|
||||||
|
|
||||||
|
export {
|
||||||
|
GOARCH_AMD64,
|
||||||
|
GOARCH_i386,
|
||||||
|
GOARCH_ARM64,
|
||||||
|
GOARCH_ARM32,
|
||||||
|
runAsUserToolTip,
|
||||||
|
};
|
||||||
|
|||||||
@@ -14,6 +14,22 @@
|
|||||||
@click="$store.dispatch('reload')"
|
@click="$store.dispatch('reload')"
|
||||||
/>
|
/>
|
||||||
</q-banner>
|
</q-banner>
|
||||||
|
<q-banner
|
||||||
|
v-if="!hosted && tokenExpired"
|
||||||
|
inline-actions
|
||||||
|
class="bg-yellow text-black text-center"
|
||||||
|
>
|
||||||
|
<q-icon size="xl" name="warning" />
|
||||||
|
<span><br />Your code signing token is no longer valid.<br/><br/>
|
||||||
|
If you have downgraded or cancelled your sponsorship, please delete your token from the Code Signing modal and refresh to get rid of this banner.<br/><br/>
|
||||||
|
For any issues or to renew your sponsorship please email support@amidaware.com<br/><br/></span>
|
||||||
|
<q-btn
|
||||||
|
color="dark"
|
||||||
|
icon="refresh"
|
||||||
|
label="Refresh"
|
||||||
|
@click="$store.dispatch('reload')"
|
||||||
|
/>
|
||||||
|
</q-banner>
|
||||||
<q-toolbar>
|
<q-toolbar>
|
||||||
<q-btn
|
<q-btn
|
||||||
dense
|
dense
|
||||||
@@ -167,6 +183,7 @@ export default {
|
|||||||
const needRefresh = computed(() => store.state.needrefresh);
|
const needRefresh = computed(() => store.state.needrefresh);
|
||||||
const user = computed(() => store.state.username);
|
const user = computed(() => store.state.username);
|
||||||
const hosted = computed(() => store.state.hosted);
|
const hosted = computed(() => store.state.hosted);
|
||||||
|
const tokenExpired = computed(() => store.state.tokenExpired);
|
||||||
|
|
||||||
const latestReleaseURL = computed(() => {
|
const latestReleaseURL = computed(() => {
|
||||||
return latestTRMMVersion.value
|
return latestTRMMVersion.value
|
||||||
@@ -259,6 +276,8 @@ export default {
|
|||||||
user,
|
user,
|
||||||
needRefresh,
|
needRefresh,
|
||||||
darkMode,
|
darkMode,
|
||||||
|
hosted,
|
||||||
|
tokenExpired,
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
showUserPreferences,
|
showUserPreferences,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export default function () {
|
|||||||
agentPlatform: "windows",
|
agentPlatform: "windows",
|
||||||
agentTableLoading: false,
|
agentTableLoading: false,
|
||||||
needrefresh: false,
|
needrefresh: false,
|
||||||
|
tokenExpired: false,
|
||||||
refreshSummaryTab: false,
|
refreshSummaryTab: false,
|
||||||
tableHeight: "300px",
|
tableHeight: "300px",
|
||||||
tabHeight: "300px",
|
tabHeight: "300px",
|
||||||
@@ -83,6 +84,9 @@ export default function () {
|
|||||||
SET_REFRESH_NEEDED(state, action) {
|
SET_REFRESH_NEEDED(state, action) {
|
||||||
state.needrefresh = action;
|
state.needrefresh = action;
|
||||||
},
|
},
|
||||||
|
SET_TOKEN_EXPIRED(state, action) {
|
||||||
|
state.tokenExpired = action;
|
||||||
|
},
|
||||||
SET_SPLITTER(state, val) {
|
SET_SPLITTER(state, val) {
|
||||||
// top toolbar is 50px. Filebar is 40px and agent filter tabs are 44px
|
// top toolbar is 50px. Filebar is 40px and agent filter tabs are 44px
|
||||||
state.tableHeight = `${Screen.height - 50 - 40 - 78 - val}px`;
|
state.tableHeight = `${Screen.height - 50 - 40 - 78 - val}px`;
|
||||||
@@ -212,6 +216,7 @@ export default function () {
|
|||||||
context.commit("SET_URL_ACTION", data.url_action);
|
context.commit("SET_URL_ACTION", data.url_action);
|
||||||
context.commit("setShowCommunityScripts", data.show_community_scripts);
|
context.commit("setShowCommunityScripts", data.show_community_scripts);
|
||||||
context.commit("SET_HOSTED", data.hosted);
|
context.commit("SET_HOSTED", data.hosted);
|
||||||
|
context.commit("SET_TOKEN_EXPIRED", data.token_is_expired);
|
||||||
|
|
||||||
if (data.date_format && data.date_format !== "")
|
if (data.date_format && data.date_format !== "")
|
||||||
context.commit("setDateFormat", data.date_format);
|
context.commit("setDateFormat", data.date_format);
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ export function formatDateInputField(isoDateString, noTimezone = false) {
|
|||||||
if (noTimezone) {
|
if (noTimezone) {
|
||||||
isoDateString = isoDateString.replace("Z", "");
|
isoDateString = isoDateString.replace("Z", "");
|
||||||
}
|
}
|
||||||
return date.formatDate(isoDateString, "YYYY-MM-DDTHH:mm:ss");
|
return date.formatDate(isoDateString, "YYYY-MM-DDTHH:mm");
|
||||||
}
|
}
|
||||||
|
|
||||||
// converts a local date string "YYYY-MM-DDTHH:mm:ss" to an iso date string with the local timezone
|
// converts a local date string "YYYY-MM-DDTHH:mm:ss" to an iso date string with the local timezone
|
||||||
|
|||||||
Reference in New Issue
Block a user