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

Reply via email to