Added Different view for non-admins

This commit is contained in:
Luca Haid
2025-02-03 13:58:06 +01:00
parent f90ef688f5
commit 556216fe44
3 changed files with 222 additions and 152 deletions

View File

@@ -13,6 +13,14 @@ class DeviceController extends mfBaseController
if (!$me->is(["Admin"])) {
$this->redirect("Dashboard");
}
if ($this->me->is(["Admin"])) {
$this->allowedPops = array_column(PopModel::getAll(), 'id');
} else {
$networkIds = array_column($this->me->getProperty('my_networks'), 'id');
$popIds = array_column(PopNetworkModel::search(['Networks' => $networkIds]), 'pop_id');
$this->allowedPops = array_unique(array_merge([55], $popIds));
}
}
protected function indexAction()
@@ -75,6 +83,13 @@ class DeviceController extends mfBaseController
$this->redirect("Device");
}
if (!$this->me->is(["Admin"])) {
if (!in_array($device->pop_id, $this->allowedPops)) {
$this->layout()->setFlash("Gerät nicht gefunden", "error");
$this->redirect("Device");
}
}
$this->layout()->setTemplate("Device/Detail");
$devicesconfig = DeviceModel::getconifg($id);
$devices = DeviceModel::getOne($id);
@@ -99,7 +114,6 @@ class DeviceController extends mfBaseController
$this->layout()->set("devicetypes", DevicetypeModel::getAll());
$this->layout()->set("pops", PopModel::getAll());
$this->layout()->set("devices", DeviceModel::getAll());
}
protected function editAction()
@@ -123,6 +137,11 @@ class DeviceController extends mfBaseController
protected function saveAction()
{
if (!$this->me->is(["Admin"])) {
$this->layout()->setFlash("Keine Berechtigung", "error");
$this->redirect("Device");
}
$r = $this->request;
$id = $r->id;
//var_dump($r->get());exit;
@@ -395,7 +414,7 @@ class DeviceController extends mfBaseController
private function getDevices()
{
$devices = DeviceModel::getAll();
$devices = DeviceModel::search(['popIds' => $this->allowedPops]);
foreach ($devices as $device) {
$locationText = "";
@@ -415,7 +434,7 @@ class DeviceController extends mfBaseController
if ($device->last_config_backup) {
if (time() - $device->last_config_backup <= 172800) {
$backup = 'ok';
if ($device->autobackup==1) {
if ($device->autobackup == 1) {
$backup = 'auto';
}
} else {
@@ -443,5 +462,4 @@ class DeviceController extends mfBaseController
return $data ?? [];
}
}

View File

@@ -136,6 +136,13 @@ class DeviceModel
}
}
if (array_key_exists("popIds", $filter)) {
$popids = $filter['popIds'];
if (is_array($popids)) {
$where .= " AND pop_id IN (" . implode(",", $popids) . ")";
}
}
//var_dump($filter, $where);exit;
return $where;
}

View File

@@ -1,41 +1,56 @@
const deviceManufacturerFilterOptions = window?.TT_CONFIG?.DEVICE_MANUFACTURERS.map(manufacturer => ({
value: manufacturer.name,
text: manufacturer.name,
text: manufacturer.name,
}));
const deviceTypeFilterOptions = window?.TT_CONFIG?.DEVICE_TYPES.map(type => ({
value: type.name,
text: type.name,
text: type.name,
}));
window.TT_CONFIG['IS_ADMIN'] = '0'
Vue.component('device-view-switch', {
//language=Vue
template: `
<div class="device-view-switch" style="margin-bottom: 10px">
<div v-if="!isOverflowing" class="button-group" style="display:grid; grid-template-columns: repeat(3, 1fr); gap: 10px; justify-content: center; align-items: center; text-align: center; width: 100%;">
<button @click="$emit('input', 'DeviceTable')" :class="{ 'active': value === 'DeviceTable' }" class="btn btn-primary">Devices</button>
<button v-show="window.TT_CONFIG['IS_ADMIN'] === '1'" @click="$emit('input', 'DeviceManufacturer')" :class="{ 'active': value === 'DeviceManufacturer' }" class="btn btn-primary">Hersteller</button>
<button v-show="window.TT_CONFIG['IS_ADMIN'] === '1'" @click="$emit('input', 'DeviceType')" :class="{ 'active': value === 'DeviceType' }" class="btn btn-primary">Geräte Typen</button>
</div>
<div v-else>
<div class="dropdown">
<button @click="showDropdown = !showDropdown"
class="btn btn-primary dropdown-toggle">Ansicht</button>
<div v-show="showDropdown" class="dropdown-menu show">
<a href="#" @click="$emit('input', 'DeviceTable'); showDropdown = false" class="dropdown-item">Devices</a>
<a v-show="window.TT_CONFIG['IS_ADMIN'] === '1'" href="#" @click="$emit('input', 'DeviceManufacturer'); showDropdown = false" class="dropdown-item">Hersteller</a>
<a v-show="window.TT_CONFIG['IS_ADMIN'] === '1'" href="#" @click="$emit('input', 'DeviceType'); showDropdown = false" class="dropdown-item">Geräte Typen</a>
</div>
</div>
</div>
</div>
`,
props: ['value'],
<div class="device-view-switch" style="margin-bottom: 10px">
<div v-if="!isOverflowing"
class="button-group"
style="display:grid; grid-template-columns: repeat(3, 1fr); gap: 10px; justify-content: center; align-items: center; text-align: center; width: 100%;">
<button @click="$emit('input', 'DeviceTable')" :class="{ 'active': value === 'DeviceTable' }" class="btn btn-primary">Devices</button>
<button @click="$emit('input', 'DeviceManufacturer')"
:class="{ 'active': value === 'DeviceManufacturer' }"
class="btn btn-primary">Hersteller
</button>
<button @click="$emit('input', 'DeviceType')"
:class="{ 'active': value === 'DeviceType' }"
class="btn btn-primary">Geräte Typen
</button>
</div>
<div v-else>
<div class="dropdown">
<button @click="showDropdown = !showDropdown"
class="btn btn-primary dropdown-toggle">Ansicht
</button>
<div v-show="showDropdown" class="dropdown-menu show">
<a href="#" @click="$emit('input', 'DeviceTable'); showDropdown = false" class="dropdown-item">Devices</a>
<a href="#"
@click="$emit('input', 'DeviceManufacturer'); showDropdown = false"
class="dropdown-item">Hersteller</a>
<a href="#"
@click="$emit('input', 'DeviceType'); showDropdown = false"
class="dropdown-item">Geräte Typen</a>
</div>
</div>
</div>
</div>
`,
props: ['value'],
data() {
return {
window: window,
window: window,
isOverflowing: false,
showDropdown: false,
showDropdown: false,
};
},
mounted() {
@@ -53,115 +68,142 @@ Vue.component('device-view-switch', {
})
Vue.component('DeviceTable', {
//language=Vue
template: `
<tt-table :data="window['TT_CONFIG']['DEVICES']" :config="DeviceTableConfig" excel-export>
//language=Vue
template: `
<tt-table :data="window['TT_CONFIG']['DEVICES']" :config="DeviceTableConfig" excel-export>
<template v-slot:top-buttons>
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Device/add'">
<i class="fas fa-plus"></i>
Device hinzufügen
</button>
</template>
<template v-slot:top-buttons v-if="window['TT_CONFIG']['IS_ADMIN'] === '1'">
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Device/add'">
<i class="fas fa-plus"></i>
Device hinzufügen
</button>
</template>
<template v-slot:name="{ row }">
<a target="_blank" :href="window['TT_CONFIG']['BASE_URL'] +'/Device/Detail?id=' + row.id">{{row.name}}</a>
</template>
<template v-slot:name="{ row }">
<a target="_blank" :href="window['TT_CONFIG']['BASE_URL'] +'/Device/Detail?id=' + row.id">{{row.name}}</a>
</template>
<template v-slot:locationtext="{ row }">
<a target="_blank" :href="row['locationUrl']">{{row.locationText}}</a>
</template>
<template v-slot:locationtext="{ row }">
<template v-if="window['TT_CONFIG']['IS_ADMIN'] === '1'">
<a target="_blank" :href="row['locationUrl']">{{row.locationText}}</a>
</template>
<template v-else>
{{row.locationText}}
</template>
</template>
<template v-slot:actions="{ row }">
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Device/edit/?id=' + row.id"><i class="far fa-edit" title="Bearbeiten"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Device/delete/?id=' + row.id" onclick="if(!confirm('Device wirklich löschen?')) return false;" class="text-danger" title="Löschen"><i class="fas fa-trash "></i></a>
<template v-if="row.zabbix_host_id !== '0' && row.zabbix_host_id !== null">
<a :href="window['TT_CONFIG']['ZABBIX_URL'] + '/zabbix.php?action=latest.view&hostids%5B%5D=' + row.zabbix_host_id" target="_blank" class="text-info" title="Zabbix"><i class="fas fa-server"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] + '/Graphing?id=' + row.zabbix_host_id + '&hostname=' + row.name" target="_blank" class="text-info" title="Graphen"><i class="fas fa-chart-line"></i></a>
</template>
</template>
<template v-slot:actions="{ row }">
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Device/edit/?id=' + row.id"><i class="far fa-edit" title="Bearbeiten"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Device/delete/?id=' + row.id"
onclick="if(!confirm('Device wirklich löschen?')) return false;"
class="text-danger"
title="Löschen"><i class="fas fa-trash "></i></a>
</tt-table>
`,
<template v-if="row.zabbix_host_id !== '0' && row.zabbix_host_id !== null">
<a :href="window['TT_CONFIG']['ZABBIX_URL'] + '/zabbix.php?action=latest.view&hostids%5B%5D=' + row.zabbix_host_id"
target="_blank"
class="text-info"
title="Zabbix"><i class="fas fa-server"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] + '/Graphing?id=' + row.zabbix_host_id + '&hostname=' + row.name"
target="_blank"
class="text-info"
title="Graphen"><i class="fas fa-chart-line"></i></a>
</template>
</template>
</tt-table>
`,
data() {
return {
window: window,
DeviceTableConfig: {
key: 'DeviceTable',
tableHeader: 'Device-Liste',
defaultPageSize: 25,
headers: [
{ text: 'Device Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10 },
{ text: 'Hersteller', key: 'devicemanufactor', filter: 'select',class: 'text-nowrap text-center', filterOptions: deviceManufacturerFilterOptions },
{ text: 'Geräte Typ', key: 'devicetype', filter: 'select', class: 'text-nowrap text-center', filterOptions: deviceTypeFilterOptions , priority: 7},
{ text: 'Pop/Adresse', key: 'locationText', filter: 'search' , class: 'text-nowrap text-center'},
{ text: 'IP-Adresse', key: 'ip', filter: 'search',class: 'text-center', priority: 8},
{ text: 'Mac-Adresse', key: 'mac', filter: 'search',class: 'text-center' },
{ text: 'Seriennummer', key: 'serial', filter: 'search',class: 'text-center' },
{ text: 'Preis', key: 'price', filter: 'numberRange',class: 'text-center', suffix: ' €' },
{ text: 'max. Leistung', key: 'power', filter: 'numberRange',class: 'text-center', suffix: ' W' },
{
text: 'Backup',
key: 'backup',
filter: 'iconSelect',
filterOptions: [
{ value: 'ok', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-check text-success' },
{ value: 'auto', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-a text-success' },
{ value: 'aged', text: 'Letztes Configbackup älter als 48 Stunden', icon: 'fa-regular fa-circle-xmark' },
{ value: 'na', text: 'N/A', icon: 'fa-regular fa-ban text-warning' }
],
priority: 6,
sortable: false,
}, {
text: 'Status',
key: 'zabbix_online',
filter: 'iconSelect',
filterOptions: [
{ value: 0, text: 'Status unbekannt', icon: 'fa-regular fa-circle-xmark' },
{ value: 1, text: 'Offline', icon: 'fa-regular fa-circle-xmark text-danger' },
{ value: 2, text: 'Online', icon: 'fa-regular fa-circle-check text-success' },
],
priority: 5,
sortable: false,
},
{text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9},
],
},
}
return {
window: window,
DeviceTableConfig: {
key: 'DeviceTable',
tableHeader: 'Device-Liste',
defaultPageSize: 25,
headers: [],
},
}
},
mounted() {
this.DeviceTableConfig.headers = [
{text: 'Device Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10},
{text: 'Hersteller', key: 'devicemanufactor', filter: 'select', class: 'text-nowrap text-center', filterOptions: deviceManufacturerFilterOptions},
{text: 'Geräte Typ', key: 'devicetype', filter: 'select', class: 'text-nowrap text-center', filterOptions: deviceTypeFilterOptions, priority: 7},
{text: 'Pop/Adresse', key: 'locationText', filter: 'search', class: 'text-nowrap text-center'},
{text: 'IP-Adresse', key: 'ip', filter: 'search', class: 'text-center', priority: 8},
{text: 'Mac-Adresse', key: 'mac', filter: 'search', class: 'text-center'},
{text: 'Seriennummer', key: 'serial', filter: 'search', class: 'text-center'},
];
if (this.window.TT_CONFIG['IS_ADMIN'] === '1') {
this.DeviceTableConfig.headers = [
...this.DeviceTableConfig.headers,
{text: 'Preis', key: 'price', filter: 'numberRange', class: 'text-center', suffix: ' €'},
{text: 'max. Leistung', key: 'power', filter: 'numberRange', class: 'text-center', suffix: ' W'},
{
text: 'Backup',
key: 'backup',
filter: 'iconSelect',
filterOptions: [
{value: 'ok', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-check text-success'},
{value: 'auto', text: 'Configbackup aktuell', icon: 'fa-regular fa-circle-a text-success'},
{value: 'aged', text: 'Letztes Configbackup älter als 48 Stunden', icon: 'fa-regular fa-circle-xmark'},
{value: 'na', text: 'N/A', icon: 'fa-regular fa-ban text-warning'}
],
priority: 6,
sortable: false,
}, {
text: 'Status',
key: 'zabbix_online',
filter: 'iconSelect',
filterOptions: [
{value: 0, text: 'Status unbekannt', icon: 'fa-regular fa-circle-xmark'},
{value: 1, text: 'Offline', icon: 'fa-regular fa-circle-xmark text-danger'},
{value: 2, text: 'Online', icon: 'fa-regular fa-circle-check text-success'},
],
priority: 5,
sortable: false,
},
{text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9},
]
}
}
});
Vue.component('DeviceManufacturer', {
//language=Vue
template: `
<tt-table :data="window['TT_CONFIG']['DEVICE_MANUFACTURERS']" :config="DeviceManufacturerConfig" excel-export>
<tt-table :data="window['TT_CONFIG']['DEVICE_MANUFACTURERS']" :config="DeviceManufacturerConfig" excel-export>
<template v-slot:top-buttons>
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Devicemanufactor/add'">
<i class="fas fa-plus"></i>Hersteller hinzufügen
</button>
</template>
<template v-slot:top-buttons>
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Devicemanufactor/add'">
<i class="fas fa-plus"></i>Hersteller hinzufügen
</button>
</template>
<template v-slot:actions="{ row }">
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicemanufactor/edit/?id=' + row.id"><i class="far fa-edit" title="Bearbeiten"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicemanufactor/delete/?id=' + row.id" onclick="if(!confirm('Hersteller wirklich löschen?')) return false;" class="text-danger" title="Löschen"><i class="fas fa-trash "></i></a>
</template>
<template v-slot:actions="{ row }">
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicemanufactor/edit/?id=' + row.id"><i class="far fa-edit" title="Bearbeiten"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicemanufactor/delete/?id=' + row.id"
onclick="if(!confirm('Hersteller wirklich löschen?')) return false;"
class="text-danger"
title="Löschen"><i class="fas fa-trash "></i></a>
</template>
</tt-table>
`,
</tt-table>
`,
data() {
return {
window: window,
window: window,
DeviceManufacturerConfig: {
key: 'DeviceManufacturer',
tableHeader: 'Hersteller',
key: 'DeviceManufacturer',
tableHeader: 'Hersteller',
defaultPageSize: 25,
headers: [
{ text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10 },
{ text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'},
{ text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'},
{ text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9},
headers: [
{text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10},
{text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'},
{text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'},
{text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9},
],
},
}
@@ -171,36 +213,39 @@ Vue.component('DeviceManufacturer', {
Vue.component('DeviceType', {
//language=Vue
template: `
<tt-table :data="window['TT_CONFIG']['DEVICE_TYPES']" :config="DeviceTypeConfig" excel-export>
<template v-slot:top-buttons>
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Devicetype/add'">
<i class="fas fa-plus"></i>Device Type hinzufügen
</button>
</template>
<template v-slot:actions="{ row }">
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicetype/edit/?id=' + row.id"><i class="far fa-edit" title="Bearbeiten"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicetype/delete/?id=' + row.id" onclick="if(!confirm('Gerätetyp wirklich löschen?')) return false;" class="text-danger" title="Löschen"><i class="fas fa-trash "></i></a>
</template>
</tt-table>
`,
<tt-table :data="window['TT_CONFIG']['DEVICE_TYPES']" :config="DeviceTypeConfig" excel-export>
<template v-slot:top-buttons>
<button type="button" class="btn btn-primary" @click="window.location = window['TT_CONFIG']['BASE_URL'] + '/Devicetype/add'">
<i class="fas fa-plus"></i>Device Type hinzufügen
</button>
</template>
<template v-slot:actions="{ row }">
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicetype/edit/?id=' + row.id"><i class="far fa-edit" title="Bearbeiten"></i></a>
<a :href="window['TT_CONFIG']['BASE_URL'] +'/Devicetype/delete/?id=' + row.id"
onclick="if(!confirm('Gerätetyp wirklich löschen?')) return false;"
class="text-danger"
title="Löschen"><i class="fas fa-trash "></i></a>
</template>
</tt-table>
`,
data() {
return {
window: window,
return {
window: window,
DeviceTypeConfig: {
key: 'DeviceType',
tableHeader: 'Gerätetypen',
key: 'DeviceType',
tableHeader: 'Gerätetypen',
defaultPageSize: 25,
headers: [
{ text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10 },
{ text: 'Hersteller', key: 'manufacturer', filter: 'search', class: 'text-center'},
{ text: 'Preis', key: 'price', filter: 'numberRange', class: 'text-center', suffix: ' €' },
{ text: 'max. Leistung', key: 'power', filter: 'numberRange', class: 'text-center', suffix: ' W' },
{ text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'},
{ text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'},
{ text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9},
headers: [
{text: 'Name', key: 'name', sortable: true, class: 'text-nowrap', priority: 10},
{text: 'Hersteller', key: 'manufacturer', filter: 'search', class: 'text-center'},
{text: 'Preis', key: 'price', filter: 'numberRange', class: 'text-center', suffix: ' €'},
{text: 'max. Leistung', key: 'power', filter: 'numberRange', class: 'text-center', suffix: ' W'},
{text: 'Erstellungsdatum', key: 'created', filter: 'date', class: 'text-center'},
{text: 'Erstellt von', key: 'creator', filter: 'search', class: 'text-center'},
{text: 'Aktionen', key: 'actions', class: 'text-center', sortable: false, filter: false, priority: 9},
],
},
}
@@ -210,15 +255,15 @@ Vue.component('DeviceType', {
Vue.component('Device', {
//language=Vue
template: `
<tt-card>
<device-view-switch v-model="currentView"></device-view-switch>
<component :is="currentView"></component>
</tt-card>
`,
<tt-card>
<device-view-switch v-show="window['TT_CONFIG']['IS_ADMIN'] === '1'" v-model="currentView"></device-view-switch>
<component :is="currentView"></component>
</tt-card>
`,
data() {
return {
window: window,
window: window,
currentView: 'DeviceTable',
};
},