Compare commits
17 Commits
v0.100.8-d
...
v0.101.2-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41c61ce152 | ||
|
|
8e9de8b6b6 | ||
|
|
4cf5f7a3cb | ||
|
|
9729492d1c | ||
|
|
d6da8b4a96 | ||
|
|
9264cf4044 | ||
|
|
3a45c2a309 | ||
|
|
59de35c698 | ||
|
|
5b8ac2c809 | ||
|
|
83d0ff1c0a | ||
|
|
8a6ec6ceab | ||
|
|
93dbc74e33 | ||
|
|
5f2add48a9 | ||
|
|
b7369875af | ||
|
|
2eb6580fed | ||
|
|
9f85fbb330 | ||
|
|
ee9715a4cf |
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
|
||||
|
||||
.env
|
||||
/public/env-config.js
|
||||
|
||||
1474
package-lock.json
generated
1474
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",
|
||||
"version": "0.100.8-dev",
|
||||
"version": "0.101.2-dev",
|
||||
"private": true,
|
||||
"productName": "Tactical RMM",
|
||||
"scripts": {
|
||||
@@ -10,31 +10,31 @@
|
||||
"format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quasar/extras": "1.15.0",
|
||||
"apexcharts": "3.35.4",
|
||||
"@quasar/extras": "1.15.5",
|
||||
"apexcharts": "3.35.5",
|
||||
"axios": "0.27.2",
|
||||
"dotenv": "16.0.1",
|
||||
"dotenv": "16.0.3",
|
||||
"qrcode.vue": "3.3.3",
|
||||
"quasar": "2.7.5",
|
||||
"vue": "3.2.37",
|
||||
"quasar": "2.10.0",
|
||||
"vue": "3.2.41",
|
||||
"vue3-ace-editor": "2.2.2",
|
||||
"vue3-apexcharts": "1.4.1",
|
||||
"vuedraggable": "4.1.0",
|
||||
"vue-router": "4.1.2",
|
||||
"vuex": "4.0.2"
|
||||
"vue-router": "4.1.5",
|
||||
"vuex": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/cli": "^1.3.2",
|
||||
"@intlify/vite-plugin-vue-i18n": "^5.0.1",
|
||||
"@quasar/app-vite": "^1.0.5",
|
||||
"@types/node": "^18.6.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"eslint": "^8.20.0",
|
||||
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
|
||||
"@quasar/app-vite": "^1.1.3",
|
||||
"@types/node": "^18.11.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"@typescript-eslint/parser": "^5.40.1",
|
||||
"autoprefixer": "^10.4.12",
|
||||
"eslint": "^8.25.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-vue": "^8.5.0",
|
||||
"prettier": "^2.7.1",
|
||||
"typescript": "^4.7.4"
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,6 +196,14 @@
|
||||
>
|
||||
<q-tooltip>Linux</q-tooltip>
|
||||
</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 key="checks-status" :props="props">
|
||||
@@ -356,6 +364,27 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
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() : "";
|
||||
let advancedFilter = false;
|
||||
let availability = null;
|
||||
|
||||
@@ -310,9 +310,10 @@ export default {
|
||||
}
|
||||
|
||||
function showUpdateDetails(update) {
|
||||
const color = $q.dark.isActive ? "white" : "";
|
||||
let support_urls = "";
|
||||
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(", ");
|
||||
$q.dialog({
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
<q-badge color="primary" class="q-ml-sm text-caption">{{
|
||||
v
|
||||
}}</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>
|
||||
<q-separator v-if="info.length > 1" />
|
||||
@@ -15,6 +26,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { copyToClipboard } from "quasar";
|
||||
import { notifySuccess } from "@/utils/notify";
|
||||
// composition imports
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
@@ -28,9 +41,17 @@ export default {
|
||||
const store = useStore();
|
||||
const tabHeight = computed(() => store.state.tabHeight);
|
||||
|
||||
function copyValueToClip(val) {
|
||||
copyToClipboard(val)
|
||||
.then(() => {
|
||||
notifySuccess("Copied to clipboard");
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
tabHeight,
|
||||
uid,
|
||||
copyValueToClip,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -10,10 +10,13 @@
|
||||
</q-card-actions>
|
||||
</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
|
||||
command prompt on the device you want to add.
|
||||
</p>
|
||||
<p v-else-if="info.plat === 'darwin'" class="text-subtitle1">
|
||||
Run the following command from a terminal
|
||||
</p>
|
||||
<p>
|
||||
<q-field outlined :color="$q.dark.isActive ? 'white' : 'black'">
|
||||
<code>{{ info.data.cmd }}</code>
|
||||
@@ -37,7 +40,7 @@
|
||||
</q-badge>
|
||||
<span>Do not popup any message boxes during install</span>
|
||||
</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">
|
||||
<code
|
||||
>-local-mesh "C:\\<some folder or
|
||||
@@ -46,7 +49,7 @@
|
||||
</q-badge>
|
||||
<span> To skip downloading the Mesh Agent during the install.</span>
|
||||
</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">
|
||||
<code
|
||||
>-meshdir "C:\Program Files\Your Company Name\Mesh Agent"</code
|
||||
@@ -63,7 +66,7 @@
|
||||
</q-badge>
|
||||
<span>Don't install the mesh agent</span>
|
||||
</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">
|
||||
<code>-cert "C:\\<some folder or path>\\ca.pem"</code>
|
||||
</q-badge>
|
||||
@@ -86,12 +89,12 @@
|
||||
<p class="text-italic">
|
||||
Note: the auth token above will be valid for {{ info.expires }} hours.
|
||||
</p>
|
||||
<q-btn
|
||||
<q-btn v-if="info.plat === 'windows'"
|
||||
type="a"
|
||||
:href="info.data.url"
|
||||
color="primary"
|
||||
label="Download Agent"
|
||||
/>
|
||||
></q-btn>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
@@ -223,6 +223,7 @@ const monTypeOptions = [
|
||||
const osTypeOptions = [
|
||||
{ label: "Windows", value: "windows" },
|
||||
{ label: "Linux", value: "linux" },
|
||||
{ label: "macOS", value: "darwin" },
|
||||
{ label: "All", value: "all" },
|
||||
];
|
||||
|
||||
|
||||
@@ -465,8 +465,51 @@ export default {
|
||||
});
|
||||
},
|
||||
editAgent() {
|
||||
delete this.agent.all_timezones;
|
||||
delete this.agent.timezone;
|
||||
// TODO we need to fix the serializer to not send this stuff
|
||||
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
|
||||
// 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, ";
|
||||
}
|
||||
|
||||
return result.trimRight(",");
|
||||
return result.trimEnd(",");
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -52,6 +52,15 @@
|
||||
goarch = GOARCH_AMD64;
|
||||
"
|
||||
/>
|
||||
<q-radio
|
||||
v-model="agentOS"
|
||||
val="darwin"
|
||||
label="macOS"
|
||||
@update:model-value="
|
||||
installMethod = 'mac';
|
||||
goarch = GOARCH_AMD64;
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
@@ -105,37 +114,37 @@
|
||||
v-model="goarch"
|
||||
:val="GOARCH_AMD64"
|
||||
label="64 bit"
|
||||
v-show="agentOS === 'windows'"
|
||||
/>
|
||||
<q-radio
|
||||
v-model="goarch"
|
||||
:val="GOARCH_i386"
|
||||
label="32 bit"
|
||||
v-show="agentOS === 'windows'"
|
||||
v-show="agentOS === 'windows' || agentOS === 'linux'"
|
||||
/>
|
||||
<q-radio
|
||||
v-model="goarch"
|
||||
:val="GOARCH_AMD64"
|
||||
label="64 bit"
|
||||
v-show="agentOS !== 'windows'"
|
||||
label="Intel 64 bit"
|
||||
v-show="agentOS === 'darwin'"
|
||||
/>
|
||||
<q-radio
|
||||
v-model="goarch"
|
||||
:val="GOARCH_i386"
|
||||
label="32 bit"
|
||||
v-show="agentOS !== 'windows'"
|
||||
v-show="agentOS !== 'darwin'"
|
||||
/>
|
||||
<q-radio
|
||||
v-model="goarch"
|
||||
:val="GOARCH_ARM64"
|
||||
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
|
||||
v-model="goarch"
|
||||
:val="GOARCH_ARM32"
|
||||
label="ARM 32 bit (Rasp Pi)"
|
||||
v-show="agentOS !== 'windows'"
|
||||
v-show="agentOS === 'linux'"
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
@@ -266,12 +275,13 @@ export default {
|
||||
plat: this.agentOS,
|
||||
};
|
||||
|
||||
if (this.installMethod === "manual") {
|
||||
if (this.installMethod === "manual" || this.installMethod === "mac") {
|
||||
this.$axios.post("/agents/installer/", data).then((r) => {
|
||||
this.info = {
|
||||
expires: this.expires,
|
||||
data: r.data,
|
||||
goarch: this.goarch,
|
||||
plat: this.agentOS,
|
||||
};
|
||||
this.showAgentDownload = true;
|
||||
});
|
||||
@@ -343,6 +353,9 @@ export default {
|
||||
case "bash":
|
||||
text = "Download linux install script";
|
||||
break;
|
||||
case "mac":
|
||||
text = "Show installation instructions";
|
||||
break;
|
||||
}
|
||||
|
||||
return text;
|
||||
|
||||
@@ -37,4 +37,5 @@ export function cmdPlaceholder(shell) {
|
||||
export const agentPlatformOptions = [
|
||||
{ value: "windows", label: "Windows" },
|
||||
{ value: "linux", label: "Linux" },
|
||||
{ value: "darwin", label: "macOS" },
|
||||
];
|
||||
|
||||
@@ -14,6 +14,22 @@
|
||||
@click="$store.dispatch('reload')"
|
||||
/>
|
||||
</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-btn
|
||||
dense
|
||||
@@ -167,6 +183,7 @@ export default {
|
||||
const needRefresh = computed(() => store.state.needrefresh);
|
||||
const user = computed(() => store.state.username);
|
||||
const hosted = computed(() => store.state.hosted);
|
||||
const tokenExpired = computed(() => store.state.tokenExpired);
|
||||
|
||||
const latestReleaseURL = computed(() => {
|
||||
return latestTRMMVersion.value
|
||||
@@ -259,6 +276,8 @@ export default {
|
||||
user,
|
||||
needRefresh,
|
||||
darkMode,
|
||||
hosted,
|
||||
tokenExpired,
|
||||
|
||||
// methods
|
||||
showUserPreferences,
|
||||
|
||||
@@ -17,6 +17,7 @@ export default function () {
|
||||
agentPlatform: "windows",
|
||||
agentTableLoading: false,
|
||||
needrefresh: false,
|
||||
tokenExpired: false,
|
||||
refreshSummaryTab: false,
|
||||
tableHeight: "300px",
|
||||
tabHeight: "300px",
|
||||
@@ -83,6 +84,9 @@ export default function () {
|
||||
SET_REFRESH_NEEDED(state, action) {
|
||||
state.needrefresh = action;
|
||||
},
|
||||
SET_TOKEN_EXPIRED(state, action) {
|
||||
state.tokenExpired = action;
|
||||
},
|
||||
SET_SPLITTER(state, val) {
|
||||
// top toolbar is 50px. Filebar is 40px and agent filter tabs are 44px
|
||||
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("setShowCommunityScripts", data.show_community_scripts);
|
||||
context.commit("SET_HOSTED", data.hosted);
|
||||
context.commit("SET_TOKEN_EXPIRED", data.token_is_expired);
|
||||
|
||||
if (data.date_format && data.date_format !== "")
|
||||
context.commit("setDateFormat", data.date_format);
|
||||
|
||||
Reference in New Issue
Block a user