feat: agent deployments #138

This commit is contained in:
wh1te909
2020-10-25 03:20:33 +00:00
parent 54a59be32d
commit 7e2cde6c11
3 changed files with 295 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
<template>
<q-card style="min-width: 70vw">
<q-bar>
<q-btn @click="getDeployments" class="q-mr-sm" dense flat push icon="refresh" />
<q-space />Manage Deployments
<q-space />
<q-btn dense flat icon="close" v-close-popup>
<q-tooltip content-class="bg-white text-primary" />
</q-btn>
</q-bar>
<div class="row">
<div class="q-pa-sm q-ml-sm">
<q-btn color="primary" icon="add" label="New" @click="showNewDeployment = true" />
</div>
</div>
<q-separator />
<q-card-section>
<q-table
dense
class="audit-mgr-tbl-sticky"
binary-state-sort
virtual-scroll
:data="deployments"
:columns="columns"
:visible-columns="visibleColumns"
row-key="id"
:pagination.sync="pagination"
no-data-label="No Deployments"
>
<template slot="body" slot-scope="props" :props="props">
<q-tr>
<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="mon_type" :props="props">{{ props.row.mon_type }}</q-td>
<q-td key="arch" :props="props"
><span v-if="props.row.arch === '64'">64 bit</span><span v-else>32 bit</span></q-td
>
<q-td key="expiry" :props="props">{{ props.row.expiry }}</q-td>
<q-td key="flags" :props="props"
><q-badge color="grey-8" label="View Flags" />
<q-tooltip content-style="font-size: 12px">{{ props.row.install_flags }}</q-tooltip>
</q-td>
<q-td key="link" :props="props"
><q-btn size="sm" color="primary" icon="content_copy" label="Copy" @click="copyLink(props)"
/></q-td>
<q-td key="delete" :props="props"
><q-btn size="sm" color="negative" icon="delete" @click="deleteDeployment(props.row.id)"
/></q-td>
</q-tr>
</template>
</q-table>
</q-card-section>
<q-dialog v-model="showNewDeployment">
<NewDeployment @close="showNewDeployment = false" @added="getDeployments" />
</q-dialog>
</q-card>
</template>
<script>
import axios from "axios";
import mixins from "@/mixins/mixins";
import NewDeployment from "@/components/modals/clients/NewDeployment";
import { copyToClipboard } from "quasar";
export default {
name: "Deployment",
mixins: [mixins],
components: { NewDeployment },
data() {
return {
showNewDeployment: false,
deployments: [],
columns: [
{ name: "id", field: "id" },
{ name: "uid", field: "uid" },
{ name: "clientid", field: "client_id" },
{ name: "siteid", field: "site_id" },
{ name: "client", label: "Client", field: "client_name", align: "left", sortable: true },
{ name: "site", label: "Site", field: "site_name", align: "left", sortable: true },
{ name: "mon_type", label: "Type", field: "mon_type", align: "left", sortable: true },
{ name: "arch", label: "Arch", field: "arch", align: "left", sortable: true },
{ name: "expiry", label: "Expiry", field: "expiry", align: "left", sortable: true },
{ name: "flags", label: "Flags", field: "install_flags", align: "left" },
{ name: "link", label: "Download Link", align: "left" },
{ name: "delete", label: "Delete", align: "left" },
],
visibleColumns: ["client", "site", "mon_type", "arch", "expiry", "flags", "link", "delete"],
pagination: {
rowsPerPage: 50,
sortBy: "id",
descending: true,
},
};
},
methods: {
getDeployments() {
this.$axios.get("/clients/deployments/").then(r => {
this.deployments = r.data;
});
},
deleteDeployment(pk) {
this.$q
.dialog({
title: "Delete deployment?",
cancel: true,
ok: { label: "Delete", color: "negative" },
})
.onOk(() => {
this.$axios
.delete(`/clients/${pk}/deployment/`)
.then(r => {
this.getDeployments();
this.notifySuccess("Deployment deleted");
})
.catch(() => this.notifyError("Something went wrong"));
});
},
copyLink(props) {
const api = axios.defaults.baseURL;
copyToClipboard(`${api}/clients/${props.row.uid}/deploy/`).then(() => {
this.notifySuccess("Link copied to clipboard", 1500);
});
},
},
created() {
this.getDeployments();
},
};
</script>

View File

