Compare commits

..

102 Commits

Author SHA1 Message Date
Benjamin DALSASS
b5c8a98695 N°9807 - Polishing CKEditor for iTop 3.3.0-beta1
- fix setup css broken unit test
2026-07-30 09:21:51 +02:00
Lenaick
1403914572 N°9116 - Installing modules in extension folder or production-modules doesn't have the same behavior (#981)
* N°9116 - Installing modules in extension folder or production-modules doesn't have the same behavior

* N°9116 - Installing modules in extension folder or production-modules doesn't have the same behavior

* N°9116 - Installing modules in extension folder or production-modules doesn't have the same behavior
2026-07-28 16:40:23 +02:00
Stephen Abello
b976471a0d N°9385 - Action button is not displaying its dropdown in a filtered BrowseBrick 2026-07-28 10:24:02 +02:00
Benjamin DALSASS
47981f78e3 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	css/setup.css
#	datamodels/2.x/itop-portal-base/portal/public/css/portal.css
#	datamodels/2.x/itop-portal-base/portal/public/css/portal.scss
2026-07-28 08:41:18 +02:00
Benjamin DALSASS
476ec75a2e N°9838 - Polishing CKEditor for iTop 3.2.4 2026-07-28 08:39:24 +02:00
Benjamin DALSASS
10c000ddfe N°9807 - Polishing CKEditor for iTop 3.3.0-beta1
- update with last ckeditor changes
2026-07-28 08:23:20 +02:00
Vincent Dumas
7e55b9ccfc N°9703 - Updates italian dictionnary 2026-07-27 18:51:53 +02:00
v-dumas
5bb288ffca N°9800 - broken setup in CI 2026-07-27 18:36:03 +02:00
Vincent Dumas
56d7e40f4c N°9800 New sample data for KnownError and FAQ (#982)
* N°9800 - Fix typos in sample data in User and Service in FR
* N°9800 - typo in sample Server ids and Rack id
2026-07-27 18:16:58 +02:00
Benjamin Dalsass
e0dc1fa571 N°8886 - Deprecation warning in DashetGroupBy in 3.3-dev (#972) 2026-07-27 08:26:37 +02:00
Stephen Abello
d6466c0bd6 Update setup.css 2026-07-24 14:30:17 +02:00
Stephen Abello
eb16e6cbc8 Merge branch 'support/3.2' into develop 2026-07-24 14:29:24 +02:00
Stephen Abello
42007ffd95 N°9702 - Fix user rights matrix display when an accessibility theme displayed a visual cue 2026-07-24 14:28:59 +02:00
Molkobain
6329c157e8 📝 Update releases history with 3.3.0-beta1 2026-07-24 11:31:07 +02:00
Benjamin Dalsass
9ee0548767 N°9807 - Polishing CKEditor for iTop 3.3.0-beta1 (#976) 2026-07-24 09:22:24 +02:00
Lenaick
620a6b9a51 N°9827 - Unable to launch check compatibility when a module with bad dependencies is in production-modules (#978)
* N°9827 - Unable to launch check compatibility when a module with bad dependencies is in production-modules

* Update unit tests

* N°9827 - Unable to launch check compatibility when a module with bad dependencies is in production-modules
2026-07-23 16:23:06 +02:00
Stephen Abello
968c56745a Merge branch 'support/3.2' into develop
# Conflicts:
#	core/attributedef.class.inc.php
2026-07-23 16:08:45 +02:00
Anne-Catherine
04a5e5463a N°9759 - Truncating AttributeText doesn't work as expected in case of multibytes characters (#964)
* N°9759 - Truncate AttributeText don't work as expected in case of multibytes characters

* WIP

* Move TrimValue() base definition to AttributeDefinition class, assign DBObject::SetTrim old behavior to it

* Fix variable types

* Fix variable types

* Apply code review fixes, add tests

* Define GetSize in AttributeDefinition to easy polymorphic calls instead of obscure AttributeDBFieldVoid

* Update php with right since version and ticket, remove useless method overload

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update core/attributedef.class.inc.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update core/attributedef.class.inc.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Correctly handle null values in new methods

---------

Co-authored-by: Stephen Abello <stephen.abello@combodo.com>
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2026-07-23 16:07:42 +02:00
Benjamin Dalsass
006dd3d6c2 N°9829 - Add unit tests for parent ticket changes (#979) 2026-07-23 15:32:53 +02:00
lenaick.moreira
a808e89c30 Merge branch 'support/3.3-beta1' into develop 2026-07-23 11:43:00 +02:00
lenaick.moreira
c6e50a0ed7 N°9830 - Fix setup error when trying to remove class with a TagSet attribute 2026-07-23 11:39:42 +02:00
Molkobain
d88687527e Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-07-23 10:49:09 +02:00
Molkobain
2cc071b07a Merge remote-tracking branch 'origin/support/3.3-beta1' into develop 2026-07-23 10:47:12 +02:00
Molkobain
76a410e00d Revert "N°9541 itop-virtualization-mgmt cannot currently be uninstalled" now that N°9831 has been fixed
This reverts commit 52fca750b0.
2026-07-23 10:45:44 +02:00
Molkobain
c68887c2bc N°9831 - Fix ext. management deletion plan analysis by avoiding overwriting entity for a previously processed class 2026-07-23 10:21:31 +02:00
Molkobain
837b433622 N°9831 - Fix DataCleanupService so it handles external keys the same way as \Combodo\iTop\DataFeatureRemoval\Service\StaticDeletionPlan::DeletionPlanForReferencingClasses and \DBObject::MakeDeletionPlan
- Check if ext. key is nullable first
- Then check if its a DEL_MANUAL option
2026-07-23 10:21:31 +02:00
Timmy38
52fca750b0 N°9541 itop-virtualization-mgmt cannot currently be uninstalled 2026-07-22 17:37:19 +02:00
Benjamin Dalsass
a5c14e4870 N°9723 - IsActionAllowed should work with non instantiated users objects (#973) 2026-07-21 17:41:40 +02:00
Timmy38
0e72b090ee Merge branch 'support/3.3-beta1' into develop 2026-07-21 17:06:30 +02:00
Timmy38
d1aedee245 N°9692 - Fix flag name 2026-07-21 17:04:37 +02:00
Timmy38
1b70b4bf70 N°9692 - Fix flag name 2026-07-21 12:02:31 +02:00
odain
41f51a2c0c Merge branch 'support/3.2' into develop 2026-07-21 08:03:21 +02:00
odain-cbd
73ede13443 N°9746 - Synchro execution time change fixes (#951)
* N°9746 - Synchro execution can make damage during time change (object deletions)

* N°9746 - handle timechange during synchro execution + cleanup m_bIsImportPhaseDateKnown

* N°9746 - PR fix

* N°9746 - add corner test case
2026-07-21 08:01:31 +02:00
odain-cbd
40dd72ef82 N°9746 - Synchro execution time change fixes (#951)
* N°9746 - Synchro execution can make damage during time change (object deletions)

* N°9746 - handle timechange during synchro execution + cleanup m_bIsImportPhaseDateKnown

* N°9746 - PR fix

* N°9746 - add corner test case
2026-07-21 07:59:50 +02:00
Lenaick
c8aea56171 N°9565 - Extension Mgmt : display progression during analysis (#975)
* N°9565 - Extension Mgmt : display progression during analysis

* N°9565 - Extension Mgmt : display progression during analysis

* N°9565 - Extension Mgmt : display progression during analysis

* N°9565 - Extension Mgmt : display progression during analysis

* N°9565 - Extension Mgmt : display progression during analysis

* N°9565 - Validate transaction id

* N°9565 - Move unset bForceCompilation
2026-07-20 11:38:30 +02:00
lenaick.moreira
041437cbeb Merge branch 'support/3.3-beta1' into develop 2026-07-17 17:05:46 +02:00
lenaick.moreira
85d50f31bd N°9692 - Fix null coalescing for extension installation status and clean up test cases 2026-07-17 17:05:06 +02:00
Anne-Catherine
5715e0484f N°9759 - Truncating AttributeText doesn't work as expected in case of multibytes characters (#964)
* N°9759 - Truncate AttributeText don't work as expected in case of multibytes characters

* WIP

* Move TrimValue() base definition to AttributeDefinition class, assign DBObject::SetTrim old behavior to it

* Fix variable types

* Fix variable types

* Apply code review fixes, add tests

* Define GetSize in AttributeDefinition to easy polymorphic calls instead of obscure AttributeDBFieldVoid

* Update php with right since version and ticket, remove useless method overload

* Apply suggestions from code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update core/attributedef.class.inc.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Update core/attributedef.class.inc.php

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Apply suggestion from @Molkobain code review

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>

* Correctly handle null values in new methods

---------

Co-authored-by: Stephen Abello <stephen.abello@combodo.com>
Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2026-07-17 16:40:09 +02:00
lenaick.moreira
109fdfa06b Merge branch 'support/3.3-beta1' into develop
^ Conflicts:
^	datamodels/2.x/combodo-data-feature-removal/src/Controller/DataFeatureRemovalController.php
2026-07-17 14:45:50 +02:00
lenaick.moreira
3c301affb3 N°9679 - Add remote extensions as uninstallable extension in "Extension management" 2026-07-17 14:32:46 +02:00
Lenaick
147fae7f8c N°9679 - Forced uninstallation is not logged when done by extensions management (#956) 2026-07-17 11:25:36 +02:00
odain-cbd
a5aa8c279f fix broken cache warmup after setup (#974)
* fix broken cache warmup after setup

* clear all caches after setup
2026-07-17 10:40:55 +02:00
Molkobain
13fad9efc1 N°9625 - Add Session::UnsetAll() method to ensure that even the "welcome" session value is correctly resetted (#970)
* N°9625 - Add Session::UnsetAll() method to ensure that even the "welcome" session value is correctly resetted

* N°9625 - Add unit tests

* N°9625 - Improve robustness

* N°9625 - Code review updates

* N°9625 - Fix logoff page to ensure all authentication plugins are called before emptying the session
2026-07-17 10:28:58 +02:00
Lenaick
9fbc53cf00 N°9679 - Forced uninstallation is not logged when done by extensions management (#956) 2026-07-17 09:42:58 +02:00
lenaick.moreira
04f91ab4a2 Fix error CI 2026-07-16 09:40:33 +02:00
lenaick.moreira
918f110dc9 Merge branch 'support/3.3-beta1' into develop 2026-07-15 14:46:48 +02:00
lenaick.moreira
8e0246601a Fix unit tests failed 2026-07-15 14:33:55 +02:00
lenaick.moreira
bd9cc9c15e Fix unit tests failed 2026-07-15 14:21:17 +02:00
Eric Espie
60ce21509f Merge branch 'support/3.3-beta1' into develop 2026-07-15 12:10:56 +02:00
Eric Espie
e6cdcd0a5a N°9808 - Wrong dependency when module is in production-modules 2026-07-15 12:09:55 +02:00
Lenaick
2ab3081926 N°9692 - Uninstall / Disable install when extension has module with missing dependencies (#967)
* N°9692 - Uninstall / Disable install when extension has module with missing dependencies

* N°9692 - Uninstall / Disable install when extension has module with missing dependencies

* N°9692 - Uninstall / Disable install when extension has module with missing dependencies

* N°9692 - Refactor dependency handling for extensions to use HasDependencyIssue method

* Rename cannot-be-installed to dependency_issue

* Changes following the review
2026-07-15 09:20:25 +02:00
Molkobain
5cabac63e7 N°7984 - Complete previous revert 2026-07-14 23:32:52 +02:00
Molkobain
3918dcf830 N°7984 - Update setup compiled SCSS 2026-07-14 23:08:40 +02:00
Molkobain
489300552a Revert "Issue/7984 (#688)"
The ticket was not discussed.
2026-07-14 23:07:11 +02:00
Timmy38
8507c606ba N°9788 Adapt html for behat 2026-07-13 10:48:01 +02:00
Molkobain
128989450b 🌐 Translated missing french entries 2026-07-12 21:25:17 +02:00
Molkobain
1bd404af6f 💚 Add executable flag to scripts in .make/release folder 2026-07-12 21:10:10 +02:00
Molkobain
6c770d3e16 📝 Update third-party libraries licenses 2026-07-12 21:05:54 +02:00
Molkobain
a74dbb3a73 💚 Add executable flag to scripts in .make/license folder 2026-07-12 20:57:06 +02:00
Stephen Abello
b365aa0971 N°9628 - Fix issue following 5b9e0a1d being applied to non-jQuery elements (#961) 2026-07-10 15:57:04 +02:00
v-dumas
56aa50c9b1 N°9553 - Skip test due to unexplained CI failure 2026-07-10 15:53:37 +02:00
Vincent Dumas
eacb7f3401 N°9553 - Allow loading of localized sample and structural data based on iTop default language
* Add English, French and German structural and sample data in iTop Community

* Add helper methods to allow :
  * Checking of supported module version format
  * Finding a localized file name based on a provided en_us file name and a language
  * Loading a file if the module upgrade crossed a given version
2026-07-10 14:21:56 +02:00
Eric Espie
b14045af29 N°9648 - Better dependencies error message 2026-07-10 12:10:21 +02:00
Eric Espie
7321eeb23f N°9648 - Better dependencies error message 2026-07-10 12:02:12 +02:00
odain
05b8c529fe Fix cache-warmup after any succesfull setup 2026-07-10 11:14:59 +02:00
Timmy38
a68c017225 N°9681 Fixing edge case where an installed extension may have lost its dependencies 2026-07-09 16:40:43 +02:00
Timmy38
82b52b95a1 N°9681 Update badge tooltip 2026-07-09 14:17:42 +02:00
Molkobain
556f612f7e N°9625 - Update welcome popup messages for iTop 3.3.0 (#955)
* N°9625 - Update welcome popup messages for iTop 3.3.0

* N°9625 - Update illustrations
2026-07-09 11:42:27 +02:00
Eric Espie
edc69bebba Refactor form action URL construction in WizStepDone.php 2026-07-09 08:59:44 +02:00
odain-cbd
dce1994b85 N°9675 - Set up crash - cannot get class from production (#968)
* N°9675 - Set up crash - cannot get class from production

* N°9675 - add some comments
2026-07-09 08:59:33 +02:00
Molkobain
fde6527057 N°3124 - Update PHPDoc 2026-07-08 21:48:42 +02:00
Molkobain
0de0592c18 N°3124 - Update PHPDoc 2026-07-08 21:37:47 +02:00
Vincent Dumas
c9d512cc31 N°9699 - Enable AddMeToContact without write access on Ticket (#949)
* N°9699 - Enable AddMeToContact without write access on Ticket
* exit loop as soon as Lnk found
Co-authored-by: Stephen Abello <stephen.abello@combodo.com>
2026-07-08 16:52:23 +02:00
Eric Espié
a3ef049063 N°9722 - Setup - extension dependencies must be computed with installation choice change (#965)
* WIP compileFrom

* WIP compileFrom

* WIP

* Refactor DataFeatureRemovalController to improve setup redirection and add logging for selected extensions and modules

* Refactor DataFeatureRemovalController to streamline parameter handling for extension management

* Refactor DataFeatureRemovalController and related classes for improved session management and cleanup processes

* N°9722 - replace GetMFModulesToCompile API by GetAdditionalMFModulesBeforeFinalDeltaToCompile + fix test

* N°9722 - Refacto

* N°9722 - remove extensions effectively

* N°9722 - After review

* N°9722 - After review

* N°9722 - Analyze installation before compilation in extension management

*  N°9722 - Refactor and unit tests

* N°9722 - 

* N°9722 - 

* N°9722 - cleanup + geptileia PR feedback

---------

Co-authored-by: odain <olivier.dain@combodo.com>
2026-07-08 16:41:25 +02:00
Benjamin DALSASS
87ec702c5e N°9333 - Logo selection in dashboard is broken
- test broken
2026-07-08 13:29:55 +02:00
Vincent Dumas
127be1933d N°9629 - New fields Tags and Owner on Query class (#963)
* N°9629 - Add Usages EnumSet and Owner on Query class

* N°9629 - Add Usages on structural Queries

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-08 10:37:00 +02:00
Timmy38
2c14030fc5 N°9681 Fix missing data-id 2026-07-08 09:50:35 +02:00
odain
7825c08069 N°9765 - Designer - can't upload extensions 2026-07-08 09:34:37 +02:00
Benjamin DALSASS
4ddf17233f N°9635 - Twig security issues CVE-2026-46633 and CVE-2026-46639 and CVE-2026-46640 2026-07-07 13:52:00 +02:00
Benjamin DALSASS
9493bb03d5 Merge remote-tracking branch 'origin/support/3.2' into develop
# Conflicts:
#	lib/composer/installed.php
2026-07-07 13:51:20 +02:00
Benjamin DALSASS
8f87c759b5 N°9635 - Twig security issues CVE-2026-46633 and CVE-2026-46639 and CVE-2026-46640 2026-07-07 13:47:15 +02:00
Benjamin DALSASS
348c90145d N°9635 - Twig security issues CVE-2026-46633 and CVE-2026-46639 and CVE-2026-46640 2026-07-07 13:43:51 +02:00
Eric Espié
c37143176a N°9753 - Extension management - Run setup display installation and not upgrade (#962)
* 🚧 Refactor installation mode parameter to unify naming convention

* Changed comments on wizard steps and example to clarify upgrade mode handling
2026-07-07 11:40:59 +02:00
Benjamin DALSASS
0c8229a68e N°9333 - Logo selection in dashboard is broken 2026-07-07 09:07:04 +02:00
Timmy38
fda5fe5ded N°9681 Create "Cannot be installed" badge 2026-07-06 14:58:53 +02:00
Eric Espié
6b396adeea N°9571 - Do not allow DB change or install when upgrading iTop (#958)
* N°9571 - Do not allow DB change or install when upgrading iTop

* N°9571 - Fix unit tests

* N°9711 - Removed step Install or Upgrade

* N°9711 - After revue
2026-07-06 10:31:43 +02:00
odain
c448f8411c Merge branch 'support/3.2' into develop 2026-07-03 11:52:36 +02:00
odain
4b4fe55060 N°9689 - Fix itop-portal-base dependancy 2026-07-03 11:49:47 +02:00
Eric Espie
dedcd4af19 N°9711 - Update WizStepSummary to conditionally display database parameters based on return_application parameter 2026-07-03 09:23:13 +02:00
Eric Espie
0556a03839 N°9711 - Clear setup parameters on menu node rendering in UI.php (default page display) 2026-07-03 09:10:11 +02:00
Molkobain
64df429715 Merge remote-tracking branch 'origin/support/3.2' into develop 2026-07-02 21:12:38 +02:00
Molkobain
9ae813db2b Merge remote-tracking branch 'origin/support/3.2.3' into support/3.2 2026-07-02 21:08:45 +02:00
Molkobain
768423a6aa N°7371 - Simplify initial approach by using common API, and revert modification of unnecessary js/utils.js API 2026-07-02 20:51:30 +02:00
odain-cbd
921e7c88fe N°9675 - Set up crash - cannot get class from production (#953)
* N°9675 - raise first exception encountered when starting metamodel

* N°9675 - enhance setup data consistency error feedback

* N°9675 - raise PHP CLI version issue as well

* N°9675 - geptile PR fixes + enhance regexp for cli php version

* cleanup

* N°9675 - remove maintenance mode before any setup compilation

* N°9675 - share php cli check in SetupUtils

* N°9675 - exit maintenance only before audit
2026-07-02 16:59:04 +02:00
Molkobain
d6ef4fb7bb N°9687 - Fix incorrect return type for the DBObjectSearch::ApplyDataFilter() function (#939)
* N°9687 - Fix incorrect return type for the DBObjectSearch::ApplyDataFilter() function

* N°9687 - Add unit test

* N°9687 - Improve unit test after code review

* N°9687 - Improve unit test after code review
2026-07-02 16:11:32 +02:00
Eric Espié
a335e1004b N°9711 - Block user from going back to the setup (#954)
* N°9711 - Store setup parameters in session

* N°9711 - Restrict database parameters display to administrators in setup summary
2026-07-02 12:00:22 +02:00
Molkobain
e882df96d9 📝 Remove duplicated table in PR template 2026-07-02 11:55:34 +02:00
Eric Espié
3a7439e970 N°9639 - Uninstallation Analysis result doesn't list all the object (#950)
* N°9639 - Uninstallation Analysis better count method

* N°9639 - Fix tests

* N°9639 - Refactor deletion plan handling with new entity classes for improved structure and clarity

* N°9639 - Refactor deletion plan methods to use class names instead of table names and add TotalCount method

* N°9639 - Add messages to tests

* N°9639 - Refactor data feature removal logic and update database queries for consistency

* N°9639 - Refactor SQL queries to use backticks for table and field names

* N°9639 - Enhance deletion logic and add circular reference handling in cleanup process

* N°9639 - Add filtering methods to DeletionPlan classes for improved data cleanup

* N°9639 - Add filtering methods to DeletionPlan classes for improved data cleanup

* N°9639 - Refactor DeletionPlanItem to remove unused queries and simplify constructor

* N°9639 - Refactor variable name for clarity in hierarchical key update process

* Update tests/php-unit-tests/unitary-tests/datamodels/2.x/combodo-data-feature-removal/simulate-audit-from-setup.php

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* N°9639 - Clarify comment on deletion plan to indicate prevention of infinite loops

* N°9639 - Remove unused deletion plan from DataFeatureRemovalController

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-06-30 09:37:30 +02:00
jf-cbd
7fca6424ab N°9723 - IsActionAllowed should work with non instantiated users objects (#947)
* Replace references to user objects keys since objects can be non-instantiated (so no key available) and replace them by equivalent code

* Rename test + use self variable for profile

---------

Co-authored-by: jf-cbd <jf-cbd@users.noreply.github.com>
2026-06-25 17:45:43 +02:00
jf-cbd
f09a73c45a N°7060 - create ReadOnly profiles (#935) 2026-06-25 17:38:48 +02:00
Vincent Dumas
5a174dd8fa N°9658 - Fix Profiles retrieval in User sample data loading (#948) 2026-06-25 12:08:21 +02:00
Molkobain
1d9e7f9b55 Update test so it works on both ITIL and standard request management 2026-06-20 17:47:19 +02:00
368 changed files with 13690 additions and 3596 deletions

View File

@@ -2,13 +2,17 @@
```mermaid
%%{init: { 'logLevel': 'debug', 'theme': 'base', 'themeVariables': {
'git0': 'lawngreen',
'git3': 'dodgerblue',
'git4': 'grey',
'git5': 'grey',
'git6': 'grey',
'git7': 'grey',
'git8': 'grey'
'git0': '#7ccf00',
'git1': '#7ccf00',
'git2': '#99a1af',
'git3': '#99a1af',
'git4': '#99a1af',
'git5': '#99a1af',
'git6': '#99a1af',
'git7': '#99a1af',
'git8': '#99a1af',
'git9': '#99a1af',
'git10': '#99a1af'
}, 'gitGraph': {'showBranches': true,'mainBranchName': 'develop','rotateCommitLabel': true}} }%%
gitGraph
commit id: "2016-07-06" tag: "2.3.0" type: HIGHLIGHT
@@ -106,6 +110,8 @@ gitGraph
commit id: "2025-09-25" tag: "2.7.13"
checkout support/3.2
commit id: "2026-04-27 " tag: "3.2.3"
checkout develop
commit id: "2026-07-23" tag: "3.3.0-beta1"
```
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).

View File

@@ -9,11 +9,6 @@ Any PRs not following the guidelines or with missing information will not be con
## Base information
| Question | Answer
|----------------------------------------------------------------|--------
| Related to a SourceForge thread / Another PR / A GitHub Issue / Combodo ticket? | <!-- Put the URL --> |
| Type of change? | Bug fix / Enhancement / Translations
| Question | Answer |
|---------------------------------------------------------------------------------|--------------------------------------|
| Related to a SourceForge thread / Another PR / A GitHub Issue / Combodo ticket? | <!-- Put the URL --> |

0
.make/license/gen-community-license.sh Normal file → Executable file
View File

0
.make/license/sortLicenceXml.php Normal file → Executable file
View File

0
.make/license/updateLicenses.php Normal file → Executable file
View File

0
.make/release/changelog.php Normal file → Executable file
View File

0
.make/release/update-versions.php Normal file → Executable file
View File

0
.make/release/update-xml.php Normal file → Executable file
View File

0
.make/release/update.classes.inc.php Normal file → Executable file
View File

View File

@@ -582,16 +582,30 @@ class UserRightsProfile extends UserRightsAddOnAPI
*/
public function ListProfiles($oUser)
{
$aRet = [];
$oSearch = new DBObjectSearch('URP_UserProfile');
$oSearch->AllowAllData();
$oSearch->NoContextParameters();
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
$oProfiles = new DBObjectSet($oSearch);
while ($oUserProfile = $oProfiles->Fetch()) {
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
if (!array_key_exists('profile_list', $oUser->ListChanges())) {
// Profiles list is not modified on the $oUser object, we can use DBObjectSearch with `all data` capabilities
// Note: This is the default behavior
$aRet = [];
$oSearch = new DBObjectSearch('URP_UserProfile');
$oSearch->AllowAllData();
$oSearch->NoContextParameters();
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
$oProfiles = new DBObjectSet($oSearch);
while ($oUserProfile = $oProfiles->Fetch()) {
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
}
return $aRet;
} else {
// Profiles list must be computed with memory changes.
// Note: this is a bit tricky because the user object may have been modified in memory (e.g. a profile added or removed) and we need to take that into account
$aRet = [];
$oProfilesSet = $oUser->Get('profile_list');
foreach ($oProfilesSet as $oUserProfile) {
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
}
return $aRet;
}
return $aRet;
}
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
@@ -705,26 +719,23 @@ class UserRightsProfile extends UserRightsAddOnAPI
protected function GetUserActionGrant($oUser, $sClass, $iActionCode)
{
$this->LoadCache();
// load and cache permissions for the current user on the given class
//
$iUser = $oUser->GetKey();
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])) {
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
if (is_array($aTest)) {
return $aTest;
if (count($oUser->ListChanges()) === 0) {
// load and cache permissions for the current user on the given class
if (isset($this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iActionCode])) {
$aTest = $this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iActionCode];
if (is_array($aTest)) {
return $aTest;
}
}
}
$sAction = self::$m_aActionCodes[$iActionCode];
$bStatus = null;
// Cache user's profiles
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
$aProfileList = $this->GetProfileList($oUser);
// Call the API of UserRights because it caches the list for us
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
foreach ($aProfileList as $iProfile => $oProfile) {
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
if (!is_null($bGrant)) {
if ($bGrant) {
@@ -742,7 +753,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
$aRes = [
'permission' => $iPermission,
];
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
if (count($oUser->ListChanges()) === 0) {
$this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iActionCode] = $aRes;
}
return $aRes;
}
@@ -824,18 +837,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
{
$this->LoadCache();
// Note: this code is VERY close to the code of IsActionAllowed()
$iUser = $oUser->GetKey();
// Cache user's profiles
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
$aProfileList = $this->GetProfileList($oUser);
// Note: The object set is ignored because it was interesting to optimize for huge data sets
// and acceptable to consider only the root class of the object set
$bStatus = null;
// Call the API of UserRights because it caches the list for us
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
foreach ($aProfileList as $iProfile => $oProfile) {
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
if (!is_null($bGrant)) {
if ($bGrant) {
@@ -893,6 +902,25 @@ class UserRightsProfile extends UserRightsAddOnAPI
}
return $bHasSharing;
}
/**
* @param \User $oUser
*
* @return array
* @throws \Exception
*/
public function GetProfileList(User $oUser): array
{
if (count($oUser->ListChanges()) === 0) { // if user is already in db and not changed
$iUser = $oUser->GetKey();
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
$aProfiles = UserRights::ListProfiles($oUser);
$this->aUsersProfilesList[$iUser] = $aProfiles;
}
return $this->aUsersProfilesList[$iUser];
}
return UserRights::ListProfiles($oUser);
}
}
UserRights::SelectModule('UserRightsProfile');

View File

@@ -1046,7 +1046,7 @@ HTML
// Add extra data for markup generation
// - Attribute code and AttributeDef. class
$val['attcode'] = $sAttCode;
$val['atttype'] = $oAttDef->GetType();
$val['atttype'] = $oAttDef->GetTypeShortClassName();
$val['attlabel'] = $sAttLabel;
$val['attflags'] = ($bEditMode) ? $this->GetFormAttributeFlags($sAttCode) : OPT_ATT_READONLY;
@@ -4507,7 +4507,7 @@ HTML;
$oDivField = FieldUIBlockFactory::MakeLarge("");
// UIContentBlockUIBlockFactory::MakeStandard(null,["field_container field_large"]);
$oDivField->AddDataAttribute("attribute-type", $oAttDef->GetType());
$oDivField->AddDataAttribute("attribute-type", $oAttDef->GetTypeShortClassName());
$oDivField->AddDataAttribute("attribute-label", $sAttMetaDataLabel);
$oDivField->AddDataAttribute("attribute-flag-hidden", false);
$oDivField->AddDataAttribute("attribute-flag-read-only", false);

View File

@@ -501,7 +501,7 @@ EOF
*/
public function Render($oPage, $bEditMode = false, $aExtraParams = [], $bCanEdit = true)
{
$aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? null, $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
$aExtraParams['dashboard_div_id'] = utils::Sanitize($aExtraParams['dashboard_div_id'] ?? $this->GetId(), $this->GetId(), utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
/** @var \DashboardLayoutMultiCol $oLayout */
$oLayout = new $this->sLayoutClass();

View File

@@ -25,11 +25,11 @@
*/
use Combodo\iTop\Application\Branding;
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\WebPage\ErrorPage;
use Combodo\iTop\Application\WebPage\NiceWebPage;
use Combodo\iTop\Service\Events\EventData;
use Combodo\iTop\Service\Events\EventService;
use Combodo\iTop\Service\Session\Session;
/**
* Web page used for displaying the login form
@@ -369,16 +369,7 @@ class LoginWebPage extends NiceWebPage
public static function ResetSession()
{
// Unset all of the session variables.
Session::Unset('auth_user');
Session::Unset('login_state');
Session::Unset('can_logoff');
Session::Unset('archive_mode');
Session::Unset('impersonate_user');
Session::Unset('PluginProperties');
Session::Unset('UrlMakerClass');
Session::Unset('itop_env');
Session::Unset('obj_messages');
Session::Unset('profile_list');
Session::UnsetAll();
UserRights::_ResetSessionCache();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!

View File

@@ -113,17 +113,43 @@ abstract class Query extends cmdbAbstractObject
]
));
MetaModel::Init_AddAttribute(new AttributeExternalKey(
"owner_id",
[
"targetclass" => 'Contact',
"allowed_values" => null,
"sql" => 'owner_id',
"is_null_allowed" => true,
"depends_on" => [],
"display_style" => 'select',
"always_load_in_tables" => false,
"on_target_delete" => DEL_AUTO,
]
));
MetaModel::Init_AddAttribute(new AttributeEnumSet(
"usages",
[
"allowed_values" => null,
"possible_values" => new ValueSetEnumPadded("export,reference,notif,draft,dashlet"),
"sql" => "usages",
"depends_on" => [],
"is_null_allowed" => true,
"max_items" => 12,
]
));
// Display lists
MetaModel::Init_SetZListItems(
'details',
['name', 'is_template', 'description']
['name', 'is_template', 'owner_id', 'usages', 'description']
); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', ['description', 'usages']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems('standard_search', ['name', 'description', 'is_template']); // Criteria of the std search form
MetaModel::Init_SetZListItems(
'default_search',
['name', 'description', 'is_template']
['name', 'description', 'is_template', 'owner_id', 'usages']
); // Criteria of the default search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
@@ -143,6 +169,15 @@ abstract class Query extends cmdbAbstractObject
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
}
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = [])
{
// read only attribute
if (in_array($sAttCode, ['export_count', 'export_last_date', 'export_last_user_id'])) {
return OPT_ATT_READONLY;
}
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
}
/**
* Return export url.
*
@@ -214,15 +249,15 @@ class QueryOQL extends Query
MetaModel::Init_SetZListItems(
'details',
[
'col:col1' => ['fieldset:Query:baseinfo' => ['name', 'is_template', 'description', 'oql', 'fields']],
'col:col1' => ['fieldset:Query:baseinfo' => ['name', 'is_template', 'owner_id', 'usages', 'description', 'oql', 'fields']],
'col:col2' => ['fieldset:Query:exportInfo' => ['export_count', 'export_last_date', 'export_last_user_id', 'export_last_user_contact']],
]
); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('list', ['description', 'usages']); // Attributes to be displayed for a list
// Search criteria
MetaModel::Init_SetZListItems(
'standard_search',
['name', 'description', 'is_template', 'fields', 'oql']
['name', 'description', 'is_template', 'owner_id', 'usages', 'oql']
); // Criteria of the std search form
}

14
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1cca58a0e26794fb9c546a001f7f7de8",
"content-hash": "24e7507794b971955358df5f2b143ac4",
"packages": [
{
"name": "apereo/phpcas",
@@ -5570,16 +5570,16 @@
},
{
"name": "twig/twig",
"version": "v3.24.0",
"version": "v3.28.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "a6769aefb305efef849dc25c9fd1653358c148f0"
"reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0",
"reference": "a6769aefb305efef849dc25c9fd1653358c148f0",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/597c12ed286fb9d1701a36684ce6e0cbe28ebc8b",
"reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b",
"shasum": ""
},
"require": {
@@ -5634,7 +5634,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.24.0"
"source": "https://github.com/twigphp/Twig/tree/v3.28.0"
},
"funding": [
{
@@ -5646,7 +5646,7 @@
"type": "tidelift"
}
],
"time": "2026-03-17T21:31:11+00:00"
"time": "2026-07-03T20:44:34+00:00"
}
],
"packages-dev": [

View File

@@ -730,13 +730,8 @@ abstract class DBObject implements iDisplay
public function SetTrim($sAttCode, $sValue)
{
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
$iMaxSize = $oAttDef->GetMaxSize();
$sLength = mb_strlen($sValue);
if ($iMaxSize && ($sLength > $iMaxSize)) {
$sMessage = " -truncated ($sLength chars)";
$sValue = mb_substr($sValue, 0, $iMaxSize - mb_strlen($sMessage)).$sMessage;
}
$this->Set($sAttCode, $sValue);
$this->Set($sAttCode, $oAttDef->TrimValue($sValue));
}
/**
@@ -2038,7 +2033,7 @@ abstract class DBObject implements iDisplay
}
}
if (!is_null($iMaxSize = $oAtt->GetMaxSize())) {
$iLen = mb_strlen($toCheck);
$iLen = $oAtt->GetSize($toCheck);
if ($iLen > $iMaxSize) {
return "String too long (found $iLen, limited to $iMaxSize)";
}

View File

@@ -1935,9 +1935,8 @@ class DBObjectSearch extends DBSearch
/**
* @inheritDoc
* @return DBObjectSearch
*/
protected function ApplyDataFilters(): DBObjectSearch
protected function ApplyDataFilters(): DBSearch
{
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
return $this;

View File

@@ -676,9 +676,8 @@ class DBUnionSearch extends DBSearch
/**
* @inheritDoc
* @return DBUnionSearch
*/
protected function ApplyDataFilters(): DBUnionSearch
protected function ApplyDataFilters(): DBSearch
{
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
return $this;

View File

@@ -434,7 +434,7 @@ JS
* Resize an image so that it fits the maximum width/height defined in the config file
* @param ormDocument $oImage The original image stored as an array (content / mimetype / filename)
* @return ormDocument The resampled image (or the original one if it already fit)
* @deprecated since 3.3.0 Replaced by ormDocument::ResizeImageToFit
* @deprecated 3.3.0 Use ormDocument::ResizeImageToFit instead
*/
public static function ResizeImageToFit(ormDocument $oImage, &$aDimensions = null)
{

View File

@@ -614,6 +614,13 @@ class LogChannels
* @since 3.2.0
*/
public const SECURITY = 'Security';
/**
* For Session parameters
*
* @Since 3.3.0
*/
public const SESSION_PARAMETERS = 'SessionParameters';
}
abstract class LogAPI

View File

@@ -5761,36 +5761,37 @@ abstract class MetaModel
self::$m_sEnvironment = $sEnvironment;
try {
if (!defined('MODULESROOT')) {
define('MODULESROOT', APPROOT.'env-'.self::$m_sEnvironment.'/');
if (!defined('MODULESROOT')) {
define('MODULESROOT', APPROOT.'env-'.self::$m_sEnvironment.'/');
self::$m_bTraceSourceFiles = $bTraceSourceFiles;
self::$m_bTraceSourceFiles = $bTraceSourceFiles;
// $config can be either a filename, or a Configuration object (volatile!)
if ($config instanceof Config) {
self::LoadConfig($config, $bAllowCache);
} else {
self::LoadConfig(new Config($config), $bAllowCache);
}
if ($bModelOnly) {
return;
}
// $config can be either a filename, or a Configuration object (volatile!)
if ($config instanceof Config) {
self::LoadConfig($config, $bAllowCache);
} else {
self::LoadConfig(new Config($config), $bAllowCache);
}
CMDBSource::SelectDB(self::$m_sDBName);
foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
$oPHPClass::OnMetaModelStarted();
if ($bModelOnly) {
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
EventService::InitService();
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
return;
}
ExpressionCache::Warmup();
} finally {
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
EventService::InitService();
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
}
CMDBSource::SelectDB(self::$m_sDBName);
foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
$oPHPClass::OnMetaModelStarted();
}
ExpressionCache::Warmup();
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
EventService::InitService();
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
}
/**

View File

@@ -408,7 +408,7 @@ class ormDocument
* @param int $iMaxImageHeight Maximum height for the resized image
* @param array|null $aFinalDimensions Image dimensions after resizing or null if unable to read the image
* @return ormDocument The resampled image
*
* @since 3.3.0 N°3124
*/
public function ResizeImageToFit(int $iMaxWidth, int $iMaxHeight, array|null &$aFinalDimensions = null): static
{

View File

@@ -1530,6 +1530,37 @@ class UserRights
}
}
/**
* @param User $oUser
* @param array $aExcludedProfilesId Administrator by default, but can also be other proofiles depending on needs (e.g. power portal user or REST profile)
* @return bool
* @throws ArchivedObjectException
* @throws CoreException
* @throws CoreUnexpectedValue
* @throws MySQLException
*/
public static function IsUserReadOnly(User $oUser, array $aExcludedProfilesId = [1]): bool
{
$oUserProfiles = $oUser->Get('profile_list');
$oUserRights = UserRights::GetModuleInstance();
while ($oUserProfile = $oUserProfiles->Fetch()) {
$iProfileId = $oUserProfile->Get('profileid');
if (in_array($iProfileId, $aExcludedProfilesId)) {
return false;
}
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) {
foreach (['w', 'bw', 'd', 'bd'] as $sWriteActionCode) {
$bIsGranted = $oUserRights->GetProfileActionGrant($iProfileId, $sClass, $sWriteActionCode);
if ($bIsGranted === true) {
return false;
}
}
}
}
return true;
}
/**
* @param string $sClass
* @param int $iActionCode see UR_ACTION_* constants

View File

@@ -4,7 +4,7 @@
*/
$ibo-user-rights--padding-x: $ibo-spacing-400 !default;
$ibo-user-rights--padding-y: $ibo-spacing-200 !default;
$ibo-user-rights--padding-y: $ibo-spacing-100 !default;
$ibo-user-rights--border-radius: $ibo-border-radius-400 !default;
$ibo-user-rights--is-success--background-color: $ibo-color-success-100 !default;
@@ -18,6 +18,8 @@ $ibo-user-rights--is-failure--border-color: $ibo-color-danger-500 !default;
$ibo-user-rights--is-failure--border: 1px solid $ibo-user-rights--is-failure--border-color !default;
.ibo-user-rights {
display: inline-flex;
align-items: baseline;
padding: $ibo-user-rights--padding-y $ibo-user-rights--padding-x;
border-radius: $ibo-user-rights--border-radius;
&.ibo-is-success {

View File

@@ -19,6 +19,8 @@ $ibo-badge-colors: (
'orange' : ($ibo-color-orange-100, $ibo-color-orange-900),
'red': ($ibo-color-red-100, $ibo-color-red-900),
'pink': ($ibo-color-pink-100, $ibo-color-pink-900),
'purple': ($ibo-color-purple-100, $ibo-color-purple-900),
'yellow': ($ibo-color-yellow-200, $ibo-color-yellow-900),
) !default;

View File

@@ -8,70 +8,74 @@
padding-bottom: 14px;
}
.help-text{
padding: 1px 5px;
background-color: #d7e3f8;
border: 1px solid #c6e7f5;
border-radius: 5px;
margin: 5px 0;
font-size: 0.9em;
}
.form-error ul{
padding: 1px 5px;
background-color: #f8d7da;
border: 1px solid #f5c6cb;
border-radius: 5px;
margin: 5px 0;
font-size: 0.9em;
}
.subform{
background-color: #efefef;
border-radius: 5px;
padding: 10px;
}
.form-buttons{
margin: 20px 0;
}
.form select{
padding: 0;
overflow-y: auto;
}
.form select option{
height: 30px;
display: flex;
align-items: center;
}
.turbo-refreshing{
opacity: .5;
}
.ibo-field legend{
margin-top: 24px;
}
collection-entry-element {
margin-top: 8px;
display: block;
padding: 10px 10px;
background-color: #f5f5f5;
border-radius: 5px;
}
.ts-control{
height: auto;
min-height: 30px;
}
.ibo-form-actions > .ibo-button > span{
margin-right: 5px;
}
.ibo-form textarea{
resize: vertical;
}
// WIP SDK Forms
//form[is="itop-form-element"] {
//
// .help-text{
// padding: 1px 5px;
// background-color: #d7e3f8;
// border: 1px solid #c6e7f5;
// border-radius: 5px;
// margin: 5px 0;
// font-size: 0.9em;
// }
//
// .form-error ul{
// padding: 1px 5px;
// background-color: #f8d7da;
// border: 1px solid #f5c6cb;
// border-radius: 5px;
// margin: 5px 0;
// font-size: 0.9em;
// }
//
// .subform{
// background-color: #efefef;
// border-radius: 5px;
// padding: 10px;
// }
//
// .form-buttons{
// margin: 20px 0;
// }
//
// .form select{
// padding: 0;
// overflow-y: auto;
// }
//
// .form select option{
// height: 30px;
// display: flex;
// align-items: center;
// }
//
// .turbo-refreshing{
// opacity: .5;
// }
//
// .ibo-field legend{
// margin-top: 24px;
// }
//
// collection-entry-element {
// margin-top: 8px;
// display: block;
// padding: 10px 10px;
// background-color: #f5f5f5;
// border-radius: 5px;
// }
// .ts-control{
// height: auto;
// min-height: 30px;
// }
//
// .ibo-form-actions > .ibo-button > span{
// margin-right: 5px;
// }
//
// .ibo-form textarea{
// resize: vertical;
// }
//
//}

View File

@@ -3,9 +3,9 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-input-select-icon--menu--icon--max-height: 100% !default;
$ibo-input-select-icon--menu--icon--max-width: 100% !default;
$ibo-input-select-icon--icon--padding-right: $ibo-spacing-200 !default;
$ibo-input-select-icon--max-height: 100% !default;
$ibo-input-select-icon--max-width: 100% !default;
$ibo-input-select-icon--padding-right: $ibo-spacing-200 !default;
$ibo-input-select-icon--menu--z-index: 21 !default;
$ibo-input-select-icon--menu--max-height: 300px !default;
@@ -18,9 +18,9 @@ $ibo-input-select-icon--menu--icon--margin-right: 10px !default;
display: inline-flex;
text-align: left;
>img{
max-height: $ibo-input-select-icon--menu--icon--max-height;
max-width: $ibo-input-select-icon--menu--icon--max-width;
padding-right: $ibo-input-select-icon--icon--padding-right;
max-height: $ibo-input-select-icon--max-height;
max-width: $ibo-input-select-icon--max-width;
padding-right: $ibo-input-select-icon--padding-right;
}
>span{
overflow: hidden;

View File

@@ -70,7 +70,7 @@ $ibo-vendors-ckeditor--ck-mentions--item--padding-y: $ibo-spacing-200 !default;
}
}
.ck-editor__editable_inline:not(.ck-comment__input *) {
.ck-editor__editable_inline:not(.ck-comment__input *), .ck-source-editing-area {
height: 200px;
}
@@ -84,11 +84,6 @@ $ibo-vendors-ckeditor--ck-mentions--item--padding-y: $ibo-spacing-200 !default;
}
}
// N°7552 Allow source editing area to be scrollable in full screen
.ck-maximize_editor_main .ck-source-editing-area textarea{
overflow: auto !important;
}
/* Mentions */
.ck-mentions {
.ck-button {

View File

@@ -4,7 +4,7 @@
*/
/* SCSS variables */
$common-has-description--content: "\1F6C8" !default;
$common-has-description--content: "?" !default;
$common-has-description--padding-left: $common-spacing-200 !default;
$common-has-description--color: $common-color-grey-600 !default;
$common-has-description--font-size: 0.7em !default; /* Font size is em on purpose as we want it to be proportional to its context */

View File

@@ -11,6 +11,9 @@
*
* Usage: @extend %common-font-size-XXX;
*/
%common-font-size-20 {
font-size: $common-font-size-20;
}
%common-font-size-50 {
font-size: $common-font-size-50;
}

File diff suppressed because one or more lines are too long

View File

@@ -611,32 +611,6 @@ body {
.setup-extension--missing .setup-extension--icon{
color:#a00000;
}
.setup-extension-tag {
display: inline-flex;
background-color: grey;
border-radius: 8px;
padding-left: 3px;
padding-right: 3px;
margin-right: 3px;
&.installed{
background-color:#9eff9e
}
&.notinstalled{
background-color:#ed9eff
}
&.tobeinstalled{
background-color:#9ef0ff
}
&.tobeuninstalled{
background-color:#ff9e9e
}
&.notuninstallable{
background-color:#ffc98c
}
&.removed{
background-color: #969594
}
}
.ibo-extension-details {
align-items: flex-start;

View File

@@ -20,6 +20,7 @@ Dict::Add('EN US', 'English', 'English', [
'DataFeatureRemoval:Features:Title' => 'Extensions',
'DataFeatureRemoval:Result:Title' => 'Modification requested',
'DataFeatureRemoval:NoResult:Title' => 'No modification requested',
'DataFeatureRemoval:Execution:Title' => 'Deletion Executions',
'DataFeatureRemoval:Analysis:Title' => 'Analysis result',
'DataFeatureRemoval:Analysis:Subtitle' => 'Review all elements requiring attention',
@@ -39,6 +40,14 @@ Dict::Add('EN US', 'English', 'English', [
'DataFeatureRemoval:CleanupComplete:Title' => 'All clear.',
'DataFeatureRemoval:CompilComplete' => 'Compilation successful. No Cleanup needed. You can proceed to setup.',
'DataFeatureRemoval:Compile:InProgress' => 'Compilation in progress...',
'DataFeatureRemoval:Compile:Success' => 'Compilation successful',
'DataFeatureRemoval:Compile:Error' => 'Compilation error',
'DataFeatureRemoval:RunAudit:InProgress' => 'Analysis in progress...',
'DataFeatureRemoval:RunAudit:Success' => 'Analysis completed',
'DataFeatureRemoval:RunAudit:Error' => 'Error during analysis',
'UI:Button:Analyze' => 'Analyze',
'UI:Button:ModifyChoices' => 'Change my selection',
'UI:Button:AnalyzeAndSetup' => 'Analyze and go to setup',

View File

@@ -20,6 +20,7 @@ Dict::Add('FR FR', 'French', 'Français', [
'DataFeatureRemoval:Features:Title' => 'Extensions',
'DataFeatureRemoval:Result:Title' => 'Modification demandée',
'DataFeatureRemoval:NoResult:Title' => 'Aucune modification demandée',
'DataFeatureRemoval:Execution:Title' => 'Suppressions',
'DataFeatureRemoval:Analysis:Title' => 'Résultat de lanalyse',
'DataFeatureRemoval:Analysis:Subtitle' => 'Vérifier les éléments à nettoyer',
@@ -39,6 +40,14 @@ Dict::Add('FR FR', 'French', 'Français', [
'DataFeatureRemoval:CleanupComplete:Title' => 'All clear.',
'DataFeatureRemoval:CompilComplete' => 'Compilation successful. No Cleanup needed. You can proceed to setup.',
'DataFeatureRemoval:Compile:InProgress' => 'Compilation en cours...',
'DataFeatureRemoval:Compile:Success' => 'Compilation terminée',
'DataFeatureRemoval:Compile:Error' => 'Erreur lors de la compilation',
'DataFeatureRemoval:RunAudit:InProgress' => 'Analyse en cours...',
'DataFeatureRemoval:RunAudit:Success' => 'Analyse terminée',
'DataFeatureRemoval:RunAudit:Error' => 'Erreur lors de l\'analyse',
'UI:Button:Analyze' => 'Analyser',
'UI:Button:ModifyChoices' => 'Modifier la sélection',
'UI:Button:AnalyzeAndSetup' => 'Analyser et ouvrir lassistant de configuration',

View File

@@ -8,7 +8,6 @@
namespace Combodo\iTop\DataFeatureRemoval\Controller;
require_once APPROOT.'setup/feature_removal/SetupAudit.php';
require_once APPROOT.'setup/feature_removal/DryRemovalRuntimeEnvironment.php';
use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Application\TwigBase\Controller\Controller;
@@ -19,7 +18,7 @@ use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService;
use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService;
use Combodo\iTop\DataFeatureRemoval\Service\StaticDeletionPlan;
use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment;
use Combodo\iTop\Service\Session\SessionParameters;
use Combodo\iTop\Setup\FeatureRemoval\SetupAudit;
use ContextTag;
use CoreException;
@@ -38,15 +37,22 @@ class DataFeatureRemovalController extends Controller
private array $aCountClassesToCleanup = [];
private array $aAnalysisDataTable = [];
private array $aDeletionExecutionSummary = [];
private ?RuntimeEnvironment $oRuntimeEnvironment = null;
private int $iCount = 0;
private int $iColumnCount = 2;
private RunTimeEnvironment $oRuntimeEnvironment;
public function OperationMain($sErrorMessage = null): void
{
$aParams = [];
SetupUtils::EraseSetupToken();
$oParameters = new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME);
$oParameters->Erase();
Session::Unset('aDeletionExecutionSummary');
Session::Set('bForceCompilation', true);
$oParameters->SetParameter('return_application', 'DataFeatureRemoval');
$this->AddAnalyzeParams();
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['iColumnCount'] = $this->iColumnCount;
@@ -58,7 +64,6 @@ class DataFeatureRemovalController extends Controller
$aParams['sSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup';
$aParams['iCount'] = $this->iCount;
Session::Set('bForceCompilation', true);
$this->AddLinkedStylesheet(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/css/DataFeatureRemoval.css');
$this->AddLinkedScript(utils::GetAbsoluteUrlModulesRoot().DataFeatureRemovalHelper::MODULE_NAME.'/assets/js/DataFeatureRemoval.js');
$this->DisplayPage($aParams);
@@ -92,7 +97,7 @@ class DataFeatureRemovalController extends Controller
}
// Display changed extensions
$aHiddenInputNames = [
$aSetupParameterNames = [
'selected_extensions' => '[]',
'selected_modules' => '[]',
'display_choices' => '',
@@ -106,91 +111,38 @@ class DataFeatureRemovalController extends Controller
'target_env' => ITOP_DEFAULT_ENV,
];
$aHiddenInputs = [];
foreach ($aHiddenInputNames as $sInputName => $defaultValue) {
$aHiddenInputs[$sInputName] = utils::ReadPostedParam($sInputName, $defaultValue, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
$oParameters = new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME);
foreach ($aSetupParameterNames as $sInputName => $defaultValue) {
$oParameters->SetParameter($sInputName, $oParameters->GetParameter($sInputName, $defaultValue));
}
$aParams['aHiddenInputs'] = $aHiddenInputs;
$aAddedExtensions = json_decode($aHiddenInputs['added_extensions'], true);
$aRemovedExtensions = json_decode($aHiddenInputs['removed_extensions'], true);
if ("[]" === $aHiddenInputs['selected_modules']) {
$aAddedExtensions = json_decode($oParameters->GetParameter('added_extensions', '[]'), true);
$aRemovedExtensions = json_decode($oParameters->GetParameter('removed_extensions', '[]'), true);
if ('[]' === $oParameters->GetParameter('selected_modules', '[]')) {
//it does not come from setup
// we get extensions from 1st screen uiblocks
$this->ReadExtensionsDiff();
$aHiddenInputs['force-uninstall'] = $this->bForcedUninstallation ? 'on' : '';
$oParameters->SetParameter('force-uninstall', $this->bForcedUninstallation ? 'on' : '');
$aAddedExtensions = $this->aExtensionsToCheck['to_be_installed'];
$aHiddenInputs['added_extensions'] = $this->ConvertIntoSetupFormat($aAddedExtensions);
$oParameters->SetParameter('added_extensions', $this->ConvertIntoSetupFormat($aAddedExtensions));
$aRemovedExtensions = $this->aExtensionsToCheck['to_be_removed'];
$aHiddenInputs['removed_extensions'] = $this->ConvertIntoSetupFormat($aRemovedExtensions);
$oParameters->SetParameter('removed_extensions', $this->ConvertIntoSetupFormat($aRemovedExtensions));
$aExtensionsNotUninstallable = $this->aExtensionsToCheck['extensions_not_uninstallable'];
$oParameters->SetParameter('extensions_not_uninstallable', $this->ConvertIntoSetupFormat($aExtensionsNotUninstallable));
}
$aRemoveExtensionCodes = array_keys($aRemovedExtensions);
$aParams['aAddedExtensions'] = $aAddedExtensions;
$aParams['aRemovedExtensions'] = $aRemovedExtensions;
DataFeatureRemovalLog::Debug(__METHOD__.' Extensions given in parameter', null, [
'added_extensions' => $aAddedExtensions,
'removed_extensions' => $aRemovedExtensions]);
$aParams['sTransactionId'] = utils::GetNewTransactionId();
$aParams['iColumnCount'] = $this->iColumnCount;
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetExtensionsDiff($aAddedExtensions, $aRemovedExtensions), $this->iColumnCount);
$bForceCompilation = Session::Get('bForceCompilation', false);
try {
$this->Compile($aAddedExtensions, $aRemoveExtensionCodes, $bForceCompilation);
} catch (CoreException $e) {
$aParams['DataFeatureRemovalErrorMessage'] = $e->getHtmlDesc();
$this->DisplayPage($aParams, 'AnalysisResult');
return;
} catch (Exception $e) {
$aParams['DataFeatureRemovalErrorMessage'] = $e->getMessage();
$this->DisplayPage($aParams, 'AnalysisResult');
return;
}
if ("[]" === $aHiddenInputs['selected_modules']) {
//to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists)
$oConfig = MetaModel::GetConfig();
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions));
$aHiddenInputs['selected_extensions'] = $this->ConvertIntoSetupFormat($aSelectedExtensions);
$oRunTimeEnvironment = $this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions);
$aSearchDirs = [$oRunTimeEnvironment->GetBuildDir()];
$aSelectedModules = $oRunTimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions, $aSearchDirs);
$aHiddenInputs['selected_modules'] = $this->ConvertIntoSetupFormat($aSelectedModules);
}
$sSourceEnv = MetaModel::GetEnvironment();
$oSetupAudit = new SetupAudit($sSourceEnv);
$aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
DataFeatureRemovalLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]);
$aParams['aClasses'] = $aGetRemovedClasses;
new ContextTag(ContextTag::TAG_SETUP);
$aParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php';
$aParams['aSetupParams'] = [
"_class" => "WizStepLandingBeforeAudit",
"operation" => "next",
];
foreach ($aHiddenInputs as $sInputName => $sInputValue) {
$aParams['aSetupParams']["_params[$sInputName]"] = $sInputValue;
}
[$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses);
[$aParams['aDeletionExecutionSummary'], $aParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable();
$aParams['bDeletionNeeded'] = ($aParams['iQueryCount'] > 0);
Session::Set('aDeletionExecutionSummary', serialize($this->aDeletionExecutionSummary));
if (!$aParams['bDeletionNeeded']) {
SetupUtils::CreateSetupToken();
}
$aAvailableExtensions = $this->GetExtensionsDiff($aAddedExtensions, $aRemovedExtensions);
$aParams['aAvailableExtensionsCount'] = count($aAvailableExtensions);
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($aAvailableExtensions, $this->iColumnCount);
$aParams['sAjaxURL'] = utils::GetAbsoluteUrlModulePage(DataFeatureRemovalHelper::MODULE_NAME, 'index.php');
$this->DisplayPage($aParams, 'AnalysisResult');
}
@@ -198,54 +150,124 @@ class DataFeatureRemovalController extends Controller
private function ConvertIntoSetupFormat(array $aData): string
{
$aNewData = [];
foreach ($aData as $k => $sVal) {
$aNewData[] = sprintf('"%s":"%s"', $k, $sVal);
foreach ($aData as $sCode => $sLabel) {
$aNewData[] = sprintf('"%s":"%s"', $sCode, $sLabel);
}
return "{".implode(',', $aNewData)."}";
}
/**
* @param array $aAddedExtensions
* @param array $aRemovedExtensions
* @param bool $bForceCompilation
* @return void
* @throws \ConfigException
* @throws \CoreException
* @return void
* @throws \ConfigException
* @throws \CoreException
*/
private function Compile(array $aAddedExtensions, array $aRemovedExtensions, bool $bForceCompilation = true): void
public function OperationAjaxCompile(): void
{
$aParams = [];
//to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists)
$sSourceEnv = MetaModel::GetEnvironment();
$sBuildDir = APPROOT."/env-$sSourceEnv-build";
if (! is_dir($sBuildDir)) {
SetupUtils::builddir($sBuildDir);
}
$bIsDirEmpty = count(scandir($sBuildDir)) === 2;
$oRuntimeEnvironment = new RunTimeEnvironment($sSourceEnv, false);
if ($bIsDirEmpty || $bForceCompilation) {
Session::Unset('bForceCompilation');
DataFeatureRemovalLog::Debug(
__METHOD__,
null,
['sSourceEnv' => $sSourceEnv, 'sBuildDir' => $sBuildDir, 'bIsDirEmpty' => $bIsDirEmpty, glob("$sBuildDir/*")]
);
$this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions)->CompileFrom($sSourceEnv);
$oParameters = new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME);
$aSelectedModules = json_decode($oParameters->GetParameter('selected_modules', '[]'), true);
$aSelectedExtensions = json_decode($oParameters->GetParameter('selected_extensions', '[]'), true);
$aAddedExtensions = json_decode($oParameters->GetParameter('added_extensions', '[]'), true);
$aRemovedExtensions = json_decode($oParameters->GetParameter('removed_extensions', '[]'), true);
try {
$this->ValidateTransactionId();
$oConfig = MetaModel::GetConfig();
if (count($aSelectedModules) === 0) {
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions));
$oParameters->SetParameter('selected_extensions', $this->ConvertIntoSetupFormat($aSelectedExtensions));
}
$sBuildDir = APPROOT."/env-$sSourceEnv-build";
if (! is_dir($sBuildDir)) {
SetupUtils::builddir($sBuildDir);
}
$bIsDirEmpty = count(scandir($sBuildDir)) === 2;
$bForceCompilation = Session::Get('bForceCompilation', false);
if ($bIsDirEmpty || $bForceCompilation) {
$oRuntimeEnvironment->CopySetupFiles();
if (count($aSelectedModules) === 0) {
$aSelectedModules = $oRuntimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions);
}
DataFeatureRemovalLog::Debug(
__METHOD__,
null,
['sSourceEnv' => $sSourceEnv, 'sBuildDir' => $sBuildDir, 'bIsDirEmpty' => $bIsDirEmpty, glob("$sBuildDir/*")]
);
$oRuntimeEnvironment->DoCompile($aSelectedExtensions, $aRemovedExtensions, $aSelectedModules, MFCompiler::CanUseSymbolicLinks());
Session::Unset('bForceCompilation');
} else {
if (count($aSelectedModules) === 0) {
$aSelectedModules = $oRuntimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions);
}
}
} catch (CoreException $e) {
$aParams['error_message'] = $e->getHtmlDesc();
} catch (Exception $e) {
$aParams['error_message'] = $e->getMessage();
}
$aParams['success_message'] = Dict::S('DataFeatureRemoval:Compile:Success');
$aParams['transaction_id'] = utils::GetNewTransactionId();
$oParameters->SetParameter('selected_modules', json_encode($aSelectedModules));
$this->DisplayJSONPage($aParams);
}
private function GetRuntimeEnvironment(array $aAddedExtensions, array $aRemovedExtensions): RunTimeEnvironment
public function OperationAjaxRunAudit(): void
{
if (is_null($this->oRuntimeEnvironment)) {
$oParameters = new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME);
$aParams = [];
$aPageParams = [];
try {
$this->ValidateTransactionId();
$sSourceEnv = MetaModel::GetEnvironment();
$this->oRuntimeEnvironment = new DryRemovalRuntimeEnvironment($sSourceEnv, $aAddedExtensions, $aRemovedExtensions);
$oSetupAudit = new SetupAudit($sSourceEnv);
$aRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
$oParameters->SetParameter('classes', $aRemovedClasses);
new ContextTag(ContextTag::TAG_SETUP);
$aPageParams['sLaunchSetupUrl'] = utils::GetAbsoluteUrlAppRoot().'setup/wizard.php';
$aPageParams['aSetupParams'] = [
"_class" => "WizStepLandingBeforeAudit",
"operation" => "next",
];
$aPageParams['sTransactionId'] = utils::GetNewTransactionId();
$aDeletionPlanSummaryEntities = $this->GetDeletionPlanSummaryEntities($aRemovedClasses);
[$aPageParams['aDeletionPlanSummary'], $aPageParams['iQueryCount'], $aPageParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aDeletionPlanSummaryEntities);
[$aPageParams['aDeletionExecutionSummary'], $aPageParams['bHasDeletionExecution']] = $this->GetExecutionSummaryTable();
$aPageParams['bDeletionNeeded'] = ($aPageParams['iQueryCount'] > 0);
if (!$aPageParams['bDeletionNeeded']) {
// Erase session setup parameters
SetupUtils::CreateSetupToken();
}
$this->DisplayAjaxPage($aPageParams, 'AjaxRunAudit');
return;
} catch (CoreException $e) {
$aParams['error_message'] = $e->getHtmlDesc();
} catch (Exception $e) {
$aParams['error_message'] = $e->getMessage();
}
return $this->oRuntimeEnvironment;
$this->DisplayJSONPage($aParams);
}
private function GetExecutionSummaryTable(): array
{
$sName = 'ExcutionSummary';
$sName = 'ExecutionSummary';
$this->aDeletionExecutionSummary = unserialize(Session::Get('aDeletionExecutionSummary') ?? serialize([]));
$aTableData = [];
if (count($this->aDeletionExecutionSummary) === 0) {
@@ -271,11 +293,15 @@ class DataFeatureRemovalController extends Controller
}
private function GetDeletionPlanSummaryTable(array $aRemovedClasses): array
private function GetDeletionPlanSummaryEntities(array $aRemovedClasses): array
{
$oDataCleanupService = new StaticDeletionPlan();
return $oDataCleanupService->GetCleanupSummary($aRemovedClasses);
}
private function GetDeletionPlanSummaryTable(array $aDeletionPlanSummaryEntities): array
{
$sName = 'DeletionPlanSummary';
$oDataCleanupService = new StaticDeletionPlan();
$aDeletionPlanSummaryEntities = $oDataCleanupService->GetCleanupSummary($aRemovedClasses);
$aColumns = ['Class', 'Delete Count' , 'Update Count', 'Issue Count'];
$aRows = [];
$iQueryCount = 0;
@@ -298,9 +324,10 @@ class DataFeatureRemovalController extends Controller
{
$this->ValidateTransactionId();
$this->aDeletionExecutionSummary = unserialize(Session::Get('aDeletionExecutionSummary'));
$this->aDeletionExecutionSummary = unserialize(Session::Get('aDeletionExecutionSummary') ?? serialize([]));
Session::Unset('aDeletionExecutionSummary');
$aClasses = utils::ReadPostedParam('classes', null, utils::ENUM_SANITIZATION_FILTER_CLASS);
$oParameters = new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME);
$aClasses = $oParameters->GetParameter('classes', []);
$oDataCleanupService = new DataCleanupService();
$aDeletionExecutionSummary = $oDataCleanupService->ExecuteCleanup($aClasses);
@@ -315,6 +342,7 @@ class DataFeatureRemovalController extends Controller
$oSummary->iTotalUpdateCount += $oExecutionSummary->iUpdateCount;
}
Session::Set('aDeletionExecutionSummary', serialize($this->aDeletionExecutionSummary));
$this->OperationAnalysisResult();
}
@@ -340,6 +368,7 @@ class DataFeatureRemovalController extends Controller
'uninstallable' => $oExtension->CanBeUninstalled(),
'remote' => $oExtension->IsRemote(),
'missing' => $oExtension->bRemovedFromDisk,
'dependency_issue' => $oExtension->HasDependencyIssue(),
],
];
@@ -407,12 +436,11 @@ class DataFeatureRemovalController extends Controller
/**
* Read extensions selected from posted parameters
* @return int Number of extensions to be added or removed
*/
public function ReadExtensionsDiff(): int
public function ReadExtensionsDiff(): void
{
if (!is_null($this->aExtensionsToCheck)) {
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
return;
}
$aAvailableExtensions = $this->GetAvailableExtensions();
@@ -420,6 +448,7 @@ class DataFeatureRemovalController extends Controller
$this->aExtensionsToCheck = [
'to_be_installed' => [],
'to_be_removed' => [],
'extensions_not_uninstallable' => [],
];
foreach ($aAvailableExtensions as $sCode => &$aExtensionData) {
if (!isset($aSelectedExtensionsFromUI[$sCode])) {
@@ -433,13 +462,15 @@ class DataFeatureRemovalController extends Controller
if (! $this->bForcedUninstallation && $aExtensionData['extra_flags']['uninstallable']) {
$this->bForcedUninstallation = true;
}
if (false === $aExtensionData['extra_flags']['uninstallable'] || true === $aExtensionData['extra_flags']['remote']) {
$this->aExtensionsToCheck['extensions_not_uninstallable'][] = $sCode;
}
} elseif (!$aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] === 'on') {
$aExtensionData['extra_flags']['selected'] = true;
$sLabel = $aAvailableExtensions[$sCode]['label'];
$this->aExtensionsToCheck['to_be_installed'][$sCode] = $sLabel;
}
}
return count($this->aExtensionsToCheck['to_be_installed']) + count($this->aExtensionsToCheck['to_be_removed']);
}
/**

View File

@@ -7,31 +7,22 @@
namespace Combodo\iTop\DataFeatureRemoval\Entity;
use MetaModel;
class DeletionPlanEntity
{
public readonly DeletionPlanItem $oDelete;
public readonly DeletionPlanItem $oUpdate;
public readonly DeletionPlanItem $oIssue;
public array $aQueriesForTempTable;
public array $aDependsOnTempTable;
public string $sClass;
/**
* @param \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem $oDelete
* @param \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem $oUpdate
* @param \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem $oIssue
*/
public function __construct(string $sClass)
public function __construct()
{
$this->sClass = $sClass;
$this->oDelete = $oDelete ?? new DeletionPlanItem();
$this->oUpdate = $oUpdate ?? new DeletionPlanItem();
$this->oIssue = $oIssue ?? new DeletionPlanItem();
$this->aQueriesForTempTable = [];
$this->aDependsOnTempTable = [];
}
public function TotalCount(): int
@@ -43,20 +34,4 @@ class DeletionPlanEntity
{
$this->oUpdate->FilterBy($this->oDelete);
}
public function AddQueryForTempTable(string $sQuery, ?string $sTempTableName = null): void
{
if (!in_array($sQuery, $this->aQueriesForTempTable)) {
$this->aQueriesForTempTable[] = $sQuery;
if (!is_null($sTempTableName) && !in_array($sTempTableName, $this->aDependsOnTempTable)) {
$this->aDependsOnTempTable[] = $sTempTableName;
}
}
}
public static function GetTempTableName(string $sClass): string
{
$sRootClass = MetaModel::GetRootClass($sClass);
return 'temp_'.MetaModel::DBGetTable($sRootClass);
}
}

View File

@@ -134,10 +134,6 @@ class DataCleanupService
/** @var DBObject $oDependentObj */
while ($oDependentObj = $oSet->Fetch()) {
$iDeletePropagationOption = $oExtKeyAttDef->GetDeletionPropagationOption();
if ($iDeletePropagationOption == DEL_MANUAL) {
$this->oObjectService->SetIssue(get_class($oDependentObj));
continue;
}
if ($oExtKeyAttDef->IsNullAllowed()) {
// Optional external key, list to reset
@@ -152,6 +148,12 @@ class DataCleanupService
return false;
}
} else {
// Mandatory external key
if ($iDeletePropagationOption == DEL_MANUAL) {
// Cannot be deleted automatically, must be handled manually
$this->oObjectService->SetIssue(get_class($oDependentObj));
continue;
}
// Propagate deletion only if not visited
if ($this->IsVisited($oDependentObj)) {
continue;

View File

@@ -7,7 +7,6 @@
namespace Combodo\iTop\DataFeatureRemoval\Service;
use AttributeExternalKey;
use CMDBSource;
use Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity;
use Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanEntity;
@@ -49,70 +48,6 @@ class StaticDeletionPlan
return $aSummary;
}
public function GetTempTableDefinitions(array $aClasses): array
{
$aTempTables = [];
$aDeletionPlan = $this->GetStaticDeletionPlan($aClasses ?? []);
foreach ($aDeletionPlan as $sClass => $oDeletionPlanEntity) {
$sTempTableName = DeletionPlanEntity::GetTempTableName($sClass);
$aTempTables[$sTempTableName]['name'] = $sTempTableName;
$aTempTables[$sTempTableName]['queries'] = array_unique(array_merge($aTempTables[$sTempTableName]['queries'] ?? [], $oDeletionPlanEntity->aQueriesForTempTable));
$aTempTables[$sTempTableName]['depends_on'] = array_unique(array_merge($aTempTables[$sTempTableName]['depends_on'] ?? [], $oDeletionPlanEntity->aDependsOnTempTable));
}
usort($aTempTables, function ($a, $b) use ($aTempTables) {
if (empty($a['depends_on']) && empty($b['depends_on'])) {
// Both initial classes
return 0;
}
return $this->CompareEntries($a, $b, $aTempTables);
});
$aTableDefinitions = [];
foreach ($aTempTables as $aTempTable) {
if (count($aTempTable['queries']) > 0) {
$TempTableSelect = implode("\nUNION\n", $aTempTable['queries']);
$sTempTableName = $aTempTable['name'];
$aTableDefinitions[$sTempTableName] = [
"DROP TEMPORARY TABLE IF EXISTS `$sTempTableName`",
"CREATE TEMPORARY TABLE `$sTempTableName` ($TempTableSelect)",
];
}
}
return $aTableDefinitions;
}
/**
* tells if name1 depends on name2
* @param string $sName1
* @param string $sName2
* @param array $aAllTables
*
* @return bool
*/
private function DependsOn(string $sName1, string $sName2, array $aAllTables): bool
{
$aDependsOn = $aAllTables[$sName1]['depends_on'] ?? [];
if (in_array($sName2, $aDependsOn)) {
return true;
}
// Search on step further
foreach ($aAllTables[$sName1]['depends_on'] as $sParent) {
if ($this->DependsOn($sParent, $sName2, $aAllTables)) {
return true;
}
}
return false;
}
public function CompareEntries(array $aTable1, array $aTable2, array $aAllTables): int
{
return $this->DependsOn($aTable1['name'], $aTable2['name'], $aAllTables) ? 1 : -1;
}
/**
* @param array $aClasses Classes to clean entirely
*
@@ -124,10 +59,11 @@ class StaticDeletionPlan
{
foreach ($aClasses as $sClass) {
$oDeletionPlanItem = $this->GetInitialClassDeletionPlan($sClass);
$oDeletionPlanEntity = new DeletionPlanEntity($sClass);
$oDeletionPlanEntity->oDelete->Merge($oDeletionPlanItem);
$oDeletionPlanEntity->AddQueryForTempTable($this->GetQueryForInitialClass($sClass));
$this->aDeletionPlan[$sClass] = $oDeletionPlanEntity;
// N°9831 Do not overwrite existing entity as it may already exist for this class if a previously processed class references it (issues/updates already accumulated must be kept)
if (false === array_key_exists($sClass, $this->aDeletionPlan)) {
$this->aDeletionPlan[$sClass] = new DeletionPlanEntity();
}
$this->aDeletionPlan[$sClass]->oDelete->Merge($oDeletionPlanItem);
$this->DeletionPlanForReferencingClasses($sClass);
}
@@ -141,7 +77,7 @@ class StaticDeletionPlan
$aReferencingMe = MetaModel::EnumReferencingClasses($sClass);
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
if (!isset($this->aDeletionPlan[$sRemoteClass])) {
$this->aDeletionPlan[$sRemoteClass] = new DeletionPlanEntity($sRemoteClass);
$this->aDeletionPlan[$sRemoteClass] = new DeletionPlanEntity();
}
$oDeletionPlanEntity = $this->aDeletionPlan[$sRemoteClass];
/** @var \AttributeExternalKey $oExtKeyAttDef */
@@ -162,7 +98,7 @@ class StaticDeletionPlan
$iDeletePropagationOption = $oExtKeyAttDef->GetDeletionPropagationOption();
if ($iDeletePropagationOption == DEL_MANUAL) {
// Issue, do not recurse
$oDeletionPlanItem = new DeletionPlanItem($aRemoteIdsToRemove);
$oDeletionPlanItem = new DeletionPlanItem(aIds: $aRemoteIdsToRemove);
$oDeletionPlanEntity->oIssue->Merge($oDeletionPlanItem);
continue;
}
@@ -172,16 +108,14 @@ class StaticDeletionPlan
$sTargetIdsToRemove = implode(',', $this->aDeletionPlan[$sRemoteClass]->oDelete->aIds);
$oUpdateItem = $this->UpdateHierarchicalExtKey($sRemoteClass, $sExtKeyAttCode, $sTargetIdsToRemove);
$oDeletionPlanEntity->oUpdate->Merge($oUpdateItem);
// Delete current entry an recurse !
}
// Delete entries in Remote Class
[$sQueryForTempTable, $sDependsOnTempTable] = $this->GetQueryForExtKey($sRemoteClass, $oExtKeyAttDef);
$oDeletionPlanEntity->AddQueryForTempTable($sQueryForTempTable, $sDependsOnTempTable);
$oDeletionPlanEntity->oDelete->Merge(new DeletionPlanItem($aRemoteIdsToRemove));
// Infinite loops do not occurs due to the datamodel structure
$this->DeletionPlanForReferencingClasses($sRemoteClass);
if (count($aRemoteIdsToRemove) !== 0) {
$oDeletionPlanEntity->oDelete->Merge(new DeletionPlanItem($aRemoteIdsToRemove));
// Infinite loops do not occurs due to the datamodel structure
$this->DeletionPlanForReferencingClasses($sRemoteClass);
}
}
}
}
@@ -213,12 +147,12 @@ class StaticDeletionPlan
*/
public function UpdateHierarchicalExtKey(string $sRemoteClass, string $sExtKeyAttCode, string $sIdsToRemoveInTargetClass): DeletionPlanItem
{
[$sDBTable, $sDBKey, $sDBField] = $this->GetDBInfo($sRemoteClass, $sExtKeyAttCode);
[$sDBTable, $sDBField, $sDBKey] = $this->GetDBInfoForAttcode($sRemoteClass, $sExtKeyAttCode);
$sSQL = <<<SQL
SELECT `$sDBKey`
FROM `$sDBTable` AS `updated`
INNER JOIN `$sDBTable` AS `removed` ON `updated`.`$sDBField` = `removed`.`$sDBField`
INNER JOIN `$sDBTable` AS `removed` ON `updated`.`$sDBField` = `removed`.`$sDBKey`
WHERE `removed`.`$sDBKey` IN ($sIdsToRemoveInTargetClass)
SQL;
$aIds = CMDBSource::QueryToCol($sSQL, $sDBKey);
@@ -240,10 +174,10 @@ SQL;
if (\utils::IsNullOrEmptyString($sIdsToRemoveInTargetClass)) {
return [];
}
[$sDBTable, $sDBKey, $sDBField] = $this->GetDBInfo($sRemoteClass, $sExtKeyAttCode);
$sSQL = "SELECT `$sDBKey` AS id FROM `$sDBTable` WHERE `$sDBField` IN ($sIdsToRemoveInTargetClass)";
[$sDBTable, $sDBField, $sDBKey] = $this->GetDBInfoForAttcode($sRemoteClass, $sExtKeyAttCode);
$sSQL = "SELECT `$sDBKey` FROM `$sDBTable` WHERE `$sDBField` IN ($sIdsToRemoveInTargetClass)";
return CMDBSource::QueryToCol($sSQL, 'id');
return CMDBSource::QueryToCol($sSQL, $sDBKey);
}
/**
@@ -255,9 +189,9 @@ SQL;
*/
public function GetInitialClassDeletionPlan(string $sClass): DeletionPlanItem
{
[$sDBTable, $sDBKey] = $this->GetDBInfo($sClass);
$sSQL = "SELECT `$sDBKey` FROM `$sDBTable`";
$sTable = MetaModel::DBGetTable($sClass);
$sDBKey = MetaModel::DBGetKey($sClass);
$sSQL = "SELECT `$sDBKey` FROM `$sTable`";
$aIds = CMDBSource::QueryToCol($sSQL, $sDBKey);
return new DeletionPlanItem($aIds);
@@ -273,47 +207,15 @@ SQL;
* @throws \CoreException
* @throws \Exception
*/
public function GetDBInfo(string $sClass, ?string $sExtKeyAttCode = null): array
public function GetDBInfoForAttcode(string $sClass, string $sExtKeyAttCode): array
{
if (!is_null($sExtKeyAttCode)) {
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sExtKeyAttCode);
$sDBTable = MetaModel::DBGetTable($sOriginClass);
$sDBKey = MetaModel::DBGetKey($sOriginClass);
$oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sExtKeyAttCode);
// External key is on a single DB column
$sDBField = array_keys($oAttDef->GetSQLColumns())[0];
return [$sDBTable, $sDBKey, $sDBField];
}
$sDBTable = MetaModel::DBGetTable($sClass);
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sExtKeyAttCode);
$sDBTable = MetaModel::DBGetTable($sOriginClass);
$oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sExtKeyAttCode);
// External key is on a single DB column
$sDBField = array_keys($oAttDef->GetSQLColumns())[0];
$sDBKey = MetaModel::DBGetKey($sClass);
return [$sDBTable, $sDBKey];
return [$sDBTable, $sDBField, $sDBKey];
}
private function GetQueryForInitialClass(mixed $sClass): string
{
[$sDBTable, $sDBKey] = $this->GetDBInfo($sClass);
return "SELECT `$sDBKey` AS id FROM `$sDBTable`";
}
private function GetQueryForExtKey(string $sClass, AttributeExternalKey $oExtKeyAttDef)
{
$sExtKeyAttCode = $oExtKeyAttDef->GetCode();
[$sDBTable, $sDBKey, $sDBField] = $this->GetDBInfo($sClass, $sExtKeyAttCode);
$sTargetClass = $oExtKeyAttDef->GetTargetClass();
$sTempTable = DeletionPlanEntity::GetTempTableName($sTargetClass);
$sQuery = <<<SQL
SELECT `$sDBTable`.`$sDBKey` AS id FROM `$sDBTable`
INNER JOIN `$sTempTable` ON `$sTempTable`.`id` = `$sDBTable`.`$sDBField`
SQL;
return [$sQuery, $sTempTable];
}
}

View File

@@ -0,0 +1,34 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% if bDeletionNeeded %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:DeletionPlan:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% if bDeletionPossible %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% else %}
{% UIAlert ForFailure { sTitle: '', sContent: 'DataFeatureRemoval:DeletionPlan:Error:Issues'|dict_s } %}{% EndUIAlert %}
{% endif %}
{% else %}
{% UIAlert ForSuccess { sTitle:'DataFeatureRemoval:CleanupComplete:Title'|dict_s, sContent:'DataFeatureRemoval:CompilComplete'|dict_s } %}{% EndUIAlert %}
{% UIForm Standard {sId:'launch-setup-form', Action:sLaunchSetupUrl, EncType: 'application/x-www-form-urlencoded'} %}
{% for sKey, sValue in aSetupParams %}
{% UIInput ForHidden { sName:sKey, sValue:sValue } %}
{% endfor %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Setup'|dict_s, sName:'btn_setup', sId:'btn_setup', bIsSubmit:true} %}
{% EndUIForm %}
{% endif %}
{% if bHasDeletionExecution %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Execution:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionExecutionSummary', aColumns:aDeletionExecutionSummary.Columns, aData:aDeletionExecutionSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% endif %}

View File

@@ -1,15 +1,31 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
{% UIPanel ForInformation { sTitle:'DataFeatureRemoval:Analysis:Title'|dict_s, sSubTitle: 'DataFeatureRemoval:Analysis:Subtitle'|dict_s} %}
{% if null != DataFeatureRemovalErrorMessage %}
<div id="feature_removal_error_msg_div" style="display:block">
{% UIAlert ForFailure { sTitle:'DataFeatureRemoval:Failure:Title'|dict_s, sId: 'feature_removal_error_msg', sContent:DataFeatureRemovalErrorMessage } %}
{% EndUIAlert %}
</div>
{% endif %}
{% UIAlert ForInformation { sTitle: '', sId: 'ajax_compile_in_progress_msg', AddCSSClasses: ['ibo-is-hidden', 'ibo-is-html-content'] } %}
{{ 'DataFeatureRemoval:Compile:InProgress'|dict_s }}
{% UISpinner Standard { } %}
{% EndUIAlert %}
{% UIAlert ForSuccess { sTitle:'success', sId: 'ajax_compile_success_msg', AddCSSClasses: ['ibo-is-hidden', 'ibo-is-html-content'] } %}{% EndUIAlert %}
{% UIAlert ForFailure { sTitle:'error', sId: 'ajax_compile_error_msg', AddCSSClasses: ['ibo-is-hidden', 'ibo-is-html-content'] } %}{% EndUIAlert %}
{% UIAlert ForInformation { sTitle: '', sId: 'ajax_run_audit_in_progress_msg', AddCSSClasses: ['ibo-is-hidden', 'ibo-is-html-content'] } %}
{{ 'DataFeatureRemoval:RunAudit:InProgress'|dict_s }}
{% UISpinner Standard { } %}
{% EndUIAlert %}
{% UIAlert ForSuccess { sTitle:'DataFeatureRemoval:RunAudit:Success'|dict_s, sId: 'ajax_run_audit_success_msg', AddCSSClasses: ['ibo-is-hidden', 'ibo-is-html-content'] } %}{% EndUIAlert %}
{% UIAlert ForFailure { sTitle:'error', sId: 'ajax_run_audit_error_msg', AddCSSClasses: ['ibo-is-hidden', 'ibo-is-html-content'] } %}{% EndUIAlert %}
{% if aAvailableExtensionsCount == 0 %}
{% UITitle Neutral { sTitle:'DataFeatureRemoval:NoResult:Title'|dict_s, iLevel:2 } %}{% EndUITitle %}
{% else %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Result:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
@@ -25,68 +41,10 @@
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}
{% else %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Result:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}
{% for iColumnIndex in 0..iColumnCount-1 %}
{% UIColumn Standard {} %}
{% for aExtension in aAvailableExtensions[iColumnIndex] %}
{% if aExtension['installed'] %}
{% UIExtensionDetails Installed { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% else %}
{% UIExtensionDetails NotInstalled { sCode : aExtension['code'], sLabel : aExtension['label'], sDescription : aExtension['description'], aMetaData : [aExtension['version'], aExtension['source']], aExtraFlags : aExtension['extra_flags']} %}{% EndUIExtensionDetails %}
{% endif %}
{% endfor %}
{% EndUIColumn %}
{% endfor %}
{% EndUIMultiColumn %}
{% EndUIPanel %}
{% if bDeletionNeeded %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:DeletionPlan:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionPlanSummary', aColumns:aDeletionPlanSummary.Columns, aData:aDeletionPlanSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% if bDeletionPossible %}
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'DoDeletion'} %}
{% for sKey, sClass in aClasses %}
{% UIInput ForHidden { sName:"classes[" ~ sKey ~ "]", sValue:sClass } %}
{% endfor %}
{% for sCode, sLabel in aAddedExtensions %}
{% UIInput ForHidden { sName:"aAddedExtensions[" ~ sCode ~ "]", sValue:sLabel } %}
{% endfor %}
{% for sCode, sLabel in aRemovedExtensions %}
{% UIInput ForHidden { sName:"aRemovedExtensions[" ~ sCode ~ "]", sValue:sLabel } %}
{% endfor %}
{% for sInputName, sValue in aHiddenInputs %}
{% UIInput ForHidden { sName:sInputName, sValue:sValue } %}
{% endfor %}
{% UIToolbar ForButton {} %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:DoDeletion'|dict_s, sName:'btn_deletion', sId:'btn_deletion', bIsSubmit:true} %}
{% EndUIToolbar %}
{% EndUIForm %}
{% else %}
{% UIAlert ForFailure { sContent: 'DataFeatureRemoval:DeletionPlan:Error:Issues'|dict_s } %}{% EndUIAlert %}
{% endif %}
{% else %}
{% UIAlert ForSuccess { sTitle:'DataFeatureRemoval:CleanupComplete:Title'|dict_s, sContent:'DataFeatureRemoval:CompilComplete'|dict_s, sId:value } %}{% EndUIAlert %}
{% UIForm Standard {'sId':'launch-setup-form', Action:sLaunchSetupUrl, 'EncType': 'application/x-www-form-urlencoded'} %}
{% for sKey, sValue in aSetupParams %}
{% UIInput ForHidden { sName:sKey, sValue:sValue } %}
{% endfor %}
{% UIButton ForPrimaryAction {sLabel:'UI:Button:Setup'|dict_s, sName:'btn_setup', sId:'btn_setup', bIsSubmit:true} %}
{% EndUIForm %}
{% endif %}
{% if bHasDeletionExecution %}
{% UIFieldSet Standard {sLegend:'DataFeatureRemoval:Execution:Title'|dict_s} %}
{% UIDataTable ForForm { sRef:'aDeletionExecutionSummary', aColumns:aDeletionExecutionSummary.Columns, aData:aDeletionExecutionSummary.Data} %}{% EndUIDataTable %}
{% EndUIFieldSet %}
{% endif %}
{% endif %}
<div id="ajax_run_audit" class="ibo-block"></div>
{% UIForm Standard {} %}
{% UIInput ForHidden { sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden { sName:'operation', sValue:'Main'} %}

View File

@@ -0,0 +1,56 @@
{# @copyright Copyright (C) 2010-2026 Combodo SARL #}
{# @license http://opensource.org/licenses/AGPL-3.0 #}
function ajax_run_audit(sTransactionId) {
$('#ajax_run_audit_in_progress_msg').removeClass('ibo-is-hidden');
$.post(
'{{ sAjaxURL|raw }}',
{ operation: 'ajax_run_audit', transaction_id: sTransactionId },
function (data) {
$('#ajax_run_audit_in_progress_msg').addClass('ibo-is-hidden');
if (data.error_message) {
$('#ajax_run_audit_error_msg .ibo-alert--title').html(data.error_message);
$('#ajax_run_audit_error_msg').removeClass('ibo-is-hidden');
} else {
$('#ajax_run_audit_success_msg').removeClass('ibo-is-hidden');
$('#ajax_run_audit').html(data);
}
}
)
.fail(function() {
$('#ajax_run_audit_in_progress_msg').addClass('ibo-is-hidden');
$('#ajax_run_audit_error_msg .ibo-alert--title').html('{{ 'DataFeatureRemoval:RunAudit:Error'|dict_s }}');
$('#ajax_run_audit_error_msg').removeClass('ibo-is-hidden');
});
}
function ajax_compile() {
$('#ajax_compile_in_progress_msg').removeClass('ibo-is-hidden');
$.post(
'{{ sAjaxURL|raw }}',
{ operation: 'ajax_compile', transaction_id: '{{ sTransactionId }}' },
function (data) {
$('#ajax_compile_in_progress_msg').addClass('ibo-is-hidden');
if (data.error_message) {
$('#ajax_compile_error_msg .ibo-alert--title').html(data.error_message);
$('#ajax_compile_error_msg').removeClass('ibo-is-hidden');
} else {
$('#ajax_compile_success_msg .ibo-alert--title').html(data.success_message);
$('#ajax_compile_success_msg').removeClass('ibo-is-hidden');
ajax_run_audit(data.transaction_id);
}
},
'json'
)
.fail(function() {
$('#ajax_compile_in_progress_msg').addClass('ibo-is-hidden');
$('#ajax_compile_error_msg .ibo-alert--title').html('{{ 'DataFeatureRemoval:Compile:Error'|dict_s }}');
$('#ajax_compile_error_msg').removeClass('ibo-is-hidden');
});
}
ajax_compile();

View File

@@ -5,7 +5,6 @@
{% UIForm Standard {} %}
{% UIInput ForHidden {sName:'operation', sValue:'AnalysisResult'} %}
{% UIInput ForHidden {sName:'transaction_id', sValue:sTransactionId} %}
{% UIInput ForHidden {sName:'return_application', sValue:'itop'} %}
{% UIPanel Neutral { sTitle:'DataFeatureRemoval:Features:Title'|dict_s, sSubTitle: '' } %}
{% UIMultiColumn Standard {} %}

View File

@@ -90,6 +90,6 @@ Dict::Add('FR FR', 'French', 'Français', [
'Class:TriggerOnAttachmentDelete' => 'Déclencheur sur la suppression d\'une pièce jointe',
'Class:TriggerOnAttachmentDelete+' => 'Déclencheur sur la suppression d\'une pièce jointe d\'un objet',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email' => 'Ajoute le fichier supprimé dans l\'email',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => 'If checked, the deleted file will be automatically attached to the email when an email action is triggered~~',
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => 'Si coché, le fichier supprimé sera automatiquement joint à l\'email quand une action email sera lancée',
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Les Triggers sur les objets ne sont pas autorisés sur la classe Attachement. Veuillez utiliser les triggers spécifiques pour cette classe',
]);

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<NetworkDeviceType alias="NetworkDeviceType" id="10">
<name>Router</name>
</NetworkDeviceType>
<NetworkDeviceType alias="NetworkDeviceType" id="11">
<name>Switch</name>
</NetworkDeviceType>
</Set>

View File

@@ -16,7 +16,7 @@
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<nb_u>2</nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
@@ -40,9 +40,9 @@
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<rack_id></rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<nb_u>1</nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
@@ -59,16 +59,16 @@
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber></serialnumber>
<location_id>0</location_id>
<location_id>2</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<rack_id>0</rack_id>
<rack_id></rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<nb_u>2</nb_u>
<managementip></managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>
@@ -85,16 +85,16 @@
<business_criticity>low</business_criticity>
<move2production></move2production>
<serialnumber>US3215687014</serialnumber>
<location_id>0</location_id>
<location_id>2</location_id>
<status>production</status>
<brand_id>1</brand_id>
<model_id>4</model_id>
<asset_number></asset_number>
<purchase_date>2021-07-30</purchase_date>
<end_of_warranty>2025-07-29</end_of_warranty>
<rack_id>0</rack_id>
<rack_id></rack_id>
<enclosure_id>0</enclosure_id>
<nb_u></nb_u>
<nb_u>2</nb_u>
<managementip>10.10.24.2</managementip>
<powerA_id>0</powerA_id>
<powerB_id>0</powerB_id>

View File

@@ -32,7 +32,6 @@ SetupWebPage::AddModule(
],
'data.sample' => [
'data/data.sample.model.xml',
'data/data.sample.networkdevicetype.xml',
'data/data.sample.servers.xml',
'data/data.sample.nw-devices.xml',
'data/data.sample.software.xml',
@@ -106,6 +105,7 @@ if (!class_exists('ConfigMgmtInstaller')) {
*/
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
{
}
}
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<Rack alias="Rack" id="1">
<Rack alias="Rack" id="15">
<name>Rack1</name>
<description></description>
<org_id>2</org_id>
@@ -14,6 +14,6 @@
<asset_number></asset_number>
<purchase_date></purchase_date>
<end_of_warranty></end_of_warranty>
<nb_u></nb_u>
<nb_u>12</nb_u>
</Rack>
</Set>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<TagSetFieldDataFor_FAQ__domains id="1">
<code>software</code>
<label>Software 💾</label>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains id="2">
<code>hardware</code>
<label>Hardware 💻</label>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains id="3">
<code>server</code>
<label>Server 🏢</label>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains id="4">
<code>mobile</code>
<label>Mobile 📱</label>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains id="5">
<code>network</code>
<label>Network ☁️</label>
</TagSetFieldDataFor_FAQ__domains>
</Set>

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<FAQ alias="FAQ" id="6">
<title>💻 Anfrage für IT-Ausrüstung</title>
<summary>So beantragen Sie IT-Ausrüstung</summary>
<description>&lt;h4&gt;&lt;strong&gt;📌 Zweck&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Dieser Ablauf beschreibt die Schritte zur Beantragung von IT-Ausrüstung wie Laptops, Monitore, Peripheriegeräte oder Softwarelizenzen. Alle Anfragen müssen über die freigegebenen Kanäle eingereicht werden, damit Nachverfolgung, Genehmigung und Bereitstellung sichergestellt sind.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;👥 Geltungsbereich&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Gilt für alle Mitarbeitenden, externen Kräfte und Abteilungen, die IT-Ausrüstung für ihre Arbeit benötigen.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;✅ Schritt 1: Bedarf klären&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Prüfen Sie, ob die Ausrüstung für Rolle oder Projekt erforderlich ist.&lt;/li&gt;&lt;li&gt;Prüfen Sie die Verfügbarkeit im IT-Bestand.&lt;/li&gt;&lt;li&gt;Stellen Sie sicher, dass die Anfrage den IT-Richtlinien entspricht.&lt;/li&gt;&lt;/ul&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;📝 Schritt 2: Anfrage einreichen&lt;/strong&gt;&lt;/h4&gt;&lt;ol&gt;&lt;li&gt;Öffnen Sie das IT-Anfrageportal und füllen Sie das Formular vollständig aus.&lt;/li&gt;&lt;li&gt;Geben Sie Name, Abteilung, Gerätetyp, Menge, Begründung und gewünschtes Lieferdatum an.&lt;/li&gt;&lt;li&gt;Alternativ senden Sie eine E-Mail an it-requests@[yourorganization].com.&lt;/li&gt;&lt;/ol&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;🔍 Schritt 3: Genehmigung&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Die Führungskraft prüft geschäftlichen Bedarf und Budget. Danach validiert das IT-Team Kompatibilität, Verfügbarkeit und Sicherheitsvorgaben. Bei hohen Kosten kann zusätzlich eine Finanzfreigabe erforderlich sein.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;📦 Schritt 4: Bereitstellung&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Lagerware wird nach Freigabe zeitnah ausgeliefert. Bei Sonderbestellungen informiert die IT über die Lieferzeit und übernimmt bei Bedarf die Ersteinrichtung.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;🔄 Rückgabe und Ersatz&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Defekte oder nicht mehr benötigte Geräte werden über eine Rückgabeanfrage an die IT gemeldet und zurückgeführt.&lt;/p&gt;</description>
<category_id>7</category_id>
<error_code></error_code>
<key_words>PC, Phone, Laptop, Desktop</key_words>
<domains><Set>
<Tag>hardware</Tag><Tag>process</Tag></Set>
</domains>
</FAQ>
<FAQ alias="FAQ" id="8">
<title>📌 Urlaubsverwaltung</title>
<summary></summary>
<description>&lt;h4&gt;&lt;strong&gt;❓ Wie beantrage ich Urlaub?&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Sie können Urlaub über das interne HR-Portal oder per E-Mail an Ihre Führungskraft und HR beantragen. Geben Sie Name, Zeitraum und Urlaubsart an.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;⏳ Welche Fristen gelten?&lt;/strong&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Regulärer Urlaub möglichst frühzeitig, idealerweise mindestens 15 Tage vorher.&lt;/li&gt;&lt;li&gt;Sonderurlaub so schnell wie möglich ankündigen.&lt;/li&gt;&lt;li&gt;Krankheit oder Unfall am selben Tag melden.&lt;/li&gt;&lt;/ul&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;📅 Wie viele Urlaubstage habe ich?&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Der Anspruch richtet sich nach Vertrag und lokaler Gesetzgebung. Ihr aktueller Saldo ist im HR-Portal sichtbar.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;🔄 Kann ich Urlaub ändern oder stornieren?&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Ja, je nach Unternehmensrichtlinie und mit Zustimmung der Führungskraft. Änderungen sollten frühzeitig gemeldet werden.&lt;/p&gt;&lt;hr&gt;&lt;h4&gt;&lt;strong&gt;🆘 An wen wende ich mich bei Problemen?&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Bei technischen Problemen kontaktieren Sie den IT-Support, bei Fragen zu Rechten und Saldo das HR-Team.&lt;/p&gt;</description>
<category_id>4</category_id>
<error_code></error_code>
<key_words>Leave</key_words>
<domains><Set>
<Tag>process</Tag></Set>
</domains>
</FAQ>
<FAQ alias="FAQ" id="1">
<title>🖨️ Fehlerdiagnose bei Druckern</title>
<summary>Fragenkatalog zur Analyse von Druckproblemen</summary>
<description>&lt;h2&gt;❓ Fragen zur Fehlersuche&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Druckermarke bekannt?&lt;/strong&gt; HP, IBM, Epson oder andere.&lt;/p&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Ist der Drucker mit Strom versorgt?&lt;/strong&gt; Ja oder Nein.&lt;/p&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Ist der Drucker eingeschaltet?&lt;/strong&gt; Ja oder Nein.&lt;/p&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Ist Papier eingelegt?&lt;/strong&gt; Ja oder Nein.&lt;/p&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Gibt es Meldungen zum Tintenstand oder andere Warnungen?&lt;/strong&gt; Falls ja, welche?&lt;/p&gt;&lt;hr&gt;&lt;p&gt;&lt;strong&gt;Wurde bereits ein Neustart versucht?&lt;/strong&gt; Ja oder Nein.&lt;/p&gt;</description>
<category_id>3</category_id>
<error_code></error_code>
<key_words>printer</key_words>
<domains><Set>
<Tag>printer</Tag><Tag>process</Tag></Set>
</domains>
</FAQ>
<FAQ alias="FAQ" id="4">
<title>📶 Fehlerdiagnose für WLAN-Verbindung</title>
<summary>Fragenkatalog zur Analyse von WLAN-Problemen</summary>
<description>&lt;h2&gt;🔍 Grundprüfungen&lt;/h2&gt;&lt;p&gt;Ist WLAN am Gerät aktiviert, ist das Symbol sichtbar und funktionieren andere Geräte im selben Netzwerk?&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🌐 Netzwerkspezifische Prüfungen&lt;/h2&gt;&lt;p&gt;Ist der Router eingeschaltet, sind die LEDs normal, ist die SSID sichtbar und wurde das richtige Passwort verwendet?&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;💻 Gerätespezifische Prüfungen&lt;/h2&gt;&lt;p&gt;Wurde das Gerät neu gestartet, das WLAN neu verbunden und die Entfernung zum Router geprüft?&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🛠️ Erweiterte Schritte&lt;/h2&gt;&lt;p&gt;Treiber aktualisieren, Störquellen prüfen, Routerkanal anpassen und bei Bedarf Router zurücksetzen.&lt;/p&gt;</description>
<category_id>6</category_id>
<error_code></error_code>
<key_words></key_words>
<domains><Set>
<Tag>network</Tag></Set>
</domains>
</FAQ>
<FAQ alias="FAQ" id="2">
<title>🖥️ Fehlerdiagnose für Windows-Verbindung</title>
<summary>Fragenkatalog zur Analyse von Windows-Verbindungsproblemen</summary>
<description>&lt;h2&gt;🔍 Allgemeine Prüfungen&lt;/h2&gt;&lt;p&gt;Besteht eine Internetverbindung, ist das WLAN- oder Ethernet-Symbol sichtbar und funktionieren andere Geräte im selben Netzwerk?&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🌐 Netzwerkspezifische Prüfungen&lt;/h2&gt;&lt;p&gt;Prüfen Sie Flugmodus, Router-Neustart, korrektes Passwort und ggf. den Einfluss eines VPN.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🔗 Windows-spezifische Prüfungen&lt;/h2&gt;&lt;p&gt;Computer neu starten, Windows-Updates prüfen, Netzwerktreiber aktualisieren und die integrierte Problembehandlung ausführen.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🛠️ Erweiterte Schritte&lt;/h2&gt;&lt;p&gt;Netzwerk zurücksetzen, Sicherheitssoftware prüfen und testweise ein anderes Netzwerk verwenden.&lt;/p&gt;</description>
<category_id>5</category_id>
<error_code></error_code>
<key_words>windows connection</key_words>
<domains><Set>
<Tag>software</Tag></Set>
</domains>
</FAQ>
<FAQ alias="FAQ" id="7">
<title>🖨️🔄 Drucker-Firmware aktualisieren</title>
<summary></summary>
<description>&lt;h2&gt;📌 Vorbereitung&lt;/h2&gt;&lt;p&gt;Benötigt werden ein Computer im selben Netzwerk, die passende Firmware-Datei und eine stabile Verbindung. Der Drucker darf während des Updates nicht ausgeschaltet werden.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🔍 Modell und Version ermitteln&lt;/h2&gt;&lt;p&gt;Prüfen Sie das exakte Modell und notieren Sie die aktuell installierte Firmware-Version.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;📥 Firmware herunterladen&lt;/h2&gt;&lt;p&gt;Laden Sie die aktuelle Version von der offiziellen Herstellerseite und prüfen Sie die Kompatibilität für Modell und Region.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🔄 Update durchführen&lt;/h2&gt;&lt;p&gt;Das Update kann über Hersteller-Software, Druckermenü oder per USB erfolgen. Folgen Sie den Schritten des Herstellers und unterbrechen Sie den Vorgang nicht.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;✅ Nachkontrolle&lt;/h2&gt;&lt;p&gt;Drucker neu starten, Testseite drucken und Funktionen wie Drucken, Scannen und Netzwerk prüfen.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🚨 Fehlerbehebung&lt;/h2&gt;&lt;p&gt;Bei Fehlern Verbindung prüfen, neu starten und bei Bedarf den Herstellersupport kontaktieren.&lt;/p&gt;</description>
<category_id>3</category_id>
<category_id_friendlyname>Printer</category_id_friendlyname>
<category_name>Printer</category_name>
<error_code></error_code>
<key_words>printer, firmware</key_words>
<domains><Set>
<Tag>printer</Tag></Set>
</domains>
</FAQ>
<FAQ alias="FAQ" id="5">
<title>💙💻 Fehlerdiagnose bei Windows-Bluescreen</title>
<summary>Fragenkatalog zur Analyse von Windows-Bluescreen-Problemen</summary>
<description>&lt;h2&gt;🔍 Erste Prüfungen&lt;/h2&gt;&lt;p&gt;Tritt der Bluescreen wiederholt auf, bei einem bestimmten Schritt oder zufällig? Notieren Sie den angezeigten Fehlercode.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🛠️ Basismaßnahmen&lt;/h2&gt;&lt;p&gt;Neustart durchführen, Windows aktualisieren, externe Geräte trennen und einen Malware-Scan starten.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🖥️ Erweiterte Prüfungen&lt;/h2&gt;&lt;p&gt;Ereignisanzeige prüfen, Treiber aktualisieren sowie Systemprüfungen wie SFC, DISM, RAM- und Datenträgertests ausführen.&lt;/p&gt;&lt;hr&gt;&lt;h2&gt;🔄 Wiederherstellungsoptionen&lt;/h2&gt;&lt;p&gt;Abgesicherten Modus testen, Systemwiederherstellung verwenden und falls nötig Windows zurücksetzen oder neu installieren.&lt;/p&gt;</description>
<category_id>5</category_id>
<error_code></error_code>
<key_words>Blue Screen, Windows</key_words>
<domains><Set>
</Set>
</domains>
</FAQ>
</Set>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<FAQCategory alias="FAQCategory" id="1">
<name>Konfiguration</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="2">
<name>Datenbank</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="4">
<name>Personalwesen</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="6">
<name>Netzwerk</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="7">
<name>PC</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="3">
<name>Drucker</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="5">
<name>Windows</name>
</FAQCategory>
</Set>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<FAQCategory alias="FAQCategory" id="1">
<name>Configuration</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="2">
<name>Database</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="4">
<name>Human resources</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="6">
<name>Network</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="7">
<name>PC</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="3">
<name>Printer</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="5">
<name>Windows</name>
</FAQCategory>
</Set>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<FAQCategory alias="FAQCategory" id="1">
<name>Configuration</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="2">
<name>Base de données</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="4">
<name>Ressources humaines</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="6">
<name>Réseau</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="7">
<name>PC</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="3">
<name>Imprimante</name>
</FAQCategory>
<FAQCategory alias="FAQCategory" id="5">
<name>Windows</name>
</FAQCategory>
</Set>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="2">
<code>hardware</code>
<label>Hardware 💻</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="4">
<code>mobile</code>
<label>Mobil 📱</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="5">
<code>network</code>
<label>Netzwerk ☁️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="6">
<code>printer</code>
<label>Drucker 🖨️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="7">
<code>process</code>
<label>Prozess ⚙️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="3">
<code>server</code>
<label>Server 🏢</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="1">
<code>software</code>
<label>Software 💾</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
</Set>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="2">
<code>hardware</code>
<label>Hardware 💻</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="4">
<code>mobile</code>
<label>Mobile 📱</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="5">
<code>network</code>
<label>Network ☁️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="6">
<code>printer</code>
<label>Printer 🖨️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="7">
<code>process</code>
<label>Process ⚙️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="3">
<code>server</code>
<label>Server 🏢</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="1">
<code>software</code>
<label>Software 💾</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
</Set>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="2">
<code>hardware</code>
<label>Matériel 💻</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="4">
<code>mobile</code>
<label>Mobile 📱</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="5">
<code>network</code>
<label>Réseau ☁️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="6">
<code>printer</code>
<label>Imprimante 🖨️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="7">
<code>process</code>
<label>Processus ⚙️</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="3">
<code>server</code>
<label>Serveur 🏢</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
<TagSetFieldDataFor_FAQ__domains alias="TagSetFieldDataFor_FAQ__domains" id="1">
<code>software</code>
<label>Logiciel 💾</label>
<description></description>
</TagSetFieldDataFor_FAQ__domains>
</Set>

View File

@@ -27,7 +27,9 @@ SetupWebPage::AddModule(
//'data.struct.itop-knownerror-mgmt.xml',
],
'data.sample' => [
'data/data.sample.faq-domains.xml',
'data/data.sample.faqdomain.en_us.xml',
'data/data.sample.faqcategory.en_us.xml',
'data/data.sample.faq.en_us.xml',
],
// Documentation

View File

@@ -159,7 +159,7 @@ function DoInstall(WebPage $oPage)
foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) {
if ($oExtension->sSource == iTopExtension::SOURCE_REMOTE) {
if (count($oExtension->aMissingDependencies) > 0) {
if ($oExtension->HasDependencyIssue()) {
$oPage->add('<div class="choice">');
$oPage->add('<input type="checkbox" disabled>&nbsp;');
$sTitle = Dict::Format('iTopHub:InstallationEffect:MissingDependencies_Details', implode(', ', $oExtension->aMissingDependencies));

View File

@@ -133,8 +133,7 @@ class HubController
throw new Exception('Sorry the installation of extensions is not allowed in demo mode');
}
$aSelectModules = $oRuntimeEnv->CompileFrom('production'); // WARNING symlinks does not seem to be compatible with manual Commit
$oRuntimeEnv->CompileFrom('production'); // WARNING symlinks does not seem to be compatible with manual Commit
$oRuntimeEnv->UpdateIncludes($oConfig);
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */);

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<lnkErrorToFunctionalCI alias="lnkErrorToFunctionalCI" id="4">
<functionalci_id><![CDATA[SELECT FunctionalCI WHERE name='Server1']]></functionalci_id>
<error_id>2</error_id>
</lnkErrorToFunctionalCI>
<lnkErrorToFunctionalCI alias="lnkErrorToFunctionalCI" id="1">
<functionalci_id><![CDATA[SELECT FunctionalCI WHERE name='Server2']]></functionalci_id>
<error_id>2</error_id>
</lnkErrorToFunctionalCI>
<lnkErrorToFunctionalCI alias="lnkErrorToFunctionalCI" id="2">
<functionalci_id><![CDATA[SELECT FunctionalCI WHERE name='Server3']]></functionalci_id>
<error_id>2</error_id>
</lnkErrorToFunctionalCI>
<lnkErrorToFunctionalCI alias="lnkErrorToFunctionalCI" id="3">
<functionalci_id><![CDATA[SELECT FunctionalCI WHERE name='Server4']]></functionalci_id>
<error_id>2</error_id>
</lnkErrorToFunctionalCI>
</Set>

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<KnownError alias="KnownError" id="1">
<name>Verminderte VM-Leistung auf ESXi-8.0U2-Hosts nach dem Update auf vCenter Server 8.0U2b</name>
<org_id>3</org_id>
<problem_id>0</problem_id>
<symptom>- Hohe Latenz (bis zu 500 ms) bei Speicher-Lese-/Schreibvorgängen für VMs auf ESXi-8.0U2-Hosts.
- vCenter-Alarme:
+ &quot;Storage device latency is high&quot; (Schwellwert überschritten: &gt; 30 ms).
+ &quot;Virtual machine disk I/O latency is high&quot;.
- Auswirkungen auf Anwendungen:
+ Verlangsamungen bei Datenbanken (SQL, Oracle).
+ Timeouts in kritischen Anwendungen (z. B. ERP, SAP).
- Zeitraum des Auftretens: Seit dem Update von vCenter Server auf Version 8.0U2b (ausgerollt am 10. Juli 2026).
Betroffene Umgebung:
- ESXi-Hosts: 5 Server (Cluster PROD-01).
- Storage: Dell EMC PowerStore 5000 (über iSCSI verbunden).
- vCenter Server: Version 8.0U2b (Build 21513536).</symptom>
<root_cause>Kompatibilitätsproblem zwischen:
- Dem nativen iSCSI-Treiber in ESXi 8.0U2 (vmw_iscsi) und vCenter Server 8.0U2b.
- Einem bekannten Fehler im NMP-(Native Multi-Pathing)-Storage-Scheduler, der nach dem vCenter-Update zu fehlerhafter Multipath-Verwaltung führt.
VMware-Referenz:
- KB 90827 (ähnlich, aber nicht identisch).
- ESXi-Logs: Wiederholte Meldungen &quot;NMP: nmp_DeviceRequestFastDeviceProbe: NMP device state in doubt&quot; in /var/log/vmkernel.log.</root_cause>
<workaround>Option 1: NMP-Dienst zurücksetzen (temporär)
1. Per SSH auf jeden betroffenen ESXi-Host verbinden.
2. Folgende Befehle ausführen:
esxcli storage nmp device list # Betroffene Geräte auflisten
esxcli storage nmp device set --device &lt;NAA_ID&gt; --state in_use # Aktiven Pfad erzwingen
3. Die betroffenen VMs neu starten. ⚠️ Effekt: Löst das Problem für 2448 Stunden, danach tritt die Latenz nach Host-Neustart erneut auf.
Option 2: Multipathing für betroffene LUNs deaktivieren
1. In vCenter zu: Host &gt; Configure &gt; Storage &gt; Storage Devices navigieren.
2. Betroffene LUN auswählen &gt; Edit Multipathing Policy &gt; &quot;Fixed&quot; wählen (statt &quot;Most Recently Used&quot;). ⚠️ Risiko: Redundanzverlust bei Ausfall eines Pfads.
Option 3: Rollback von vCenter auf Version 8.0U2a
- vCenter auf Version 8.0U2a zurücksetzen (Build 21495409).
- Auswirkung: Verlust von Funktionen aus 8.0U2b (z. B. Sicherheitsverbesserungen).</workaround>
<solution>- Maßnahme: VMware ESXi-Patch 8.0U2c anwenden (Patch ESXi80U2c-21567894), der den Fehler im NMP-Scheduler behebt.
- Zuständiges Team: Virtualization + Storage Team.
- Geplantes Datum: 18. Juli 2026 (geplantes Wartungsfenster).
- Vorgehen:
1. ESXi-Hosts nacheinander in den Wartungsmodus versetzen.
2. Patch über vSphere Lifecycle Manager (vLCM) einspielen.
3. Hosts neu starten und die Leistung prüfen.</solution>
<error_code>&quot;Storage device latency is high&quot; &quot;Virtual machine disk I/O latency is high&quot;</error_code>
<domain>Application</domain>
<vendor>VMWare</vendor>
<model>ESXi</model>
<version>8.0U2</version>
</KnownError>
<KnownError alias="KnownError" id="2">
<name>Apache HTTP Server (apache2) stürzt nach Kernel-Update (5.15.0-86-generic) auf Ubuntu-22.04-LTS-Servern zufällig mit &apos;Segmentation Fault&apos; ab</name>
<org_id>2</org_id>
<problem_id>0</problem_id>
<symptom>- Der Apache2-Dienst stürzt plötzlich ab, ohne eindeutige Logs in /var/log/apache2/error.log.
- System-Logs (/var/log/syslog) zeigen:
Jul 14 08:45:23 web-server-01 kernel: [12345.678901] apache2[12345]: segfault at 7f8e12345678 ip 00007f8e12345678 sp 00007ffd12345678 error 4 in libapr-1.so.0.7.0[7f8e12345000+20000]
- Auswirkungen für Benutzer:
+ Totalausfall der Website (HTTP 503 Service Unavailable).
+ Durchschnittliche Ausfallzeit pro Vorfall: 510 Minuten (manueller Neustart erforderlich).
- Häufigkeit: 23 Mal pro Tag seit dem 12. Juli 2026.
- Betroffene Umgebung:
+ Server: 3 Webserver (web-server-01, web-server-02, web-server-03).
+ Betriebssystem: Ubuntu 22.04 LTS.
+ Kernel-Version: 5.15.0-86-generic (aktualisiert am 12. Juli 2026).
+ Apache-Version: 2.4.52.
+ Geladene Apache-Module: mod_ssl, mod_rewrite, mod_php8.1, mod_security2.</symptom>
<root_cause>- Konflikt zwischen Linux-Kernel 5.15.0-86-generic und mod_security2 (Version 2.9.5):
+ Kernel 5.15.0-86 führt eine Änderung im Speichermanagement für Multi-Thread-Prozesse ein.
+ Das Modul mod_security2 (für WAF-Sicherheit) ist mit diesem Update nicht kompatibel und verursacht einen Segmentation Fault (ungültiger Speicherzugriff).
- Nachweise:
+ Das Problem verschwindet, wenn mod_security2 deaktiviert wird.
+ Das Problem tritt auf Servern mit Kernel 5.15.0-82-generic (Vorversion) nicht auf.
- Externe Referenzen:
+ Gemeldeter Fehler in Apache JIRA (ähnlich).
+ Diskussion auf Server Fault (Community).</root_cause>
<workaround>- Option 1: mod_security2 vorübergehend deaktivieren
1. Apache-Konfigurationsdatei bearbeiten:
sudo nano /etc/apache2/mods-enabled/security2.conf
2 . Folgende Zeile auskommentieren:
# SecRuleEngine On
3. Apache neu starten:
sudo systemctl restart apache2
⚠️ Auswirkung: Der Webserver wird anfälliger für Angriffe (z. B. SQL-Injection, XSS).
✅ Vorteil: Das Problem wird sofort behoben.
- Option 2: Auf den vorherigen Kernel zurückgehen (5.15.0-82-generic)
1. Server mit dem älteren Kernel neu starten:
sudo reboot
2. In GRUB Kernel 5.15.0-82-generic auswählen.⚠️ Auswirkung: Sicherheits-Patches aus Kernel 5.15.0-86 fehlen.
- Option 3: Apache-Threads begrenzen
1. Apache-Konfiguration anpassen (/etc/apache2/apache2.conf):
StartServers 2
MinSpareThreads 5
MaxSpareThreads 10
ThreadsPerChild 5
MaxRequestWorkers 20
2. Apache neu starten:
sudo systemctl restart apache2
⚠️ Auswirkung: Reduzierte Leistung (weniger gleichzeitige Anfragen).</workaround>
<solution>- Maßnahme: Upgrade von mod_security2 auf Version 2.9.6 (kompatibel mit Kernel 5.15.0-86).
+ Korrigierte Version: libapache2-mod-security2 2.9.6-1ubuntu0.22.04.1 (im Ubuntu-Proposed-Repository verfügbar).
- Zuständiges Team: DevOps + Security Team.
- Geplantes Datum: 17. Juli 2026 (Wartungsfenster: 02:0004:00 UTC).
- Vorgehen:
1. Proposed-Repository hinzufügen:
sudo add-apt-repository ppa:ubuntu-security-proposed
sudo apt update
2. mod_security2 aktualisieren:
sudo apt install --only-upgrade libapache2-mod-security2
3. Apache neu starten:
sudo systemctl restart apache2
4. Version prüfen:
apache2ctl -M | grep security</solution>
<error_code></error_code>
<domain>Application</domain>
<vendor>Linux</vendor>
<model>Apache</model>
<version>2.4.52</version>
</KnownError>
</Set>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<KnownError alias="KnownError" id="1">
<name>Degraded VM Performance on ESXi 8.0U2 Hosts After vCenter Server 8.0U2b Update</name>
<org_id>3</org_id>
<problem_id>0</problem_id>
<symptom>- High latency (up to 500 ms) on storage read/write operations for VMs hosted on ESXi 8.0U2 hosts.
- vCenter Alarms:
+ &quot;Storage device latency is high&quot; (Threshold exceeded: &gt; 30 ms).
+ &quot;Virtual machine disk I/O latency is high&quot;.
- Application Impact:
+ Slowdowns in databases (SQL, Oracle).
+ Timeouts in critical applications (e.g., ERP, SAP).
- Occurrence Period: Since the vCenter Server update to version 8.0U2b (deployed on July 10, 2026).
Affected Environment:
- ESXi Hosts: 5 servers (PROD-01 Cluster).
- Storage: Dell EMC PowerStore 5000 (connected via iSCSI).
- vCenter Server: Version 8.0U2b (build 21513536).</symptom>
<root_cause>Compatibility issue between:
- The native iSCSI driver in ESXi 8.0U2 (vmw_iscsi) and vCenter Server 8.0U2b.
- A known bug in the NMP (Native Multi-Pathing) storage scheduler causing incorrect multipathing management after the vCenter update.
VMware Reference:
- KB 90827 (similar but not identical).
- ESXi Logs: Repeated messages &quot;NMP: nmp_DeviceRequestFastDeviceProbe: NMP device state in doubt&quot; in /var/log/vmkernel.log.</root_cause>
<workaround>Option 1: Reset the NMP Service (Temporary)
1. SSH into each affected ESXi host.
2. Run the following commands:
esxcli storage nmp device list # List affected devices
esxcli storage nmp device set --device &lt;NAA_ID&gt; --state in_use # Force active path
3. Restart the affected VMs. ⚠️ Effect: Resolves the issue for 2448 hours, but latency reappears after a host reboot.
Option 2: Disable Multipathing for Affected LUNs
1. In vCenter, navigate to: Host &gt; Configure &gt; Storage &gt; Storage Devices.
2. Select the affected LUN &gt; Edit Multipathing Policy &gt; Choose &quot;Fixed&quot; (instead of &quot;Most Recently Used&quot;). ⚠️ Risk: Loss of redundancy if one path fails.
Option 3: Roll Back vCenter to Version 8.0U2a
- Rollback vCenter to version 8.0U2a (build 21495409).
- Impact: Loss of 8.0U2b features (e.g., security improvements).</workaround>
<solution>- Action: Apply the VMware ESXi 8.0U2c patch (patch ESXi80U2c-21567894), which fixes the NMP scheduler bug.
- Responsible Team: Virtualization + Storage Team.
- Planned Date: July 18, 2026 (scheduled maintenance window).
- Procedure:
1. Place ESXi hosts in maintenance mode one by one.
2. Apply the patch via vSphere Lifecycle Manager (vLCM).
3. Reboot hosts and verify performance.</solution>
<error_code>&quot;Storage device latency is high&quot; &quot;Virtual machine disk I/O latency is high&quot;</error_code>
<domain>Application</domain>
<vendor>VMWare</vendor>
<model>ESXi</model>
<version>8.0U2</version>
</KnownError>
<KnownError alias="KnownError" id="2">
<name>Apache HTTP Server (apache2) Crashes Randomly with &apos;Segmentation Fault&apos; on Ubuntu 22.04 LTS Servers After Kernel Update (5.15.0-86-generic)</name>
<org_id>2</org_id>
<problem_id>0</problem_id>
<symptom>- The Apache2 service crashes suddenly without clear logs in /var/log/apache2/error.log.
- System logs (/var/log/syslog) show:
Jul 14 08:45:23 web-server-01 kernel: [12345.678901] apache2[12345]: segfault at 7f8e12345678 ip 00007f8e12345678 sp 00007ffd12345678 error 4 in libapr-1.so.0.7.0[7f8e12345000+20000]
- User Impact:
+ Total unavailability of the website (HTTP 503 Service Unavailable).
+ Average downtime per incident: 510 minutes (manual restart required).
- Frequency: 23 times per day since July 12, 2026.
- Affected Environment:
+ Servers: 3 web servers (web-server-01, web-server-02, web-server-03).
+ Operating System: Ubuntu 22.04 LTS.
+ Kernel Version: 5.15.0-86-generic (updated on July 12, 2026).
+ Apache Version: 2.4.52.
+ Loaded Apache Modules: mod_ssl, mod_rewrite, mod_php8.1, mod_security2.</symptom>
<root_cause>- Conflict between Linux kernel 5.15.0-86-generic and mod_security2 (version 2.9.5):
+ The 5.15.0-86 kernel introduces a change in memory management for multi-threaded processes.
+ The mod_security2 module (used for WAF security) is not compatible with this update, causing a segmentation fault (invalid memory access).
- Evidence:
+ The issue disappears when mod_security2 is disabled.
+ The issue does not occur on servers running kernel 5.15.0-82-generic (previous version).
- External References:
+ Reported bug on Apache JIRA (similar).
+ Discussion on Server Fault (community).</root_cause>
<workaround>- Option 1: Temporarily Disable mod_security2
1. Edit the Apache configuration file:
sudo nano /etc/apache2/mods-enabled/security2.conf
2 . Comment out the line:
# SecRuleEngine On
3. Restart Apache:
sudo systemctl restart apache2
⚠️ Impact: The web server becomes vulnerable to attacks (e.g., SQL injection, XSS).
✅ Benefits: Immediately resolves the issue.
- Option 2: Revert to the Previous Kernel (5.15.0-82-generic)
1. Reboot the server with the older kernel:
sudo reboot
2. In GRUB, select kernel 5.15.0-82-generic.⚠️ Impact: The server misses security patches from kernel 5.15.0-86.
- Option 3: Limit Apache Threads
1. Modify Apache configuration (/etc/apache2/apache2.conf):
StartServers 2
MinSpareThreads 5
MaxSpareThreads 10
ThreadsPerChild 5
MaxRequestWorkers 20
2. Restart Apache:
sudo systemctl restart apache2
⚠️ Impact: Reduced performance (fewer concurrent requests handled).</workaround>
<solution>- Action: Upgrade mod_security2 to version 2.9.6 (compatible with kernel 5.15.0-86).
+ Fixed Version: libapache2-mod-security2 2.9.6-1ubuntu0.22.04.1 (available in Ubuntu proposed repository).
- Responsible Team: DevOps + Security Team.
- Planned Date: July 17, 2026 (maintenance window: 02:0004:00 UTC).
- Procedure:
1. Add the proposed repository:
sudo add-apt-repository ppa:ubuntu-security-proposed
sudo apt update
2. Upgrade mod_security2:
sudo apt install --only-upgrade libapache2-mod-security2
3. Restart Apache:
sudo systemctl restart apache2
4. Verify the version:
apache2ctl -M | grep security</solution>
<error_code></error_code>
<domain>Application</domain>
<vendor>Linux</vendor>
<model>Apache</model>
<version>2.4.52</version>
</KnownError>
</Set>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<KnownError alias="KnownError" id="1">
<name>Dégradation des performances des VMs sur les hôtes ESXi 8.0U2 après mise à jour du vCenter Server 8.0U2b</name>
<org_id>3</org_id>
<problem_id>0</problem_id>
<symptom>- Latence élevée (jusquà 500 ms) sur les opérations de stockage (lecture/écriture) pour les VMs hébergées sur les hôtes ESXi 8.0U2.
- Alarmes vCenter:
+ &quot;Storage device latency is high&quot; (Threshold exceeded: &gt; 30 ms).
+ &quot;Virtual machine disk I/O latency is high&quot;.
- Impact sur les applications :
+ Ralentissements des bases de données (SQL, Oracle).
+ Timeouts sur les applications critiques (ex. : ERP, SAP).
- Période d'occurrence : Depuis la mise à jour du vCenter Server vers la version 8.0U2b (déployée le 10/07/2026).
Environnement affecté :
- Hôtes ESXi : 5 serveurs (Cluster PROD-01).
- Stockage : Baie Dell EMC PowerStore 5000 (connectée en iSCSI).
- vCenter Server : Version 8.0U2b (build 21513536).</symptom>
<root_cause>Problème de compatibilité entre :
- Le pilote iSCSI natif dESXi 8.0U2 (vmw_iscsi) et la version 8.0U2b du vCenter Server.
- Un bug connu dans le scheduler de stockage NMP (Native Multi-Pathing) qui provoque une mauvaise gestion des chemins multiples (multipathing) après la mise à jour du vCenter.
VMware Reference:
- KB 90827 (similaire, mais non identique).
- Log ESXi : Messages répétés &quot;NMP: nmp_DeviceRequestFastDeviceProbe: NMP device state in doubt&quot; dans /var/log/vmkernel.log.</root_cause>
<workaround>Option 1: Réinitialiser le service NMP (temporaire)
1. Se connecter en SSH à chaque hôte ESXi affecté.
2. Exécuter les commandes :
esxcli storage nmp device list # List affected devices
esxcli storage nmp device set --device &lt;NAA_ID&gt; --state in_use # Force active path
3. Redémarrer les VMs concernées. ⚠️ Effet : Résout le problème pendant 2448h, mais la latence réapparaît après un redémarrage de lhôte.
Option 2: Désactiver le multipathing pour les LUNs concernés
1. Dans vCenter, aller dans: Host &gt; Configure &gt; Storage &gt; Storage Devices.
2. Sélectionner le LUN concerné &gt; Edit Multipathing Policy &gt; Choisir &quot;Fixed&quot; (au lieu de &quot;Most Recently Used&quot;). ⚠️ Risque : Perte de redondance en cas de panne dun chemin.
Option 3: Revenir à la version précédente de vCenter (8.0U2a)
- Rollback du vCenter vers la version 8.0U2a (build 21495409).
- Impact : Perte des fonctionnalités de 8.0U2b (ex. : améliorations de sécurité).</workaround>
<solution>- Action : Appliquer le correctif VMware ESXi 8.0U2c (patch ESXi80U2c-21567894), qui corrige le bug du scheduler NMP.
- Responsable : Équipe Virtualisation + Stockage.
- Date prévue : 18 juillet 2026 (fenêtre de maintenance planifiée).
- Procédure:
1. Mettre en maintenance les hôtes ESXi un par un.
2. Appliquer le patch via vSphere Lifecycle Manager (vLCM).
3. Redémarrer les hôtes et vérifier les performances.</solution>
<error_code>&quot;Storage device latency is high&quot; &quot;Virtual machine disk I/O latency is high&quot;</error_code>
<domain>Application</domain>
<vendor>VMWare</vendor>
<model>ESXi</model>
<version>8.0U2</version>
</KnownError>
<KnownError alias="KnownError" id="2">
<name>Service Apache HTTP Server (apache2) plante aléatoirement avec l'erreur 'Segmentation Fault' sur les serveurs Ubuntu 22.04 LTS après mise à jour du noyau (5.15.0-86-generic)</name>
<org_id>2</org_id>
<problem_id>0</problem_id>
<symptom>- Le service Apache2 s'arrête brutalement sans journalisation claire dans /var/log/apache2/error.log.
- Message dans les logs système (/var/log/syslog):
Jul 14 08:45:23 web-server-01 kernel: [12345.678901] apache2[12345]: segfault at 7f8e12345678 ip 00007f8e12345678 sp 00007ffd12345678 error 4 in libapr-1.so.0.7.0[7f8e12345000+20000]
- Impact utilisateur:
+ Indisponibilité totale du site web (HTTP 503 Service Unavailable).
+ Durée moyenne de l'incident : 5 à 10 minutes (redémarrage manuel nécessaire).
- Fréquence : 2 à 3 fois par jour depuis le 12 juillet 2026.
- Environnement affecté :
+ Serveurs : 3 serveurs web (web-server-01, web-server-02, web-server-03).
+ Système d'exploitation : Ubuntu 22.04 LTS.
+ Version du noyau : 5.15.0-86-generic (mis à jour le 12/07/2026).
+ Version d'Apache : 2.4.52.
+ Modules Apache chargés : mod_ssl, mod_rewrite, mod_php8.1, mod_security2.</symptom>
<root_cause>- Conflit entre le noyau Linux 5.15.0-86-generic et le module mod_security2 (version 2.9.5) :
+ Le noyau 5.15.0-86 introduit une modification dans la gestion de la mémoire pour les processus multi-threadés.
+ Le module mod_security2 (utilisé pour la sécurité WAF) n'est pas compatible avec cette mise à jour, provoquant un segmentation fault (accès mémoire invalide).
- Preuve :
+ Le problème disparaît lorsque mod_security2 est désactivé.
+ Le problème n'existe pas sur les serveurs sous le noyau 5.15.0-82-generic (version précédente).
- Référence externe :
+ Bug rapporté sur Apache JIRA (similaire).
+ Discussion sur Server Fault (communauté).</root_cause>
<workaround>- Option 1: Désactiver temporairement mod_security2
1. Éditer le fichier de configuration Apache :
sudo nano /etc/apache2/mods-enabled/security2.conf
2 . Commenter la ligne :
# SecRuleEngine On
3. Redémarrer Apache:
sudo systemctl restart apache2
⚠️ Le serveur web devient vulnérable aux attaques (ex. : SQL injection, XSS).
✅ Avantages : Résout immédiatement le problème.
- Option 2: Revenir au noyau précédent (5.15.0-82-generic)
1. Redémarrer le serveur avec l'ancien noyau:
sudo reboot
2. Dans le GRUB, sélectionner le noyau 5.15.0-82-generic.⚠️ Impact : Le serveur ne bénéficie pas des correctifs de sécurité du noyau 5.15.0-86.
- Option 3: Limiter le nombre de threads pour Apache
1. Modifier la configuration Apache (/etc/apache2/apache2.conf) :
StartServers 2
MinSpareThreads 5
MaxSpareThreads 10
ThreadsPerChild 5
MaxRequestWorkers 20
2. Redémarrer Apache :
sudo systemctl restart apache2
⚠️ Impact : Réduction des performances (moins de requêtes simultanées gérées).</workaround>
<solution>- Action: Mettre à jour mod_security2 vers la version 2.9.6 (compatible avec le noyau 5.15.0-86).
+ Version corrigée : libapache2-mod-security2 2.9.6-1ubuntu0.22.04.1 (disponible dans les dépôts Ubuntu proposed).
- Responsable : Équipe DevOps + Sécurité.
- Date prévue : 17 juillet 2026 (fenêtre de maintenance de 02:00 à 04:00).
- Procédure :
1. Ajouter le dépôt proposed :
sudo add-apt-repository ppa:ubuntu-security-proposed
sudo apt update
2. Mettre à jour mod_security2 :
sudo apt install --only-upgrade libapache2-mod-security2
3. Redémarrer Apache :
sudo systemctl restart apache2
4. Vérifier la version:
apache2ctl -M | grep security</solution>
<error_code></error_code>
<domain>Application</domain>
<vendor>Linux</vendor>
<model>Apache</model>
<version>2.4.52</version>
</KnownError>
</Set>

View File

@@ -25,6 +25,8 @@ SetupWebPage::AddModule(
//'data.struct.itop-knownerror-mgmt.xml',
],
'data.sample' => [
'data/data.sample.knownerror.en_us.xml',
'data/data.sample.errortofunctionalci.xml',
],
// Documentation

View File

@@ -50,13 +50,13 @@ const oOpenSignInWindow = function (url, name) {
then we load it in the already opened secondary window, and then
we bring such window back on top/in front of its parent window. */
oWindowObjectReference = window.open(url, name, sWindowFeatures);
oWindowObjectReference.trigger('focus');
oWindowObjectReference.focus();
} else {
/* Else the window reference must exist and the window
is not closed; therefore, we can bring it back on top of any other
window with the focus() method. There would be no need to re-create
the window or to reload the referenced resource. */
oWindowObjectReference.trigger('focus');
oWindowObjectReference.focus();
}
/* Let know every second our child window that we're waiting for it to complete,
once we reach our landing page, it'll send us a reply

View File

@@ -28,7 +28,7 @@ SetupWebPage::AddModule(
'category' => 'Portal',
// Setup
'dependencies' => [
'itop-attachments/3.2.1', //CMDBChangeOpAttachmentRemoved
'itop-attachments/3.2.1||true', //CMDBChangeOpAttachmentRemoved
],
'mandatory' => true,
'visible' => false,

File diff suppressed because one or more lines are too long

View File

@@ -36,7 +36,7 @@ $ipb-field--is-mandatory--font-size: 0.6rem !default;
.form_field_label > .control-label[data-tooltip-instantiated="true"]:after {
cursor: pointer;
@extend %common-font-size-50;
@extend %common-font-size-20;
}
.form_field .form_mandatory .control-label:after{

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,7 @@ $ipb--fieldset--border: 1px solid $ipb--fieldset--border-color !default;
$ipb--fieldset--inside--fieldset--background-color: $ipb-color-grey-100 !default;
$ipb-field--has-tooltip--content: "\f05a" !default;
$ipb-field--has-tooltip--content: "\f128" !default;
$ipb-field--has-tooltip--color: $ipb-color-grey-700 !default;
$ipb-field--is-mandatory--content: "\f069" !default;

View File

@@ -17,4 +17,8 @@ $ipb-vendors-ckeditor--ck-content--text-color: $ipb-color-grey-900 !default;
.ipb-is-html-content {
@extend .ck-content;
}
.ck-source-editing-area {
height: 180px;
}

View File

@@ -36,20 +36,24 @@ class IpbDropdown extends HTMLElement {
return;
}
button.addEventListener('click', (event) => {
event.stopPropagation();
const isOpen = menu.classList.contains('show');
document.querySelectorAll('ipb-dropdown.show').forEach(m => m.classList.remove('show'));
// N°9385 - add a test in order to know if the event addEventListener is already added to the button, if not add it
if ($(button).data('has_listener') === undefined) {
button.addEventListener('click', (event) => {
event.stopPropagation();
const isOpen = menu.classList.contains('show');
document.querySelectorAll('ipb-dropdown.show').forEach(m => m.classList.remove('show'));
if (!isOpen) {
menu.classList.add('show');
if (container === 'body') {
this.moveToBody(menu);
}
this.changePlacement(menu, button);
this.changeZIndex(menu, button);
}
});
if (!isOpen) {
menu.classList.add('show');
if (container === 'body') {
this.moveToBody(menu);
}
this.changePlacement(menu, button);
this.changeZIndex(menu, button);
}
});
$(button).data('has_listener', true);
}
let me = this;
document.addEventListener('click', (event) => {

View File

@@ -689,7 +689,7 @@ class ManageBrickController extends BrickController
$sValue = $oAttDef->GetAsHTML($oCurrentRow->Get($sItemAttr));
$sSortValue = $oCurrentRow->Get($sItemAttr);
}
$sAttType = $oAttDef->GetType();
$sAttType = $oAttDef->GetTypeShortClassName();
unset($oAttDef);
// For simple fields, we get the raw (stored) value as well

View File

@@ -1385,7 +1385,7 @@ class ObjectController extends BrickController
'object_id' => $oNewLink->GetKey(),
'prefix' => 'lnk__',
'attribute_code' => $sAttCode,
'attribute_type' => $oAttDef->GetType(),
'attribute_type' => $oAttDef->GetTypeShortClassName(),
'value_html' => $sValue,
];
@@ -1442,7 +1442,7 @@ class ObjectController extends BrickController
'object_class' => $sObjectClass,
'object_id' => $oObject->GetKey(),
'attribute_code' => $oAttDef->GetCode(),
'attribute_type' => $oAttDef->GetType(),
'attribute_type' => $oAttDef->GetTypeShortClassName(),
];
// - Value raw

View File

@@ -324,7 +324,7 @@ class BrowseBrickHelper
'object_class' => $sCurrentObjectClass,
'object_id' => $sCurrentObjectId,
'attribute_code' => $sNameAttCode,
'attribute_type' => $sNameAttDef->GetType(),
'attribute_type' => $sNameAttDef->GetTypeShortClassName(),
'value_raw' => $value->Get($sNameAttCode),
],
];
@@ -415,7 +415,7 @@ class BrowseBrickHelper
'object_class' => $sCurrentObjectClass,
'object_id' => $sCurrentObjectId,
'attribute_code' => $aField['code'],
'attribute_type' => $oAttDef->GetType(),
'attribute_type' => $oAttDef->GetTypeShortClassName(),
'value_raw' => $attValueRaw,
'value_html' => $sHtmlForFieldValue,
];

View File

@@ -85,6 +85,13 @@
<class id="Attachment"/>
</classes>
</group>
<group id="Ticket" _delta="define">
<classes>
<class id="Ticket"/>
<class id="WorkOrder"/>
<class id="Attachment"/>
</classes>
</group>
<group id="Portal" _delta="define">
<classes>
<class id="lnkFunctionalCIToTicket"/>
@@ -205,6 +212,60 @@
</group>
</groups>
<profiles>
<profile id="5500" _delta="define">
<name>Configuration ReadOnly</name>
<description>This read-only profile allows to see CIs objects.</description>
<groups>
<group id="Configuration">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
<group id="General">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="5501" _delta="define">
<name>Ticket ReadOnly</name>
<description>This read-only profile allows to see Ticket objects.</description>
<groups>
<group id="Ticket">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
<group id="General">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="5502" _delta="define">
<name>Service Catalog ReadOnly</name>
<description>This read-only profile allows to see Service Catalog objects.</description>
<groups>
<group id="Service">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
<group id="General">
<actions>
<action id="action:read">allow</action>
<action id="action:bulk read">allow</action>
</actions>
</group>
</groups>
</profile>
<profile id="117" _delta="define">
<name>SuperUser</name>
<description>This profile allows all actions which are not Administrator restricted.</description>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ContractType alias="ContractType" id="78">
<name>Hosting</name>
</ContractType>
<ContractType alias="ContractType" id="79">
<name>IT-Outsourcing</name>
</ContractType>
<ContractType alias="ContractType" id="77">
<name>Wartung</name>
</ContractType>
<ContractType alias="ContractType" id="76">
<name>Support</name>
</ContractType>
</Set>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<CustomerContract alias="CustomerContract" id="3">
<name>Kundenvertrag</name>
<org_id>7</org_id>
<description>Kundenvertrag zur Bereitstellung von Services fuer einen externen Kunden.</description>
<start_date>2026-01-01</start_date>
<end_date>2030-12-31</end_date>
<cost>10000</cost>
<cost_currency>euros</cost_currency>
<contracttype_id>79</contracttype_id>
<billing_frequency>yearly</billing_frequency>
<provider_id>2</provider_id>
<status>production</status>
</CustomerContract>
<CustomerContract alias="CustomerContract" id="1">
<name>Kundenvertrag Vertriebsabteilung</name>
<org_id>6</org_id>
<description>Interner Vertrag zur Bereitstellung von Services fuer die Vertriebsabteilung</description>
<start_date>2019-01-01</start_date>
<end_date>2030-12-31</end_date>
<cost>0</cost>
<cost_currency>euros</cost_currency>
<contracttype_id>0</contracttype_id>
<billing_frequency>monthly</billing_frequency>
<provider_id>2</provider_id>
<status>production</status>
</CustomerContract>
</Set>

View File

@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ServiceSubcategory alias="ServiceSubcategory" id="28">
<name>Zugriffsprobleme</name>
<description>Hilfe bei einem Zugriffsproblem anfordern</description>
<service_id>7</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="17">
<name>API-Integration</name>
<description>Verbindung zwischen internen und externen Anwendungen.</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="13">
<name>CRM (z. B. Salesforce, HubSpot)</name>
<description>Einrichtung, Anpassung und Support für das Customer-Relationship-Management.</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="22">
<name>Sensibilisierung für Cybersicherheit</name>
<description>Schulung der Mitarbeitenden zu bewährten Praktiken (Phishing, Passwörter usw.).</description>
<service_id>6</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="3">
<name>Datensicherung</name>
<description>Automatische Sicherung kritischer Dateien (täglich/wöchentlich/monatlich).</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="21">
<name>Datenschutz (DSGVO)</name>
<description>Unterstützung bei der Einhaltung gesetzlicher Vorgaben (DSGVO, HIPAA usw.).</description>
<service_id>6</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="1">
<name>ERP (z. B. SAP, Odoo)</name>
<description>Zugriff, Support und Schulung für integrierte Managementsoftware.</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="10">
<name>Dateispeicherung und -freigabe</name>
<description>Bereitstellung kollaborativer Speicherbereiche (z. B. SharePoint, Nextcloud).</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="12">
<name>Hardwarevorfall</name>
<description>Unterstützung bei einem Hardwareausfall anfordern.</description>
<service_id>1</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="19">
<name>Hardware-Upgrade</name>
<description>Austausch oder Erweiterung von Komponenten (RAM, Festplatte usw.).</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="7">
<name>Lokales Netzwerk (LAN/Wi-Fi)</name>
<description>Installation, Konfiguration und Wartung von Netzwerkgeräten.</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="27">
<name>Multi-Faktor-Authentifizierung (MFA)</name>
<description>Konfiguration und Support für Multi-Faktor-Authentifizierung.</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="4">
<name>Fehlerbehebung im Netzwerk</name>
<description>Hilfe bei der Behebung eines Netzwerkproblems anfordern.</description>
<service_id>3</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="5">
<name>Bestellung neuer Desktop-Computer</name>
<description>Einen neuen Desktop-Computer für neue Mitarbeitende oder als Ersatz für ein altes System bestellen.</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="8">
<name>Bestellung neuer Laptops</name>
<description>Einen neuen Laptop für mobile Mitarbeitende oder als Ersatz für ein altes Gerät bestellen.</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="11">
<name>Neues Peripheriegerät</name>
<description>Ein Peripheriegerät bestellen: Tastatur, Maus, persönlicher Drucker ...</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="20">
<name>Sicherheitsaudit</name>
<description>Schwachstellenanalysen, Penetrationstests und Empfehlungen.</description>
<service_id>6</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="23">
<name>Sicherheitsvorfall</name>
<description>Reaktion auf Cyberangriffe, Datenlecks oder Sicherheitsverletzungen.</description>
<service_id>6</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="6">
<name>Serververwaltung</name>
<description>Präventive Wartung, Software-Updates und 24/7-Überwachung.</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="16">
<name>Softwarevorfall</name>
<description>Hilfe bei der Behebung eines Softwareproblems anfordern.</description>
<service_id>1</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="15">
<name>Softwarevorfall</name>
<description>Unterstützung bei einem softwarebezogenen Problem anfordern.</description>
<service_id>2</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="18">
<name>Softwareinstallation</name>
<description>Bereitstellung von Office-Software (z. B. Microsoft 365, LibreOffice) und Geschäftssoftware.</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="14">
<name>Individuelle Entwicklung</name>
<description>Entwicklung maßgeschneiderter Tools (Dashboards, Automatisierungen, Skripte).</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="24">
<name>Benutzerkonto-Erstellung</name>
<description>Erstellung von Konten für neue Mitarbeitende oder Auftragnehmer.</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="26">
<name>Benutzerkonto-Löschung</name>
<description>Deaktivierung von Konten für ausscheidende Mitarbeitende oder am Ende ihrer Verträge.</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="25">
<name>Benutzerkonto-Aktualisierung</name>
<description>Hinzufügen oder Entfernen von Berechtigungen (z. B. Zugriff auf einen freigegebenen Ordner oder eine Anwendung).</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="2">
<name>VPN-Zugriff</name>
<description>Konfiguration und Support für sicheren Fernzugriff auf interne Ressourcen.</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
</Set>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ServiceFamily alias="ServiceFamily" id="1">
<name>IT-Services</name>
<icon>
<mimetype>image/svg+xml</mimetype>
<filename>icons8-open-end-wrench.svg</filename>
<data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNDBweCIgaGVpZ2h0PSIyNDBweCI+PHJhZGlhbEdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2phIiBjeD0iOS4xNjkiIGN5PSIzOC42NyIgcj0iMTIuMTM1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuNzA2IiBzdG9wLWNvbG9yPSIjNzg3Zjg1Ii8+PHN0b3Agb2Zmc2V0PSIuNzEzIiBzdG9wLWNvbG9yPSIjN2E4MTg3Ii8+PHN0b3Agb2Zmc2V0PSIuNzkzIiBzdG9wLWNvbG9yPSIjOTA5ODlmIi8+PHN0b3Agb2Zmc2V0PSIuODY4IiBzdG9wLWNvbG9yPSIjOWRhNWFlIi8+PHN0b3Agb2Zmc2V0PSIuOTMiIHN0b3AtY29sb3I9IiNhMWFhYjMiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjMEJESnMzV3RwcE1nbzRZOUE3R2dqYSkiIGQ9Ik0xOS45MTUsMjEuOGMtNC42NzksNC42NzktOS4zNzUsOS4zNzUtOS41NTEsOS41NTFsNi4zNjQsNi4zNjQgYzAuMTc3LTAuMTc3LDQuODcyLTQuODcyLDkuNTUxLTkuNTUxTDE5LjkxNSwyMS44eiIvPjxyYWRpYWxHcmFkaWVudCBpZD0iMEJESnMzV3RwcE1nbzRZOUE3R2dqYiIgY3g9IjEzLjQyNSIgY3k9IjM1LjQ5OSIgcj0iMTQuNjg4IiBncmFkaWVudFRyYW5zZm9ybT0icm90YXRlKDE4MCAyNC4zMjIgMjMuNzU4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjcwNiIgc3RvcC1jb2xvcj0iIzc4N2Y4NSIvPjxzdG9wIG9mZnNldD0iLjcxMyIgc3RvcC1jb2xvcj0iIzdhODE4NyIvPjxzdG9wIG9mZnNldD0iLjc5MyIgc3RvcC1jb2xvcj0iIzkwOTg5ZiIvPjxzdG9wIG9mZnNldD0iLjg2OCIgc3RvcC1jb2xvcj0iIzlkYTVhZSIvPjxzdG9wIG9mZnNldD0iLjkzIiBzdG9wLWNvbG9yPSIjYTFhYWIzIi8+PC9yYWRpYWxHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoIzBCREpzM1d0cHBNZ280WTlBN0dnamIpIiBkPSJNMjQuNzI4LDI5LjcxNWM0LjY3OS00LjY3OSw5LjM3NS05LjM3NSw5LjU1MS05LjU1MUwyNy45MTUsMTMuOCBjLTAuMTc3LDAuMTc3LTQuODcyLDQuODcyLTkuNTUxLDkuNTUxTDI0LjcyOCwyOS43MTV6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2pjIiB4MT0iMjIuMTE5IiB4Mj0iMzMuOTI2IiB5MT0iLTI1NTIuODgzIiB5Mj0iLTI1NjQuNjkiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMzkuMDQ2IDI1OTguMDMzKSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzhmOTc5ZSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ExYWFiMyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCMwQkRKczNXdHBwTWdvNFk5QTdHZ2pkKSIgZD0iTTQwLjY2MiwxMy4zMTJjLTEuNjk1LDEuNjk1LTQuNDQ1LDEuNjk1LTYuMTM5LDBzLTEuNjk1LTQuNDQ1LDAtNi4xMzkgYzAuNDE0LTAuNDE0LDIuMDgxLTIuMDgxLDMuNzgtMy43OGMwLjQwNy0wLjQwNywwLjIyNi0xLjExOS0wLjMzMi0xLjI1NmMtMS4zNzctMC4zMzgtMi44NTgtMC40MDktNC4zOTktMC4xMTkgYy00LjUxOSwwLjg1Mi04LjA0Myw0LjYzMy04LjUxMiw5LjIwN2MtMC42ODQsNi42Nyw0Ljg4MywxMi4yMzYsMTEuNTUzLDExLjU1MWM0LjU3NC0wLjQ3LDguMzU1LTMuOTk0LDkuMjA2LTguNTEzIGMwLjI5LTEuNTQxLDAuMjE5LTMuMDIxLTAuMTE5LTQuMzk4Yy0wLjEzOC0wLjU2LTAuODQ5LTAuNzQxLTEuMjU2LTAuMzMyQzQyLjc0MywxMS4yMzEsNDEuMDc2LDEyLjg5OSw0MC42NjIsMTMuMzEyeiIvPjwvc3ZnPgo=</data>
<downloads_count>0</downloads_count>
</icon>
</ServiceFamily>
</Set>

File diff suppressed because one or more lines are too long

View File

@@ -29,10 +29,10 @@
</icon>
</Service>
<Service alias="Service" id="1">
<name>Computers and peripherals</name>
<name>Ordinateurs et périphériques</name>
<org_id>2</org_id>
<servicefamily_id>1</servicefamily_id>
<description>Ordering of new hardware (Desktop computer, laptop computer, monitor, mouse, keyboard...) and support in case of hardware failure.</description>
<description>Commande de nouveau matériel (ordinateur de bureau, ordinateur portable, écran, souris, clavier...) et support en cas de panne matérielle.</description>
<status>production</status>
<icon>
<mimetype>image/svg+xml</mimetype>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<SLA alias="SLA" id="4">
<name>SLA Bronze</name>
<description>Service-Level-Agreement Bronze fuer Services mit niedriger Kritikalitaet</description>
<org_id>2</org_id>
</SLA>
<SLA alias="SLA" id="2">
<name>SLA Gold</name>
<description>Service-Level-Agreement Gold fuer Services mit hoher Kritikalitaet</description>
<org_id>2</org_id>
</SLA>
<SLA alias="SLA" id="3">
<name>SLA Silver</name>
<description>Service-Level-Agreement Silver fuer Services mit mittlerer Kritikalitaet</description>
<org_id>2</org_id>
</SLA>
</Set>

View File

@@ -0,0 +1,387 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<SLT alias="SLT" id="5">
<name>TTO Vorfall Priorität kritisch 1 Stunde</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="3">
<name>TTO Vorfall Priorität kritisch 15 Minuten</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>15</value>
<unit>minutes</unit>
</SLT>
<SLT alias="SLT" id="4">
<name>TTO Vorfall Priorität kritisch 30 Minuten</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>30</value>
<unit>minutes</unit>
</SLT>
<SLT alias="SLT" id="7">
<name>TTO Vorfall Priorität hoch 1 Stunde</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="8">
<name>TTO Vorfall Priorität hoch 2 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="6">
<name>TTO Vorfall Priorität hoch 30 Minuten</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>30</value>
<unit>minutes</unit>
</SLT>
<SLT alias="SLT" id="12">
<name>TTO Vorfall Priorität niedrig 2 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="13">
<name>TTO Vorfall Priorität niedrig 4 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="14">
<name>TTO Vorfall Priorität niedrig 8 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="9">
<name>TTO Vorfall Priorität mittel 1 Stunde</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="10">
<name>TTO Vorfall Priorität mittel 2 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="11">
<name>TTO Vorfall Priorität mittel 4 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="27">
<name>TTO Serviceanfrage Priorität kritisch 1 Stunde</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="28">
<name>TTO Serviceanfrage Priorität kritisch 2 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="29">
<name>TTO Serviceanfrage Priorität kritisch 4 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="30">
<name>TTO Serviceanfrage Priorität hoch 2 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="31">
<name>TTO Serviceanfrage Priorität hoch 4 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="32">
<name>TTO Serviceanfrage Priorität hoch 8 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="37">
<name>TTO Serviceanfrage Priorität niedrig 16 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="38">
<name>TTO Serviceanfrage Priorität niedrig 32 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="36">
<name>TTO Serviceanfrage Priorität niedrig 8 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="35">
<name>TTO Serviceanfrage Priorität mittel 16 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="33">
<name>TTO Serviceanfrage Priorität mittel 4 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="34">
<name>TTO Serviceanfrage Priorität mittel 8 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="15">
<name>TTR Vorfall Priorität kritisch 1 Stunde</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="16">
<name>TTR Vorfall Priorität kritisch 2 Stunden</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="17">
<name>TTR Vorfall Priorität kritisch 4 Stunden</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="18">
<name>TTR Vorfall Priorität hoch 2 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="19">
<name>TTR Vorfall Priorität hoch 4 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="20">
<name>TTR Vorfall Priorität hoch 8 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="25">
<name>TTR Vorfall Priorität niedrig 16 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="26">
<name>TTR Vorfall Priorität niedrig 32 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="24">
<name>TTR Vorfall Priorität niedrig 8 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="23">
<name>TTR Vorfall Priorität mittel 16 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="21">
<name>TTR Vorfall Priorität mittel 4 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="22">
<name>TTR Vorfall Priorität mittel 8 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="41">
<name>TTR Serviceanfrage Priorität kritisch 16 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="39">
<name>TTR Serviceanfrage Priorität kritisch 4 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="40">
<name>TTR Serviceanfrage Priorität kritisch 8 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="43">
<name>TTR Serviceanfrage Priorität hoch 16 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="44">
<name>TTR Serviceanfrage Priorität hoch 32 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="42">
<name>TTR Serviceanfrage Priorität hoch 8 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="50">
<name>TTR Serviceanfrage Priorität niedrig 128 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>128</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="48">
<name>TTR Serviceanfrage Priorität niedrig 32 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="49">
<name>TTR Serviceanfrage Priorität niedrig 64 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>64</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="45">
<name>TTR Serviceanfrage Priorität mittel 16 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="46">
<name>TTR Serviceanfrage Priorität mittel 32 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="47">
<name>TTR Serviceanfrage Priorität mittel 64 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>64</value>
<unit>hours</unit>
</SLT>
</Set>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ContractType alias="ContractType" id="78">
<name>Hosting</name>
</ContractType>
<ContractType alias="ContractType" id="79">
<name>IT-Outsourcing</name>
</ContractType>
<ContractType alias="ContractType" id="77">
<name>Wartung</name>
</ContractType>
<ContractType alias="ContractType" id="76">
<name>Support</name>
</ContractType>
</Set>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<CustomerContract alias="CustomerContract" id="3">
<name>Kundenvertrag</name>
<org_id>7</org_id>
<description>Kundenvertrag zur Bereitstellung von Services fuer einen externen Kunden.</description>
<start_date>2026-01-01</start_date>
<end_date>2030-12-31</end_date>
<cost>10000</cost>
<cost_currency>euros</cost_currency>
<contracttype_id>79</contracttype_id>
<billing_frequency>yearly</billing_frequency>
<provider_id>2</provider_id>
<status>production</status>
</CustomerContract>
<CustomerContract alias="CustomerContract" id="1">
<name>Kundenvertrag Vertriebsabteilung</name>
<org_id>6</org_id>
<description>Interner Vertrag zur Bereitstellung von Services fuer die Vertriebsabteilung</description>
<start_date>2019-01-01</start_date>
<end_date>2030-12-31</end_date>
<cost>0</cost>
<cost_currency>euros</cost_currency>
<contracttype_id>0</contracttype_id>
<billing_frequency>monthly</billing_frequency>
<provider_id>2</provider_id>
<status>production</status>
</CustomerContract>
</Set>

View File

@@ -0,0 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ServiceSubcategory alias="ServiceSubcategory" id="28">
<name>Zugriffsprobleme</name>
<description>Hilfe bei einem Zugriffsproblem anfordern</description>
<service_id>7</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="17">
<name>API-Integration</name>
<description>Verbindung zwischen internen und externen Anwendungen.</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="13">
<name>CRM (z. B. Salesforce, HubSpot)</name>
<description>Einrichtung, Anpassung und Support für das Customer-Relationship-Management.</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="22">
<name>Sensibilisierung für Cybersicherheit</name>
<description>Schulung der Mitarbeitenden zu bewährten Praktiken (Phishing, Passwörter usw.).</description>
<service_id>6</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="3">
<name>Datensicherung</name>
<description>Automatische Sicherung kritischer Dateien (täglich/wöchentlich/monatlich).</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="21">
<name>Datenschutz (DSGVO)</name>
<description>Unterstützung bei der Einhaltung gesetzlicher Vorgaben (DSGVO, HIPAA usw.).</description>
<service_id>6</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="1">
<name>ERP (z. B. SAP, Odoo)</name>
<description>Zugriff, Support und Schulung für integrierte Managementsoftware.</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="10">
<name>Dateispeicherung und -freigabe</name>
<description>Bereitstellung kollaborativer Speicherbereiche (z. B. SharePoint, Nextcloud).</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="12">
<name>Hardwarevorfall</name>
<description>Unterstützung bei einem Hardwareausfall anfordern.</description>
<service_id>1</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="19">
<name>Hardware-Upgrade</name>
<description>Austausch oder Erweiterung von Komponenten (RAM, Festplatte usw.).</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="7">
<name>Lokales Netzwerk (LAN/Wi-Fi)</name>
<description>Installation, Konfiguration und Wartung von Netzwerkgeräten.</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="27">
<name>Multi-Faktor-Authentifizierung (MFA)</name>
<description>Konfiguration und Support für Multi-Faktor-Authentifizierung.</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="4">
<name>Fehlerbehebung im Netzwerk</name>
<description>Hilfe bei der Behebung eines Netzwerkproblems anfordern.</description>
<service_id>3</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="5">
<name>Bestellung neuer Desktop-Computer</name>
<description>Einen neuen Desktop-Computer für neue Mitarbeitende oder als Ersatz für ein altes System bestellen.</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="8">
<name>Bestellung neuer Laptops</name>
<description>Einen neuen Laptop für mobile Mitarbeitende oder als Ersatz für ein altes Gerät bestellen.</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="11">
<name>Neues Peripheriegerät</name>
<description>Ein Peripheriegerät bestellen: Tastatur, Maus, persönlicher Drucker ...</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="20">
<name>Sicherheitsaudit</name>
<description>Schwachstellenanalysen, Penetrationstests und Empfehlungen.</description>
<service_id>6</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="23">
<name>Sicherheitsvorfall</name>
<description>Reaktion auf Cyberangriffe, Datenlecks oder Sicherheitsverletzungen.</description>
<service_id>6</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="6">
<name>Serververwaltung</name>
<description>Präventive Wartung, Software-Updates und 24/7-Überwachung.</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="16">
<name>Softwarevorfall</name>
<description>Hilfe bei der Behebung eines Softwareproblems anfordern.</description>
<service_id>1</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="15">
<name>Softwarevorfall</name>
<description>Unterstützung bei einem softwarebezogenen Problem anfordern.</description>
<service_id>2</service_id>
<request_type>incident</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="18">
<name>Softwareinstallation</name>
<description>Bereitstellung von Office-Software (z. B. Microsoft 365, LibreOffice) und Geschäftssoftware.</description>
<service_id>1</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="14">
<name>Individuelle Entwicklung</name>
<description>Entwicklung maßgeschneiderter Tools (Dashboards, Automatisierungen, Skripte).</description>
<service_id>2</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="24">
<name>Benutzerkonto-Erstellung</name>
<description>Erstellung von Konten für neue Mitarbeitende oder Auftragnehmer.</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="26">
<name>Benutzerkonto-Löschung</name>
<description>Deaktivierung von Konten für ausscheidende Mitarbeitende oder am Ende ihrer Verträge.</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="25">
<name>Benutzerkonto-Aktualisierung</name>
<description>Hinzufügen oder Entfernen von Berechtigungen (z. B. Zugriff auf einen freigegebenen Ordner oder eine Anwendung).</description>
<service_id>7</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
<ServiceSubcategory alias="ServiceSubcategory" id="2">
<name>VPN-Zugriff</name>
<description>Konfiguration und Support für sicheren Fernzugriff auf interne Ressourcen.</description>
<service_id>3</service_id>
<request_type>service_request</request_type>
<status>production</status>
<approvalrule_id>0</approvalrule_id>
</ServiceSubcategory>
</Set>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ServiceFamily alias="ServiceFamily" id="1">
<name>IT-Services</name>
<icon>
<mimetype>image/svg+xml</mimetype>
<filename>icons8-open-end-wrench.svg</filename>
<data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNDBweCIgaGVpZ2h0PSIyNDBweCI+PHJhZGlhbEdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2phIiBjeD0iOS4xNjkiIGN5PSIzOC42NyIgcj0iMTIuMTM1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuNzA2IiBzdG9wLWNvbG9yPSIjNzg3Zjg1Ii8+PHN0b3Agb2Zmc2V0PSIuNzEzIiBzdG9wLWNvbG9yPSIjN2E4MTg3Ii8+PHN0b3Agb2Zmc2V0PSIuNzkzIiBzdG9wLWNvbG9yPSIjOTA5ODlmIi8+PHN0b3Agb2Zmc2V0PSIuODY4IiBzdG9wLWNvbG9yPSIjOWRhNWFlIi8+PHN0b3Agb2Zmc2V0PSIuOTMiIHN0b3AtY29sb3I9IiNhMWFhYjMiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjMEJESnMzV3RwcE1nbzRZOUE3R2dqYSkiIGQ9Ik0xOS45MTUsMjEuOGMtNC42NzksNC42NzktOS4zNzUsOS4zNzUtOS41NTEsOS41NTFsNi4zNjQsNi4zNjQgYzAuMTc3LTAuMTc3LDQuODcyLTQuODcyLDkuNTUxLTkuNTUxTDE5LjkxNSwyMS44eiIvPjxyYWRpYWxHcmFkaWVudCBpZD0iMEJESnMzV3RwcE1nbzRZOUE3R2dqYiIgY3g9IjEzLjQyNSIgY3k9IjM1LjQ5OSIgcj0iMTQuNjg4IiBncmFkaWVudFRyYW5zZm9ybT0icm90YXRlKDE4MCAyNC4zMjIgMjMuNzU4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjcwNiIgc3RvcC1jb2xvcj0iIzc4N2Y4NSIvPjxzdG9wIG9mZnNldD0iLjcxMyIgc3RvcC1jb2xvcj0iIzdhODE4NyIvPjxzdG9wIG9mZnNldD0iLjc5MyIgc3RvcC1jb2xvcj0iIzkwOTg5ZiIvPjxzdG9wIG9mZnNldD0iLjg2OCIgc3RvcC1jb2xvcj0iIzlkYTVhZSIvPjxzdG9wIG9mZnNldD0iLjkzIiBzdG9wLWNvbG9yPSIjYTFhYWIzIi8+PC9yYWRpYWxHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoIzBCREpzM1d0cHBNZ280WTlBN0dnamIpIiBkPSJNMjQuNzI4LDI5LjcxNWM0LjY3OS00LjY3OSw5LjM3NS05LjM3NSw5LjU1MS05LjU1MUwyNy45MTUsMTMuOCBjLTAuMTc3LDAuMTc3LTQuODcyLDQuODcyLTkuNTUxLDkuNTUxTDI0LjcyOCwyOS43MTV6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2pjIiB4MT0iMjIuMTE5IiB4Mj0iMzMuOTI2IiB5MT0iLTI1NTIuODgzIiB5Mj0iLTI1NjQuNjkiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMzkuMDQ2IDI1OTguMDMzKSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzhmOTc5ZSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ExYWFiMyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCMwQkRKczNXdHBwTWdvNFk5QTdHZ2pkKSIgZD0iTTQwLjY2MiwxMy4zMTJjLTEuNjk1LDEuNjk1LTQuNDQ1LDEuNjk1LTYuMTM5LDBzLTEuNjk1LTQuNDQ1LDAtNi4xMzkgYzAuNDE0LTAuNDE0LDIuMDgxLTIuMDgxLDMuNzgtMy43OGMwLjQwNy0wLjQwNywwLjIyNi0xLjExOS0wLjMzMi0xLjI1NmMtMS4zNzctMC4zMzgtMi44NTgtMC40MDktNC4zOTktMC4xMTkgYy00LjUxOSwwLjg1Mi04LjA0Myw0LjYzMy04LjUxMiw5LjIwN2MtMC42ODQsNi42Nyw0Ljg4MywxMi4yMzYsMTEuNTUzLDExLjU1MWM0LjU3NC0wLjQ3LDguMzU1LTMuOTk0LDkuMjA2LTguNTEzIGMwLjI5LTEuNTQxLDAuMjE5LTMuMDIxLTAuMTE5LTQuMzk4Yy0wLjEzOC0wLjU2LTAuODQ5LTAuNzQxLTEuMjU2LTAuMzMyQzQyLjc0MywxMS4yMzEsNDEuMDc2LDEyLjg5OSw0MC42NjIsMTMuMzEyeiIvPjwvc3ZnPgo=</data>
<downloads_count>0</downloads_count>
</icon>
</ServiceFamily>
</Set>

File diff suppressed because one or more lines are too long

View File

@@ -29,10 +29,10 @@
</icon>
</Service>
<Service alias="Service" id="1">
<name>Computers and peripherals</name>
<name>Ordinateurs et périphériques</name>
<org_id>2</org_id>
<servicefamily_id>1</servicefamily_id>
<description>Ordering of new hardware (Desktop computer, laptop computer, monitor, mouse, keyboard...) and support in case of hardware failure.</description>
<description>Commande de nouveau matériel (ordinateur de bureau, ordinateur portable, écran, souris, clavier...) et support en cas de panne matérielle.</description>
<status>production</status>
<icon>
<mimetype>image/svg+xml</mimetype>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<SLA alias="SLA" id="4">
<name>SLA Bronze</name>
<description>Service-Level-Agreement Bronze fuer Services mit niedriger Kritikalitaet</description>
<org_id>2</org_id>
</SLA>
<SLA alias="SLA" id="2">
<name>SLA Gold</name>
<description>Service-Level-Agreement Gold fuer Services mit hoher Kritikalitaet</description>
<org_id>2</org_id>
</SLA>
<SLA alias="SLA" id="3">
<name>SLA Silver</name>
<description>Service-Level-Agreement Silver fuer Services mit mittlerer Kritikalitaet</description>
<org_id>2</org_id>
</SLA>
</Set>

View File

@@ -0,0 +1,387 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<SLT alias="SLT" id="5">
<name>TTO Vorfall Priorität kritisch 1 Stunde</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="3">
<name>TTO Vorfall Priorität kritisch 15 Minuten</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>15</value>
<unit>minutes</unit>
</SLT>
<SLT alias="SLT" id="4">
<name>TTO Vorfall Priorität kritisch 30 Minuten</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>30</value>
<unit>minutes</unit>
</SLT>
<SLT alias="SLT" id="7">
<name>TTO Vorfall Priorität hoch 1 Stunde</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="8">
<name>TTO Vorfall Priorität hoch 2 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="6">
<name>TTO Vorfall Priorität hoch 30 Minuten</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>30</value>
<unit>minutes</unit>
</SLT>
<SLT alias="SLT" id="12">
<name>TTO Vorfall Priorität niedrig 2 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="13">
<name>TTO Vorfall Priorität niedrig 4 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="14">
<name>TTO Vorfall Priorität niedrig 8 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="9">
<name>TTO Vorfall Priorität mittel 1 Stunde</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="10">
<name>TTO Vorfall Priorität mittel 2 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="11">
<name>TTO Vorfall Priorität mittel 4 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="27">
<name>TTO Serviceanfrage Priorität kritisch 1 Stunde</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="28">
<name>TTO Serviceanfrage Priorität kritisch 2 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="29">
<name>TTO Serviceanfrage Priorität kritisch 4 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="30">
<name>TTO Serviceanfrage Priorität hoch 2 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="31">
<name>TTO Serviceanfrage Priorität hoch 4 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="32">
<name>TTO Serviceanfrage Priorität hoch 8 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="37">
<name>TTO Serviceanfrage Priorität niedrig 16 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="38">
<name>TTO Serviceanfrage Priorität niedrig 32 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="36">
<name>TTO Serviceanfrage Priorität niedrig 8 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="35">
<name>TTO Serviceanfrage Priorität mittel 16 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="33">
<name>TTO Serviceanfrage Priorität mittel 4 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="34">
<name>TTO Serviceanfrage Priorität mittel 8 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>tto</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="15">
<name>TTR Vorfall Priorität kritisch 1 Stunde</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>1</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="16">
<name>TTR Vorfall Priorität kritisch 2 Stunden</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="17">
<name>TTR Vorfall Priorität kritisch 4 Stunden</name>
<priority>1</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="18">
<name>TTR Vorfall Priorität hoch 2 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>2</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="19">
<name>TTR Vorfall Priorität hoch 4 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="20">
<name>TTR Vorfall Priorität hoch 8 Stunden</name>
<priority>2</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="25">
<name>TTR Vorfall Priorität niedrig 16 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="26">
<name>TTR Vorfall Priorität niedrig 32 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="24">
<name>TTR Vorfall Priorität niedrig 8 Stunden</name>
<priority>4</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="23">
<name>TTR Vorfall Priorität mittel 16 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="21">
<name>TTR Vorfall Priorität mittel 4 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="22">
<name>TTR Vorfall Priorität mittel 8 Stunden</name>
<priority>3</priority>
<request_type>incident</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="41">
<name>TTR Serviceanfrage Priorität kritisch 16 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="39">
<name>TTR Serviceanfrage Priorität kritisch 4 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>4</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="40">
<name>TTR Serviceanfrage Priorität kritisch 8 Stunden</name>
<priority>1</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="43">
<name>TTR Serviceanfrage Priorität hoch 16 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="44">
<name>TTR Serviceanfrage Priorität hoch 32 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="42">
<name>TTR Serviceanfrage Priorität hoch 8 Stunden</name>
<priority>2</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>8</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="50">
<name>TTR Serviceanfrage Priorität niedrig 128 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>128</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="48">
<name>TTR Serviceanfrage Priorität niedrig 32 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="49">
<name>TTR Serviceanfrage Priorität niedrig 64 Stunden</name>
<priority>4</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>64</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="45">
<name>TTR Serviceanfrage Priorität mittel 16 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>16</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="46">
<name>TTR Serviceanfrage Priorität mittel 32 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>32</value>
<unit>hours</unit>
</SLT>
<SLT alias="SLT" id="47">
<name>TTR Serviceanfrage Priorität mittel 64 Stunden</name>
<priority>3</priority>
<request_type>service_request</request_type>
<metric>ttr</metric>
<value>64</value>
<unit>hours</unit>
</SLT>
</Set>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ContactType alias="ContactType" id="75">
<name>Administrator</name>
</ContactType>
<ContactType alias="ContactType" id="73">
<name>Einkaeufer</name>
</ContactType>
<ContactType alias="ContactType" id="1">
<name>Kundenbetreuer</name>
</ContactType>
<ContactType alias="ContactType" id="2">
<name>Helpdesk</name>
</ContactType>
<ContactType alias="ContactType" id="3">
<name>Manager</name>
</ContactType>
<ContactType alias="ContactType" id="74">
<name>Vertrieb</name>
</ContactType>
<ContactType alias="ContactType" id="4">
<name>Supportmitarbeiter</name>
</ContactType>
<ContactType alias="ContactType" id="5">
<name>Support Stufe 1</name>
</ContactType>
<ContactType alias="ContactType" id="6">
<name>Teamleiter</name>
</ContactType>
</Set>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<DocumentType alias="DocumentType" id="72">
<name>Architektur</name>
</DocumentType>
<DocumentType alias="DocumentType" id="69">
<name>Vertrag</name>
</DocumentType>
<DocumentType alias="DocumentType" id="71">
<name>Verfahren</name>
</DocumentType>
<DocumentType alias="DocumentType" id="70">
<name>Prozess</name>
</DocumentType>
</Set>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Set>
<ContactType alias="ContactType" id="17">
<name>Customer manager</name>
</ContactType>
<ContactType alias="ContactType" id="12">
<name>Helpdesk</name>
</ContactType>
<ContactType alias="ContactType" id="15">
<name>Manager</name>
</ContactType>
<ContactType alias="ContactType" id="14">
<name>Support Agent</name>
</ContactType>
<ContactType alias="ContactType" id="13">
<name>Support level1</name>
</ContactType>
<ContactType alias="ContactType" id="16">
<name>Team leader</name>
</ContactType>
</Set>

View File

@@ -4,80 +4,64 @@
<contactid>9</contactid>
<email>jules.vernes@it.com</email>
<org_id_friendlyname>IT Department</org_id_friendlyname>
<login>Agent</login>
<login>SupportAgent</login>
<language>EN US</language>
<status>disabled</status>
<profile_list>
<Set>
<URP_UserProfile id="5">
<profileid>5</profileid>
<profile>Support Agent</profile>
<reason></reason>
</URP_UserProfile>
</Set>
</profile_list>
<allowed_org_list>
<Set>
</Set>
</allowed_org_list>
<password><![CDATA[R6rQ;p]JT*FA$aaP^4]]></password>
<password><![CDATA[SupportAgent]]></password>
<expiration>force_expire</expiration>
<password_renewed_date>2026-06-04</password_renewed_date>
</UserLocal>
<URP_UserProfile id="5">
<userid>4</userid>
<userlogin>SupportAgent</userlogin>
<profileid>SELECT URP_Profiles WHERE id='5'</profileid>
<profile>Support Agent</profile>
<reason></reason>
</URP_UserProfile>
<UserLocal alias="UserLocal" id="5">
<contactid>26</contactid>
<contactid_friendlyname>Jean Ferrat</contactid_friendlyname>
<org_id_friendlyname>IT Department</org_id_friendlyname>
<login>config</login>
<login>ConfigManager</login>
<language>EN US</language>
<status>disabled</status>
<profile_list>
<Set>
<URP_UserProfile id="6">
<profileid>3</profileid>
<profile>Configuration Manager</profile>
<reason></reason>
</URP_UserProfile>
</Set>
</profile_list>
<allowed_org_list>
<Set>
</Set>
</allowed_org_list>
<password><![CDATA[$W[:"7+Gf"Y\sd8#E~]]></password>
<password><![CDATA[ConfigManager]]></password>
<expiration>force_expire</expiration>
<password_renewed_date>2026-06-04</password_renewed_date>
</UserLocal>
<URP_UserProfile id="6">
<userid>5</userid>
<userlogin>ConfigManager</userlogin>
<profileid>SELECT URP_Profiles WHERE id='3'</profileid>
<profile>Configuration Manager</profile>
<reason></reason>
</URP_UserProfile>
<UserLocal alias="UserLocal" id="2">
<contactid>15</contactid>
<email>agatha.christie@demo.com</email>
<org_id_friendlyname>Sales Department</org_id_friendlyname>
<login>Portal</login>
<login>PortalUser</login>
<language>EN US</language>
<status>disabled</status>
<profile_list>
<Set>
<URP_UserProfile id="2">
<profileid>2</profileid>
<profile>Portal user</profile>
<reason></reason>
</URP_UserProfile>
</Set>
</profile_list>
<allowed_org_list>
<Set>
<URP_UserOrg id="2">
<allowed_org_id>6</allowed_org_id>
<allowed_org_name>Sales Department</allowed_org_name>
<reason></reason>
<allowed_org_id_obsolescence_flag>no</allowed_org_id_obsolescence_flag>
</URP_UserOrg>
</Set>
</allowed_org_list>
<password><![CDATA[-Why]KDdMJvkuB8#e]]></password>
<password><![CDATA[PortalUser]]></password>
<expiration>force_expire</expiration>
<password_renewed_date>2026-04-17</password_renewed_date>
</UserLocal>
<URP_UserProfile id="2">
<userid>2</userid>
<userlogin>PortalUser</userlogin>
<profileid>SELECT URP_Profiles WHERE id='2'</profileid>
<profile>Portal user</profile>
<reason></reason>
</URP_UserProfile>
<URP_UserOrg id="2">
<userid>2</userid>
<userlogin>PortalUser</userlogin>
<allowed_org_id>6</allowed_org_id>
<allowed_org_name>Sales Department</allowed_org_name>
<reason></reason>
<allowed_org_id_obsolescence_flag>no</allowed_org_id_obsolescence_flag>
</URP_UserOrg>
<UserLocal alias="UserLocal" id="3">
<contactid>6</contactid>
<email>claude.monet@demo.com</email>
@@ -85,32 +69,48 @@
<login>SalesManager</login>
<language>EN US</language>
<status>disabled</status>
<profile_list>
<Set>
<URP_UserProfile id="4">
<profileid>12</profileid>
<profile>Portal power user</profile>
<reason></reason>
</URP_UserProfile>
<URP_UserProfile id="3">
<profileid>2</profileid>
<profile>Portal user</profile>
<reason></reason>
</URP_UserProfile>
</Set>
</profile_list>
<allowed_org_list>
<Set>
<URP_UserOrg id="1">
<allowed_org_id>6</allowed_org_id>
<allowed_org_name>Sales Department</allowed_org_name>
<reason></reason>
<allowed_org_id_obsolescence_flag>no</allowed_org_id_obsolescence_flag>
</URP_UserOrg>
</Set>
</allowed_org_list>
<password><![CDATA[D%r7hoZ})5*hvq5`{Q]]></password>
<password><![CDATA[SalesManager]]></password>
<expiration>force_expire</expiration>
<password_renewed_date>2026-06-04</password_renewed_date>
</UserLocal>
<URP_UserProfile id="4">
<userid>3</userid>
<userlogin>SalesManager</userlogin>
<profileid>SELECT URP_Profiles WHERE id='12'</profileid>
<profile>Portal power user</profile>
<reason></reason>
</URP_UserProfile>
<URP_UserProfile id="3">
<userid>3</userid>
<userlogin>SalesManager</userlogin>
<profileid>SELECT URP_Profiles WHERE id='2'</profileid>
<profile>Portal user</profile>
<reason></reason>
</URP_UserProfile>
<URP_UserOrg id="1">
<userid>3</userid>
<userlogin>SalesManager</userlogin>
<allowed_org_id>6</allowed_org_id>
<allowed_org_name>Sales Department</allowed_org_name>
<reason></reason>
<allowed_org_id_obsolescence_flag>no</allowed_org_id_obsolescence_flag>
</URP_UserOrg>
<UserLocal alias="UserLocal" id="6">
<contactid>18</contactid>
<email>rene.descartes@demo.com</email>
<org_id_friendlyname>Demo</org_id_friendlyname>
<login>SuperUser</login>
<language>EN US</language>
<status>disabled</status>
<password><![CDATA[SuperUser]]></password>
<expiration>force_expire</expiration>
<password_renewed_date>2026-04-17</password_renewed_date>
</UserLocal>
<URP_UserProfile id="7">
<userid>6</userid>
<userlogin>SuperUser</userlogin>
<profileid>SELECT URP_Profiles WHERE id='117'</profileid>
<profile>Super User</profile>
<reason></reason>
</URP_UserProfile>
</Set>

View File

@@ -2174,22 +2174,5 @@
</profiles>
</user_rights>
<constants/>
<snippets>
<snippet id="GestionCssInfo" _delta="define">
<placement>module</placement>
<module>itop-structure</module>
<rank>-1</rank>
<content>
<![CDATA[
class GestionCssInfo implements iBackofficeStyleExtension
{
public function GetStyle(): string
{
return '.ibo-field--label>.ibo-has-description::after, .ibo-input-with-label--label.ibo-has-description::after{content:"\1F6C8"; font-weight: 200;} ';
}
}
]]>
</content>
</snippet>
</snippets>
<snippets/>
</itop_design>

View File

@@ -32,7 +32,6 @@ SetupWebPage::AddModule(
'data/data.sample.persons.xml',
'data/data.sample.teams.xml',
'data/data.sample.contactteam.xml',
'data/data.sample.contacttype.xml',
'data/data.sample.auditdomain.xml',
'data/data.sample.auditcategory.xml',
'data/data.sample.auditcategory-auditdomain.xml',

View File

@@ -6,7 +6,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Person WHERE id=:this->agent_id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="4">
<name>Bearbeiter des Tickets, außer der Bearbeiter selbst löst eine Benachrichtigung aus.</name>
@@ -16,7 +16,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Person WHERE id=:this->agent_id AND id != :current_contact_id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="3">
<name>Melder und Kontaktliste des Tickets</name>
@@ -27,7 +27,7 @@
SELECT Person WHERE id=:this->caller_id
]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="1">
<name>Melder des Tickets</name>
@@ -35,7 +35,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Person WHERE id=:this->caller_id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="2">
<name>Kontaktliste des Tickets</name>
@@ -43,7 +43,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Contact AS C JOIN lnkContactToTicket AS L ON L.contact_id=C.id WHERE L.ticket_id=:this->id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="7">
<name>Manager des Ticketmelders</name>
@@ -51,7 +51,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Person AS manager JOIN Person AS employee ON employee.manager_id = manager.id WHERE employee.id=:this->caller_id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="9">
<name>Auslösende Person einer Benachrichtigung</name>
@@ -61,7 +61,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Person WHERE id = :current_contact_id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="6">
<name>Teammitglieder des Tickets</name>
@@ -71,7 +71,7 @@
WHERE L.team_id = :this->team_id
]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="5">
<name>Teammitglieder des Tickets, die nicht Bearbeiter sind</name>
@@ -83,7 +83,7 @@
WHERE L.team_id = :this->team_id AND P.id != :this->agent_id
]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="10">
<name>Team des Tickets</name>
@@ -91,7 +91,7 @@
<is_template>yes</is_template>
<oql><![CDATA[SELECT Team WHERE id = :this->team_id]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="11">
<name>Kontaktliste eines Funktionales CI</name>
@@ -101,7 +101,7 @@
WHERE L.functionalci_id = :this->id
]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="12">
<name>Kontaktliste eines Dienstes</name>
@@ -111,7 +111,7 @@
WHERE L.service_id = :this->id
]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
<QueryOQL alias="QueryOQL" id="13">
<name>Kontaktliste eines Vertrages</name>
@@ -121,6 +121,6 @@
WHERE L.contract_id = :this->id
]]></oql>
<fields>id,email</fields>
<finalclass>QueryOQL</finalclass>
<usages>notif</usages>
</QueryOQL>
</Set>

Some files were not shown because too many files have changed in this diff Show More