diff --git a/config/Migrations/20230704135047_UniqueIndexForUsergroups.php b/config/Migrations/20230704135047_UniqueIndexForUsergroups.php new file mode 100644 index 0000000000..2fc33e5a78 --- /dev/null +++ b/config/Migrations/20230704135047_UniqueIndexForUsergroups.php @@ -0,0 +1,59 @@ + +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. + +declare(strict_types=1); + +use Migrations\AbstractMigration; + +/** + * Class UniqueIndexForUsergroups + * + * Created via: + * oitc migrations create UniqueIndexForUsergroups + * + * Run migration: + * oitc migrations migrate + * + */ +class UniqueIndexForUsergroups extends AbstractMigration { + /** + * Change Method. + * + * More information on this method is available here: + * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method + * @return void + */ + public function change(): void { + if ($this->hasTable('usergroups')) { + $this->table('usergroups') + ->addIndex( + [ + 'name', + ], + ['unique' => true] + ) + ->update(); + } + } +} diff --git a/plugins/GrafanaModule/src/Controller/GrafanaUserdashboardsController.php b/plugins/GrafanaModule/src/Controller/GrafanaUserdashboardsController.php index 1825bdd8c7..76b945e226 100644 --- a/plugins/GrafanaModule/src/Controller/GrafanaUserdashboardsController.php +++ b/plugins/GrafanaModule/src/Controller/GrafanaUserdashboardsController.php @@ -35,6 +35,8 @@ use Cake\Http\Exception\NotFoundException; use Cake\Log\Log; use Cake\ORM\TableRegistry; +use GrafanaModule\Model\Entity\GrafanaUserdashboardMetric; +use GrafanaModule\Model\Entity\GrafanaUserdashboardPanel; use GrafanaModule\Model\Table\GrafanaConfigurationsTable; use GrafanaModule\Model\Table\GrafanaUserdashboardMetricsTable; use GrafanaModule\Model\Table\GrafanaUserdashboardPanelsTable; @@ -402,6 +404,127 @@ public function delete($id) { $this->viewBuilder()->setOption('serialize', ['success', 'message']); } + /** + * @param int|null $id + */ + public function copy($id = null) { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var GrafanaUserdashboardsTable $GrafanaUserdashboardsTable */ + $GrafanaUserdashboardsTable = TableRegistry::getTableLocator()->get('GrafanaModule.GrafanaUserdashboards'); + /** @var GrafanaUserdashboardPanelsTable $GrafanaUserdashboardPanelsTable */ + $GrafanaUserdashboardPanelsTable = TableRegistry::getTableLocator()->get('GrafanaModule.GrafanaUserdashboardPanels'); + /** @var GrafanaUserdashboardMetricsTable $GrafanaUserdashboardMetricsTable */ + $GrafanaUserdashboardMetricsTable = TableRegistry::getTableLocator()->get('GrafanaModule.GrafanaUserdashboardMetrics'); + + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + + if ($this->request->is('get')) { + $dashboards = $GrafanaUserdashboardsTable->getGrafanaUserdashboardsForCopy(func_get_args(), $MY_RIGHTS); + $this->set('dashboards', $dashboards); + $this->viewBuilder()->setOption('serialize', ['dashboards']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + $postData = $this->request->getData('data', []); + + foreach ($postData as $index => $dashboardData) { + if (!isset($dashboardData['Dashboard']['id'])) { + //Create/clone Grafana User Dashboard + $sourceId = $dashboardData['Source']['id']; + $sourceDashboard = $GrafanaUserdashboardsTable->getSourceGrafanaUserdashboardForCopy($sourceId, $MY_RIGHTS); + + $newDashboardData = $sourceDashboard; + $newDashboardData['name'] = $dashboardData['Dashboard']['name']; + + $newDashboardEntity = $GrafanaUserdashboardsTable->newEntity($newDashboardData); + } + + $action = 'copy'; + if (isset($dashboardData['Dashboard']['id'])) { + //Update existing Grafana Userdashboard + //This happens, if a user copy multiple dashboards, and one run into an validation error + //All dashboards without validation errors got already saved to the database + $newDashboardEntity = $GrafanaUserdashboardsTable->get($dashboardData['Dashboard']['id']); + $newDashboardEntity->setAccess('id', false); + $newDashboardEntity->setAccess('container_id', false); + $newDashboardEntity->set('name', $dashboardData['Dashboard']['name']); + $action = 'edit'; + } + $GrafanaUserdashboardsTable->save($newDashboardEntity); + + $postData[$index]['Error'] = []; + if ($newDashboardEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newDashboardEntity->getErrors(); + } else { + //No errors + + // Due to Grafana User Dashboards are a bit special, we need to create the Dashboard first, + // than add panels and in the last step we can add metrics to the panels :/ + // Therefor we only do this for new copies, not for an update (due to validation errors) + if ($action === 'copy') { + $sourcePanels = $GrafanaUserdashboardPanelsTable->getPanelsByUserdashboardIdForCopy($dashboardData['Source']['id']); + if (!empty($sourcePanels)) { + foreach ($sourcePanels as $sourcePanel) { + /** @var GrafanaUserdashboardPanel $sourcePanel */ + $newPanelEntity = $GrafanaUserdashboardPanelsTable->newEntity([ + 'userdashboard_id' => $newDashboardEntity->get('id'), + 'row' => $sourcePanel->row, + 'unit' => $sourcePanel->unit, + 'title' => $sourcePanel->title, + 'visualization_type' => $sourcePanel->visualization_type, + 'stacking_mode' => $sourcePanel->stacking_mode + ]); + + $GrafanaUserdashboardPanelsTable->save($newPanelEntity); + if (!$newPanelEntity->hasErrors()) { + // Copy metrics form source dashboard/panel into the new panel + $sourceMetrics = $GrafanaUserdashboardMetricsTable->getMetricsByPanelIdForCopy($sourcePanel->get('id')); + if (!empty($sourceMetrics)) { + foreach ($sourceMetrics as $sourceMetric) { + /** @var GrafanaUserdashboardMetric $sourceMetric */ + $newMetricEntity = $GrafanaUserdashboardMetricsTable->newEntity([ + 'panel_id' => $newPanelEntity->get('id'), + 'metric' => $sourceMetric->metric, + 'host_id' => $sourceMetric->host_id, + 'service_id' => $sourceMetric->service_id, + 'color' => $sourceMetric->color + ]); + $GrafanaUserdashboardMetricsTable->save($newMetricEntity); + } + } + } + + } + } + } + + $postData[$index]['Dashboard']['id'] = $newDashboardEntity->get('id'); + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } + + /**************************** + * AJAX METHODS * + ****************************/ + /** * @throws \Exception */ diff --git a/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardMetricsTable.php b/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardMetricsTable.php index 07fea10ad6..89abea7627 100644 --- a/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardMetricsTable.php +++ b/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardMetricsTable.php @@ -166,4 +166,17 @@ public function existsById($id) { return $this->exists(['GrafanaUserdashboardMetrics.id' => $id]); } + /** + * @param int $panelId + * @return \Cake\Datasource\ResultSetInterface + */ + public function getMetricsByPanelIdForCopy(int $panelId) { + $result = $this->find() + ->where([ + 'GrafanaUserdashboardMetrics.panel_id' => $panelId + ]) + ->all(); + return $result; + } + } diff --git a/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardPanelsTable.php b/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardPanelsTable.php index fc5b2b2a4b..66c4fecb6e 100644 --- a/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardPanelsTable.php +++ b/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardPanelsTable.php @@ -147,4 +147,18 @@ public function getNextRow($dashboardId) { return $result->get('row') + 1; } + /** + * @param int $dashboardId + * @return \Cake\Datasource\ResultSetInterface + */ + public function getPanelsByUserdashboardIdForCopy(int $dashboardId){ + $result = $this->find() + ->where([ + 'GrafanaUserdashboardPanels.userdashboard_id' => $dashboardId + ]) + ->all(); + + return $result; + } + } diff --git a/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardsTable.php b/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardsTable.php index c27136b888..a7f5c94f06 100644 --- a/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardsTable.php +++ b/plugins/GrafanaModule/src/Model/Table/GrafanaUserdashboardsTable.php @@ -366,11 +366,66 @@ public function getGrafanaUserdashboardsWithPanelsAndMetricsById($id) { return $query->first(); } + /** + * @param array $ids + * @param array $MY_RIGHTS + * @return array + */ + public function getGrafanaUserdashboardsForCopy($ids = [], array $MY_RIGHTS = []) { + $query = $this->find() + ->select([ + 'GrafanaUserdashboards.id', + 'GrafanaUserdashboards.name' + ]) + ->where(['GrafanaUserdashboards.id IN' => $ids]) + ->order(['GrafanaUserdashboards.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'GrafanaUserdashboards.container_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + /** + * @param $sourceAutomapId + * @param array $MY_RIGHTS + * @return array + */ + public function getSourceGrafanaUserdashboardForCopy($sourceAutomapId, array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['GrafanaUserdashboards.id' => $sourceAutomapId]); + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'GrafanaUserdashboards.container_id IN' => $MY_RIGHTS + ]); + } + + $result = $query->firstOrFail(); + $dbResult = $this->emptyArrayIfNull($result->toArray()); + if (empty($dbResult)) { + return []; + } + + // Remove IDs of source elements + $dashboard = [ + 'container_id' => $dbResult['container_id'], + 'configuration_id' => $dbResult['configuration_id'] + ]; + + return $dashboard; + } + /** * @param int $containerId * @return array */ - public function getOrphanedGrafanaUserdashboardsByContainerId(int $containerId){ + public function getOrphanedGrafanaUserdashboardsByContainerId(int $containerId) { $query = $this->find() ->where(['container_id' => $containerId]); $result = $query->all(); diff --git a/plugins/GrafanaModule/templates/GrafanaUserdashboards/copy.php b/plugins/GrafanaModule/templates/GrafanaUserdashboards/copy.php new file mode 100644 index 0000000000..523f979919 --- /dev/null +++ b/plugins/GrafanaModule/templates/GrafanaUserdashboards/copy.php @@ -0,0 +1,110 @@ + +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'GrafanaUserdashboards', 'GrafanaModule')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceDashboard.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'GrafanaUserdashboards', 'GrafanaModule')): ?> + + +
+
+
+
+
+
+
+
diff --git a/plugins/GrafanaModule/templates/GrafanaUserdashboards/index.php b/plugins/GrafanaModule/templates/GrafanaUserdashboards/index.php index 835e73d6ed..31d60819ae 100644 --- a/plugins/GrafanaModule/templates/GrafanaUserdashboards/index.php +++ b/plugins/GrafanaModule/templates/GrafanaUserdashboards/index.php @@ -209,6 +209,14 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'GrafanaUserdashboards', 'GrafanaModule')): ?> + + + + + + Acl->hasPermission('delete', 'GrafanaUserdashboards', 'GrafanaModule')): ?> + Acl->hasPermission('copy', 'GrafanaUserdashboards', 'GrafanaModule')): ?> + + + Acl->hasPermission('edit', 'GrafanaUserdashboards', 'GrafanaModule')): ?> +
+ + + + +
+ Acl->hasPermission('delete', 'GrafanaUserdashboards', 'GrafanaModule')): ?> -
+
diff --git a/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsCopyController.js b/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsCopyController.js new file mode 100644 index 0000000000..ee87090f9e --- /dev/null +++ b/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsCopyController.js @@ -0,0 +1,55 @@ +angular.module('openITCOCKPIT') + .controller('Grafana_userdashboardsCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('GrafanaUserdashboardsIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/grafana_module/grafana_userdashboards/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceDashboards = []; + for(var key in result.data.dashboards){ + $scope.sourceDashboards.push({ + Source: { + id: result.data.dashboards[key].id, + name: result.data.dashboards[key].name, + }, + Dashboard: { + name: result.data.dashboards[key].name + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/grafana_module/grafana_userdashboards/copy/.json?angular=true", + { + data: $scope.sourceDashboards + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('GrafanaUserdashboardsIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceDashboards = result.data.result; + }); + }; + + + $scope.load(); + + }); diff --git a/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsIndexController.js b/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsIndexController.js index c1cc504388..94357438a3 100644 --- a/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsIndexController.js +++ b/plugins/GrafanaModule/webroot/js/scripts/controllers/GrafanaUserdashboardsIndexController.js @@ -95,6 +95,11 @@ angular.module('openITCOCKPIT') return object; }; + $scope.linkForCopy = function(){ + var ids = Object.keys(MassChangeService.getSelected()); + return ids.join(','); + }; + $scope.changepage = function(page){ if(page !== $scope.currentPage){ $scope.currentPage = page; @@ -107,33 +112,56 @@ angular.module('openITCOCKPIT') $scope.load(); }; - $scope.synchronizeWithGrafana = function(id){ - $('#synchronizeWithGrafanaModal').modal('show'); - - $scope.syncError = false; - var data = { - id: id - }; - - $http.post("/grafana_module/grafana_userdashboards/synchronizeWithGrafana.json?angular=true", data).then(function(result){ + // This method can now be called with a singel id, or an object with multiple ids + // where the key of the object has to be the ID of the dashboard you want to sync + $scope.synchronizeWithGrafana = function(_ids){ + // Convert singel ID into an object + // For example when synchronize is selected from the dropdown menu + var ids = {}; + if(typeof _ids !== "object"){ + ids[_ids] = 'Dashboard'; + }else{ + ids = _ids; + } + var count = Object.keys(ids).length; + var i = 0; + var issueCount = 0; - if(result.data.success){ - new Noty({ - theme: 'metroui', - type: 'success', - text: 'Synchronization successfully', - timeout: 3500 - }).show(); - $('#synchronizeWithGrafanaModal').modal('hide'); - $scope.load(); - return; - } + if(count === 0){ + return; + } - $scope.syncError = result.data.message; - }, function errorCallback(result){ - $scope.syncError = result.data.message; - }); + $('#synchronizeWithGrafanaModal').modal('show'); + for(var id in ids){ + $scope.syncError = false; + var data = { + id: id + }; + + $http.post("/grafana_module/grafana_userdashboards/synchronizeWithGrafana.json?angular=true", data).then(function(result){ + i++; + if(result.data.success){ + if(i === count && issueCount === 0){ + new Noty({ + theme: 'metroui', + type: 'success', + text: 'Synchronization successfully', + timeout: 3500 + }).show(); + $('#synchronizeWithGrafanaModal').modal('hide'); + $scope.load(); + return; + } + }else{ + $scope.syncError = result.data.message; + } + }, function errorCallback(result){ + i++; + issueCount++; + $scope.syncError = result.data.message; + }); + } }; diff --git a/plugins/GrafanaModule/webroot/js/scripts/ng.states.js b/plugins/GrafanaModule/webroot/js/scripts/ng.states.js index c8e2069d2a..ee3ae99f66 100644 --- a/plugins/GrafanaModule/webroot/js/scripts/ng.states.js +++ b/plugins/GrafanaModule/webroot/js/scripts/ng.states.js @@ -31,6 +31,12 @@ openITCOCKPIT.config(function($stateProvider){ controller: "Grafana_userdashboardsViewController" }) + .state('GrafanaUserdashboardsCopy', { + url: '/grafana_module/grafana_userdashboards/copy/:ids', + templateUrl: "/grafana_module/grafana_userdashboards/copy.html", + controller: "Grafana_userdashboardsCopyController" + }) + .state('GrafanaConfigurationIndex', { url: '/grafana_module/grafana_configuration/index', templateUrl: "/grafana_module/grafana_configuration/index.html", diff --git a/plugins/MapModule/src/Controller/MapsController.php b/plugins/MapModule/src/Controller/MapsController.php index 3f679196e8..c38c041c87 100755 --- a/plugins/MapModule/src/Controller/MapsController.php +++ b/plugins/MapModule/src/Controller/MapsController.php @@ -314,6 +314,12 @@ public function copy($id = null) { ] ]); $mapData['Map']['containers']['_ids'] = $newMapEntity->getContainerIds(); + if (isset($mapData['Map']['refresh_interval'])) { + $mapData['Map']['refresh_interval'] = $mapData['Map']['refresh_interval'] * 1000; + } + + $newMapEntity->setAccess('*', false); + $newMapEntity->setAccess(['name', 'title', 'refresh_interval'], true); $newMapEntity = $MapsTable->patchEntity($newMapEntity, $mapData['Map']); $action = 'edit'; } else { diff --git a/src/Controller/AutomapsController.php b/src/Controller/AutomapsController.php index 4a6448bf8f..351e1c9722 100644 --- a/src/Controller/AutomapsController.php +++ b/src/Controller/AutomapsController.php @@ -381,6 +381,95 @@ public function icon() { return; } + /** + * @param int|null $id + */ + public function copy($id = null) { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var AutomapsTable $AutomapsTable */ + $AutomapsTable = TableRegistry::getTableLocator()->get('Automaps'); + + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + + if ($this->request->is('get')) { + $automaps = $AutomapsTable->getAutomapsForCopy(func_get_args(), $MY_RIGHTS); + $this->set('automaps', $automaps); + $this->viewBuilder()->setOption('serialize', ['automaps']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + $postData = $this->request->getData('data'); + + foreach ($postData as $index => $automapData) { + if (!isset($automapData['Automap']['id'])) { + //Create/clone automap + $sourceAutomapId = $automapData['Source']['id']; + $sourceAutomap = $AutomapsTable->getSourceAutomapForCopy($sourceAutomapId, $MY_RIGHTS); + + $newAutomapData = [ + 'name' => $automapData['Automap']['name'], + 'description' => $automapData['Automap']['description'], + 'container_id' => $sourceAutomap['container_id'], + 'recursive' => $sourceAutomap['recursive'], + 'host_regex' => $automapData['Automap']['host_regex'], + 'service_regex' => $automapData['Automap']['service_regex'], + 'show_ok' => $sourceAutomap['show_ok'], + 'show_warning' => $sourceAutomap['show_warning'], + 'show_critical' => $sourceAutomap['show_critical'], + 'show_unknown' => $sourceAutomap['show_unknown'], + 'show_downtime' => $sourceAutomap['show_downtime'], + 'show_acknowledged' => $sourceAutomap['show_acknowledged'], + 'show_label' => $sourceAutomap['show_label'], + 'group_by_host' => $sourceAutomap['group_by_host'], + 'use_paginator' => $sourceAutomap['use_paginator'], + 'font_size' => $sourceAutomap['font_size'], + ]; + + $newAutomapEntity = $AutomapsTable->newEntity($newAutomapData); + } + + $action = 'copy'; + if (isset($automapData['Automap']['id'])) { + //Update existing automap + //This happens, if a user copy multiple automaps, and one run into an validation error + //All automaps without validation errors got already saved to the database + $newAutomapEntity = $AutomapsTable->get($automapData['Automap']['id']); + $newAutomapEntity->setAccess('*', false); + $newAutomapEntity->setAccess(['name', 'description', 'host_regex', 'service_regex'], true); + + $newAutomapEntity = $AutomapsTable->patchEntity($newAutomapEntity, $automapData['Automap']); + $action = 'edit'; + } + $AutomapsTable->save($newAutomapEntity); + + $postData[$index]['Error'] = []; + if ($newAutomapEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newAutomapEntity->getErrors(); + } else { + //No errors + $postData[$index]['Automap']['id'] = $newAutomapEntity->get('id'); + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } + /**************************** * AJAX METHODS * ****************************/ diff --git a/src/Controller/CommandsController.php b/src/Controller/CommandsController.php index 7fca3cd0a7..164656ac2b 100644 --- a/src/Controller/CommandsController.php +++ b/src/Controller/CommandsController.php @@ -404,6 +404,8 @@ public function copy($id = null) { //This happens, if a user copy multiple commands, and one run into an validation error //All commands without validation errors got already saved to the database $newCommandEntity = $CommandsTable->get($commandData['Command']['id']); + $newCommandEntity->setAccess('*', false); + $newCommandEntity->setAccess(['name', 'command_line', 'description'], true); $newCommandEntity = $CommandsTable->patchEntity($newCommandEntity, $commandData['Command']); $newCommandData = $newCommandEntity->toArray(); $action = 'edit'; diff --git a/src/Controller/ContactgroupsController.php b/src/Controller/ContactgroupsController.php index 48c7b9f655..9901d12764 100644 --- a/src/Controller/ContactgroupsController.php +++ b/src/Controller/ContactgroupsController.php @@ -308,7 +308,7 @@ public function delete($id) { 'Contactgroups' ] ]); - if($ContainersTable->allowDelete($container->id, $this->MY_RIGHTS)){ + if ($ContainersTable->allowDelete($container->id, CT_CONTACTGROUP)) { if ($ContainersTable->delete($container)) { $User = new User($this->getUser()); Cache::clear('permissions'); @@ -360,8 +360,13 @@ public function copy($id = null) { /** @var $ContactgroupsTable ContactgroupsTable */ $ContactgroupsTable = TableRegistry::getTableLocator()->get('Contactgroups'); + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + if ($this->request->is('get')) { - $contactgroups = $ContactgroupsTable->getContactgroupsForCopy(func_get_args()); + $contactgroups = $ContactgroupsTable->getContactgroupsForCopy(func_get_args(), $MY_RIGHTS); $this->set('contactgroups', $contactgroups); $this->viewBuilder()->setOption('serialize', ['contactgroups']); return; @@ -416,6 +421,8 @@ public function copy($id = null) { //This happens, if a user copy multiple contacts, and one run into an validation error //All contacts without validation errors got already saved to the database $newContactgroupEntity = $ContactgroupsTable->get($contactgroupData['Contactgroup']['id']); + $newContactgroupEntity->setAccess('*', false); + $newContactgroupEntity->setAccess(['name', 'description'], true); $newContactgroupEntity = $ContactgroupsTable->patchEntity($newContactgroupEntity, $contactgroupData['Contactgroup']); $newContactgroupData = $newContactgroupEntity->toArray(); $action = 'edit'; @@ -455,6 +462,7 @@ public function copy($id = null) { if ($hasErrors) { $this->response = $this->response->withStatus(400); } + Cache::clear('permissions'); $this->set('result', $postData); $this->viewBuilder()->setOption('serialize', ['result']); } diff --git a/src/Controller/ContactsController.php b/src/Controller/ContactsController.php index e464e161d7..4166163d21 100644 --- a/src/Controller/ContactsController.php +++ b/src/Controller/ContactsController.php @@ -402,9 +402,13 @@ public function copy($id = null) { /** @var $ContactsTable ContactsTable */ $ContactsTable = TableRegistry::getTableLocator()->get('Contacts'); + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } if ($this->request->is('get')) { - $contacts = $ContactsTable->getContactsForCopy(func_get_args()); + $contacts = $ContactsTable->getContactsForCopy(func_get_args(), $MY_RIGHTS); $this->set('contacts', $contacts); $this->viewBuilder()->setOption('serialize', ['contacts']); return; @@ -501,6 +505,8 @@ public function copy($id = null) { //This happens, if a user copy multiple contacts, and one run into an validation error //All contacts without validation errors got already saved to the database $newContactEntity = $ContactsTable->get($contactData['Contact']['id']); + $newContactEntity->setAccess('*', false); + $newContactEntity->setAccess(['name', 'description', 'email', 'phone'], true); $newContactEntity = $ContactsTable->patchEntity($newContactEntity, $contactData['Contact']); $newContactData = $newContactEntity->toArray(); $action = 'edit'; diff --git a/src/Controller/ContainersController.php b/src/Controller/ContainersController.php index 1afc979fe1..b3c539bb3a 100644 --- a/src/Controller/ContainersController.php +++ b/src/Controller/ContainersController.php @@ -438,7 +438,7 @@ public function delete($id = null) { $containerForChangelog = $container->toArray(); //check if the current container contains subcontainers - $deletionAllowed = $ContainersTable->allowDelete($id); + $deletionAllowed = $ContainersTable->allowDelete($id, $container->containertype_id); if ($deletionAllowed) { Cache::clear('permissions'); if ($ContainersTable->delete($container)) { diff --git a/src/Controller/HostgroupsController.php b/src/Controller/HostgroupsController.php index 7386ed2180..0cfaac1982 100644 --- a/src/Controller/HostgroupsController.php +++ b/src/Controller/HostgroupsController.php @@ -234,7 +234,7 @@ public function edit($id = null) { } if ($this->request->is('post') && $this->isAngularJsRequest()) { - //Update contact data + //Update hostgroup data $User = new User($this->getUser()); /** @var ContainersTable $ContainersTable */ @@ -322,7 +322,7 @@ public function delete($id = null) { return; } - if ($ContainersTable->allowDelete($container->id, $this->MY_RIGHTS)) { + if ($ContainersTable->allowDelete($container->id, CT_HOSTGROUP)) { if ($ContainersTable->delete($container)) { $User = new User($this->getUser()); /** @var ChangelogsTable $ChangelogsTable */ @@ -843,6 +843,127 @@ public function append() { } } + /** + * @param int|null $id + */ + public function copy($id = null) { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var HostgroupsTable $HostgroupsTable */ + $HostgroupsTable = TableRegistry::getTableLocator()->get('Hostgroups'); + + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + + if ($this->request->is('get')) { + $hostgroups = $HostgroupsTable->getHostgroupsForCopy(func_get_args(), $MY_RIGHTS); + $this->set('hostgroups', $hostgroups); + $this->viewBuilder()->setOption('serialize', ['hostgroups']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + /** @var ContainersTable $ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + + $ContainersTable->acquireLock(); + + + $postData = $this->request->getData('data'); + $User = new User($this->getUser()); + $userId = $User->getId(); + + foreach ($postData as $index => $hostgroupData) { + if (!isset($hostgroupData['Hostgroup']['id'])) { + //Create/clone hostgroup + $sourceHostgroupId = $hostgroupData['Source']['id']; + $sourceHostgroup = $HostgroupsTable->getSourceHostgroupForCopy($sourceHostgroupId, $MY_RIGHTS); + + $newHostgroupData = [ + 'description' => $hostgroupData['Hostgroup']['description'], + 'hostgroup_url' => $sourceHostgroup['hostgroup_url'], + 'uuid' => UUID::v4(), + 'container' => [ + 'name' => $hostgroupData['Hostgroup']['container']['name'], + 'containertype_id' => CT_HOSTGROUP, + 'parent_id' => $sourceHostgroup['container']['parent_id'] + ], + 'hosts' => [ + '_ids' => $sourceHostgroup['hosts']['_ids'] + ], + 'hosttemplates' => [ + '_ids' => $sourceHostgroup['hosttemplates']['_ids'] + ], + ]; + + $newHostgroupEntity = $HostgroupsTable->newEntity($newHostgroupData); + + } + + $action = 'copy'; + if (isset($hostgroupData['Hostgroup']['id'])) { + //Update existing hostgroup + //This happens, if a user copy multiple hostgroups, and one run into an validation error + //All hostgroups without validation errors got already saved to the database + $newHostgroupEntity = $HostgroupsTable->get($hostgroupData['Hostgroup']['id'], [ + 'contain' => [ + 'Containers' + ] + ]); + $newHostgroupEntity->setAccess('*', false); + $newHostgroupEntity->container->setAccess('*', false); + $newHostgroupEntity->container->setAccess('name', true); + $newHostgroupEntity = $HostgroupsTable->patchEntity($newHostgroupEntity, $hostgroupData['Hostgroup']); + $newHostgroupData = $newHostgroupEntity->toArray(); + $action = 'edit'; + } + $HostgroupsTable->save($newHostgroupEntity); + + $postData[$index]['Error'] = []; + if ($newHostgroupEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newHostgroupEntity->getErrors(); + } else { + //No errors + $postData[$index]['Hostgroup']['id'] = $newHostgroupEntity->get('id'); + + /** @var ChangelogsTable $ChangelogsTable */ + $ChangelogsTable = TableRegistry::getTableLocator()->get('Changelogs'); + + $changelog_data = $ChangelogsTable->parseDataForChangelog( + $action, + 'hostgroups', + $postData[$index]['Hostgroup']['id'], + OBJECT_HOSTGROUP, + $newHostgroupEntity->get('container')->get('parent_id'), + $userId, + $newHostgroupEntity->get('container')->get('name'), + ['Hostgroup' => $newHostgroupData] + ); + if ($changelog_data) { + /** @var Changelog $changelogEntry */ + $changelogEntry = $ChangelogsTable->newEntity($changelog_data); + $ChangelogsTable->save($changelogEntry); + } + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + Cache::clear('permissions'); + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } + /**************************** * AJAX METHODS * ****************************/ diff --git a/src/Controller/HostsController.php b/src/Controller/HostsController.php index 6e0648b36f..ac1bdf277c 100644 --- a/src/Controller/HostsController.php +++ b/src/Controller/HostsController.php @@ -1658,8 +1658,13 @@ public function copy($id = null) { /** @var HosttemplatesTable $HosttemplatesTable */ $HosttemplatesTable = TableRegistry::getTableLocator()->get('Hosttemplates'); + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + if ($this->request->is('get')) { - $hosts = $HostsTable->getHostsForCopy(func_get_args()); + $hosts = $HostsTable->getHostsForCopy(func_get_args(), $MY_RIGHTS); $this->set('hosts', $hosts); $this->viewBuilder()->setOption('serialize', ['hosts']); return; @@ -1722,7 +1727,7 @@ public function copy($id = null) { 'sla_id' ] ); - /** @var \App\Model\Entity\Hosttemplate $hosttemplate */ + $hosttemplate = $HosttemplatesTable->getHosttemplateForDiff($sourceHost->get('hosttemplate_id')); $tmpHost = $HostsTable->newEmptyEntity(); @@ -1820,6 +1825,8 @@ public function copy($id = null) { $newHost->set('hosttemplate_flap_detection_on_up', $newHost->get('flap_detection_on_up')); $newHost->set('hosttemplate_flap_detection_on_down', $newHost->get('flap_detection_on_down')); $newHost->set('hosttemplate_flap_detection_on_unreachable', $newHost->get('flap_detection_on_unreachable')); + $newHost->setAccess('*', false); + $newHost->setAccess(['name', 'description', 'address', 'host_url'], true); $newHost = $HostsTable->patchEntity($newHost, $host2copyData['Host']); $extDataForChangelog = $newHost->toArray(); } diff --git a/src/Controller/HosttemplatesController.php b/src/Controller/HosttemplatesController.php index 6261545622..f21b115cf8 100644 --- a/src/Controller/HosttemplatesController.php +++ b/src/Controller/HosttemplatesController.php @@ -373,8 +373,13 @@ public function copy($id = null) { /** @var $HosttemplatesTable HosttemplatesTable */ $HosttemplatesTable = TableRegistry::getTableLocator()->get('Hosttemplates'); + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + if ($this->request->is('get')) { - $hosttemplates = $HosttemplatesTable->getHosttemplatesForCopy(func_get_args()); + $hosttemplates = $HosttemplatesTable->getHosttemplatesForCopy(func_get_args(), $MY_RIGHTS); /** @var $CommandsTable CommandsTable */ $CommandsTable = TableRegistry::getTableLocator()->get('Commands'); $commands = $CommandsTable->getCommandByTypeAsList(HOSTCHECK_COMMAND); @@ -434,6 +439,8 @@ public function copy($id = null) { //This happens, if a user copy multiple hosttemplates, and one run into an validation error //All hosttemplates without validation errors got already saved to the database $newHosttemplateEntity = $HosttemplatesTable->get($hosttemplateData['Hosttemplate']['id']); + $newHosttemplateEntity->setAccess('*', false); + $newHosttemplateEntity->setAccess(['name', 'description', 'command_id', 'hosttemplatecommandargumentvalues'], true); $newHosttemplateEntity = $HosttemplatesTable->patchEntity($newHosttemplateEntity, $hosttemplateData['Hosttemplate']); $newHosttemplateData = $newHosttemplateEntity->toArray(); $action = 'edit'; diff --git a/src/Controller/LocationsController.php b/src/Controller/LocationsController.php index 5aaf7276f9..dc200a98ae 100644 --- a/src/Controller/LocationsController.php +++ b/src/Controller/LocationsController.php @@ -295,7 +295,7 @@ public function delete($containerId = null) { return; } - if ($ContainersTable->allowDelete($container->get('id'))) { + if ($ContainersTable->allowDelete($container->get('id'), CT_LOCATION)) { if ($ContainersTable->delete($container)) { $User = new User($this->getUser()); /** @var ChangelogsTable $ChangelogsTable */ diff --git a/src/Controller/ServicegroupsController.php b/src/Controller/ServicegroupsController.php index e901879850..720d38208f 100644 --- a/src/Controller/ServicegroupsController.php +++ b/src/Controller/ServicegroupsController.php @@ -326,7 +326,7 @@ public function delete($id = null) { return; } - if ($ContainersTable->allowDelete($container->id, $this->MY_RIGHTS)) { + if ($ContainersTable->allowDelete($container->id, CT_SERVICEGROUP)) { if ($ContainersTable->delete($container)) { $User = new User($this->getUser()); /** @var ChangelogsTable $ChangelogsTable */ @@ -738,6 +738,125 @@ public function extended() { $this->viewBuilder()->setOption('serialize', ['username']); } + /** + * @param int|null $id + */ + public function copy($id = null) { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var ServicegroupsTable $ServicegroupsTable */ + $ServicegroupsTable = TableRegistry::getTableLocator()->get('Servicegroups'); + + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + + if ($this->request->is('get')) { + $servicegroups = $ServicegroupsTable->getServicegroupsForCopy(func_get_args(), $MY_RIGHTS); + $this->set('servicegroups', $servicegroups); + $this->viewBuilder()->setOption('serialize', ['servicegroups']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + /** @var ContainersTable $ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + + $ContainersTable->acquireLock(); + + $postData = $this->request->getData('data'); + $User = new User($this->getUser()); + $userId = $User->getId(); + + foreach ($postData as $index => $servicegroupData) { + if (!isset($servicegroupData['Servicegroup']['id'])) { + //Create/clone servicegroup + $sourceServicegroupId = $servicegroupData['Source']['id']; + $sourceServicegroup = $ServicegroupsTable->getSourceServicegroupForCopy($sourceServicegroupId, $MY_RIGHTS); + + $newServicegroupData = [ + 'description' => $servicegroupData['Servicegroup']['description'], + 'servicegroup_url' => $sourceServicegroup['servicegroup_url'], + 'uuid' => UUID::v4(), + 'container' => [ + 'name' => $servicegroupData['Servicegroup']['container']['name'], + 'containertype_id' => CT_SERVICEGROUP, + 'parent_id' => $sourceServicegroup['container']['parent_id'] + ], + 'services' => [ + '_ids' => $sourceServicegroup['services']['_ids'] + ], + 'servicetemplates' => [ + '_ids' => $sourceServicegroup['servicetemplates']['_ids'] + ], + ]; + + $newServicegroupEntity = $ServicegroupsTable->newEntity($newServicegroupData); + + } + + $action = 'copy'; + if (isset($servicegroupData['Servicegroup']['id'])) { + //Update existing servicegroup + //This happens, if a user copy multiple servicegroups, and one run into an validation error + //All servicegroups without validation errors got already saved to the database + $newServicegroupEntity = $ServicegroupsTable->get($servicegroupData['Servicegroup']['id'], [ + 'contain' => [ + 'Containers' + ] + ]); + $newServicegroupEntity->setAccess('*', false); + $newServicegroupEntity->container->setAccess('*', false); + $newServicegroupEntity->container->setAccess('name', true); + $newServicegroupEntity = $ServicegroupsTable->patchEntity($newServicegroupEntity, $servicegroupData['Servicegroup']); + $newServicegroupData = $newServicegroupEntity->toArray(); + $action = 'edit'; + } + $ServicegroupsTable->save($newServicegroupEntity); + + $postData[$index]['Error'] = []; + if ($newServicegroupEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newServicegroupEntity->getErrors(); + } else { + //No errors + $postData[$index]['Servicegroup']['id'] = $newServicegroupEntity->get('id'); + + /** @var ChangelogsTable $ChangelogsTable */ + $ChangelogsTable = TableRegistry::getTableLocator()->get('Changelogs'); + + $changelog_data = $ChangelogsTable->parseDataForChangelog( + $action, + 'servicegroups', + $postData[$index]['Servicegroup']['id'], + OBJECT_SERVICEGROUP, + $newServicegroupEntity->get('container')->get('parent_id'), + $userId, + $newServicegroupEntity->get('container')->get('name'), + ['Servicegroup' => $newServicegroupData] + ); + if ($changelog_data) { + /** @var Changelog $changelogEntry */ + $changelogEntry = $ChangelogsTable->newEntity($changelog_data); + $ChangelogsTable->save($changelogEntry); + } + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + Cache::clear('permissions'); + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } /**************************** * AJAX METHODS * diff --git a/src/Controller/ServicesController.php b/src/Controller/ServicesController.php index dc1cc3c227..f0f9743959 100644 --- a/src/Controller/ServicesController.php +++ b/src/Controller/ServicesController.php @@ -993,6 +993,12 @@ public function copy() { } $host = $HostsTable->getHostForServiceEdit($hostId); + + if (!$this->allowedByContainerId($host['Host']['hosts_to_containers_sharing']['_ids'])) { + $this->render403(); + return; + } + $hostContactsAndContactgroups = $HostsTable->getContactsAndContactgroupsById($host['Host']['id']); $hosttemplateContactsAndContactgroups = $HosttemplatesTable->getContactsAndContactgroupsById($host['Host']['hosttemplate_id']); diff --git a/src/Controller/ServicetemplategroupsController.php b/src/Controller/ServicetemplategroupsController.php index ac8ec707d3..a10d3d15b5 100644 --- a/src/Controller/ServicetemplategroupsController.php +++ b/src/Controller/ServicetemplategroupsController.php @@ -44,7 +44,6 @@ use itnovum\openITCOCKPIT\Core\AngularJS\Api; use itnovum\openITCOCKPIT\Core\Comparison\ServiceComparisonForSave; use itnovum\openITCOCKPIT\Core\HostgroupConditions; -use itnovum\openITCOCKPIT\Core\KeyValueStore; use itnovum\openITCOCKPIT\Core\ServicetemplategroupsConditions; use itnovum\openITCOCKPIT\Core\UUID; use itnovum\openITCOCKPIT\Core\ValueObjects\User; @@ -79,7 +78,6 @@ public function index() { $all_servicetemplategroups = []; foreach ($servicetemplategroups as $servicetemplategroup) { - // debug($servicetemplategroup); $servicetemplategroup['allow_edit'] = $this->hasPermission('edit', 'servicetemplategroups'); if ($this->hasRootPrivileges === false) { $servicetemplategroup['allow_edit'] = $this->isWritableContainer($servicetemplategroup['Servicetemplategroup']['container_id']); @@ -87,17 +85,6 @@ public function index() { $all_servicetemplategroups[] = $servicetemplategroup; } - // debug($all_servicetemplategroups); - - /* foreach ($hostgroups as $hostgroup) { - $hostgroup['allowEdit'] = $this->hasPermission('edit', 'hostgroups'); - if ($this->hasRootPrivileges === false && $hostgroup['allowEdit'] === true) { - $hostgroup['allowEdit'] = $this->allowedByContainerId($hostgroup->get('container')->get('parent_id')); - } - - $all_hostgroups[] = $hostgroup; - } - */ $this->set('all_servicetemplategroups', $all_servicetemplategroups); $this->viewBuilder()->setOption('serialize', ['all_servicetemplategroups']); } @@ -458,7 +445,7 @@ public function delete($id = null) { 'Servicetemplategroups' ] ]); - if ($ContainersTable->allowDelete($container->id, $this->MY_RIGHTS)) { + if ($ContainersTable->allowDelete($container->id, CT_SERVICETEMPLATEGROUP)) { if ($ContainersTable->delete($container)) { $User = new User($this->getUser()); Cache::clear('permissions'); @@ -499,6 +486,119 @@ public function delete($id = null) { } + public function copy() { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var ServicetemplategroupsTable $ServicetemplategroupsTable */ + $ServicetemplategroupsTable = TableRegistry::getTableLocator()->get('Servicetemplategroups'); + + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + + if ($this->request->is('get')) { + $servicetemplategroups = $ServicetemplategroupsTable->getServicetemplategroupsForCopy(func_get_args(), $MY_RIGHTS); + $this->set('servicetemplategroups', $servicetemplategroups); + $this->viewBuilder()->setOption('serialize', ['servicetemplategroups']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + $postData = $this->request->getData('data'); + $User = new User($this->getUser()); + $userId = $User->getId(); + + /** @var $ContainersTable ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + + $ContainersTable->acquireLock(); + + foreach ($postData as $index => $servicetemplategroupData) { + if (!isset($servicetemplategroupData['Servicetemplategroup']['id'])) { + //Create/clone service template group + $sourceServicetemplategroupId = $servicetemplategroupData['Source']['id']; + $sourceServicetemplategroup = $ServicetemplategroupsTable->getSourceServicetemplategroupForCopy($sourceServicetemplategroupId, $MY_RIGHTS); + + $newServicetemplategroupData = [ + 'description' => $servicetemplategroupData['Servicetemplategroup']['description'], + 'uuid' => UUID::v4(), + 'container' => [ + 'name' => $servicetemplategroupData['Servicetemplategroup']['container']['name'], + 'containertype_id' => CT_SERVICETEMPLATEGROUP, + 'parent_id' => $sourceServicetemplategroup['container']['parent_id'] + ], + 'servicetemplates' => [ + '_ids' => $sourceServicetemplategroup['servicetemplates']['_ids'] + ] + ]; + + $newServicetemplategroupEntity = $ServicetemplategroupsTable->newEntity($newServicetemplategroupData); + + } + + $action = 'copy'; + if (isset($servicetemplategroupData['Servicetemplategroup']['id'])) { + //Update existing servicetemplategroup + //This happens, if a user copy multiple servicetemplategroup, and one run into an validation error + //All servicetemplategroup without validation errors got already saved to the database + $newServicetemplategroupEntity = $ServicetemplategroupsTable->get($servicetemplategroupData['Servicetemplategroup']['id'], [ + 'contain' => [ + 'Containers' + ] + ]); + $newServicetemplategroupEntity->setAccess('*', false); + $newServicetemplategroupEntity->setAccess('description', true); + $newServicetemplategroupEntity->container->setAccess('*', false); + $newServicetemplategroupEntity->container->setAccess('name', true); + $newServicetemplategroupEntity = $ServicetemplategroupsTable->patchEntity($newServicetemplategroupEntity, $servicetemplategroupData['Servicetemplategroup']); + $newServicetemplategroupData = $newServicetemplategroupEntity->toArray(); + $action = 'edit'; + } + $ServicetemplategroupsTable->save($newServicetemplategroupEntity); + + $postData[$index]['Error'] = []; + if ($newServicetemplategroupEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newServicetemplategroupEntity->getErrors(); + } else { + //No errors + $postData[$index]['Servicetemplategroup']['id'] = $newServicetemplategroupEntity->get('id'); + + /** @var ChangelogsTable $ChangelogsTable */ + $ChangelogsTable = TableRegistry::getTableLocator()->get('Changelogs'); + + $changelog_data = $ChangelogsTable->parseDataForChangelog( + $action, + 'servicetemplategroups', + $postData[$index]['Servicetemplategroup']['id'], + OBJECT_SERVICETEMPLATEGROUP, + $newServicetemplategroupEntity->get('container')->get('parent_id'), + $userId, + $newServicetemplategroupEntity->get('container')->get('name'), + ['Servicetemplategroup' => $newServicetemplategroupData] + ); + if ($changelog_data) { + /** @var Changelog $changelogEntry */ + $changelogEntry = $ChangelogsTable->newEntity($changelog_data); + $ChangelogsTable->save($changelogEntry); + } + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + Cache::clear('permissions'); + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } /******************************** * ALLOCATION METHODS * diff --git a/src/Controller/ServicetemplatesController.php b/src/Controller/ServicetemplatesController.php index ac186f0662..d4b4b86c25 100644 --- a/src/Controller/ServicetemplatesController.php +++ b/src/Controller/ServicetemplatesController.php @@ -390,8 +390,13 @@ public function copy($id = null) { /** @var $ServicetemplatesTable ServicetemplatesTable */ $ServicetemplatesTable = TableRegistry::getTableLocator()->get('Servicetemplates'); + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + if ($this->request->is('get')) { - $servicetemplates = $ServicetemplatesTable->getServicetemplatesForCopy(func_get_args()); + $servicetemplates = $ServicetemplatesTable->getServicetemplatesForCopy(func_get_args(), $MY_RIGHTS); /** @var $CommandsTable CommandsTable */ $CommandsTable = TableRegistry::getTableLocator()->get('Commands'); $commands = $CommandsTable->getCommandByTypeAsList(CHECK_COMMAND); @@ -459,6 +464,8 @@ public function copy($id = null) { //This happens, if a user copy multiple servicetemplates, and one run into an validation error //All servicetemplates without validation errors got already saved to the database $newServicetemplateEntity = $ServicetemplatesTable->get($servicetemplateData['Servicetemplate']['id']); + $newServicetemplateEntity->setAccess('*', false); + $newServicetemplateEntity->setAccess(['template_name', 'name', 'description', 'command_id', 'servicetemplatecommandargumentvalues'], true); $newServicetemplateEntity = $ServicetemplatesTable->patchEntity($newServicetemplateEntity, $servicetemplateData['Servicetemplate']); $newServicetemplateData = $newServicetemplateEntity->toArray(); $action = 'edit'; diff --git a/src/Controller/TenantsController.php b/src/Controller/TenantsController.php index 0d07a717c4..2e0bf55686 100644 --- a/src/Controller/TenantsController.php +++ b/src/Controller/TenantsController.php @@ -296,7 +296,7 @@ public function delete($containerId = null) { } - if ($ContainersTable->allowDelete($tenant['container']['id'])) { + if ($ContainersTable->allowDelete($tenant['container']['id'], CT_TENANT)) { if ($ContainersTable->delete($ContainersTable->get($tenant['container']['id']))) { Cache::clear('permissions'); diff --git a/src/Controller/TimeperiodsController.php b/src/Controller/TimeperiodsController.php index 82b6716587..5fb58e1d16 100644 --- a/src/Controller/TimeperiodsController.php +++ b/src/Controller/TimeperiodsController.php @@ -153,7 +153,7 @@ public function viewDetails($id = null) { return; } $timeperiod['events'] = $TimeperiodsTable->parseTimerangesForCalendar($timeperiod['timeperiod_timeranges']); - + $this->set('timeperiod', $timeperiod); $this->viewBuilder()->setOption('serialize', ['timeperiod']); } @@ -363,11 +363,16 @@ public function copy($id = null) { return; } + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + /** @var TimeperiodsTable $TimeperiodsTable */ $TimeperiodsTable = TableRegistry::getTableLocator()->get('Timeperiods'); if ($this->request->is('get')) { - $timeperiods = $TimeperiodsTable->getTimeperiodsForCopy(func_get_args()); + $timeperiods = $TimeperiodsTable->getTimeperiodsForCopy(func_get_args(), $MY_RIGHTS); $this->set('timeperiods', $timeperiods); $this->viewBuilder()->setOption('serialize', ['timeperiods']); return; @@ -419,6 +424,9 @@ public function copy($id = null) { //This happens, if a user copy multiple timeperiods, and one run into an validation error //All timeperiods without validation errors got already saved to the database $newTimeperiodEntity = $TimeperiodsTable->get($timeperiodData['Timeperiod']['id']); + $newTimeperiodEntity->setAccess('*', false); + $newTimeperiodEntity->setAccess('name', true); + $newTimeperiodEntity->setAccess('description', true); $newTimeperiodEntity = $TimeperiodsTable->patchEntity($newTimeperiodEntity, $timeperiodData['Timeperiod']); $newTimeperiodData = $newTimeperiodEntity->toArray(); $action = 'edit'; diff --git a/src/Controller/UsercontainerrolesController.php b/src/Controller/UsercontainerrolesController.php index bd3f9b4965..e06f6580e2 100644 --- a/src/Controller/UsercontainerrolesController.php +++ b/src/Controller/UsercontainerrolesController.php @@ -62,11 +62,11 @@ public function index() { $this->MY_RIGHTS ); $containerWithWritePermissions = array_filter($this->MY_RIGHTS_LEVEL, function ($v) { - return $v == 2; + return $v == WRITE_RIGHT; }, ARRAY_FILTER_USE_BOTH); foreach ($all_usercontainerroles as $index => $usercontainerrole) { $userRoleContainerIds = Hash::extract($usercontainerrole['containers'], '{n}._joinData[permission_level=2].container_id'); - if(!$this->hasRootPrivileges && !empty(array_diff($userRoleContainerIds, $containerWithWritePermissions))){ + if (!$this->hasRootPrivileges && !empty(array_diff($userRoleContainerIds, $containerWithWritePermissions))) { unset($all_usercontainerroles[$index]); continue; //insufficient user (container) rights } @@ -81,7 +81,7 @@ public function index() { } } - foreach ($usercontainerrole['users'] as $userIndex => $user){ + foreach ($usercontainerrole['users'] as $userIndex => $user) { $usercontainerrole['users'][$userIndex]['allow_edit'] = $this->hasRootPrivileges; if ($this->hasRootPrivileges === false) { @@ -117,7 +117,7 @@ public function index() { } } - $all_usercontainerroles[$index]['users'] = $usercontainerrole['users']; + $all_usercontainerroles[$index]['users'] = $usercontainerrole['users']; } $this->set('all_usercontainerroles', $all_usercontainerroles); @@ -252,6 +252,86 @@ public function delete($id = null) { return; } + /** + * @param int|null $id + */ + public function copy($id = null) { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var UsercontainerrolesTable $UsercontainerrolesTable */ + $UsercontainerrolesTable = TableRegistry::getTableLocator()->get('Usercontainerroles'); + + $MY_RIGHTS = $this->MY_RIGHTS; + if ($this->hasRootPrivileges) { + $MY_RIGHTS = []; + } + + if ($this->request->is('get')) { + $usercontainerroles = $UsercontainerrolesTable->getUserContainerRolesForCopy(func_get_args(), $MY_RIGHTS); + $this->set('usercontainerroles', $usercontainerroles); + $this->viewBuilder()->setOption('serialize', ['usercontainerroles']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + $postData = $this->request->getData('data'); + + foreach ($postData as $index => $usercontainerroleData) { + if (!isset($usercontainerroleData['Usercontainerrole']['id'])) { + //Create/clone Usercontainerrole + $sourceUsercontainerroleId = $usercontainerroleData['Source']['id']; + $sourceUsercontainerrole = $UsercontainerrolesTable->getSourceUserContainerRoleForCopy($sourceUsercontainerroleId, $MY_RIGHTS); + + + $newUsercontainerroleData = [ + 'name' => $usercontainerroleData['Usercontainerrole']['name'], + 'containers' => $UsercontainerrolesTable->containerPermissionsForSave($sourceUsercontainerrole['ContainersUsercontainerrolesMemberships']), + 'ldapgroups' => [ + '_ids' => $sourceUsercontainerrole['ldapgroups']['_ids'] + ] + ]; + + $newUsercontainerroleEntity = $UsercontainerrolesTable->newEntity($newUsercontainerroleData); + } + + $action = 'copy'; + if (isset($usercontainerroleData['Usercontainerrole']['id'])) { + //Update existing Usercontainerrole + //This happens, if a user copy multiple Usercontainerroles, and one run into an validation error + //All Usercontainerroles without validation errors got already saved to the database + $newUsercontainerroleEntity = $UsercontainerrolesTable->get($usercontainerroleData['Usercontainerrole']['id']); + $newUsercontainerroleEntity->setAccess('*', false); + $newUsercontainerroleEntity->setAccess(['name'], true); + + $newUsercontainerroleEntity = $UsercontainerrolesTable->patchEntity($newUsercontainerroleEntity, $usercontainerroleData['Usercontainerrole']); + $action = 'edit'; + } + $UsercontainerrolesTable->save($newUsercontainerroleEntity); + + $postData[$index]['Error'] = []; + if ($newUsercontainerroleEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newUsercontainerroleEntity->getErrors(); + } else { + //No errors + $postData[$index]['Usercontainerrole']['id'] = $newUsercontainerroleEntity->get('id'); + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + Cache::clear('permissions'); + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } + /**************************** * AJAX METHODS * ****************************/ diff --git a/src/Controller/UsergroupsController.php b/src/Controller/UsergroupsController.php index 10f70e8c84..712d0c8e74 100644 --- a/src/Controller/UsergroupsController.php +++ b/src/Controller/UsergroupsController.php @@ -31,6 +31,7 @@ use Acl\Model\Table\ArosTable; use App\Lib\AclDependencies; use App\Model\Table\ArosAcosTable; +use App\Model\Table\ContainersTable; use App\Model\Table\LdapgroupsTable; use App\Model\Table\SystemsettingsTable; use App\Model\Table\UsergroupsTable; @@ -42,7 +43,6 @@ use Cake\Utility\Hash; use itnovum\openITCOCKPIT\Core\AngularJS\Api; use itnovum\openITCOCKPIT\Database\PaginateOMat; -use itnovum\openITCOCKPIT\Filter\Filter; use itnovum\openITCOCKPIT\Filter\GenericFilter; use itnovum\openITCOCKPIT\Filter\LdapgroupFilter; @@ -118,6 +118,12 @@ public function add() { return; } + /** @var ContainersTable $ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + // Usergroups has nothing to do with containers, but are also using the CakePHP TreeBehavior + // For this reason we use the same lock to avoid broken nested set. + $ContainersTable->acquireLock(); + /** @var UsergroupsTable $UsergroupsTable */ $UsergroupsTable = TableRegistry::getTableLocator()->get('Usergroups'); $usergroup = $UsergroupsTable->newEmptyEntity(); @@ -132,6 +138,8 @@ public function add() { return; } + $ContainersTable->releaseLock(); + //Save Acos /** @var ArosTable $ArosTable */ $ArosTable = TableRegistry::getTableLocator()->get('Acl.Aros'); @@ -237,6 +245,12 @@ public function edit($id = null) { } if ($this->request->is('post')) { + /** @var ContainersTable $ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + // Usergroups has nothing to do with containers, but are also using the CakePHP TreeBehavior + // For this reason we use the same lock to avoid broken nested set. + $ContainersTable->acquireLock(); + $usergroup = $UsergroupsTable->get($id); $usergroup->setAccess('id', false); if ($usergroup->get('name') === 'Administrator') { @@ -254,6 +268,8 @@ public function edit($id = null) { return; } + $ContainersTable->releaseLock(); + //Save Acos $AclDependencies = new AclDependencies(); $selectedAcos = $this->request->getData('Acos'); @@ -261,7 +277,7 @@ public function edit($id = null) { /** @var ArosTable $ArosTable */ $ArosTable = TableRegistry::getTableLocator()->get('Acl.Aros'); - /** @var ArosAcosTable c */ + /** @var ArosAcosTable $ArosAcosTable */ $ArosAcosTable = TableRegistry::getTableLocator()->get('ArosAcos'); $aro = $ArosTable->find() ->where([ @@ -313,6 +329,12 @@ public function delete($id = null) { throw new \RuntimeException('You cannot delete your own user group!'); } + /** @var ContainersTable $ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + // Usergroups has nothing to do with containers, but are also using the CakePHP TreeBehavior + // For this reason we use the same lock to avoid broken nested set. + $ContainersTable->acquireLock(); + $usergroup = $UsergroupsTable->get($id); if ($usergroup->get('name') === 'Administrator') { @@ -330,6 +352,117 @@ public function delete($id = null) { $this->viewBuilder()->setOption('serialize', ['success']); } + /** + * @param int|null $id + */ + public function copy($id = null) { + if (!$this->isAngularJsRequest()) { + //Only ship HTML Template + return; + } + + /** @var UsergroupsTable $UsergroupsTable */ + $UsergroupsTable = TableRegistry::getTableLocator()->get('Usergroups'); + + if ($this->request->is('get')) { + $usergroups = $UsergroupsTable->getUsergroupsForCopy(func_get_args()); + $this->set('usergroups', $usergroups); + $this->viewBuilder()->setOption('serialize', ['usergroups']); + return; + } + + $hasErrors = false; + + if ($this->request->is('post')) { + + /** @var ContainersTable $ContainersTable */ + $ContainersTable = TableRegistry::getTableLocator()->get('Containers'); + // Usergroups has nothing to do with containers, but are also using the CakePHP TreeBehavior + // For this reason we use the same lock to avoid broken nested set. + $ContainersTable->acquireLock(); + + $postData = $this->request->getData('data'); + + foreach ($postData as $index => $usergroupData) { + if (!isset($usergroupData['Usergroup']['id'])) { + //Create/clone usergroup + $sourceUsergroupId = $usergroupData['Source']['id']; + $sourceUsergroup = $UsergroupsTable->getSourceUsergroupForCopy($sourceUsergroupId); + + $newUsergroupData = [ + 'name' => $usergroupData['Usergroup']['name'], + 'description' => $usergroupData['Usergroup']['description'], + 'ldapgroups' => [ + '_ids' => $sourceUsergroup['ldapgroups']['_ids'] + ] + ]; + + $newUsergroupEntity = $UsergroupsTable->newEntity($newUsergroupData); + + } + + $action = 'copy'; + if (isset($usergroupData['Usergroup']['id'])) { + //Update existing usergroup + //This happens, if a user copy multiple usergroups, and one run into a validation error + //All usergroups without validation errors got already saved to the database + $newUsergroupEntity = $UsergroupsTable->get($usergroupData['Usergroup']['id']); + $newUsergroupEntity->setAccess('*', false); + $newUsergroupEntity->setAccess('name', true); + $newUsergroupEntity->setAccess('description', true); + $newUsergroupEntity = $UsergroupsTable->patchEntity($newUsergroupEntity, $usergroupData['Usergroup']); + $action = 'edit'; + } + $UsergroupsTable->save($newUsergroupEntity); + + $postData[$index]['Error'] = []; + if ($newUsergroupEntity->hasErrors()) { + $hasErrors = true; + $postData[$index]['Error'] = $newUsergroupEntity->getErrors(); + } else { + //No errors + $postData[$index]['Usergroup']['id'] = $newUsergroupEntity->get('id'); + if ($action === 'copy') { + /** @var ArosTable $ArosTable */ + $ArosTable = TableRegistry::getTableLocator()->get('Acl.Aros'); + $ArosAcosTable = TableRegistry::getTableLocator()->get('ArosAcos'); + $aro = $ArosTable->find() + ->where([ + 'Aros.foreign_key' => $newUsergroupEntity->get('id') + ]) + ->firstOrFail(); + /** @var ArosAcosTable $ArosAcosTable */ + $ArosAcosTable = TableRegistry::getTableLocator()->get('ArosAcos'); + + $arosAcos = $ArosAcosTable->find() + ->where([ + 'ArosAcos.aro_id' => $sourceUsergroup['aro']['id'] + ]) + ->all(); + foreach ($arosAcos as $aroAco) { + $arosToAcos[] = $ArosAcosTable->newEntity([ + 'aro_id' => $aro->get('id'), + 'aco_id' => (int)$aroAco['aco_id'], + '_create' => (int)$aroAco['_create'], + '_read' => (int)$aroAco['_read'], + '_update' => (int)$aroAco['_update'], + '_delete' => (int)$aroAco['_delete'], + ]); + } + $ArosAcosTable->saveMany($arosToAcos); + } + } + } + } + + if ($hasErrors) { + $this->response = $this->response->withStatus(400); + } + Cache::clear('permissions'); + $this->set('result', $postData); + $this->viewBuilder()->setOption('serialize', ['result']); + } + /**************************** * AJAX METHODS * ****************************/ diff --git a/src/Model/Table/AutomapsTable.php b/src/Model/Table/AutomapsTable.php index 030d1de6c1..1ed970d102 100644 --- a/src/Model/Table/AutomapsTable.php +++ b/src/Model/Table/AutomapsTable.php @@ -91,7 +91,7 @@ public function validationDefault(Validator $validator): Validator { $validator ->boolean('show_ok') - ->requirePresence('show_ok', true, __('You have to choose at least one option.')) + ->requirePresence('show_ok', 'create', __('You have to choose at least one option.')) ->notEmptyString('show_ok') ->add('show_ok', 'custom', [ 'rule' => [$this, 'checkStatusOptions'], @@ -279,4 +279,44 @@ public function getAutomapsForAngular($selected, AutomapsFilter $AutomapsFilter, asort($automaps, SORT_FLAG_CASE | SORT_NATURAL); return $automaps; } + + /** + * @param array $ids + * @param array $MY_RIGHTS + * @return array + */ + public function getAutomapsForCopy($ids = [], array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['Automaps.id IN' => $ids]) + ->order(['Automaps.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Automaps.container_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + /** + * @param $sourceAutomapId + * @param array $MY_RIGHTS + * @return array + */ + public function getSourceAutomapForCopy($sourceAutomapId, array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['Automaps.id' => $sourceAutomapId]); + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Automaps.container_id IN' => $MY_RIGHTS + ]); + } + + $result = $query->firstOrFail(); + return $this->emptyArrayIfNull($result->toArray()); + } } diff --git a/src/Model/Table/ContactgroupsTable.php b/src/Model/Table/ContactgroupsTable.php index 4b8c6b87cd..708c22b49c 100644 --- a/src/Model/Table/ContactgroupsTable.php +++ b/src/Model/Table/ContactgroupsTable.php @@ -405,9 +405,10 @@ public function getContactgroupsByContainerIdsForContainerDelete($containerIds) /** * @param array $ids + * @param array $MY_RIGHTS * @return array */ - public function getContactgroupsForCopy($ids = []) { + public function getContactgroupsForCopy($ids = [], array $MY_RIGHTS = []) { if (!is_array($ids)) { $ids = [$ids]; } @@ -418,11 +419,23 @@ public function getContactgroupsForCopy($ids = []) { 'Containers.name', 'Contactgroups.id', 'Contactgroups.description', + 'Contactgroups.container_id', ]) ->contain(['Containers']) ->where([ 'Contactgroups.id IN' => $ids, - ]) + ]); + + if(!empty($MY_RIGHTS)) { + $query->innerJoinWith('Containers', function (Query $q) use ($MY_RIGHTS) { + if (!empty($MY_RIGHTS)) { + return $q->where(['Containers.parent_id IN' => $MY_RIGHTS]); + } + return $q; + }); + } + + $query ->disableHydration() ->all(); diff --git a/src/Model/Table/ContactsTable.php b/src/Model/Table/ContactsTable.php index 522d9655b6..10ff37b7e1 100644 --- a/src/Model/Table/ContactsTable.php +++ b/src/Model/Table/ContactsTable.php @@ -143,13 +143,13 @@ public function validationDefault(Validator $validator): Validator { $validator ->integer('host_timeperiod_id') ->allowEmptyString('host_timeperiod_id', null, false) - ->requirePresence('host_timeperiod_id') + ->requirePresence('host_timeperiod_id', 'create') ->greaterThan('host_timeperiod_id', 0); $validator ->integer('service_timeperiod_id') ->allowEmptyString('service_timeperiod_id', null, false) - ->requirePresence('service_timeperiod_id') + ->requirePresence('service_timeperiod_id', 'create') ->greaterThan('service_timeperiod_id', 0); $validator @@ -165,21 +165,21 @@ public function validationDefault(Validator $validator): Validator { ], __('You have to choose at least one command.')); $validator - ->requirePresence('notify_host_recovery', true, __('You have to choose at least one option.')) + ->requirePresence('notify_host_recovery', 'create', __('You have to choose at least one option.')) ->add('notify_host_recovery', 'custom', [ 'rule' => [$this, 'checkHostNotificationOptions'], 'message' => 'You have to choose at least one option.', ]); $validator - ->requirePresence('notify_service_recovery', true, __('You have to choose at least one option.')) + ->requirePresence('notify_service_recovery', 'create', __('You have to choose at least one option.')) ->add('notify_service_recovery', 'custom', [ 'rule' => [$this, 'checkHostNotificationOptions'], 'message' => 'You have to choose at least one option.', ]); $validator - ->requirePresence('containers', true, __('You have to choose at least one option.')) + ->requirePresence('containers', 'create', __('You have to choose at least one option.')) ->allowEmptyString('containers', null, false) ->multipleOptions('containers', [ 'min' => 1 @@ -375,9 +375,10 @@ public function getContactById($id, $contain = ['Containers']) { /** * @param array $ids + * @param array $MY_RIGHTS * @return array */ - public function getContactsForCopy($ids = []) { + public function getContactsForCopy($ids = [], array $MY_RIGHTS = []) { $query = $this->find() ->select([ 'Contacts.id', @@ -386,8 +387,21 @@ public function getContactsForCopy($ids = []) { 'Contacts.email', 'Contacts.phone' ]) + ->contain('Containers') ->where(['Contacts.id IN' => $ids]) - ->order(['Contacts.id' => 'asc']) + ->order(['Contacts.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->innerJoinWith('Containers', function (Query $q) use ($MY_RIGHTS) { + if (!empty($MY_RIGHTS)) { + return $q->where(['Containers.id IN' => $MY_RIGHTS]); + } + return $q; + }); + } + + $query + ->distinct('Contacts.id') ->disableHydration() ->all(); diff --git a/src/Model/Table/ContainersTable.php b/src/Model/Table/ContainersTable.php index 61188aecaa..d138226e6e 100644 --- a/src/Model/Table/ContainersTable.php +++ b/src/Model/Table/ContainersTable.php @@ -1106,14 +1106,25 @@ private function getNodeAndEdgesForChilds(int $containerId, array $childsArray) * checks if the given container contains subcontainers * return false if it has subcontainers - so it cant be deleted * return true if its empty and can be safely deleted - * @param int $id + * @param int $id Id of the container to check + * @param int $containertype_id Containertypeid of the container * @return bool */ - public function allowDelete($id): bool { + public function allowDelete($id, int $containertype_id): bool { if (!$this->existsById($id)) { throw new NotFoundException(__('Invalid container')); } + // This container types do not have any child containers! + // Therefore, they can be safely deleted. + switch ($containertype_id){ + case CT_CONTACTGROUP: + case CT_HOSTGROUP: + case CT_SERVICEGROUP: + case CT_SERVICETEMPLATEGROUP: + return true; + } + $subContainers = $this->getContainerWithAllChildren($id); // check content of subcontainers /* diff --git a/src/Model/Table/HostgroupsTable.php b/src/Model/Table/HostgroupsTable.php index 5f76032805..ad7f9fdbde 100644 --- a/src/Model/Table/HostgroupsTable.php +++ b/src/Model/Table/HostgroupsTable.php @@ -1296,11 +1296,62 @@ public function getHostgroupsByContainerIdAndHostIds($containerIds, $hostIds, $t } } + /** + * @param array $ids + * @param array $MY_RIGHTS + * @return array + */ + public function getHostgroupsForCopy($ids = [], array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['Hostgroups.id IN' => $ids]) + ->contain([ + 'Containers' + ]) + ->order(['Hostgroups.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Containers.parent_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + public function getSourceHostgroupForCopy($id, array $MY_RIGHTS) { + $query = $this->find() + ->where(['Hostgroups.id' => $id]) + ->contain([ + 'Hosts', + 'Hosttemplates', + 'Containers' + ]); + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Containers.parent_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration(); + $result = $query->firstOrFail(); + $hostgroup = $result; + $hostgroup['hosts'] = [ + '_ids' => Hash::extract($result, 'hosts.{n}.id') + ]; + $hostgroup['hosttemplates'] = [ + '_ids' => Hash::extract($result, 'hosttemplates.{n}.id') + ]; + return $hostgroup; + } + /** * @param int $containerId * @return array */ - public function getOrphanedHostgroupsByContainerId(int $containerId){ + public function getOrphanedHostgroupsByContainerId(int $containerId) { $query = $this->find() ->where(['container_id' => $containerId]); $result = $query->all(); diff --git a/src/Model/Table/HostsTable.php b/src/Model/Table/HostsTable.php index 375032ab73..73f0a0eec3 100644 --- a/src/Model/Table/HostsTable.php +++ b/src/Model/Table/HostsTable.php @@ -20,6 +20,7 @@ use Cake\ORM\TableRegistry; use Cake\Utility\Hash; use Cake\Validation\Validator; +use itnovum\openITCOCKPIT\Core\FileDebugger; use itnovum\openITCOCKPIT\Core\HostConditions; use itnovum\openITCOCKPIT\Core\ValueObjects\User; use itnovum\openITCOCKPIT\Database\PaginateOMat; @@ -3031,9 +3032,10 @@ public function isTimeperiodUsedByHost($timeperiodId) { /** * @param array $ids + * @param array $MY_RIGHTS * @return array */ - public function getHostsForCopy($ids = []) { + public function getHostsForCopy($ids = [], array $MY_RIGHTS = []) { $query = $this->find() ->select([ 'Hosts.id', @@ -3043,7 +3045,18 @@ public function getHostsForCopy($ids = []) { 'Hosts.host_url' ]) ->where(['Hosts.id IN' => $ids]) - ->order(['Hosts.id' => 'asc']) + ->order(['Hosts.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->innerJoin(['HostsToContainersSharing' => 'hosts_to_containers'], [ + 'HostsToContainersSharing.host_id = Hosts.id' + ]); + $query->where([ + 'HostsToContainersSharing.container_id IN' => $MY_RIGHTS + ]); + } + + $query ->disableHydration() ->all(); diff --git a/src/Model/Table/HosttemplatesTable.php b/src/Model/Table/HosttemplatesTable.php index 71b46e66f5..1188baa2f9 100644 --- a/src/Model/Table/HosttemplatesTable.php +++ b/src/Model/Table/HosttemplatesTable.php @@ -631,9 +631,10 @@ public function getContainerIdById($id) { /** * @param array $ids + * @param array $MY_RIGHTS * @return array */ - public function getHosttemplatesForCopy($ids = []) { + public function getHosttemplatesForCopy($ids = [], array $MY_RIGHTS = []) { $contain = [ 'Hosttemplatecommandargumentvalues' => [ 'Commandarguments' @@ -654,7 +655,13 @@ public function getHosttemplatesForCopy($ids = []) { ]) ->contain($contain) ->where(['Hosttemplates.id IN' => $ids]) - ->order(['Hosttemplates.id' => 'asc']) + ->order(['Hosttemplates.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere(['Hosttemplates.container_id IN' => $MY_RIGHTS]); + } + + $query ->disableHydration() ->all(); diff --git a/src/Model/Table/ServicegroupsTable.php b/src/Model/Table/ServicegroupsTable.php index ab873351f9..0011ba4b2f 100644 --- a/src/Model/Table/ServicegroupsTable.php +++ b/src/Model/Table/ServicegroupsTable.php @@ -1198,11 +1198,62 @@ public function getServicegroupsByContainerIdAndServiceIds($containerIds, $servi } } + /** + * @param array $ids + * @param array $MY_RIGHTS + * @return array + */ + public function getServicegroupsForCopy($ids = [], array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['Servicegroups.id IN' => $ids]) + ->contain([ + 'Containers' + ]) + ->order(['Servicegroups.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Containers.parent_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + public function getSourceServicegroupForCopy($id, array $MY_RIGHTS) { + $query = $this->find() + ->where(['Servicegroups.id' => $id]) + ->contain([ + 'Services', + 'Servicetemplates', + 'Containers' + ]); + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Containers.parent_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration(); + $result = $query->firstOrFail(); + $servicegroup = $result; + $servicegroup['services'] = [ + '_ids' => Hash::extract($result, 'services.{n}.id') + ]; + $servicegroup['servicetemplates'] = [ + '_ids' => Hash::extract($result, 'servicetemplates.{n}.id') + ]; + return $servicegroup; + } + /** * @param int $containerId * @return array */ - public function getOrphanedServicegroupsByContainerId(int $containerId){ + public function getOrphanedServicegroupsByContainerId(int $containerId) { $query = $this->find() ->where(['container_id' => $containerId]); $result = $query->all(); diff --git a/src/Model/Table/ServicetemplategroupsTable.php b/src/Model/Table/ServicetemplategroupsTable.php index fed768e8ff..e4733f91f7 100644 --- a/src/Model/Table/ServicetemplategroupsTable.php +++ b/src/Model/Table/ServicetemplategroupsTable.php @@ -451,7 +451,7 @@ public function getServicetemplatesByServicetemplategroupId($id) { ->disableHydration() ->first(); - if(empty(!$servicetemplates['servicetemplates'])){ + if (empty(!$servicetemplates['servicetemplates'])) { return []; } return Hash::extract($servicetemplates['servicetemplates'], '{n}.id'); @@ -725,11 +725,59 @@ public function getServicetemplategroupsByContainerId(array $containerIds) { return $servicetemplategroups; } + /** + * @param array $ids + * @param array $MY_RIGHTS + * @return array + */ + public function getServicetemplategroupsForCopy($ids = [], array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['Servicetemplategroups.id IN' => $ids]) + ->contain([ + 'Containers' + ]) + ->order(['Servicetemplategroups.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Containers.parent_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + public function getSourceServicetemplategroupForCopy($id, array $MY_RIGHTS) { + $query = $this->find() + ->where(['Servicetemplategroups.id' => $id]) + ->contain([ + 'Servicetemplates', + 'Containers' + ]); + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Containers.parent_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration(); + $result = $query->firstOrFail(); + $servicetemplategroup = $result; + $servicetemplategroup['servicetemplates'] = [ + '_ids' => Hash::extract($result, 'servicetemplates.{n}.id') + ]; + + return $servicetemplategroup; + } + /** * @param int $containerId * @return array */ - public function getOrphanedServicetemplategroupsByContainerId(int $containerId){ + public function getOrphanedServicetemplategroupsByContainerId(int $containerId) { $query = $this->find() ->where(['container_id' => $containerId]); $result = $query->all(); diff --git a/src/Model/Table/ServicetemplatesTable.php b/src/Model/Table/ServicetemplatesTable.php index 64cfa0ad65..e7601d8cc8 100644 --- a/src/Model/Table/ServicetemplatesTable.php +++ b/src/Model/Table/ServicetemplatesTable.php @@ -880,9 +880,10 @@ public function getServicetemplatesForAngular($containerIds, ServicetemplateFilt /** * @param array $ids + * @param array $MY_RIGHTS * @return array */ - public function getServicetemplatesForCopy($ids = []) { + public function getServicetemplatesForCopy($ids = [], array $MY_RIGHTS = []) { if (!is_array($ids)) { $ids = [$ids]; } @@ -904,7 +905,13 @@ public function getServicetemplatesForCopy($ids = []) { ] ]) ->where(['Servicetemplates.id IN' => $ids]) - ->order(['Servicetemplates.id' => 'asc']) + ->order(['Servicetemplates.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere(['Servicetemplates.container_id IN' => $MY_RIGHTS]); + } + + $query ->disableHydration() ->all(); diff --git a/src/Model/Table/TimeperiodsTable.php b/src/Model/Table/TimeperiodsTable.php index 166d9916eb..5da0e36129 100644 --- a/src/Model/Table/TimeperiodsTable.php +++ b/src/Model/Table/TimeperiodsTable.php @@ -89,7 +89,7 @@ public function validationDefault(Validator $validator): Validator { $validator ->integer('container_id') ->greaterThan('container_id', 0) - ->requirePresence('container_id') + ->requirePresence('container_id', 'create') ->allowEmptyString('container_id', null, false); $validator @@ -333,18 +333,28 @@ public function getTimeperiodsAsList($ids = []) { /** * @param array $ids + * @paran array $MY_RIGHTS * @return array */ - public function getTimeperiodsForCopy($ids = []) { + public function getTimeperiodsForCopy($ids = [], array $MY_RIGHTS = []) { $query = $this->find() ->select([ 'Timeperiods.id', 'Timeperiods.name', 'Timeperiods.description' ]) - ->where(['Timeperiods.id IN' => $ids]) - ->order(['Timeperiods.id' => 'asc']) - ->disableHydration() + ->where([ + 'Timeperiods.id IN' => $ids + ]) + ->order(['Timeperiods.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'Timeperiods.container_id IN' => $MY_RIGHTS + ]); + } + + $query->disableHydration() ->all(); return $this->formatResultAsCake2($query->toArray(), false); diff --git a/src/Model/Table/UsercontainerrolesTable.php b/src/Model/Table/UsercontainerrolesTable.php index 90cfbf7c92..628869e9b6 100644 --- a/src/Model/Table/UsercontainerrolesTable.php +++ b/src/Model/Table/UsercontainerrolesTable.php @@ -32,6 +32,7 @@ use Cake\ORM\TableRegistry; use Cake\Utility\Hash; use Cake\Validation\Validator; +use itnovum\openITCOCKPIT\Core\FileDebugger; use itnovum\openITCOCKPIT\Database\PaginateOMat; use itnovum\openITCOCKPIT\Filter\GenericFilter; use itnovum\openITCOCKPIT\Filter\UsercontainerrolesFilter; @@ -408,6 +409,79 @@ public function getContainerPermissionsByLdapUserMemberOf($memberOfGroups = []) return $result; } + /** + * @param array $ids + * @param array $MY_RIGHTS + * @return array + */ + public function getUsercontainerrolesForCopy($ids = [], array $MY_RIGHTS = []) { + $query = $this->find() + ->where(['Usercontainerroles.id IN' => $ids]) + ->contain([ + 'Containers', + ]) + ->matching('Containers') + ->order(['Usercontainerroles.id' => 'asc']); + + if (!empty($MY_RIGHTS)) { + $query->andWhere([ + 'ContainersUsercontainerrolesMemberships.container_id IN' => $MY_RIGHTS + ]); + } + + $query->group([ + 'Usercontainerroles.id' + ]); + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + /** + * @param $id + * @param array $MY_RIGHTS + * @return array|\Cake\Datasource\EntityInterface + */ + public function getSourceUserContainerRoleForCopy($id, array $MY_RIGHTS = []) { + $query = $this->find() + ->where([ + 'Usercontainerroles.id' => $id + ]) + ->contain([ + 'Containers', + 'Ldapgroups' => [ + 'fields' => [ + 'Ldapgroups.id' + ] + ] + ]) + ->disableHydration() + ->first(); + + + $usercontainerrole = $query; + + + $usercontainerrole['containers'] = [ + '_ids' => Hash::extract($query, 'containers.{n}.id') + ]; + $usercontainerrole['ldapgroups'] = [ + '_ids' => Hash::extract($query, 'ldapgroups.{n}.id') + ]; + + + //Build up data struct for radio inputs + $usercontainerrole['ContainersUsercontainerrolesMemberships'] = []; + foreach ($query['containers'] as $container) { + $usercontainerrole['ContainersUsercontainerrolesMemberships'][$container['id']] = (int)$container['_joinData']['permission_level']; + } + + return $usercontainerrole; + } + + /** * @param int $containerId * @return array diff --git a/src/Model/Table/UsergroupsTable.php b/src/Model/Table/UsergroupsTable.php index 7107dbdc0e..bbf9f4de06 100644 --- a/src/Model/Table/UsergroupsTable.php +++ b/src/Model/Table/UsergroupsTable.php @@ -7,6 +7,7 @@ use App\Lib\Traits\PaginationAndScrollIndexTrait; use Cake\ORM\Table; use Cake\ORM\TableRegistry; +use Cake\Utility\Hash; use Cake\Validation\Validator; use itnovum\openITCOCKPIT\Database\PaginateOMat; use itnovum\openITCOCKPIT\Filter\GenericFilter; @@ -224,4 +225,54 @@ public function getUsergroupByLdapUserMemberOf($memberOfGroups = []) { return $this->emptyArrayIfNull($query); } + + /** + * @param array $ids + * @return array + */ + public function getUsergroupsForCopy($ids = []) { + $query = $this->find() + ->select([ + 'Usergroups.id', + 'Usergroups.name', + 'Usergroups.description', + ]) + ->where(['Usergroups.id IN' => $ids]) + ->order(['Usergroups.id' => 'asc']); + + $query->disableHydration() + ->all(); + + return $this->emptyArrayIfNull($query->toArray()); + } + + /** + * @param int $id + * @return array + */ + public function getSourceUsergroupForCopy($id) { + $usergroup = $this->find() + ->contain([ + 'Aros' => [ + 'Acos' + ], + 'Ldapgroups' => [ + 'fields' => [ + 'Ldapgroups.id' + ] + ] + ]) + ->where([ + 'Usergroups.id' => $id + ]) + ->firstOrFail(); + + $usergroup = $usergroup->toArray(); + + $usergroup['ldapgroups'] = [ + '_ids' => Hash::extract($usergroup, 'ldapgroups.{n}.id') + ]; + + return $usergroup; + } } diff --git a/src/Template/Angular/mass_delete.php b/src/Template/Angular/mass_delete.php index 34c0dcaac2..6475f608d8 100644 --- a/src/Template/Angular/mass_delete.php +++ b/src/Template/Angular/mass_delete.php @@ -35,7 +35,7 @@ ng-if="!issue.isAngular" href="{{issue.url}}">{{issue.message}} - {{issue.message}}
diff --git a/src/Template/Automaps/copy.php b/src/Template/Automaps/copy.php new file mode 100644 index 0000000000..446aa3b460 --- /dev/null +++ b/src/Template/Automaps/copy.php @@ -0,0 +1,148 @@ + +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'automaps')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceAutomap.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'Automaps')): ?> + + +
+
+
+
+
+
+
+
diff --git a/src/Template/Automaps/index.php b/src/Template/Automaps/index.php index 55f1e3b0a8..ad77ce896e 100644 --- a/src/Template/Automaps/index.php +++ b/src/Template/Automaps/index.php @@ -250,6 +250,16 @@ class="dropdown-item"> + + Acl->hasPermission('copy', 'automaps')): ?> + + + + + + + Acl->hasPermission('delete', 'automaps')): ?>
-
+
({{selectedElements}})
-
+
-
+
+ Acl->hasPermission('copy', 'automaps')): ?> +
+ Acl->hasPermission('delete', 'automaps')): ?> -
+
diff --git a/src/Template/Browsers/index.php b/src/Template/Browsers/index.php index c86a4a53a0..a02746cd16 100755 --- a/src/Template/Browsers/index.php +++ b/src/Template/Browsers/index.php @@ -889,6 +889,23 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'hosts')): ?> + + + + + + Acl->hasPermission('deactivate', 'hosts')): ?> + + + + + Acl->hasPermission('serviceList', 'services')): ?> @@ -903,7 +920,6 @@ class="dropdown-item"> - Acl->hasPermission('add', 'hostgroups', '')): ?> @@ -911,13 +927,11 @@ class="dropdown-item" href="javascript:void(0);"> - Acl->hasPermission('deactivate', 'hosts')): ?> - - - + Acl->hasPermission('wizard', 'agentconnector')): ?> + + + Acl->hasPermission('index', 'changelogs')): ?> diff --git a/src/Template/Commands/index.php b/src/Template/Commands/index.php index 1d3d712a87..0640c404a6 100755 --- a/src/Template/Commands/index.php +++ b/src/Template/Commands/index.php @@ -220,6 +220,14 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'commands')): ?> + + + + + + Acl->hasPermission('delete', 'commands')): ?> + Acl->hasPermission('copy', 'contactgroups')): ?> + + + + + + Acl->hasPermission('delete', 'contactgroups')): ?> + Acl->hasPermission('copy', 'contacts')): ?> + + + + + + Acl->hasPermission('delete', 'contacts')): ?> +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'hostgroups')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceHostgroup.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'Hostgroups')): ?> + + +
+
+
+
+
+
+
+
diff --git a/src/Template/Hostgroups/extended.php b/src/Template/Hostgroups/extended.php index 1b299e8c5f..9515636c31 100644 --- a/src/Template/Hostgroups/extended.php +++ b/src/Template/Hostgroups/extended.php @@ -63,8 +63,7 @@

