diff --git a/core/bulkchange.class.inc.php b/core/bulkchange.class.inc.php index 4578df9de..90d061634 100644 --- a/core/bulkchange.class.inc.php +++ b/core/bulkchange.class.inc.php @@ -1002,7 +1002,7 @@ class BulkChange $oPage->p(Dict::S('UI:History:BulkImports+')); - $oBulkChangeSearch = DBObjectSearch::FromOQL("SELECT CMDBChange WHERE userinfo LIKE '%(CSV)'"); + $oBulkChangeSearch = DBObjectSearch::FromOQL("SELECT CMDBChange WHERE origin IN ('csv-interactive', 'csv-import.php')"); $iQueryLimit = $bShowAll ? 0 : MetaModel::GetConfig()->GetMaxDisplayLimit() + 1; $oBulkChanges = new DBObjectSet($oBulkChangeSearch, array('date' => false), array(), null, $iQueryLimit); diff --git a/core/cmdbchange.class.inc.php b/core/cmdbchange.class.inc.php index efb40de5e..05c829fc8 100644 --- a/core/cmdbchange.class.inc.php +++ b/core/cmdbchange.class.inc.php @@ -49,6 +49,7 @@ class CMDBChange extends DBObject //MetaModel::Init_InheritAttributes(); MetaModel::Init_AddAttribute(new AttributeDateTime("date", array("allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array()))); MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array()))); + MetaModel::Init_AddAttribute(new AttributeEnum("origin", array("allowed_values"=>new ValueSetEnum('interactive,csv-interactive,csv-import.php,webservice-soap,webservice-rest,synchro-data-source,email-processing,custom-extension'), "sql"=>"origin", "default_value"=>"interactive", "is_null_allowed"=>true, "depends_on"=>array()))); } // Helper to keep track of the author of a given change, diff --git a/core/cmdbobject.class.inc.php b/core/cmdbobject.class.inc.php index d7a62dc8e..0df0836f5 100644 --- a/core/cmdbobject.class.inc.php +++ b/core/cmdbobject.class.inc.php @@ -93,7 +93,8 @@ abstract class CMDBObject extends DBObject // Note: this value is static, but that could be changed because it is sometimes a real issue (see update of interfaces / connected_to protected static $m_oCurrChange = null; protected static $m_sInfo = null; // null => the information is built in a standard way - + protected static $m_sOrigin = null; // null => the origin is 'interactive' + /** * Specify another change (this is mainly for backward compatibility) */ @@ -134,6 +135,15 @@ abstract class CMDBObject extends DBObject self::$m_sInfo = $sInfo; } + /** + * Provides information about the origin of the change + * @param $sOrigin String: one of: interactive, csv-interactive, csv-import.php, webservice-soap, webservice-rest, syncho-data-source, email-processing, custom-extension + */ + public static function SetTrackOrigin($sOrigin) + { + self::$m_sOrigin = $sOrigin; + } + /** * Get the additional information (defaulting to user name) */ @@ -148,7 +158,22 @@ abstract class CMDBObject extends DBObject return self::$m_sInfo; } } - + + /** + * Get the 'origin' information (defaulting to 'interactive') + */ + protected static function GetTrackOrigin() + { + if (is_null(self::$m_sOrigin)) + { + return 'interactive'; + } + else + { + return self::$m_sOrigin; + } + } + /** * Create a standard change record (done here 99% of the time, and nearly once per page) */ @@ -157,6 +182,7 @@ abstract class CMDBObject extends DBObject self::$m_oCurrChange = MetaModel::NewObject("CMDBChange"); self::$m_oCurrChange->Set("date", time()); self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo()); + self::$m_oCurrChange->Set("origin", self::GetTrackOrigin()); self::$m_oCurrChange->DBInsert(); } diff --git a/pages/csvimport.php b/pages/csvimport.php index 0ca6ab398..f78662901 100644 --- a/pages/csvimport.php +++ b/pages/csvimport.php @@ -29,6 +29,7 @@ try require_once('../approot.inc.php'); require_once(APPROOT.'/application/application.inc.php'); require_once(APPROOT.'/application/itopwebpage.class.inc.php'); + require_once(APPROOT.'/application/ajaxwebpage.class.inc.php'); require_once(APPROOT.'/application/startup.inc.php'); @@ -305,7 +306,8 @@ try // We're doing it for real, let's create a change $sUserString = CMDBChange::GetCurrentUserName().' (CSV)'; CMDBObject::SetTrackInfo($sUserString); - + CMDBObject::SetTrackOrigin('csv-interactive'); + $oMyChange = CMDBObject::GetCurrentChange(); } @@ -1485,14 +1487,21 @@ EOF if (Utils::GetConfig()->Get('csv_import_history_display')) { - $oPage->SetCurrentTabContainer('tabs1'); - $oPage->SetCurrentTab(Dict::S('UI:History:BulkImports')); - BulkChange::DisplayImportHistory($oPage); + $oPage->SetCurrentTabContainer('tabs1'); + $oPage->AddAjaxTab(Dict::S('UI:History:BulkImports'), utils::GetAbsoluteUrlAppRoot().'pages/csvimport.php?step=11', true /* bCache */); } } switch($iStep) { + case 11: + // Asynchronous tab + $oPage = new ajax_page(''); + BulkChange::DisplayImportHistory($oPage); + $oPage->add_ready_script('$("#CSVImportHistory table.listResults").tableHover();'); + $oPage->add_ready_script('$("#CSVImportHistory table.listResults").tablesorter( { widgets: ["myZebra", "truncatedList"]} );'); + break; + case 10: // Case generated by BulkChange::DisplayImportHistory $iChange = (int)utils::ReadParam('changeid', 0); diff --git a/setup/applicationinstaller.class.inc.php b/setup/applicationinstaller.class.inc.php index 49f408ec2..d526700fd 100644 --- a/setup/applicationinstaller.class.inc.php +++ b/setup/applicationinstaller.class.inc.php @@ -562,7 +562,7 @@ class ApplicationInstaller SetupPage::log_info("Renaming '{$sDBPrefix}priv_internalUser' failed (already done in a previous upgrade?)"); } } - + // Module specific actions (migrate the data) // $aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT.$sModulesDir); @@ -582,6 +582,47 @@ class ApplicationInstaller { throw new Exception("Failed to create/upgrade the database structure for environment '$sTargetEnvironment'"); } + + // priv_change now has an 'origin' field to distinguish between the various input sources + // Let's initialize the field with 'interactive' for all records were it's null + // Then check if some records should hold a different value, based on a pattern matching in the userinfo field + CMDBSource::SelectDB($sDBName); + try + { + $sCount = "SELECT COUNT(*) FROM `{$sDBPrefix}priv_change` WHERE `origin` IS NULL"; + $iCount = (int)CMDBSource::QueryToScalar($sCount); + if ($iCount > 0) + { + SetupPage::log_info("Initializing '{$sDBPrefix}priv_change.origin' ($iCount records to update)"); + + // By default all uninitialized values are considered as 'interactive' + $sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'interactive' WHERE `origin` IS NULL"; + CMDBSource::Query($sInit); + + // CSV Import was identified by the comment at the end + $sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'csv-import.php' WHERE `userinfo` LIKE '%Web Service (CSV)'"; + CMDBSource::Query($sInit); + + // CSV Import was identified by the comment at the end + $sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'csv-interactive' WHERE `userinfo` LIKE '%(CSV)' AND origin = 'interactive'"; + CMDBSource::Query($sInit); + + // Syncho data sources were identified by the comment at the end (Yes: Synchronisation with a S!!) + $sInit = "UPDATE `{$sDBPrefix}priv_change` SET `origin` = 'synchro-data-source' WHERE `userinfo` LIKE '%(Synchronisation)'"; + + CMDBSource::Query($sInit); + + SetupPage::log_info("Initialization of '{$sDBPrefix}priv_change.origin' completed."); + } + else + { + SetupPage::log_info("'{$sDBPrefix}priv_change.origin' already initialized, nothing to do."); + } + } + catch (Exception $e) + { + SetupPage::log_error("Initializing '{$sDBPrefix}priv_change.origin' failed: ".$e->getMessage()); + } SetupPage::log_info("Database Schema Successfully Updated for environment '$sTargetEnvironment'."); } diff --git a/synchro/synchrodatasource.class.inc.php b/synchro/synchrodatasource.class.inc.php index aa09e35d9..e90f338f9 100644 --- a/synchro/synchrodatasource.class.inc.php +++ b/synchro/synchrodatasource.class.inc.php @@ -2200,6 +2200,7 @@ class SynchroExecution $this->m_oChange->Set("date", time()); $sUserString = CMDBChange::GetCurrentUserName(); $this->m_oChange->Set("userinfo", $sUserString.' '.Dict::S('Core:SyncDataExchangeComment')); + $this->m_oChange->Set("origin", 'synchro-data-source'); $iChangeId = $this->m_oChange->DBInsert(); // Start logging this execution (stats + protection against reentrance) diff --git a/webservices/import.php b/webservices/import.php index ce09f1e2b..5fb0c6195 100644 --- a/webservices/import.php +++ b/webservices/import.php @@ -724,7 +724,8 @@ try $sMoreInfo = CMDBChange::GetCurrentUserName().', Web Service (CSV)'; } CMDBObject::SetTrackInfo($sMoreInfo); - + CMDBObject::SetTrackOrigin('csv-import.php'); + $oMyChange = CMDBObject::GetCurrentChange(); } diff --git a/webservices/rest.php b/webservices/rest.php index b760c7374..4e3c20768 100644 --- a/webservices/rest.php +++ b/webservices/rest.php @@ -185,6 +185,7 @@ try } $oRS = $aOpToRestService[$sOperation]['service_provider']; + CMDBObject::SetTrackOrigin('webservice-rest'); $oResult = $oRS->ExecOperation($sVersion, $sOperation, $aJsonData); } } diff --git a/webservices/soapserver.php b/webservices/soapserver.php index 69bc76cd6..a76a43df1 100644 --- a/webservices/soapserver.php +++ b/webservices/soapserver.php @@ -75,6 +75,7 @@ else if ($_SERVER["REQUEST_METHOD"] == "POST") { + CMDBObject::SetTrackOrigin('webservice-soap'); $oSoapServer->handle(); } else