Check financial acls for product in extension
authorEileen McNaughton <emcnaughton@wikimedia.org>
Sun, 26 Nov 2023 03:18:08 +0000 (16:18 +1300)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Sun, 26 Nov 2023 05:27:10 +0000 (18:27 +1300)
Civi/Test/ContributionPageTestTrait.php
ext/financialacls/financialacls.php
ext/financialacls/tests/phpunit/Civi/Financialacls/BaseTestClass.php
ext/financialacls/tests/phpunit/Civi/Financialacls/ProductTest.php [new file with mode: 0644]

index 7d6a0d1cf63d774a821703d27678b96d8691c28d..f0ed59006eb751336b2b9aedaf2ef3e4b8fe24e8 100644 (file)
@@ -117,6 +117,37 @@ trait ContributionPageTestTrait {
       'entity_id' => $contributionPageResult['id'],
       'price_set_id' => $this->ids['PriceSet'][$identifier],
     ]);
+    $this->createTestEntity('Product', [
+      'name' => '5_dollars',
+      'description' => '5 dollars worth of monopoly money',
+      'options' => 'White, Black, Green',
+      'price' => 1,
+      'min_contribution' => 5,
+      'cost' => .05,
+    ], '5_dollars');
+    $this->createTestEntity('Product', [
+      'name' => '10_dollars',
+      'description' => '10 dollars worth of monopoly money',
+      'options' => 'White, Black, Green',
+      'price' => 2,
+      'min_contribution' => 10,
+      'cost' => .05,
+    ], '10_dollars');
+    $this->createTestEntity('Premium', [
+      'entity_id' => $this->getContributionPageID($identifier),
+      'entity_table' => 'civicrm_contribution_page',
+      'premiums_intro_title' => 'Get free monopoly money with your donation',
+    ], $identifier);
+    $this->createTestEntity('PremiumsProduct', [
+      'premiums_id' => $this->ids['Premium'][$identifier],
+      'product_id' => $this->ids['Product']['5_dollars'],
+      'weight' => 1,
+    ]);
+    $this->createTestEntity('PremiumsProduct', [
+      'premiums_id' => $this->ids['Premium'][$identifier],
+      'product_id' => $this->ids['Product']['10_dollars'],
+      'weight' => 2,
+    ]);
     return $contributionPageResult;
   }
 
index 334105d92ebefcf4cc0d372d57480fd2368e3cb2..da20a0922f2fd37263e4539dd1ad5622848873ef 100644 (file)
@@ -57,12 +57,13 @@ function financialacls_civicrm_pre($op, $objectName, $id, &$params) {
   if (!financialacls_is_acl_limiting_enabled()) {
     return;
   }
-  if ($objectName === 'LineItem' && !empty($params['check_permissions'])) {
+  if (in_array($objectName, ['LineItem', 'Product'], TRUE) && !empty($params['check_permissions'])) {
+    if (empty($params['financial_type_id']) && !empty($params['id'])) {
+      $dao = CRM_Core_DAO_AllCoreTables::getFullName($objectName);
+      $params['financial_type_id'] = CRM_Core_DAO::getFieldValue($dao, $params['id'], 'financial_type_id');
+    }
     $operationMap = ['delete' => CRM_Core_Action::DELETE, 'edit' => CRM_Core_Action::UPDATE, 'create' => CRM_Core_Action::ADD];
     CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes($types, $operationMap[$op]);
-    if (empty($params['financial_type_id'])) {
-      $params['financial_type_id'] = CRM_Core_DAO::getFieldValue('CRM_Price_DAO_LineItem', $params['id'], 'financial_type_id');
-    }
     if (!array_key_exists($params['financial_type_id'], $types)) {
       throw new CRM_Core_Exception('You do not have permission to ' . $op . ' this line item');
     }
@@ -93,6 +94,7 @@ function financialacls_civicrm_selectWhereClause($entity, &$clauses) {
     case 'MembershipType':
     case 'ContributionRecur':
     case 'Contribution':
+    case 'Product':
       $clauses['financial_type_id'][] = _financialacls_civicrm_get_type_clause();
       break;
 
@@ -173,7 +175,7 @@ function _financialacls_civicrm_get_accessible_financial_types(): array {
  *
  * @return string
  *
- * @throws \CRM_Core_Exception
+ * @noinspection PhpUnhandledExceptionInspection
  */
 function _financialacls_civicrm_get_membership_type_clause(): string {
   $financialTypes = _financialacls_civicrm_get_accessible_financial_types();
index 8aea3973245a7ebabe280eaf5de8f295d8d5b6e8..894db1f311ef4949df035465feddbd99dc5e113c 100644 (file)
@@ -7,6 +7,7 @@ use Civi\Api4\FinancialType;
 use Civi\Api4\PriceField;
 use Civi\Api4\PriceFieldValue;
 use Civi\Api4\PriceSet;
+use Civi\Api4\Product;
 use Civi\Test;
 use Civi\Test\CiviEnvBuilder;
 use Civi\Test\HeadlessInterface;
@@ -49,6 +50,7 @@ class BaseTestClass extends TestCase implements HeadlessInterface, HookInterface
   public function tearDown(): void {
     Contribution::delete(FALSE)->addWhere('id', '>', 0)->execute();
     FinancialType::delete(FALSE)->addWhere('name', 'LIKE', '%test%')->execute();
+    Product::delete(FALSE)->addWhere('name', '=', '10_dollars')->execute();
     $this->cleanupPriceSets();
   }
 
diff --git a/ext/financialacls/tests/phpunit/Civi/Financialacls/ProductTest.php b/ext/financialacls/tests/phpunit/Civi/Financialacls/ProductTest.php
new file mode 100644 (file)
index 0000000..07c2836
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+
+namespace Civi\Financialacls;
+
+require_once 'BaseTestClass.php';
+
+/**
+ * @group headless
+ */
+class ProductTest extends BaseTestClass {
+
+  /**
+   * Test api applies permissions on line item actions (delete & get).
+   *
+   * @dataProvider versionThreeAndFour
+   */
+  public function testProductApiPermissions($version): void {
+    $this->createTestEntity('Product', [
+      'name' => '10_dollars',
+      'description' => '10 dollars worth of monopoly money',
+      'options' => 'White, Black, Green',
+      'price' => 2,
+      'min_contribution' => 10,
+      'cost' => .05,
+      'financial_type_id:name' => 'Member Dues',
+    ], '10_dollars');
+    $this->_apiversion = $version;
+    $this->setupLoggedInUserWithLimitedFinancialTypeAccess();
+    $products = $this->callAPISuccess('Product', 'get', ['sequential' => TRUE])['values'];
+    $this->assertCount(1, $products);
+    $this->callAPISuccessGetCount('Product', ['check_permissions' => TRUE], 0);
+    $this->callAPIFailure('Product', 'Delete', ['check_permissions' => TRUE, 'id' => $products[0]['id']]);
+    $this->callAPISuccess('Product', 'Delete', ['check_permissions' => FALSE, 'id' => $products[0]['id']]);
+  }
+
+}