Compare commits

...

22 Commits

Author SHA1 Message Date
wh1te909
8403ac0e93 Release 0.101.16 2023-03-22 17:00:29 +00:00
wh1te909
c2f21b70dd bump version 2023-03-22 16:59:35 +00:00
wh1te909
520145e0e3 bump dev ver 2023-03-21 18:49:28 +00:00
wh1te909
6a132187a2 fix phantom column fixes amidaware/tacticalrmm#1264 2023-03-20 14:08:58 +00:00
wh1te909
a63a9ccd76 update reqs 2023-03-20 01:28:54 +00:00
wh1te909
ff1eb791db feat: increase size of notes text box closes amidaware/tacticalrmm#1407 2023-03-10 05:31:50 +00:00
wh1te909
13bd88b979 feat: bulk run checks by client or site amidaware/tacticalrmm@7d017f9494 2023-03-10 00:22:12 +00:00
wh1te909
5b0c244920 update reqs 2023-03-10 00:20:51 +00:00
wh1te909
0318a17cac update reqs 2023-03-05 20:49:03 +00:00
wh1te909
b7a91563b0 Release 0.101.13 2023-01-18 20:05:20 +00:00
wh1te909
75296ed8ee bump version 2023-01-18 20:04:26 +00:00
wh1te909
09bee45b2f update reqs and dev version 2023-01-16 23:03:30 +00:00
wh1te909
3573c48872 formatting 2023-01-16 08:38:34 +00:00
wh1te909
784841c221 syntax typo 2023-01-16 08:37:15 +00:00
wh1te909
ed788a1861 update reqs 2023-01-16 08:35:07 +00:00
wh1te909
ab19afca16 Release 0.101.11 2022-12-21 18:44:46 +00:00
wh1te909
bd6b08505a bump version 2022-12-21 18:44:21 +00:00
wh1te909
acd64f25f2 add ui for self reset amidaware/tacticalrmm#1378 2022-12-20 23:38:19 +00:00
wh1te909
087be2c232 update reqs 2022-12-20 23:35:44 +00:00
wh1te909
91a3272843 format 2022-12-20 23:35:32 +00:00
wh1te909
6e64f0a11b formatting 2022-12-20 21:02:55 +00:00
wh1te909
8f34f76a1d fix edit apikey amidaware/tacticalrmm#1369 2022-12-08 23:27:26 +00:00
20 changed files with 2393 additions and 4048 deletions

View File

@@ -5,7 +5,7 @@
"esbenp.prettier-vscode",
"editorconfig.editorconfig",
"vue.volar",
"wayou.vscode-todo-highlight",
"wayou.vscode-todo-highlight"
],
"unwantedRecommendations": [
"octref.vetur",

View File

@@ -4,7 +4,7 @@
"editor.formatOnSave": true,
"[vue][javascript][typescript][javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": ["source.fixAll.eslint"],
"editor.codeActionsOnSave": ["source.fixAll.eslint"]
},
"eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"],
"typescript.tsdk": "node_modules/typescript/lib",
@@ -15,7 +15,7 @@
"**/node_modules/": true,
"/node_modules/**": true,
"**/env/": true,
"/env/**": true,
"/env/**": true
}
}
}

View File

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

6055
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "web",
"version": "0.101.9",
"version": "0.101.16",
"private": true,
"productName": "Tactical RMM",
"scripts": {
@@ -10,13 +10,13 @@
"format": "prettier --write \"**/*.{js,ts,vue,,html,md,json}\" --ignore-path .gitignore"
},
"dependencies": {
"@quasar/extras": "1.15.6",
"apexcharts": "3.35.5",
"axios": "0.27.2",
"@quasar/extras": "1.15.11",
"apexcharts": "3.37.1",
"axios": "1.3.4",
"dotenv": "16.0.3",
"qrcode.vue": "3.3.3",
"quasar": "2.10.2",
"vue": "3.2.45",
"qrcode.vue": "3.3.4",
"quasar": "2.11.8",
"vue": "3.2.47",
"vue3-ace-editor": "2.2.2",
"vue3-apexcharts": "1.4.1",
"vuedraggable": "4.1.0",
@@ -24,17 +24,17 @@
"vuex": "4.1.0"
},
"devDependencies": {
"@quasar/cli": "^1.3.2",
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@quasar/app-vite": "^1.1.3",
"@types/node": "^18.11.10",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"autoprefixer": "10.4.13",
"eslint": "8.28.0",
"eslint-config-prettier": "8.5.0",
"@quasar/cli": "^2.0.0",
"@intlify/unplugin-vue-i18n": "^0.9.2",
"@quasar/app-vite": "^1.2.1",
"@types/node": "^18.15.3",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"autoprefixer": "10.4.14",
"eslint": "8.36.0",
"eslint-config-prettier": "8.7.0",
"eslint-plugin-vue": "8.7.1",
"prettier": "2.8.0",
"typescript": "4.9.3"
"prettier": "2.8.4",
"typescript": "4.9.5"
}
}