@@ -81,6 +81,9 @@
<q-item clickable v-close-popup @click="showInstallAgent = true">
<q-item-section>Install Agent</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="showDeployment = true">
<q-item-section>Manage Deployments</q-item-section>
</q-item>
<q-item clickable v-close-popup @click="showUpdateAgentsModal = true">
<q-item-section>Update Agents</q-item-section>
</q-item>
@@ -211,6 +214,11 @@
<q-dialog v-model="showBulkPatchManagement" position="top">
<BulkPatchManagement @close="showBulkPatchManagement = false" />
</q-dialog>
<!-- Agent Deployment -->
<q-dialog v-model="showDeployment">
<Deployment @close="showDeployment = false" />
</q-dialog>
</q-bar>
</div>
</template>
@@ -234,6 +242,7 @@ import AuditManager from "@/components/AuditManager";
import BulkCommand from "@/components/modals/agents/BulkCommand";
import BulkScript from "@/components/modals/agents/BulkScript";
import BulkPatchManagement from "@/components/modals/agents/BulkPatchManagement";
import Deployment from "@/components/Deployment";
export default {
name: "FileBar",
@@ -256,6 +265,7 @@ export default {
BulkCommand,
BulkScript,
BulkPatchManagement,
Deployment,
},
props: ["clients"],
data() {
@@ -276,6 +286,7 @@ export default {
showBulkCommand: false,
showBulkScript: false,
showBulkPatchManagement: false,
showDeployment: false,
};
},
methods: {

View File

@@ -0,0 +1,154 @@
<template>
<q-card style="min-width: 25vw" v-if="loaded">
<q-card-section class="row">
<q-card-actions align="left">
<div class="text-h6">Create a Deployment</div>
</q-card-actions>
<q-space />
<q-card-actions align="right">
<q-btn v-close-popup flat round dense icon="close" />
</q-card-actions>
</q-card-section>
<q-card-section>
<q-form @submit.prevent="create">
<q-card-section v-if="tree !== null" class="q-gutter-sm">
<q-select
outlined
dense
options-dense
label="Client"
v-model="client"
:options="Object.keys(tree)"
@input="site = sites[0]"
/>
</q-card-section>
<q-card-section class="q-gutter-sm">
<q-select dense options-dense outlined label="Site" v-model="site" :options="sites" />
</q-card-section>
<q-card-section>
<div class="q-gutter-sm">
<q-radio v-model="agenttype" val="server" label="Server" @input="power = false" />
<q-radio v-model="agenttype" val="workstation" label="Workstation" />
</div>
</q-card-section>
<q-card-section>
Expiry
<div class="q-gutter-sm">
<q-input filled v-model="datetime">
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy transition-show="scale" transition-hide="scale">
<q-date v-model="datetime" mask="YYYY-MM-DD HH:mm" />
</q-popup-proxy>
</q-icon>
</template>
<template v-slot:append>
<q-icon name="access_time" class="cursor-pointer">
<q-popup-proxy transition-show="scale" transition-hide="scale">
<q-time v-model="datetime" mask="YYYY-MM-DD HH:mm" />
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</div>
</q-card-section>
<q-card-section>
<div class="q-gutter-sm">
<q-checkbox v-model="rdp" dense label="Enable RDP" />
<q-checkbox v-model="ping" dense label="Enable Ping" />
<q-checkbox v-model="power" dense v-show="agenttype === 'workstation'" label="Disable sleep/hibernate" />
</div>
</q-card-section>
<q-card-section>
OS
<div class="q-gutter-sm">
<q-radio v-model="arch" val="64" label="64 bit" />
<q-radio v-model="arch" val="32" label="32 bit" />
</div>
</q-card-section>
<q-card-actions align="left">
<q-btn label="Create" color="primary" type="submit" />
</q-card-actions>
</q-form>
</q-card-section>
</q-card>
</template>
<script>
import mixins from "@/mixins/mixins";
import { date } from "quasar";
export default {
name: "NewDeployment",
mixins: [mixins],
data() {
return {
datetime: null,
loaded: false,
tree: {},
client: null,
site: null,
agenttype: "server",
power: false,
rdp: false,
ping: false,
arch: "64",
};
},
methods: {
create() {
const data = {
client: this.client,
site: this.site,
expires: this.datetime,
agenttype: this.agenttype,
power: this.power ? 1 : 0,
rdp: this.rdp ? 1 : 0,
ping: this.ping ? 1 : 0,
arch: this.arch,
};
this.$axios
.post("/clients/deployments/", data)
.then(r => {
this.$emit("close");
this.$emit("added");
this.notifySuccess("Deployment added");
})
.catch(() => this.notifyError("Something went wrong"));
},
getCurrentDate() {
let d = new Date();
d.setDate(d.getDate() + 30);
this.datetime = date.formatDate(d, "YYYY-MM-DD HH:mm");
},
getClientsSites() {
this.$q.loading.show();
this.$axios
.get("/clients/loadclients/")
.then(r => {
this.tree = r.data;
this.client = Object.keys(r.data)[0];
this.loaded = true;
this.$q.loading.hide();
})
.catch(() => {
this.notifyError("Something went wrong");
this.$q.loading.hide();
});
},
},
computed: {
sites() {
if (this.tree !== null && this.client !== null) {
this.site = this.tree[this.client][0];
return this.tree[this.client];
}
},
},
created() {
this.getCurrentDate();
this.getClientsSites();
},
};
</script>