Compare commits

..

15 Commits

Author SHA1 Message Date
wh1te909
974ba53926 add delete token and move to comp api 2022-07-03 01:34:29 +00:00
wh1te909
021fbbe14f update reqs 2022-07-03 01:05:49 +00:00
wh1te909
bbd74c34b7 improve error message when backend is offline or dns issues 2022-06-28 00:46:41 +00:00
wh1te909
dfef0a5b4b bump dev version 2022-06-27 07:32:11 +00:00
wh1te909
ee687bf559 remove manual workflow 2022-06-27 07:30:59 +00:00
wh1te909
627d0e91f1 add manual workflow 2022-06-27 07:26:21 +00:00
wh1te909
bffaba1f60 testing sendcmd websocket 2022-06-26 06:59:59 +00:00
wh1te909
fdf28539cb update reqs 2022-06-26 06:59:29 +00:00
wh1te909
ac1246c81c update installer 2022-06-23 05:25:55 +00:00
wh1te909
4feed0c65c update quasar extras 2022-06-23 05:25:34 +00:00
wh1te909
197f2f237b start refactor amidaware/tacticalrmm@b588bab268 2022-06-20 19:43:35 +00:00
wh1te909
0dc0d010bd update reqs 2022-06-20 19:41:58 +00:00
wh1te909
b17aff8c6f add bulk recovery ui amidaware/tacticalrmm@c404ae7ac8 2022-06-03 00:37:51 +00:00
wh1te909
63147ce116 add option for https dev server 2022-05-30 07:46:30 +00:00
wh1te909
ba9f93962a update deps and browserlist 2022-05-29 18:39:26 +00:00
15 changed files with 1154 additions and 1025 deletions

View File

@@ -3,3 +3,4 @@ DEV_URL = "https://api.example.com"
APP_URL = "https://app.example.com" APP_URL = "https://app.example.com"
DEV_HOST = 0.0.0.0 DEV_HOST = 0.0.0.0
DEV_PORT = 80 DEV_PORT = 80
USE_HTTPS = false

1643
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.100.0-dev", "version": "0.100.2-dev",
"private": true, "private": true,
"productName": "Tactical RMM", "productName": "Tactical RMM",
"scripts": { "scripts": {
@@ -10,47 +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.14.0", "@quasar/extras": "1.14.2",
"apexcharts": "3.35.2", "apexcharts": "3.35.3",
"axios": "0.27.2", "axios": "0.27.2",
"dotenv": "16.0.0", "dotenv": "16.0.1",
"qrcode.vue": "3.3.3", "qrcode.vue": "3.3.3",
"quasar": "2.7.1", "quasar": "2.7.4",
"vue": "3.2.31", "vue": "3.2.37",
"vue3-ace-editor": "2.2.2", "vue3-ace-editor": "2.2.2",
"vue3-apexcharts": "1.4.1", "vue3-apexcharts": "1.4.1",
"vuedraggable": "4.1.0", "vuedraggable": "4.1.0",
"vue-router": "4.0.15", "vue-router": "4.0.16",
"vuex": "4.0.2" "vuex": "4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@quasar/cli": "^1.3.2", "@quasar/cli": "^1.3.2",
"@intlify/vite-plugin-vue-i18n": "^3.3.1", "@intlify/vite-plugin-vue-i18n": "^3.4.0",
"@quasar/app-vite": "^1.0.1", "@quasar/app-vite": "^1.0.4",
"@types/node": "^12.20.21", "@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.10.0", "@typescript-eslint/eslint-plugin": "^5.30.3",
"@typescript-eslint/parser": "^5.10.0", "@typescript-eslint/parser": "^5.30.3",
"autoprefixer": "^10.4.2", "autoprefixer": "^10.4.7",
"eslint": "^8.10.0", "eslint": "^8.18.0",
"eslint-config-prettier": "^8.1.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-vue": "^8.5.0", "eslint-plugin-vue": "^8.5.0",
"prettier": "^2.5.1", "prettier": "^2.7.1",
"typescript": "^4.6.4" "typescript": "^4.7.4"
},
"browserslist": [
"last 3 Chrome versions",
"last 3 Firefox versions",
"last 3 Edge versions",
"last 2 Safari versions",
"last 3 Android versions",
"last 3 ChromeAndroid versions",
"last 3 FirefoxAndroid versions",
"last 2 iOS versions",
"last 3 Opera versions"
],
"engines": {
"node": ">= 12.22.1",
"npm": ">= 6.13.4",
"yarn": ">= 1.21.1"
} }
} }