{{(hostgroup.Hostgroup.container.name) && hostgroup.Hostgroup.container.name || - ''}} - {{hostgroup.Hostgroup.uuid}} +q {{hostgroup.Hostgroup.uuid}}

+ Acl->hasPermission('copy', 'hostgroups')): ?> + + + + + + Acl->hasPermission('externalcommands', 'hosts')): ?> +
- - + Acl->hasPermission('copy', 'hostgroups')): ?> + + Acl->hasPermission('delete', 'hostgroups')): ?>
@@ -254,6 +258,21 @@ class="dropdown-item txt-color-red">
+
+ + +
diff --git a/src/Template/Hosts/browser.php b/src/Template/Hosts/browser.php index 213fdd5938..3d06565acb 100644 --- a/src/Template/Hosts/browser.php +++ b/src/Template/Hosts/browser.php @@ -1709,6 +1709,15 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> + Acl->hasPermission('copy', 'hosttemplates')): ?> + + + + + + Acl->hasPermission('delete', 'hosttemplates')): ?> +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'servicegroups')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceServicegroup.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'Servicegroups')): ?> + + +
+
+
+
+
+
+
+
diff --git a/src/Template/Servicegroups/extended.php b/src/Template/Servicegroups/extended.php index ee86d1cbb0..908460edb9 100644 --- a/src/Template/Servicegroups/extended.php +++ b/src/Template/Servicegroups/extended.php @@ -63,7 +63,10 @@

