jenkins-bot has submitted this change and it was merged. Change subject: CRM-18212 allow triggers to be managed offline. ......................................................................
CRM-18212 allow triggers to be managed offline. This commit adds a setting which when set (in civicrm.settings.php or through the api or drush - not through the UI) allows you to designate the site as having it's triggers managed offline. This is good for when it really is not appropriate to give the web use that mysql permission. ie when replication is in play because it can allow privilige escalation https://github.com/civicrm/civicrm-core/pull/8036 Bug: T131224 Change-Id: Iedc8dfca17be38a9ea2b5848bb069e7c84805bf8 --- M CRM/Core/DAO.php M CRM/Core/Error.php M CRM/Logging/Schema.php 3 files changed, 113 insertions(+), 20 deletions(-) Approvals: Awight: Looks good to me, approved jenkins-bot: Verified diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 3657d07..15a0417 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -1288,6 +1288,92 @@ } /** + * Execute a query altering triggers. + * + * As this requires a high permission level we funnel the queries through here to + * facilitate them being taken 'offline'. + * + * @param string $triggerSQL + * The sql to run to create or drop the triggers. + * @param array $params + * Optional parameters to interpolate into the string. + */ + public static function executeTriggerQuery($triggerSQL, $params = array()) { + if (civicrm_api3('Setting', 'getvalue', array('name' => 'logging_no_trigger_permission', 'group' => 'CiviCRM Preferences'))) { + $prefix = 'trigger' . CRM_Utils_Request::id(); + CRM_Core_DAO::logQuery("DELIMITER //", $params, TRUE, FALSE, $prefix, TRUE); + CRM_Core_DAO::logQuery($triggerSQL . '//', $params, TRUE, FALSE, $prefix, TRUE); + CRM_Core_Session::setStatus(ts('The mysql commands you need to run are stored in %1', array( + 1 => CRM_Core_Error::getDebugLoggerFileName($prefix))) + ); + CRM_Core_DAO::logQuery("DELIMITER ;", $params, TRUE, FALSE, $prefix, TRUE); + } + else { + // Multilingual needs to be false. + CRM_Core_DAO::executeQuery($triggerSQL, $params, TRUE, NULL, FALSE, FALSE); + } + } + + /** + * Get the query that would be generated. + * + * This could be used in tests or where it is desirable to log the query rather than run it. + * + * @param string $query + * Query to be executed. + * + * @param array $params + * @param bool $abort + * @param bool $i18nRewrite + * + * @return string + * The resolved mysql query. + */ + public static function getQuery( + $query, + $params = array(), + $abort = TRUE, + $i18nRewrite = TRUE + ) { + $queryStr = self::composeQuery($query, $params, $abort); + global $dbLocale; + if ($i18nRewrite and $dbLocale) { + $queryStr = CRM_Core_I18n_Schema::rewriteQuery($query); + } + return $queryStr; + } + + /** + * Log the query that would be generated. + * + * @param string $query + * Query to be executed. + * + * @param array $params + * @param bool $abort + * @param bool $i18nRewrite + * @param string $outputFilePrefix + * @param bool $raw + * Should we omit data like timestamp and debug level? + */ + public static function logQuery( + $query, + $params = array(), + $abort = TRUE, + $i18nRewrite = TRUE, + $outputFilePrefix = '', + $raw = FALSE + ) { + $queryStr = self::getQuery($query, $params, $abort, $i18nRewrite); + if ($raw) { + CRM_Core_Error::debug_raw_message($queryStr, FALSE, $outputFilePrefix) ; + } + else { + CRM_Core_Error::debug_log_message($queryStr, FALSE, $outputFilePrefix); + } + } + + /** * Execute a query and get the single result. * * @param string $query @@ -1890,7 +1976,7 @@ // test for create view and trigger permissions and if allowed, add the option to go multilingual // and logging // I'm not sure why we use the getStaticProperty for an error, rather than checking for DB_Error - $errorScope = CRM_Core_TemporaryErrorScope::ignoreException(); + CRM_Core_TemporaryErrorScope::ignoreException(); $dao = new CRM_Core_DAO(); if ($view) { $dao->query('CREATE OR REPLACE VIEW civicrm_domain_view AS SELECT * FROM civicrm_domain'); @@ -2103,17 +2189,8 @@ $triggerName = "{$validName}_{$whenName}_{$eventName}"; $triggerSQL = "CREATE TRIGGER $triggerName $whenName $eventName ON $tableName FOR EACH ROW BEGIN $varString $sqlString END"; - /* - CRM_Core_DAO::executeQuery("DROP TRIGGER IF EXISTS $triggerName"); - CRM_Core_DAO::executeQuery( - $triggerSQL, - array(), - TRUE, - NULL, - FALSE, - FALSE - ); - */ + CRM_Core_DAO::executeTriggerQuery("DROP TRIGGER IF EXISTS $triggerName"); + CRM_Core_DAO::executeTriggerQuery($triggerSQL); } } } diff --git a/CRM/Core/Error.php b/CRM/Core/Error.php index cc7d535..5f5739c 100644 --- a/CRM/Core/Error.php +++ b/CRM/Core/Error.php @@ -661,8 +661,19 @@ * @return Log */ public static function createDebugLogger($prefix = '', $logConfig = array()) { + return Log::singleton('file', self::getDebugLoggerFileName($prefix), '', $logConfig); + } + + /** + * Get the log filename for the supplied prefix. + * + * @param $prefix + * + * @return string + */ + public static function getDebugLoggerFileName($prefix) { self::generateLogFileName($prefix); - return Log::singleton('file', \Civi::$statics[__CLASS__]['logger_file' . $prefix], '', $logConfig); + return \Civi::$statics[__CLASS__]['logger_file' . $prefix]; } /** diff --git a/CRM/Logging/Schema.php b/CRM/Logging/Schema.php index 4b584e5..5efa2ed 100644 --- a/CRM/Logging/Schema.php +++ b/CRM/Logging/Schema.php @@ -224,14 +224,14 @@ $validName = CRM_Core_DAO::shortenSQLName($table, 48, TRUE); // before triggers - $dao->executeQuery("DROP TRIGGER IF EXISTS {$validName}_before_insert"); - $dao->executeQuery("DROP TRIGGER IF EXISTS {$validName}_before_update"); - $dao->executeQuery("DROP TRIGGER IF EXISTS {$validName}_before_delete"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$validName}_before_insert"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$validName}_before_update"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$validName}_before_delete"); // after triggers - $dao->executeQuery("DROP TRIGGER IF EXISTS {$validName}_after_insert"); - $dao->executeQuery("DROP TRIGGER IF EXISTS {$validName}_after_update"); - $dao->executeQuery("DROP TRIGGER IF EXISTS {$validName}_after_delete"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$validName}_after_insert"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$validName}_after_update"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$validName}_after_delete"); } */ // now lets also be safe and drop all triggers that start with @@ -244,7 +244,7 @@ while ($triggers->fetch()) { // note that drop trigger has a wierd syntax and hence we do not // send the trigger name as a string (i.e. its not quoted - $dao->executeQuery("DROP TRIGGER IF EXISTS {$triggers->Trigger}"); + $dao->executeTriggerQuery("DROP TRIGGER IF EXISTS {$triggers->Trigger}"); } } } @@ -680,6 +680,11 @@ * Predicate whether the logging triggers are in place. */ private function triggersExist() { + if (civicrm_api3('Setting', 'getvalue', array('name' => 'logging_no_trigger_permission', 'group' => 'CiviCRM Preferences'))) { + // The mysql user does not have permission to check but since they have gone to the effort + // of setting this setting we assume they do. + return TRUE; + } // FIXME: probably should be a bit more thorough… // note that the LIKE parameter is TABLE NAME return (bool) CRM_Core_DAO::singleValueQuery("SHOW TRIGGERS LIKE 'civicrm_contact'"); -- To view, visit https://gerrit.wikimedia.org/r/280157 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Iedc8dfca17be38a9ea2b5848bb069e7c84805bf8 Gerrit-PatchSet: 8 Gerrit-Project: wikimedia/fundraising/crm/civicrm Gerrit-Branch: master Gerrit-Owner: Eileen <[email protected]> Gerrit-Reviewer: Awight <[email protected]> Gerrit-Reviewer: Eileen <[email protected]> Gerrit-Reviewer: Ejegg <[email protected]> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