View File

@@ -51,7 +51,7 @@ module.exports = configure(function (/* ctx */) {
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
build: { build: {
target: { target: {
browser: ["es2019", "edge88", "firefox78", "chrome87", "safari13.1"], browser: ["es2021"],
node: "node16", node: "node16",
}, },
@@ -86,7 +86,7 @@ module.exports = configure(function (/* ctx */) {
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
devServer: { devServer: {
https: false, https: process.env.USE_HTTPS === "true",
open: false, // opens browser window automatically open: false, // opens browser window automatically
host: process.env.DEV_HOST, host: process.env.DEV_HOST,
port: process.env.DEV_PORT, port: process.env.DEV_PORT,

View File

@@ -31,6 +31,17 @@ export default function ({ app, router, store }) {
return response; return response;
}, },
async function (error) { async function (error) {
if (error.code && error.code === "ERR_NETWORK") {
Notify.create({
color: "negative",
message: "Backend is offline (network error)",
caption:
"Open your browser's dev tools and check the console tab for more detailed error messages",
timeout: 5000,
});
return Promise.reject({ ...error });
}
let text; let text;
if (!error.response) { if (!error.response) {

View File

@@ -142,6 +142,10 @@
<q-item clickable v-close-popup @click="clearCache"> <q-item clickable v-close-popup @click="clearCache">
<q-item-section>Clear Cache</q-item-section> <q-item-section>Clear Cache</q-item-section>
</q-item> </q-item>
<!-- bulk recover agents -->
<q-item clickable v-close-popup @click="bulkRecoverAgents">
<q-item-section>Recover All Agents</q-item-section>
</q-item>
</q-list> </q-list>
</q-menu> </q-menu>
</q-btn> </q-btn>
@@ -262,6 +266,20 @@ export default {
.get("/core/clearcache/") .get("/core/clearcache/")
.then((r) => this.notifySuccess(r.data)); .then((r) => this.notifySuccess(r.data));
}, },
bulkRecoverAgents() {
this.$q
.dialog({
title: "Bulk Recover All Agents?",
message:
"This will restart the Tactical and Mesh Agent services on all agents",
cancel: true,
})
.onOk(() => {
this.$axios
.get("/agents/bulkrecovery/")
.then((r) => this.notifySuccess(r.data));
});
},
openHelp(mode) { openHelp(mode) {
let url; let url;
switch (mode) { switch (mode) {

View File

@@ -61,10 +61,7 @@
<q-td key="client" :props="props">{{ props.row.client_name }}</q-td> <q-td key="client" :props="props">{{ props.row.client_name }}</q-td>
<q-td key="site" :props="props">{{ props.row.site_name }}</q-td> <q-td key="site" :props="props">{{ props.row.site_name }}</q-td>
<q-td key="mon_type" :props="props">{{ props.row.mon_type }}</q-td> <q-td key="mon_type" :props="props">{{ props.row.mon_type }}</q-td>
<q-td key="arch" :props="props" <q-td key="goarch" :props="props">{{ props.row.goarch }}</q-td>
><span v-if="props.row.arch === '64'">64 bit</span
><span v-else>32 bit</span></q-td
>
<q-td key="expiry" :props="props">{{ <q-td key="expiry" :props="props">{{
formatDate(props.row.expiry) formatDate(props.row.expiry)
}}</q-td> }}</q-td>
@@ -130,7 +127,13 @@ const columns = [
align: "left", align: "left",
sortable: true, sortable: true,
}, },
{ name: "arch", label: "Arch", field: "arch", align: "left", sortable: true }, {
name: "goarch",
label: "Arch",
field: "goarch",
align: "left",
sortable: true,
},
{ {
name: "expiry", name: "expiry",
label: "Expiry", label: "Expiry",

View File

@@ -54,9 +54,9 @@
/> />
</q-card-section> </q-card-section>
<q-card-section> <q-card-section>
<div class="q-pl-sm">OS</div> <div class="q-pl-sm">Arch</div>
<q-radio v-model="state.arch" val="64" label="64 bit" /> <q-radio v-model="state.goarch" :val="GOARCH_AMD64" label="64 bit" />
<q-radio v-model="state.arch" val="32" label="32 bit" /> <q-radio v-model="state.goarch" :val="GOARCH_i386" label="32 bit" />
</q-card-section> </q-card-section>
<q-card-actions align="right"> <q-card-actions align="right">
<q-btn dense flat label="Cancel" v-close-popup /> <q-btn dense flat label="Cancel" v-close-popup />
@@ -84,6 +84,7 @@ import {
formatDateInputField, formatDateInputField,
formatDateStringwithTimezone, formatDateStringwithTimezone,
} from "@/utils/format"; } from "@/utils/format";
import { GOARCH_AMD64, GOARCH_i386 } from "@/constants/constants";
// ui imports // ui imports
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue"; import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
@@ -108,7 +109,7 @@ export default {
power: false, power: false,
rdp: false, rdp: false,
ping: false, ping: false,
arch: "64", goarch: GOARCH_AMD64,
}); });
const loading = ref(false); const loading = ref(false);
@@ -145,6 +146,10 @@ export default {
// quasar dialog // quasar dialog
dialogRef, dialogRef,
onDialogHide, onDialogHide,
// constants
GOARCH_AMD64,
GOARCH_i386,
}; };
}, },
}; };

View File

@@ -40,7 +40,7 @@
label="Windows" label="Windows"
@update:model-value=" @update:model-value="
installMethod = 'exe'; installMethod = 'exe';
arch = '64'; goarch = GOARCH_AMD64;
" "
/> />
<q-radio <q-radio
@@ -48,8 +48,8 @@
val="linux" val="linux"
label="Linux" label="Linux"
@update:model-value=" @update:model-value="
installMethod = 'linux'; installMethod = 'bash';
arch = 'amd64'; goarch = GOARCH_AMD64;
" "
/> />
</div> </div>
@@ -102,38 +102,38 @@
Arch Arch
<div class="q-gutter-sm"> <div class="q-gutter-sm">
<q-radio <q-radio
v-model="arch" v-model="goarch"
val="64" :val="GOARCH_AMD64"
label="64 bit" label="64 bit"
v-show="agentOS === 'windows'" v-show="agentOS === 'windows'"
/> />
<q-radio <q-radio
v-model="arch" v-model="goarch"
val="32" :val="GOARCH_i386"
label="32 bit" label="32 bit"
v-show="agentOS === 'windows'" v-show="agentOS === 'windows'"
/> />
<q-radio <q-radio
v-model="arch" v-model="goarch"
val="amd64" :val="GOARCH_AMD64"
label="64 bit" label="64 bit"
v-show="agentOS !== 'windows'" v-show="agentOS !== 'windows'"
/> />
<q-radio <q-radio
v-model="arch" v-model="goarch"
val="386" :val="GOARCH_i386"
label="32 bit" label="32 bit"
v-show="agentOS !== 'windows'" v-show="agentOS !== 'windows'"
/> />
<q-radio <q-radio
v-model="arch" v-model="goarch"
val="arm64" :val="GOARCH_ARM64"
label="ARM 64 bit" label="ARM 64 bit"
v-show="agentOS !== 'windows'" v-show="agentOS !== 'windows'"
/> />
<q-radio <q-radio
v-model="arch" v-model="goarch"
val="arm" :val="GOARCH_ARM32"
label="ARM 32 bit (Rasp Pi)" label="ARM 32 bit (Rasp Pi)"
v-show="agentOS !== 'windows'" v-show="agentOS !== 'windows'"
/> />
@@ -177,6 +177,12 @@
import mixins from "@/mixins/mixins"; import mixins from "@/mixins/mixins";
import AgentDownload from "@/components/modals/agents/AgentDownload.vue"; import AgentDownload from "@/components/modals/agents/AgentDownload.vue";
import { getBaseUrl } from "@/boot/axios"; import { getBaseUrl } from "@/boot/axios";
import {
GOARCH_AMD64,
GOARCH_i386,
GOARCH_ARM64,
GOARCH_ARM32,
} from "@/constants/constants";
export default { export default {
name: "InstallAgent", name: "InstallAgent",
@@ -187,6 +193,10 @@ export default {
}, },
data() { data() {
return { return {
GOARCH_AMD64: GOARCH_AMD64,
GOARCH_i386: GOARCH_i386,
GOARCH_ARM64: GOARCH_ARM64,
GOARCH_ARM32: GOARCH_ARM32,
client_options: [], client_options: [],
client: null, client: null,
site: null, site: null,
@@ -198,7 +208,7 @@ export default {
showAgentDownload: false, showAgentDownload: false,
info: {}, info: {},
installMethod: "exe", installMethod: "exe",
arch: "64", goarch: GOARCH_AMD64,
agentOS: "windows", agentOS: "windows",
}; };
}, },
@@ -240,7 +250,7 @@ export default {
.replace(/([^a-zA-Z0-9]+)/g, ""); .replace(/([^a-zA-Z0-9]+)/g, "");
const fileName = const fileName =
this.arch === "64" this.goarch === GOARCH_AMD64
? `rmm-${clientStripped}-${siteStripped}-${this.agenttype}.exe` ? `rmm-${clientStripped}-${siteStripped}-${this.agenttype}.exe`
: `rmm-${clientStripped}-${siteStripped}-${this.agenttype}-x86.exe`; : `rmm-${clientStripped}-${siteStripped}-${this.agenttype}-x86.exe`;
@@ -253,10 +263,10 @@ export default {
power: this.power ? 1 : 0, power: this.power ? 1 : 0,
rdp: this.rdp ? 1 : 0, rdp: this.rdp ? 1 : 0,
ping: this.ping ? 1 : 0, ping: this.ping ? 1 : 0,
arch: this.arch, goarch: this.goarch,
api, api,
fileName, fileName,
os: this.agentOS, plat: this.agentOS,
}; };
if (this.installMethod === "manual") { if (this.installMethod === "manual") {
@@ -264,7 +274,7 @@ export default {
this.info = { this.info = {
expires: this.expires, expires: this.expires,
data: r.data, data: r.data,
arch: this.arch, goarch: this.goarch,
}; };
this.showAgentDownload = true; this.showAgentDownload = true;
}); });
@@ -289,7 +299,7 @@ export default {
}); });
} else if ( } else if (
this.installMethod === "powershell" || this.installMethod === "powershell" ||
this.installMethod === "linux" this.installMethod === "bash"
) { ) {
this.$q.loading.show(); this.$q.loading.show();
let ext = this.installMethod === "powershell" ? "ps1" : "sh"; let ext = this.installMethod === "powershell" ? "ps1" : "sh";
@@ -333,7 +343,7 @@ export default {
case "manual": case "manual":
text = "Show manual installation instructions"; text = "Show manual installation instructions";
break; break;
case "linux": case "bash":
text = "Download linux install script"; text = "Download linux install script";
break; break;
} }

View File

@@ -8,11 +8,12 @@
</q-btn> </q-btn>
</q-bar> </q-bar>
<q-separator /> <q-separator />
<q-banner class="bg-warning"> <q-banner class="bg-info">
<template v-slot:avatar> <template v-slot:avatar>
<q-icon name="info" /> <q-icon name="info" />
</template> </template>
Agents will now automatically self update, this tool is no longer needed. Agents will automatically self update at 35 min past the hour, every hour.
Use this tool to manually trigger an agent update cycle.
</q-banner> </q-banner>
<q-card-section> <q-card-section>
Select Version Select Version

View File

@@ -0,0 +1,211 @@
<template>
<q-dialog
ref="dialogRef"
@hide="onDialogHide"
persistent
@keydown.esc="onDialogHide"
>
<q-card
class="q-dialog-plugin"
:style="{ 'min-width': !ret ? '40vw' : '70vw' }"
>
<q-bar>
Send command on {{ agent.hostname }}
<q-space />
<q-chip v-if="!wsConnected" color="red" text-color="white" icon="error"
>Websocket diconnected!</q-chip
>
<q-space />
<q-btn dense flat icon="close" v-close-popup>
<q-tooltip class="bg-white text-primary">Close</q-tooltip>
</q-btn>
</q-bar>
<q-form @submit="submit">
<q-card-section>
<p>Shell</p>
<div class="q-gutter-sm">
<q-radio
v-if="agent.plat !== 'windows'"
dense
v-model="state.shell"
val="/bin/bash"
label="Bash"
@update:model-value="state.custom_shell = null"
/>
<q-radio
v-if="agent.plat !== 'windows'"
dense
v-model="state.shell"
val="custom"
label="Custom"
/>
<q-radio
v-if="agent.plat === 'windows'"
dense
v-model="state.shell"
val="cmd"
label="CMD"
/>
<q-radio
v-if="agent.plat === 'windows'"
dense
v-model="state.shell"
val="powershell"
label="Powershell"
/>
</div>
</q-card-section>
<q-card-section v-if="state.shell === 'custom'">
<q-input
v-model="state.custom_shell"
outlined
label="Custom shell"
stack-label
placeholder="/usr/bin/python3"
:rules="[(val) => !!val || '*Required']"
/>
</q-card-section>
<q-card-section>
<q-input
v-model.number="state.timeout"
dense
outlined
type="number"
style="max-width: 150px"
label="Timeout (seconds)"
stack-label
:rules="[
(val) => !!val || '*Required',
(val) => val >= 10 || 'Minimum is 10 seconds',
(val) => val <= 3600 || 'Maximum is 3600 seconds',
]"
/>
</q-card-section>
<q-card-section>
<q-input
v-model="state.cmd"
outlined
label="Command"
stack-label
:placeholder="cmdPlaceholder(state.shell)"
:rules="[(val) => !!val || '*Required']"
/>
</q-card-section>
<q-card-actions align="right">
<q-btn flat dense push label="Cancel" v-close-popup />
<q-btn
:loading="loading"
:disable="!wsConnected"
flat
dense
push
label="Send"
color="primary"
type="submit"
>
</q-btn>
</q-card-actions>
<q-card-section
v-if="ret !== null"
class="q-pl-md q-pr-md q-pt-none q-ma-none scroll"
style="max-height: 50vh"
>
<pre>{{ ret }}</pre>
</q-card-section>
</q-form>
</q-card>
</q-dialog>
</template>
<script>
// composition imports
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
import { useStore } from "vuex";
import { useDialogPluginComponent } from "quasar";
import { cmdPlaceholder } from "@/composables/agents";
import { getWSUrl } from "@/websocket/channels";
export default {
name: "SendCommand",
emits: [...useDialogPluginComponent.emits],
props: {
agent: !Object,
},
setup(props) {
const store = useStore();
// setup quasar dialog plugin
const { dialogRef, onDialogHide } = useDialogPluginComponent();
// run command logic
const state = ref({
shell: props.agent.plat === "windows" ? "cmd" : "/bin/bash",
cmd: null,
timeout: 30,
custom_shell: null,
agent_id: props.agent.agent_id,
});
const loading = ref(false);
const ret = ref(null);
// websocket
const ws = ref(null);
const wsConnected = ref(false);
function setupWS() {
const token = computed(() => store.state.token);
console.log("Starting send command websocket");
let url = getWSUrl("sendcmd", token.value);
ws.value = new WebSocket(url);
ws.value.onopen = () => {
wsConnected.value = true;
console.log("Send command websocket connected");
};
ws.value.onmessage = (e) => {
const data = JSON.parse(e.data);
ret.value = data.ret;
loading.value = false;
};
ws.value.onclose = () => {
console.log("Send command websocket disconnected");
wsConnected.value = false;
};
ws.value.onerror = () => {
wsConnected.value = false;
console.log("Send command websocket error");
ws.value.onclose();
};
}
function submit() {
ret.value = null;
loading.value = true;
ret.value = ws.value.send(JSON.stringify(state.value));
}
onMounted(() => {
setupWS();
});
onBeforeUnmount(() => {
ws.value.close();
});
return {
// reactive data
state,
loading,
ret,
wsConnected,
// methods
submit,
cmdPlaceholder,
// quasar dialog
dialogRef,
onDialogHide,
};
},
};
</script>

View File

@@ -12,11 +12,15 @@
color="positive" color="positive"
class="full-width" class="full-width"
@click="doCodeSign" @click="doCodeSign"
:loading="loading"
> >
<q-tooltip <q-tooltip
>Force all existing agents to be updated to the code-signed >Force all existing agents to be updated to the code-signed
version</q-tooltip version</q-tooltip
> >
<template v-slot:loading>
<q-spinner-facebook />
</template>
</q-btn> </q-btn>
</q-card-section> </q-card-section>
<q-form @submit.prevent="editToken"> <q-form @submit.prevent="editToken">
@@ -33,56 +37,92 @@
</q-card-section> </q-card-section>
<q-card-section class="row items-center"> <q-card-section class="row items-center">
<q-btn label="Save" color="primary" type="submit" /> <q-btn label="Save" color="primary" type="submit" />
<q-space />
<q-btn label="Delete" color="negative" @click="confirmDelete" />
</q-card-section> </q-card-section>
</q-form> </q-form>
</q-card> </q-card>
</template> </template>
<script> <script>
import mixins from "@/mixins/mixins"; import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
import axios from "axios";
import { notifySuccess } from "@/utils/notify";
const endpoint = "/core/codesign/";
export default { export default {
name: "CodeSign", name: "CodeSign",
mixins: [mixins], setup() {
data() { const $q = useQuasar();
const settings = ref({ token: "" });
const loading = ref(false);
async function getToken() {
try {
const { data } = await axios.get(endpoint);
settings.value = data;
} catch (e) {
console.error(e);
}
}
async function deleteToken() {
try {
await axios.delete(endpoint);
notifySuccess("Token was deleted!");
await getToken();
} catch (e) {
console.error(e);
}
}
function confirmDelete() {
$q.dialog({
title: "Delete token?",
cancel: true,
persistent: true,
}).onOk(() => {
deleteToken();
});
}
async function doCodeSign() {
loading.value = true;
try {
const { data } = await axios.post(endpoint);
loading.value = false;
notifySuccess(data);
} catch (e) {
loading.value = false;
console.error(e);
}
}
async function editToken() {
$q.loading.show();
try {
const { data } = await axios.patch(endpoint, settings.value);
$q.loading.hide();
notifySuccess(data);
} catch (e) {
$q.loading.hide();
console.error(e);
}
}
onMounted(() => {
getToken();
});
return { return {
settings: { settings,
token: "", loading,
}, confirmDelete,
doCodeSign,
editToken,
}; };
}, },
methods: {
getToken() {
this.$axios.get("/core/codesign/").then((r) => {
this.settings = r.data;
});
},
editToken() {
this.$q.loading.show();
this.$axios
.patch("/core/codesign/", this.settings)
.then((r) => {
this.$q.loading.hide();
this.notifySuccess(r.data);
})
.catch(() => {
this.$q.loading.hide();
});
},
doCodeSign() {
this.$q.loading.show();
this.$axios
.post("/core/codesign/")
.then((r) => {
this.$q.loading.hide();
this.notifySuccess(r.data);
})
.catch(() => {
this.$q.loading.hide();
});
},
},
mounted() {
this.getToken();
},
}; };
</script> </script>

View File

@@ -0,0 +1,6 @@
const GOARCH_AMD64 = "amd64";
const GOARCH_i386 = "386";
const GOARCH_ARM64 = "arm64";
const GOARCH_ARM32 = "arm";
export { GOARCH_AMD64, GOARCH_i386, GOARCH_ARM64, GOARCH_ARM32 };

View File

@@ -144,7 +144,7 @@ import { ref, computed, onMounted, onBeforeUnmount } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useStore } from "vuex"; import { useStore } from "vuex";
import axios from "axios"; import axios from "axios";
import { getBaseUrl } from "@/boot/axios"; import { getWSUrl } from "@/websocket/channels";
// ui imports // ui imports
import AlertsIcon from "@/components/AlertsIcon.vue"; import AlertsIcon from "@/components/AlertsIcon.vue";
@@ -184,10 +184,6 @@ export default {
}).onOk(() => store.dispatch("getDashInfo")); }).onOk(() => store.dispatch("getDashInfo"));
} }
function wsUrl() {
return getBaseUrl().split("://")[1];
}
const serverCount = ref(0); const serverCount = ref(0);
const serverOfflineCount = ref(0); const serverOfflineCount = ref(0);
const workstationCount = ref(0); const workstationCount = ref(0);
@@ -200,13 +196,8 @@ export default {
// 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);
console.log("Starting websocket"); console.log("Starting websocket");
const proto = let url = getWSUrl("dashinfo", token.value);
process.env.NODE_ENV === "production" || process.env.DOCKER_BUILD ws.value = new WebSocket(url);
? "wss"
: "ws";
ws.value = new WebSocket(
`${proto}://${wsUrl()}/ws/dashinfo/?access_token=${token.value}`
);
ws.value.onopen = () => { ws.value.onopen = () => {
console.log("Connected to ws"); console.log("Connected to ws");
}; };

11
src/websocket/channels.js Normal file
View File

@@ -0,0 +1,11 @@
import { getBaseUrl } from "@/boot/axios";
export function getWSUrl(path, token) {
const url = getBaseUrl().split("://")[1];
const proto =
process.env.NODE_ENV === "production" || process.env.DOCKER_BUILD
? "wss"
: "ws";
return `${proto}://${url}/ws/${path}/?access_token=${token}`;
}