{{(servicegroup.Servicegroup.container.name) && servicegroup.Servicegroup.container.name || - ''}} + ''}} {{servicegroup.Servicegroup.uuid}}

@@ -114,6 +117,15 @@ class="dropdown-item" + Acl->hasPermission('copy', 'servicegroups')): ?> + + + + + + + Acl->hasPermission('externalcommands', 'services')): ?>
- - + Acl->hasPermission('copy', 'servicegroups')): ?> + + Acl->hasPermission('delete', 'servicegroups')): ?>
@@ -254,6 +258,21 @@ class="dropdown-item txt-color-red">
+
+ + +
diff --git a/src/Template/Services/disabled.php b/src/Template/Services/disabled.php index e4f7010f40..ff1b1a7d8e 100755 --- a/src/Template/Services/disabled.php +++ b/src/Template/Services/disabled.php @@ -264,6 +264,15 @@ class="dropdown-item"> $AdditionalLinks = new \App\Lib\AdditionalLinks($this); echo $AdditionalLinks->getLinksAsHtmlList('services', 'disabled', 'list'); ?> + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> $AdditionalLinks = new \App\Lib\AdditionalLinks($this); echo $AdditionalLinks->getLinksAsHtmlList('services', 'notMonitored', 'list'); ?> + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> + Acl->hasPermission('copy', 'hosts')): ?> + + + + + + + Acl->hasPermission('allocateToHost', 'servicetemplategroups')): ?> @@ -429,6 +439,15 @@ class="dropdown-item"> $AdditionalLinks = new \App\Lib\AdditionalLinks($this); echo $AdditionalLinks->getLinksAsHtmlList('services', 'index', 'list'); ?> + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> + + Acl->hasPermission('copy', 'services')): ?> + + + + + + Acl->hasPermission('delete', 'services')): ?> + +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'servicetemplategroups')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceServicetemplategroup.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'Servicetemplategroups')): ?> + + +
+
+
+
+
+
+
+
diff --git a/src/Template/Servicetemplategroups/index.php b/src/Template/Servicetemplategroups/index.php index 0b2896b7cf..04c3c52285 100644 --- a/src/Template/Servicetemplategroups/index.php +++ b/src/Template/Servicetemplategroups/index.php @@ -207,6 +207,14 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'servicetemplategroups')): ?> + + + + + + Acl->hasPermission('delete', 'servicetemplategroups')): ?>
+ + Acl->hasPermission('copy', 'servicetemplategroups')): ?> + + + Acl->hasPermission('delete', 'servicetemplategroups')): ?>
diff --git a/src/Template/Servicetemplates/index.php b/src/Template/Servicetemplates/index.php index afa83b9833..c4159eb266 100755 --- a/src/Template/Servicetemplates/index.php +++ b/src/Template/Servicetemplates/index.php @@ -254,6 +254,14 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'servicetemplates')): ?> + + + + + + Acl->hasPermission('delete', 'servicetemplates')): ?> +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'Usercontainerroles')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceUsercontainerrole.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'Usercontainerroles')): ?> + + +
+
+
+
+
+
+
+
diff --git a/src/Template/Usercontainerroles/index.php b/src/Template/Usercontainerroles/index.php index d624b6ff3f..81e06da5c6 100644 --- a/src/Template/Usercontainerroles/index.php +++ b/src/Template/Usercontainerroles/index.php @@ -181,8 +181,17 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'usercontainerroles')): ?> + + + + + + Acl->hasPermission('delete', 'usercontainerroles')): ?> - +
+ Acl->hasPermission('copy', 'usercontainerroles')): ?> + + Acl->hasPermission('delete', 'usercontainerroles')): ?>
diff --git a/src/Template/Usergroups/copy.php b/src/Template/Usergroups/copy.php new file mode 100644 index 0000000000..95d697f397 --- /dev/null +++ b/src/Template/Usergroups/copy.php @@ -0,0 +1,119 @@ + +// +// This file is dual licensed +// +// 1. +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// 2. +// If you purchased an openITCOCKPIT Enterprise Edition you can use this file +// under the terms of the openITCOCKPIT Enterprise Edition license agreement. +// License agreement and license key will be shipped with the order +// confirmation. +?> + +
+
+
+
+

