/** * @param \Civi\API\Event\AuthorizeEvent $event * API authorization event. * * @throws \Civi\API\Exception\UnauthorizedException */ public function onApiAuthorize(\Civi\API\Event\AuthorizeEvent $event) { $apiRequest = $event->getApiRequest(); if ($apiRequest['version'] < 4) { // return early unless we’re told explicitly to do the permission check if (empty($apiRequest['params']['check_permissions']) or $apiRequest['params']['check_permissions'] == FALSE) { $event->authorize(); $event->stopPropagation(); return; } require_once 'CRM/Core/DAO/permissions.php'; $permissions = _civicrm_api3_permissions($apiRequest['entity'], $apiRequest['action'], $apiRequest['params']); // $params might’ve been reset by the alterAPIPermissions() hook if (isset($apiRequest['params']['check_permissions']) and $apiRequest['params']['check_permissions'] == FALSE) { $event->authorize(); $event->stopPropagation(); return; } if (!\CRM_Core_Permission::check($permissions) and !self::checkACLPermission($apiRequest)) { if (is_array($permissions)) { foreach ($permissions as &$permission) { if (is_array($permission)) { $permission = '( ' . implode(' or ', $permission) . ' )'; } } $permissions = implode(' and ', $permissions); } // FIXME: Generating the exception ourselves allows for detailed error // but doesn't play well with multiple authz subscribers. throw new \Civi\API\Exception\UnauthorizedException("API permission check failed for {$apiRequest['entity']}/{$apiRequest['action']} call; insufficient permission: require {$permissions}"); } $event->authorize(); $event->stopPropagation(); } }
/** * Check permissions for a given API call. * * @param $entity string API entity being accessed * @param $action string API action being performed * @param $params array params of the API call * @param $throw bool whether to throw exception instead of returning false * * @return bool whether the current API user has the permission to make the call */ function _civicrm_api3_api_check_permission($entity, $action, &$params, $throw = TRUE) { // return early unless we’re told explicitly to do the permission check if (empty($params['check_permissions']) or $params['check_permissions'] == FALSE) { return TRUE; } require_once 'CRM/Core/Permission.php'; require_once 'CRM/Core/DAO/.permissions.php'; $permissions = _civicrm_api3_permissions($entity, $action, $params); // $params might’ve been reset by the alterAPIPermissions() hook if (isset($params['check_permissions']) and $params['check_permissions'] == FALSE) { return TRUE; } foreach ($permissions as $perm) { if (!CRM_Core_Permission::check($perm)) { if ($throw) { throw new Exception("API permission check failed for {$entity}/{$action} call; missing permission: {$perm}."); } else { return FALSE; } } } return TRUE; }
/** * Check permissions for a given API call. * * @param $entity string API entity being accessed * @param $action string API action being performed * @param $params array params of the API call * @param $throw deprecated bool whether to throw exception instead of returning false * * @throws Exception * @return bool whether the current API user has the permission to make the call */ function _civicrm_api3_api_check_permission($entity, $action, &$params, $throw = TRUE) { // return early unless we’re told explicitly to do the permission check if (empty($params['check_permissions']) or $params['check_permissions'] == FALSE) { return TRUE; } require_once 'CRM/Core/DAO/permissions.php'; $permissions = _civicrm_api3_permissions($entity, $action, $params); // $params might’ve been reset by the alterAPIPermissions() hook if (isset($params['check_permissions']) and $params['check_permissions'] == FALSE) { return TRUE; } if (!CRM_Core_Permission::check($permissions)) { if ($throw) { if (is_array($permissions)) { $permissions = implode(' and ', $permissions); } throw new Exception("API permission check failed for {$entity}/{$action} call; insufficient permission: require {$permissions}"); } else { //@todo remove this - this is an internal api function called with $throw set to TRUE. It is only called with false // in tests & that should be tidied up return FALSE; } } return TRUE; }