View File

@@ -4,18 +4,18 @@
module.exports = {
plugins: [
// https://github.com/postcss/autoprefixer
require('autoprefixer')({
require("autoprefixer")({
overrideBrowserslist: [
'last 4 Chrome versions',
'last 4 Firefox versions',
'last 4 Edge versions',
'last 4 Safari versions',
'last 4 Android versions',
'last 4 ChromeAndroid versions',
'last 4 FirefoxAndroid versions',
'last 4 iOS versions'
]
})
"last 4 Chrome versions",
"last 4 Firefox versions",
"last 4 Edge versions",
"last 4 Safari versions",
"last 4 Android versions",
"last 4 ChromeAndroid versions",
"last 4 FirefoxAndroid versions",
"last 4 iOS versions",
],
}),
// https://github.com/elchininet/postcss-rtlcss
// 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
// 3. uncomment the following line:
// require('postcss-rtlcss')
]
}
],
};

View File

@@ -12,6 +12,25 @@ 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
export async function fetchRoles(params = {}) {
try {

View File

@@ -374,16 +374,10 @@ export default {
"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,
});
}
}
// originally I was modifying cols directly but this led to phantom colum so doing it this way now
// https://github.com/amidaware/tacticalrmm/issues/1264
const allColumns = [...cols, ...hiddenFields.map((field) => ({ field }))];
const lowerTerms = terms ? terms.toLowerCase() : "";
let advancedFilter = false;
@@ -437,7 +431,7 @@ export default {
}
// Normal text filter
return cols.some((col) => {
return allColumns.some((col) => {
const val = cellValue(col, row) + "";
const haystack =
val === "undefined" || val === "null" ? "" : val.toLowerCase();

View File

@@ -0,0 +1,75 @@
<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

@@ -166,7 +166,7 @@ export default {
type: "textarea",
isValid: (val) => !!val,
},
style: "width: 30vw; max-width: 50vw;",
style: "width: 90vw; max-width: 90vw",
ok: { label: "Add" },
cancel: true,
}).onOk(async () => {
@@ -193,7 +193,7 @@ export default {
type: "textarea",
isValid: (val) => !!val,
},
style: "width: 30vw; max-width: 50vw;",
style: "width: 90vw; max-width: 90vw",
ok: { label: "Save" },
cancel: true,
}).onOk(async (data) => {

View File

@@ -8,16 +8,16 @@
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>
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" />
@@ -42,10 +42,9 @@ export default {
const tabHeight = computed(() => store.state.tabHeight);
function copyValueToClip(val) {
copyToClipboard(val)
.then(() => {
notifySuccess("Copied to clipboard");
})
copyToClipboard(val).then(() => {
notifySuccess("Copied to clipboard");
});
}
return {

View File

@@ -128,7 +128,7 @@ import { useDialogPluginComponent } from "quasar";
import { useCheckModal } from "@/composables/checks";
import { useScriptDropdown } from "@/composables/scripts";
import { validateRetcode } from "@/utils/validation";
import { envVarsLabel } from "@/constants/constants"
import { envVarsLabel } from "@/constants/constants";
// ui imports
import TacticalDropdown from "@/components/ui/TacticalDropdown.vue";
@@ -146,10 +146,15 @@ export default {
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
// setup script dropdown
const { script, scriptOptions, defaultTimeout, defaultArgs, defaultEnvVars } =
useScriptDropdown(props.check ? props.check.script : undefined, {
onMount: true,
});
const {
script,
scriptOptions,
defaultTimeout,
defaultArgs,
defaultEnvVars,
} = useScriptDropdown(props.check ? props.check.script : undefined, {
onMount: true,
});
// check logic
const { state, loading, submit, failOptions, severityOptions } =

View File

@@ -122,7 +122,7 @@ export default {
try {
const result = props.APIKey
? await editAPIKey(data)
? await editAPIKey(data.id, data)
: await saveAPIKey(data);
onDialogOK();
notifySuccess(result);

View File

@@ -89,7 +89,8 @@
<p class="text-italic">
Note: the auth token above will be valid for {{ info.expires }} hours.
</p>
<q-btn v-if="info.plat === 'windows'"
<q-btn
v-if="info.plat === 'windows'"
type="a"
:href="info.data.url"
color="primary"

View File

@@ -221,11 +221,18 @@ export default {
const { dialogRef, onDialogHide } = useDialogPluginComponent();
// setup dropdowns
const { script, scriptOptions, defaultTimeout, defaultArgs, defaultEnvVars, syntax, link } =
useScriptDropdown(props.script, {
onMount: true,
filterByPlatform: props.agent.plat,
});
const {
script,
scriptOptions,
defaultTimeout,
defaultArgs,
defaultEnvVars,
syntax,
link,
} = useScriptDropdown(props.script, {
onMount: true,
filterByPlatform: props.agent.plat,
});
const { customFieldOptions } = useCustomFieldDropdown({ onMount: true });
// main run script functionaity

View File

@@ -836,10 +836,15 @@ export default {
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
// setup dropdowns
const { script, scriptOptions, defaultTimeout, defaultArgs, defaultEnvVars } =
useScriptDropdown(undefined, {
onMount: true,
});
const {
script,
scriptOptions,
defaultTimeout,
defaultArgs,
defaultEnvVars,
} = useScriptDropdown(undefined, {
onMount: true,
});
// set defaultTimeout to 30
defaultTimeout.value = 30;

View File

@@ -30,7 +30,7 @@ export function useScriptDropdown(setScript = null, { onMount = false } = {}) {
);
defaultTimeout.value = tmpScript.timeout;
defaultArgs.value = tmpScript.args;
defaultEnvVars.value = tmpScript.env_vars,
defaultEnvVars.value = tmpScript.env_vars;
syntax.value = tmpScript.syntax;
link.value =
tmpScript.script_type === "builtin"

View File

@@ -6,5 +6,5 @@ export const GOARCH_ARM32 = "arm";
export 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.";
export const envVarsLabel =
"Environment vars (press Enter after typing each key=value pair)"
export const envVarsLabel =
"Environment vars (press Enter after typing each key=value pair)";

View File

@@ -19,10 +19,15 @@
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-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"
@@ -135,6 +140,32 @@
<q-item-label>Preferences</q-item-label>
</q-item-section>
</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-section>
<q-item-label>Logout</q-item-label>
@@ -156,10 +187,13 @@ import { useQuasar } from "quasar";
import { useStore } from "vuex";
import axios from "axios";
import { getWSUrl } from "@/websocket/channels";
import { resetTwoFactor } from "@/api/accounts";
import { notifySuccess } from "@/utils/notify";
// ui imports
import AlertsIcon from "@/components/AlertsIcon.vue";
import UserPreferences from "@/components/modals/coresettings/UserPreferences.vue";
import ResetPass from "@/components/accounts/ResetPass.vue";
export default {
name: "MainLayout",
@@ -197,6 +231,26 @@ export default {
}).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 serverOfflineCount = ref(0);
const workstationCount = ref(0);
@@ -281,6 +335,8 @@ export default {
// methods
showUserPreferences,
resetPassword,
reset2FA,
updateAvailable,
};
},

View File

@@ -173,6 +173,18 @@
</q-menu>
</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-item clickable v-close-popup>
@@ -690,6 +702,17 @@ export default {
})
.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) {
let data = {
id: node.id,