+ + +

+
+ Acl->hasPermission('index', 'usergroups')): ?> + + + + +
+
+
+
+
+
+ + + {{sourceUsergroup.Source.name}} + +
+
+
+ + + + + +
+
{{ error }}
+
+
+ +
+ + +
+
{{ error }}
+
+
+ +
+
+ +
+
+
+ + Acl->hasPermission('index', 'Usergroups')): ?> + + +
+
+
+
+
+
+
+
diff --git a/src/Template/Usergroups/index.php b/src/Template/Usergroups/index.php index fab4156320..373925514a 100644 --- a/src/Template/Usergroups/index.php +++ b/src/Template/Usergroups/index.php @@ -168,8 +168,17 @@ class="dropdown-item"> + Acl->hasPermission('copy', 'usergroups')): ?> + + + + + + Acl->hasPermission('delete', 'usergroups')): ?> - +
+ Acl->hasPermission('copy', 'usergroups')): ?> + + Acl->hasPermission('delete', 'usergroups')): ?>
diff --git a/webroot/js/scripts/controllers/Automaps/AutomapsCopyController.js b/webroot/js/scripts/controllers/Automaps/AutomapsCopyController.js new file mode 100644 index 0000000000..0b53a535dc --- /dev/null +++ b/webroot/js/scripts/controllers/Automaps/AutomapsCopyController.js @@ -0,0 +1,59 @@ +angular.module('openITCOCKPIT') + .controller('AutomapsCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('AutomapsIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/automaps/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceAutomaps = []; + for(var key in result.data.automaps){ + $scope.sourceAutomaps.push({ + Source: { + id: result.data.automaps[key].id, + name: result.data.automaps[key].name, + }, + Automap: { + name: result.data.automaps[key].name, + description: result.data.automaps[key].description, + host_regex: result.data.automaps[key].host_regex, + service_regex: result.data.automaps[key].service_regex + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/automaps/copy/.json?angular=true", + { + data: $scope.sourceAutomaps + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('AutomapsIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceAutomaps = result.data.result; + }); + }; + + + $scope.load(); + + + }); diff --git a/webroot/js/scripts/controllers/Automaps/AutomapsIndexController.js b/webroot/js/scripts/controllers/Automaps/AutomapsIndexController.js index 8516bad88a..22c700c514 100644 --- a/webroot/js/scripts/controllers/Automaps/AutomapsIndexController.js +++ b/webroot/js/scripts/controllers/Automaps/AutomapsIndexController.js @@ -93,6 +93,10 @@ angular.module('openITCOCKPIT') return objects; }; + $scope.linkForCopy = function(){ + var ids = Object.keys(MassChangeService.getSelected()); + return ids.join(','); + }; $scope.changepage = function(page){ $scope.undoSelection(); @@ -123,4 +127,4 @@ angular.module('openITCOCKPIT') $scope.selectedElements = MassChangeService.getCount(); }, true); - }); \ No newline at end of file + }); diff --git a/webroot/js/scripts/controllers/Hostgroups/HostgroupsCopyController.js b/webroot/js/scripts/controllers/Hostgroups/HostgroupsCopyController.js new file mode 100644 index 0000000000..60adeedb5c --- /dev/null +++ b/webroot/js/scripts/controllers/Hostgroups/HostgroupsCopyController.js @@ -0,0 +1,59 @@ +angular.module('openITCOCKPIT') + .controller('HostgroupsCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('HostgroupsIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/hostgroups/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceHostgroups = []; + for(var key in result.data.hostgroups){ + $scope.sourceHostgroups.push({ + Source: { + id: result.data.hostgroups[key].id, + name: result.data.hostgroups[key].container.name, + }, + Hostgroup: { + container: { + name: result.data.hostgroups[key].container.name + }, + description: result.data.hostgroups[key].description + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/hostgroups/copy/.json?angular=true", + { + data: $scope.sourceHostgroups + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('HostgroupsIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceHostgroups = result.data.result; + }); + }; + + + $scope.load(); + + + }); diff --git a/webroot/js/scripts/controllers/Hostgroups/HostgroupsIndexController.js b/webroot/js/scripts/controllers/Hostgroups/HostgroupsIndexController.js index e6500038a5..c3cf42d321 100644 --- a/webroot/js/scripts/controllers/Hostgroups/HostgroupsIndexController.js +++ b/webroot/js/scripts/controllers/Hostgroups/HostgroupsIndexController.js @@ -101,6 +101,11 @@ angular.module('openITCOCKPIT') return baseUrl; }; + $scope.linkForCopy = function(){ + var ids = Object.keys(MassChangeService.getSelected()); + return ids.join(','); + }; + $scope.changepage = function(page){ $scope.undoSelection(); if(page !== $scope.currentPage){ diff --git a/webroot/js/scripts/controllers/Servicegroups/ServicegroupsCopyController.js b/webroot/js/scripts/controllers/Servicegroups/ServicegroupsCopyController.js new file mode 100644 index 0000000000..eebde42e98 --- /dev/null +++ b/webroot/js/scripts/controllers/Servicegroups/ServicegroupsCopyController.js @@ -0,0 +1,59 @@ +angular.module('openITCOCKPIT') + .controller('ServicegroupsCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('ServicegroupsIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/servicegroups/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceServicegroups = []; + for(var key in result.data.servicegroups){ + $scope.sourceServicegroups.push({ + Source: { + id: result.data.servicegroups[key].id, + name: result.data.servicegroups[key].container.name, + }, + Servicegroup: { + container: { + name: result.data.servicegroups[key].container.name + }, + description: result.data.servicegroups[key].description + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/servicegroups/copy/.json?angular=true", + { + data: $scope.sourceServicegroups + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('ServicegroupsIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceServicegroups = result.data.result; + }); + }; + + + $scope.load(); + + + }); diff --git a/webroot/js/scripts/controllers/Servicegroups/ServicegroupsIndexController.js b/webroot/js/scripts/controllers/Servicegroups/ServicegroupsIndexController.js index 517b74d3e1..b3a9b24286 100644 --- a/webroot/js/scripts/controllers/Servicegroups/ServicegroupsIndexController.js +++ b/webroot/js/scripts/controllers/Servicegroups/ServicegroupsIndexController.js @@ -101,6 +101,11 @@ angular.module('openITCOCKPIT') return baseUrl; }; + $scope.linkForCopy = function(){ + var ids = Object.keys(MassChangeService.getSelected()); + return ids.join(','); + }; + $scope.changepage = function(page){ $scope.undoSelection(); if(page !== $scope.currentPage){ diff --git a/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsCopyController.js b/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsCopyController.js new file mode 100644 index 0000000000..3b16b4ace4 --- /dev/null +++ b/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsCopyController.js @@ -0,0 +1,59 @@ +angular.module('openITCOCKPIT') + .controller('ServicetemplategroupsCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('ServicetemplategroupsIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/servicetemplategroups/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceServicetemplategroups = []; + for(var key in result.data.servicetemplategroups){ + $scope.sourceServicetemplategroups.push({ + Source: { + id: result.data.servicetemplategroups[key].id, + name: result.data.servicetemplategroups[key].container.name, + }, + Servicetemplategroup: { + container: { + name: result.data.servicetemplategroups[key].container.name + }, + description: result.data.servicetemplategroups[key].description + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/servicetemplategroups/copy/.json?angular=true", + { + data: $scope.sourceServicetemplategroups + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('ServicetemplategroupsIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceServicetemplategroups = result.data.result; + }); + }; + + + $scope.load(); + + + }); diff --git a/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsIndexController.js b/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsIndexController.js index 99208ee66c..a8cb056ea5 100644 --- a/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsIndexController.js +++ b/webroot/js/scripts/controllers/Servicetemplategroups/ServicetemplategroupsIndexController.js @@ -103,6 +103,11 @@ angular.module('openITCOCKPIT') return objects; }; + $scope.linkForCopy = function(){ + var ids = Object.keys(MassChangeService.getSelected()); + return ids.join(','); + }; + $scope.allocateToMatchingHostgroup = function(servicetemplategroupId){ $('#loaderModal').modal('show'); @@ -171,4 +176,4 @@ angular.module('openITCOCKPIT') $scope.selectedElements = MassChangeService.getCount(); }, true); - }); \ No newline at end of file + }); diff --git a/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesCopyController.js b/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesCopyController.js new file mode 100644 index 0000000000..d29bf570ee --- /dev/null +++ b/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesCopyController.js @@ -0,0 +1,56 @@ +angular.module('openITCOCKPIT') + .controller('UsercontainerrolesCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('UsercontainerrolesIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/usercontainerroles/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceUsercontainerroles = []; + for(var key in result.data.usercontainerroles){ + $scope.sourceUsercontainerroles.push({ + Source: { + id: result.data.usercontainerroles[key].id, + name: result.data.usercontainerroles[key].name, + }, + Usercontainerrole: { + name: result.data.usercontainerroles[key].name + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/usercontainerroles/copy/.json?angular=true", + { + data: $scope.sourceUsercontainerroles + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('UsercontainerrolesIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceUsercontainerroles = result.data.result; + }); + }; + + + $scope.load(); + + + }); diff --git a/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesIndexController.js b/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesIndexController.js index 0aaa43559b..f73f338ef9 100644 --- a/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesIndexController.js +++ b/webroot/js/scripts/controllers/Usercontainerroles/UsercontainerrolesIndexController.js @@ -99,6 +99,11 @@ angular.module('openITCOCKPIT') $scope.load(); }; + $scope.linkForCopy = function(){ + var ids = Object.keys(MassChangeService.getSelected()); + return ids.join(','); + }; + //Fire on page load defaultFilter(); SortService.setCallback($scope.load); diff --git a/webroot/js/scripts/controllers/Usergroups/UsergroupsCopyController.js b/webroot/js/scripts/controllers/Usergroups/UsergroupsCopyController.js new file mode 100644 index 0000000000..c72b61e7fd --- /dev/null +++ b/webroot/js/scripts/controllers/Usergroups/UsergroupsCopyController.js @@ -0,0 +1,57 @@ +angular.module('openITCOCKPIT') + .controller('UsergroupsCopyController', function($scope, $http, $state, $stateParams, QueryStringService, NotyService, RedirectService){ + + var ids = $stateParams.ids.split(','); + + if(ids.length === 0 || ids[0] === ''){ + //No ids to copy given - redirect + RedirectService.redirectWithFallback('UsergroupsIndex'); + return; + } + + + $scope.load = function(){ + $http.get("/usergroups/copy/" + ids.join('/') + ".json", { + params: { + 'angular': true, + } + }).then(function(result){ + $scope.sourceUsergroups = []; + for(var key in result.data.usergroups){ + $scope.sourceUsergroups.push({ + Source: { + id: result.data.usergroups[key].id, + name: result.data.usergroups[key].name, + }, + Usergroup: { + name: result.data.usergroups[key].name, + description: result.data.usergroups[key].description + } + }); + } + + $scope.init = false; + + }); + }; + + $scope.copy = function(){ + $http.post("/usergroups/copy/.json?angular=true", + { + data: $scope.sourceUsergroups + } + ).then(function(result){ + NotyService.genericSuccess(); + RedirectService.redirectWithFallback('UsergroupsIndex'); + }, function errorCallback(result){ + //Print errors + NotyService.genericError(); + $scope.sourceUsergroups = result.data.result; + }); + }; + + + $scope.load(); + + + }); diff --git a/webroot/js/scripts/ng.app.js b/webroot/js/scripts/ng.app.js index 092d145778..48ba79ee1a 100644 --- a/webroot/js/scripts/ng.app.js +++ b/webroot/js/scripts/ng.app.js @@ -623,6 +623,12 @@ var openITCOCKPIT = angular.module('openITCOCKPIT', ['gridster', 'ui.router', 'n controller: "HostgroupsAppendController" }) + .state('HostgroupsCopy', { + url: '/hostgroups/copy/:ids', + templateUrl: "/hostgroups/copy.html", + controller: "HostgroupsCopyController" + }) + .state('HostchecksIndex', { url: '/hostchecks/index/:id', templateUrl: "/hostchecks/index.html", @@ -729,6 +735,12 @@ var openITCOCKPIT = angular.module('openITCOCKPIT', ['gridster', 'ui.router', 'n controller: "ServicegroupsExtendedController" }) + .state('ServicegroupsCopy', { + url: '/servicegroups/copy/:ids', + templateUrl: "/servicegroups/copy.html", + controller: "ServicegroupsCopyController" + }) + .state('StatehistoriesHost', { url: '/statehistories/host/:id', templateUrl: "/statehistories/host.html", @@ -1090,6 +1102,12 @@ var openITCOCKPIT = angular.module('openITCOCKPIT', ['gridster', 'ui.router', 'n controller: "UsercontainerrolesEditController" }) + .state('UsercontainerrolesCopy', { + url: '/usercontainerroles/copy/:ids', + templateUrl: "/usercontainerroles/copy.html", + controller: "UsercontainerrolesCopyController" + }) + .state('UsergroupsIndex', { url: '/usergroups/index', templateUrl: "/usergroups/index.html", @@ -1108,6 +1126,12 @@ var openITCOCKPIT = angular.module('openITCOCKPIT', ['gridster', 'ui.router', 'n controller: "UsergroupsEditController" }) + .state('UsergroupsCopy', { + url: '/usergroups/copy/:ids', + templateUrl: "/usergroups/copy.html", + controller: "UsergroupsCopyController" + }) + .state('ProfileEdit', { url: '/profile/edit/', templateUrl: "/profile/edit.html", @@ -1347,6 +1371,12 @@ var openITCOCKPIT = angular.module('openITCOCKPIT', ['gridster', 'ui.router', 'n controller: "ServicetemplategroupsAllocateToHostgroupController" }) + .state('ServicetemplategroupsCopy', { + url: '/servicetemplategroups/copy/:ids', + templateUrl: "/servicetemplategroups/copy.html", + controller: "ServicetemplategroupsCopyController" + }) + .state('LocationsIndex', { url: '/locations/index', templateUrl: "/locations/index.html", @@ -1425,6 +1455,12 @@ var openITCOCKPIT = angular.module('openITCOCKPIT', ['gridster', 'ui.router', 'n controller: "AutomapsViewController" }) + .state('AutomapsCopy', { + url: '/automaps/copy/:ids', + templateUrl: "/automaps/copy.html", + controller: "AutomapsCopyController" + }) + .state('SearchIndex', { url: '/search/index', templateUrl: "/search/index.html",