Details
-
Type: Bug
-
Status: Open
-
Priority: Major
-
Resolution: Unresolved
-
Affects Version/s: 4.7.11, 4.7.25
-
Fix Version/s: None
-
Component/s: CiviCRM API
-
Labels:None
-
Versioning Impact:Patch (backwards-compatible bug fixes)
-
Documentation Required?:None
-
Funding Source:Needs Funding
-
Verified?:No
Description
Setup
- create an ACL for "Everyone" to access some group
- grant access ajax api permission to anon
Steps to Reproduce
- call API Contact.get and return address fields (from js console)
- Observe that anon users can access contacts and addresses for the configured group.
- call API Address.get for a contact in said group
- Observe below constraint violation exception in ConfigAndLog
Dead-end work-around and further observations
Upon inspection of the civicrm_acl_contact_cache table, it was decided that the call in trace:
CRM/Contact/BAO/Contact/Permission.php(235): CRM_Contact_BAO_Contact_Permission::cache(0)
was invalid because the table expects a value of NULL for anon.
It was then attempted to add
$userID = ($userID === 0)? 'NULL' : $userID;
...before...
$permission = CRM_ACL_API::whereClause($type, $tables, $whereTables, $userID);
This did indeed resolve the database constraint violation.
However, this only resulted in no results returned.
It was then surmized that since fetching addresses through Contact.get does work, that the same code-path is not active for Contact api calls in this scenario.
This was proven with adding a debug log to the function which was not hit when calling Contact.get
Trace
Oct 04 14:06:28 [info] $Fatal Error Details = Array ( [callback] => Array ( [0] => CRM_Core_Error [1] => exceptionHandler ) [code] => -3 [message] => DB Error: constraint violation [mode] => 16 [debug_info] => INSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation ) SELECT 0 as user_id, contact_a.id as contact_id, 'View' as operation FROM civicrm_contact contact_a LEFT JOIN civicrm_group_contact `civicrm_group_contact-ACL` ON (contact_a.id = `civicrm_group_contact-ACL`.contact_id AND `civicrm_group_contact-ACL`.status IN ("Added")) LEFT JOIN civicrm_group_contact_cache `civicrm_group_contact_cache-ACL` ON contact_a.id = `civicrm_group_contact_cache-ACL`.contact_id LEFT JOIN civicrm_grant ON civicrm_grant.contact_id = contact_a.id WHERE ( ( `civicrm_group_contact-ACL`.group_id IN (66) AND `civicrm_group_contact-ACL`.status IN ("Added") ) OR `civicrm_group_contact_cache-ACL`.group_id IN (66) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ON DUPLICATE KEY UPDATE user_id=VALUES(user_id), contact_id=VALUES(contact_id), operation=VALUES(operation) [nativecode=1452 ** Cannot add or update a child row: a foreign key constraint fails (`hungerfr_hungervol_civicrm_dev`.`civicrm_acl_contact_cache`, CONSTRAINT `FK_civicrm_acl_contact_cache_user_id` FOREIGN KEY (`user_id`) REFERENCES `civicrm_contact` (`id`) ON DELETE CASCADE)] [type] => DB_Error [user_info] => INSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation ) SELECT 0 as user_id, contact_a.id as contact_id, 'View' as operation FROM civicrm_contact contact_a LEFT JOIN civicrm_group_contact `civicrm_group_contact-ACL` ON (contact_a.id = `civicrm_group_contact-ACL`.contact_id AND `civicrm_group_contact-ACL`.status IN ("Added")) LEFT JOIN civicrm_group_contact_cache `civicrm_group_contact_cache-ACL` ON contact_a.id = `civicrm_group_contact_cache-ACL`.contact_id LEFT JOIN civicrm_grant ON civicrm_grant.contact_id = contact_a.id WHERE ( ( `civicrm_group_contact-ACL`.group_id IN (66) AND `civicrm_group_contact-ACL`.status IN ("Added") ) OR `civicrm_group_contact_cache-ACL`.group_id IN (66) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ON DUPLICATE KEY UPDATE user_id=VALUES(user_id), contact_id=VALUES(contact_id), operation=VALUES(operation) [nativecode=1452 ** Cannot add or update a child row: a foreign key constraint fails (`hungerfr_hungervol_civicrm_dev`.`civicrm_acl_contact_cache`, CONSTRAINT `FK_civicrm_acl_contact_cache_user_id` FOREIGN KEY (`user_id`) REFERENCES `civicrm_contact` (`id`) ON DELETE CASCADE)] [to_string] => [db_error: message="DB Error: constraint violation" code=-3 mode=callback callback=CRM_Core_Error::exceptionHandler prefix="" info=" INSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation ) SELECT 0 as user_id, contact_a.id as contact_id, 'View' as operation FROM civicrm_contact contact_a LEFT JOIN civicrm_group_contact `civicrm_group_contact-ACL` ON (contact_a.id = `civicrm_group_contact-ACL`.contact_id AND `civicrm_group_contact-ACL`.status IN ("Added")) LEFT JOIN civicrm_group_contact_cache `civicrm_group_contact_cache-ACL` ON contact_a.id = `civicrm_group_contact_cache-ACL`.contact_id LEFT JOIN civicrm_grant ON civicrm_grant.contact_id = contact_a.id WHERE ( ( `civicrm_group_contact-ACL`.group_id IN (66) AND `civicrm_group_contact-ACL`.status IN ("Added") ) OR `civicrm_group_contact_cache-ACL`.group_id IN (66) ) AND (contact_a.is_deleted = 0) GROUP BY contact_a.id ON DUPLICATE KEY UPDATE user_id=VALUES(user_id), contact_id=VALUES(contact_id), operation=VALUES(operation) [nativecode=1452 ** Cannot add or update a child row: a foreign key constraint fails (`hungerfr_hungervol_civicrm_dev`.`civicrm_acl_contact_cache`, CONSTRAINT `FK_civicrm_acl_contact_cache_user_id` FOREIGN KEY (`user_id`) REFERENCES `civicrm_contact` (`id`) ON DELETE CASCADE)]"] ) Oct 04 14:06:28 [info] $backTrace = #0 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/Error.php(935): CRM_Core_Error::backtrace("backTrace", TRUE) #1 [internal function](): CRM_Core_Error::exceptionHandler(Object(DB_Error)) #2 htdocs/sites/all/modules/contrib/civicrm/packages/PEAR.php(931): call_user_func((Array:2), Object(DB_Error)) #3 htdocs/sites/all/modules/contrib/civicrm/packages/DB.php(976): PEAR_Error->PEAR_Error("DB Error: constraint violation", -3, 16, (Array:2), "\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #4 htdocs/sites/all/modules/contrib/civicrm/packages/PEAR.php(564): DB_Error->DB_Error(-3, 16, (Array:2), "\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #5 htdocs/sites/all/modules/contrib/civicrm/packages/DB/common.php(1905): PEAR->raiseError(NULL, -3, NULL, NULL, "\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...", "DB_Error", TRUE) #6 htdocs/sites/all/modules/contrib/civicrm/packages/DB/mysql.php(895): DB_common->raiseError(-3, NULL, NULL, NULL, "1452 ** Cannot add or update a child row: a foreign key constraint fails (`hu...") #7 htdocs/sites/all/modules/contrib/civicrm/packages/DB/mysql.php(328): DB_mysql->mysqlRaiseError() #8 htdocs/sites/all/modules/contrib/civicrm/packages/DB/common.php(1216): DB_mysql->simpleQuery("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #9 htdocs/sites/all/modules/contrib/civicrm/packages/DB/DataObject.php(2438): DB_common->query("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #10 htdocs/sites/all/modules/contrib/civicrm/packages/DB/DataObject.php(1627): DB_DataObject->_query("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #11 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/DAO.php(344): DB_DataObject->query("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #12 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/DAO.php(1265): CRM_Core_DAO->query("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...", TRUE) #13 htdocs/sites/all/modules/contrib/civicrm/CRM/Contact/BAO/Contact/Permission.php(138): CRM_Core_DAO::executeQuery("\nINSERT INTO civicrm_acl_contact_cache ( user_id, contact_id, operation )\nS...") #14 htdocs/sites/all/modules/contrib/civicrm/CRM/Contact/BAO/Contact/Permission.php(235): CRM_Contact_BAO_Contact_Permission::cache(0) #15 htdocs/sites/all/modules/contrib/civicrm/CRM/Contact/BAO/Contact.php(3428): CRM_Contact_BAO_Contact_Permission::cacheSubquery() #16 htdocs/sites/all/modules/contrib/civicrm/CRM/Utils/SQL.php(48): CRM_Contact_BAO_Contact->addSelectWhereClause() #17 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/DAO.php(2415): CRM_Utils_SQL::mergeSubquery("Contact") #18 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/DAO.php(2436): CRM_Core_DAO->addSelectWhereClause() #19 htdocs/sites/all/modules/contrib/civicrm/Civi/API/SelectQuery.php(527): CRM_Core_DAO::getSelectWhereClause("a") #20 htdocs/sites/all/modules/contrib/civicrm/Civi/API/SelectQuery.php(116): Civi\API\SelectQuery->getAclClause("a", "CRM_Core_BAO_Address") #21 htdocs/sites/all/modules/contrib/civicrm/api/v3/utils.php(1340): Civi\API\SelectQuery->__construct("CRM_Core_BAO_Address", (Array:10), FALSE) #22 htdocs/sites/all/modules/contrib/civicrm/api/v3/Address.php(156): _civicrm_api3_basic_get("CRM_Core_BAO_Address", (Array:10), TRUE, "Address") #23 htdocs/sites/all/modules/contrib/civicrm/Civi/API/Provider/MagicFunctionProvider.php(89): civicrm_api3_address_get((Array:10)) #24 htdocs/sites/all/modules/contrib/civicrm/Civi/API/Kernel.php(96): Civi\API\Provider\MagicFunctionProvider->invoke((Array:9)) #25 htdocs/sites/all/modules/contrib/civicrm/Civi/API/Subscriber/ChainSubscriber.php(198): Civi\API\Kernel->run("address", "get", (Array:10)) #26 htdocs/sites/all/modules/contrib/civicrm/Civi/API/Subscriber/ChainSubscriber.php(72): Civi\API\Subscriber\ChainSubscriber->callNestedApi(Object(Civi\API\Kernel), (Array:9), (Array:4), "get", "Contact", 3) #27 [internal function](): Civi\API\Subscriber\ChainSubscriber->onApiRespond(Object(Civi\API\Event\RespondEvent), "api.respond", Object(Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher)) #28 htdocs/sites/all/modules/contrib/civicrm/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php(164): call_user_func((Array:2), Object(Civi\API\Event\RespondEvent), "api.respond", Object(Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher)) #29 htdocs/sites/all/modules/contrib/civicrm/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php(53): Symfony\Component\EventDispatcher\EventDispatcher->doDispatch((Array:4), "api.respond", Object(Civi\API\Event\RespondEvent)) #30 htdocs/sites/all/modules/contrib/civicrm/vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php(170): Symfony\Component\EventDispatcher\EventDispatcher->dispatch("api.respond", Object(Civi\API\Event\RespondEvent)) #31 htdocs/sites/all/modules/contrib/civicrm/Civi/API/Kernel.php(221): Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch("api.respond", Object(Civi\API\Event\RespondEvent)) #32 htdocs/sites/all/modules/contrib/civicrm/Civi/API/Kernel.php(98): Civi\API\Kernel->respond(Object(Civi\API\Provider\MagicFunctionProvider), (Array:9), (Array:4)) #33 htdocs/sites/all/modules/contrib/civicrm/api/api.php(23): Civi\API\Kernel->run("Contact", "get", (Array:8), NULL) #34 htdocs/sites/all/modules/contrib/civicrm/CRM/Utils/REST.php(404): civicrm_api("Contact", "get", (Array:8)) #35 htdocs/sites/all/modules/contrib/civicrm/CRM/Utils/REST.php(641): CRM_Utils_REST::process((Array:3), (Array:6)) #36 [internal function](): CRM_Utils_REST::ajax() #37 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/Invoke.php(278): call_user_func((Array:2)) #38 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/Invoke.php(86): CRM_Core_Invoke::runItem((Array:12)) #39 htdocs/sites/all/modules/contrib/civicrm/CRM/Core/Invoke.php(54): CRM_Core_Invoke::_invoke((Array:3)) #40 htdocs/sites/all/modules/contrib/civicrm/drupal/civicrm.module(448): CRM_Core_Invoke::invoke((Array:3)) #41 [internal function](): civicrm_invoke("ajax", "rest") #42 htdocs/includes/menu.inc(527): call_user_func_array("civicrm_invoke", (Array:2)) #43 htdocs/index.php(21): menu_execute_active_handler() #44 {main}