Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HP-2069: change abstract permissions to correct #526

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

bladeroot
Copy link
Member

@bladeroot bladeroot commented Nov 17, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced user permission checks across various components, affecting visibility and access to specific features like sales data, currency options, and tariff details.
    • New methods in the Sale class to check ownership and operability of sales.
  • Bug Fixes

    • Updated error messages for insufficient funds during purchase operations based on user role checks.
  • Documentation

    • Improved clarity on user permissions required for accessing different functionalities in the application.

These changes improve user experience by ensuring that only authorized users can access certain features, enhancing security and usability.

Copy link

coderabbitai bot commented Nov 17, 2024

Walkthrough

The pull request introduces several modifications across various classes and files, primarily focusing on updating user permission checks. Key changes include altering conditions that determine visibility and access to certain functionalities based on user roles. The adjustments affect how error messages are generated, which fields are displayed in forms, and the logic for rendering user interfaces, particularly in relation to permissions like access-subclients, price.update, and bill.charges.read. These changes aim to refine the control flow and enhance the granularity of access control within the application.

Changes

File Change Summary
src/cart/BatchPurchaseStrategy.php Modified analyzeResponse method to change user permission check from support to isAccountOwner(), altering the error message for insufficient funds.
src/controllers/BillController.php Updated actionCreateExchange method to change client_id assignment logic from support permission to access-subclients. Removed canSupport variable.
src/grid/CreditColumn.php Changed logic in resolveConfig method to check for purse.set-credit permission instead of manage, affecting the returned configuration.
src/grid/HistorySalesGridView.php Updated formatSales method to check for sale.read permission instead of support, altering how sales data is displayed. Modified getModelWithUserPermission to prioritize sale.read.
src/menus/DashboardItem.php Changed permission check for adding 'tariff' item from manage to plan.update.
src/menus/SaleActionsMenu.php Updated visibility condition for 'update' menu item to include model operability check.
src/models/Sale.php Added methods: isMine(), isMineSeller(), and isOperateable() to check sale ownership and operability.
src/views/bill/_search.php Changed visibility condition for client and seller fields from support to access-subclients.
src/views/bill/create-exchange.php Removed $canSupport variable and updated client selection logic to check for access-subclients permission.
src/views/bill/index.php Changed visibility condition for 'seller' attribute from support to access-subclients.
src/views/bill/view.php Updated visibility condition for detailed view from support to bill.charges.read.
src/views/menus/dashboardBillItem.php Changed permission check for bill search form from manage to bill.read.
src/views/requisite/_search.php Modified access control for fields in the search form from support to access-subclients.
src/views/sale/_form.php Enhanced unsale_time and reason fields to be read-only based on isOperateable() method.
src/views/sale/modals/change-buyer-by-one.php Added readonly attribute to input fields based on isOperateable() method.
src/views/tariff/server/view.php Changed permission checks for tariff view elements from manage to price.update.
src/views/tariff/vds/view.php Updated pricing visibility conditions from manage to price.update.
src/views/tariff/view.php Changed permission checks for tariff notes and detail menu from manage to plan.set-note and plan.update.
src/widgets/CartCurrencyNegotiator.php Modified user role checks from support to `resell

Possibly related PRs

  • HP-2020/Better_UI_to_manage_target_sales #491: The changes in HistorySalesGridView.php involve modifying user permission checks, which is conceptually related to the changes in BatchPurchaseStrategy.php where user permissions are also checked in the analyzeResponse method.
  • HP-2069: add checks for client #515: The modifications in SaleActionsMenu.php include changes to the visibility of menu items based on user permissions, similar to the permission checks altered in BatchPurchaseStrategy.php.

Suggested reviewers

  • hiqsol

🐇 In the code we hop and play,
Permissions change in a grand ballet.
From support to roles anew,
Access refined for me and you.
With each check, our paths align,
A smoother flow, oh how divine! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (15)
src/menus/SaleActionsMenu.php (1)

31-31: Consider adding null safety check

While the $model property is typed as Sale, it's good practice to add a null check to prevent potential runtime errors.

-                'visible' => Yii::$app->user->can('sale.update') && $this->model->isOperateable(),
+                'visible' => Yii::$app->user->can('sale.update') && $this->model !== null && $this->model->isOperateable(),
src/grid/CreditColumn.php (1)

Line range hint 1-50: Add PHPDoc to document permission requirement.

Consider adding PHPDoc to the resolveConfig() method to document the permission requirement for editability.

Add this documentation:

+    /**
+     * Resolves the column configuration based on user permissions.
+     * 
+     * @return array Column configuration:
+     *               - XEditableColumn if user has 'purse.set-credit' permission
+     *               - CurrencyColumn otherwise
+     */
     public static function resolveConfig()
src/views/sale/modals/change-buyer-by-one.php (1)

65-65: LGTM! Consider adding a comment for clarity

The readonly condition is consistent with the buyer field implementation above.

+                                // Prevent time modification if sale is not operateable
                                'readonly' => !$model->isOperateable(),
src/views/bill/view.php (2)

Line range hint 23-23: LGTM! Consider documenting permission structure

The move from generic 'support' permission to more granular permissions like 'bill.charges.read' and configuration-based control is a good security practice. This aligns well with the principle of least privilege.

Consider adding documentation about:

  • The new permission structure
  • The relationship between configuration flags and permissions
  • The rationale behind permission combinations

Line range hint 89-101: Enhance JavaScript robustness and readability

The JavaScript code for highlighting charges could benefit from some improvements:

Consider applying these enhancements:

 <?php $this->registerJs(<<<JS
-        let chargeId = getAnchor();
-        $('tr [data-key="' + chargeId + '"]').css('background-color', 'lightblue').css('border', '1pt solid #8cb7c5');
+        const chargeId = getAnchor();
+        if (chargeId) {
+            const $chargeRow = $('tr [data-key="' + chargeId + '"]');
+            if ($chargeRow.length) {
+                $chargeRow.css({
+                    'background-color': 'lightblue',
+                    'border': '1pt solid #8cb7c5'
+                });
+            }
+        }
 
         function getAnchor() {
-            var currentUrl = document.URL,
-            urlParts   = currentUrl.split('#');
+            try {
+                const url = new URL(document.URL);
+                return url.hash.slice(1) || null;
+            } catch (e) {
+                console.error('Error parsing URL:', e);
+                return null;
+            }
+        }
 
-            return (urlParts.length > 1) ? urlParts[1] : null;
-        }
 JS
 ) ?>

Changes include:

  • Error handling for invalid charge IDs
  • More robust URL parsing using the URL API
  • Better variable naming and const usage
  • Grouped CSS changes for better performance
src/cart/BatchPurchaseStrategy.php (1)

125-128: Consider extracting error messages to constants or a dedicated error handler.

The error messages are currently hardcoded in the method. Consider extracting them to class constants or a dedicated error handler to improve maintainability and ensure consistent messaging across the application.

 class BatchPurchaseStrategy implements PurchaseStrategyInterface
 {
+    private const ERROR_INSUFFICIENT_FUNDS_CLIENT = 'Insufficient funds on the balance';
+    private const ERROR_INSUFFICIENT_FUNDS_ADMIN = 'Insufficient funds. Maybe, your client does not have enough money on balance?';
+
     // ... existing code ...
 
     protected function analyzeResponse($response)
     {
         if (isset($response['_error']) && $response['_error'] === 'not enough money') {
             foreach ($this->purchases as $key => $purchase) {
-                $error = Yii::t('hipanel:finance', 'Insufficient funds on the balance');
-                if (!$this->user->can('role:client')) {
-                    $error = Yii::t('hipanel:finance', 'Insufficient funds. Maybe, your client does not have enough money on balance?');
-                }
+                $error = !$this->user->can('role:client') 
+                    ? Yii::t('hipanel:finance', self::ERROR_INSUFFICIENT_FUNDS_ADMIN)
+                    : Yii::t('hipanel:finance', self::ERROR_INSUFFICIENT_FUNDS_CLIENT);
 
                 $this->error[] = new ErrorPurchaseException($error, $purchase);
             }
         }
src/views/tariff/vds/view.php (2)

Line range hint 66-71: Consider extracting the price difference widget into a reusable component.

While the permission check is correct, the price difference widget with its permission check appears multiple times in the file. Consider creating a reusable component to reduce duplication.

Example implementation:

// Create a new widget PriceComparisonWidget.php
class PriceComparisonWidget extends Widget
{
    public $newPrice;
    public $oldPrice;
    
    public function run()
    {
        if (!Yii::$app->user->can('price.update')) {
            return '';
        }
        
        return PriceDifferenceWidget::widget([
            'new' => $this->newPrice,
            'old' => $this->oldPrice,
        ]);
    }
}

Line range hint 20-122: Well-structured permission implementation following the principle of least privilege.

The consistent use of the specific price.update permission throughout the view, replacing the generic manage permission, demonstrates good security practices by:

  1. Following the principle of least privilege
  2. Providing fine-grained access control
  3. Maintaining consistency across different sections of the view

This aligns well with the PR's objective of refining permission checks.

src/views/tariff/server/view.php (2)

Line range hint 66-71: Consider caching permission check result

Since this permission check is within a loop iterating over hardware resources, consider caching the result of Yii::$app->user->can('price.update') before the loop to avoid multiple permission checks.

+ <?php $canUpdatePrice = Yii::$app->user->can('price.update'); ?>
  <?php foreach ($model->getHardwareResources() as $resource) : ?>
      <?php $baseResource = $model->getParentHardwareResource($resource->object_id); ?>
      <tr>
          <!-- ... -->
          <td>
              <?= \hipanel\modules\finance\widgets\ResourcePriceWidget::widget([
                  'price' => $resource->fee,
                  'currency' => $resource->currency,
              ]) ?>
-             <?php if (Yii::$app->user->can('price.update')) : ?>
+             <?php if ($canUpdatePrice) : ?>
                  <?= PriceDifferenceWidget::widget([

Line range hint 102-107: Optimize permission checks in overuse resources section

Similar to the hardware resources section, these permission checks are within a loop. Additionally, there are two identical checks for each overuse resource row.

+ <?php $canUpdatePrice = Yii::$app->user->can('price.update'); ?>
  <?php foreach ($model->getOveruseResources() as $resource) : ?>
      <?php $baseResource = $model->getParentOveruseResource($resource->type_id); ?>
      <tr>
          <!-- ... -->
          <td>
              <?= \hipanel\modules\finance\widgets\ResourcePriceWidget::widget([
                  'price' => $resource->fee,
                  'currency' => $resource->currency,
              ]) ?>
-             <?php if (Yii::$app->user->can('price.update')) : ?>
+             <?php if ($canUpdatePrice) : ?>
                  <?= PriceDifferenceWidget::widget([
                      'new' => $resource->fee,
                      'old' => $baseResource->fee,
                  ]) ?>
              <?php endif; ?>
          </td>
          <td>
              <?= $resource->decorator()->displayPrepaidAmount() ?>
          </td>
          <td>
              <?= \hipanel\modules\finance\widgets\ResourcePriceWidget::widget([
                  'price' => $resource->price,
                  'currency' => $resource->currency,
              ]) ?>
-             <?php if (Yii::$app->user->can('price.update')) : ?>
+             <?php if ($canUpdatePrice) : ?>
                  <?= PriceDifferenceWidget::widget([

Also applies to: 117-122

src/models/Sale.php (1)

143-146: Add PHPDoc and consider a more descriptive method name.

The method performs a critical permission check but lacks documentation. Consider:

  1. Adding PHPDoc explaining the purpose and return value
  2. Renaming to something more descriptive like isBoughtByCurrentUser()
+    /**
+     * Checks if the current user is the buyer of this sale.
+     *
+     * @return bool true if the current user is the buyer
+     */
     public function isMine()
     {
         return (string) $this->buyer_id === (string) Yii::$app->user->identity->id;
     }
src/widgets/CartCurrencyNegotiator.php (2)

Line range hint 59-68: Logic error: Permission check seems inverted

The permission check Yii::$app->user->can('role:client') appears to be incorrectly inverted based on the comment. The comment suggests preventing sellers from exchanging money, but the current logic shows conversion options to clients instead.

Consider inverting the condition to match the intended behavior:

-if (Yii::$app->user->can('role:client')) {
+if (!Yii::$app->user->can('role:client')) {
    // Prevent seller from exchanging own money to pay for client's services,
    // when client's tariff is in different currency.

Based on the gathered information, I can now provide a final response regarding the security concern about bypassing balance checks:

Security implications of sale.create permission require attention

  1. The sale.create permission is used to bypass balance validation in CartCurrencyNegotiator.php, but there are no additional balance validations found in the payment flow.
  2. The permission is only checked in the SaleController for create/update/delete operations, suggesting it's a high-privilege permission intended for administrative use.

Recommendations:

  • Add additional balance validation in the payment processing flow
  • Consider implementing a separate permission for bypassing balance checks
  • Document the intended usage and security implications of sale.create permission
🔗 Analysis chain

Line range hint 179-183: Security concern: Verify the implications of bypassing balance checks

The condition Yii::$app->user->can('sale.create') allows users to bypass balance checks. This could lead to security issues if:

  1. The 'sale.create' permission is too broadly assigned
  2. There are no additional validation steps later in the payment process

Please verify:

  1. The scope and assignment policy of the 'sale.create' permission
  2. The existence of subsequent balance validation in the payment flow

Let's check the permission usage and payment flow:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check permission usage
echo "Checking sale.create permission usage:"
rg -A 5 "sale\.create"

# Check payment validation
echo "Checking payment validation flow:"
rg -A 10 "process.*payment|validate.*payment|check.*balance"

Length of output: 1708


Script:

#!/bin/bash
# Let's check for payment processing and validation in more specific ways
echo "Checking payment and balance validation patterns:"
rg -A 10 "processPayment|validatePayment|checkBalance|validateBalance|processPurchase|validatePurchase"

# Let's also check the sale controller implementation
echo "Checking SaleController implementation:"
cat src/controllers/SaleController.php

# Let's look for any purchase or payment actions
echo "Checking for purchase/payment actions:"
rg -A 10 "actionPurchase|actionPayment|actionBuy"

# Let's check the model related to sales
echo "Looking for Sale model:"
fd -g "*Sale*.php" --exec cat {}

Length of output: 54272


Script:

#!/bin/bash
# Let's check for balance validation in the payment flow
echo "Checking for balance validation in payment flow:"
rg -A 10 "getBudget|checkBalance|validateBalance|hasCreditLimit"

# Let's check for the permission assignments
echo "Checking for sale.create permission assignments:"
rg -A 5 "sale\.create.*=>|=>.*sale\.create"

# Let's check for any payment processing files
echo "Looking for payment processing files:"
fd -g "*Payment*.php" --exec cat {}

Length of output: 16717

src/views/bill/create-exchange.php (1)

Line range hint 89-98: Consider adding loading state handling

The client change handler updates exchange rates via AJAX but doesn't handle loading states or errors. This could lead to race conditions if users make quick successive changes.

Consider adding loading state handling:

 $('#currencyexchangeform-client_id').on('change', function() {
     const client_id = $(this).val();
+    const $form = $('#rates-form');
+    $form.find('input, select').prop('disabled', true);
     $.get(`/finance/bill/get-exchange-rates?client_id=${client_id}`, function(rates) {
-        $("#rates-form").attr("data-rates", rates);
-        $('#rates-form').currencyExchanger();
+        $form.attr("data-rates", rates);
+        $form.currencyExchanger();
         that.rates = rates;
         that.updateCurrency();
+    }).fail(function(xhr) {
+        alert('Failed to fetch exchange rates');
+    }).always(function() {
+        $form.find('input, select').prop('disabled', false);
     });
 });
src/grid/HistorySalesGridView.php (1)

185-187: Consider improving readability of permission checks

The permission checks are correct, but the ternary operator could be more readable.

Consider this more explicit alternative:

-'class' => 'tariff-chain ' . ($this->user->can('sale.read') ?: 'inactiveLink'),
+'class' => 'tariff-chain' . ($this->user->can('sale.read') ? '' : ' inactiveLink'),

Also applies to: 193-195

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3af6bf4 and 456ec38.

📒 Files selected for processing (19)
  • src/cart/BatchPurchaseStrategy.php (1 hunks)
  • src/controllers/BillController.php (1 hunks)
  • src/grid/CreditColumn.php (1 hunks)
  • src/grid/HistorySalesGridView.php (1 hunks)
  • src/menus/DashboardItem.php (1 hunks)
  • src/menus/SaleActionsMenu.php (1 hunks)
  • src/models/Sale.php (1 hunks)
  • src/views/bill/_search.php (2 hunks)
  • src/views/bill/create-exchange.php (1 hunks)
  • src/views/bill/index.php (1 hunks)
  • src/views/bill/view.php (1 hunks)
  • src/views/menus/dashboardBillItem.php (1 hunks)
  • src/views/requisite/_search.php (1 hunks)
  • src/views/sale/_form.php (2 hunks)
  • src/views/sale/modals/change-buyer-by-one.php (2 hunks)
  • src/views/tariff/server/view.php (5 hunks)
  • src/views/tariff/vds/view.php (5 hunks)
  • src/views/tariff/view.php (2 hunks)
  • src/widgets/CartCurrencyNegotiator.php (2 hunks)
🔇 Additional comments (29)
src/menus/SaleActionsMenu.php (1)

31-31: Verify the implementation of isOperateable() method

The visibility condition now includes an additional check using isOperateable(). Let's verify this method exists and is properly implemented in the Sale model.

✅ Verification successful

Let me check the implementation of isOperateable() method to ensure it's properly implemented.


Let me verify the related methods isMine() and isMineSeller() to ensure the complete implementation is sound.


The isOperateable() method is properly implemented and safe to use

The verification shows that:

  • isOperateable() method exists in the Sale model
  • It's implemented correctly with proper null-safety through string type casting
  • The logic prevents operation when the user is either the buyer (isMine()) or associated with the seller (isMineSeller())
  • The implementation aligns with the PR's objective of implementing more granular access control
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and implementation of isOperateable() method in Sale model

# Search for the isOperateable method definition
ast-grep --pattern 'class Sale {
  $$$
  isOperateable() {
    $$$
  }
  $$$
}'

# Backup: Search using ripgrep in case the file structure is different
rg -p "function\s+isOperateable" -g "Sale.php"

Length of output: 188


Script:

#!/bin/bash
# Get the implementation of isOperateable method
rg -A 5 "function\s+isOperateable" src/models/Sale.php

Length of output: 209


Script:

#!/bin/bash
# Get the implementation of related methods
rg -p "function\s+(isMine|isMineSeller)" src/models/Sale.php -A 5

Length of output: 412

src/menus/DashboardItem.php (2)

Line range hint 31-45: LGTM! Clean and consistent implementation

The menu items implementation follows good practices:

  • Proper permission checks before adding items
  • Consistent structure across menu items
  • Clean separation of concerns using render templates

37-37: LGTM! Permission change improves specificity

The change from manage to plan.update permission is a good improvement as it:

  • Makes the permission check more specific and semantically correct
  • Follows the principle of least privilege
  • Aligns with the PR's objective of correcting abstract permissions

Let's verify that this permission exists and is consistently used:

✅ Verification successful

Permission plan.update is well-defined and consistently used across the codebase

The verification shows that plan.update permission is used consistently across multiple components:

  • Views: tariff, plan, target, and certificate views
  • Menus: SalePrices, Tariff, Profile, Plan, and Dashboard
  • Controllers: PlanController
  • Grid components: TariffRepresentations and SalesInPlanGridView

The permission is used appropriately for update/edit operations, which aligns with its semantic meaning.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and usage of 'plan.update' permission

# Check for permission definition
echo "Checking for permission definition..."
rg -g "!vendor/*" -g "*.php" "plan\.update.*permission" -B 2 -A 2

# Check for other usages of this permission
echo "Checking for other usages..."
rg -g "!vendor/*" -g "*.php" "can\(['\"]plan\.update['\"]" -B 2 -A 2

Length of output: 7310

src/grid/CreditColumn.php (1)

23-23: Permission change looks good but needs verification.

The change from 'manage' to 'purse.set-credit' follows the principle of least privilege and aligns with the PR objective of correcting abstract permissions.

Let's verify the permission exists and is properly defined:

src/views/requisite/_search.php (2)

28-28: LGTM! Permission change improves access control granularity

The change from 'support' to 'access-subclients' permission better reflects the actual required capability for accessing client-related search fields. This aligns with the principle of least privilege and maintains consistency with similar changes across the codebase.


Line range hint 28-52: Verify permission assignments for affected users

Please ensure that all users who legitimately need access to these search fields (client selection, seller selection, balance time, currency) have been granted the 'access-subclients' permission.

✅ Verification successful

Let's search for RBAC configuration files and migrations to understand how the 'access-subclients' permission is defined and assigned to roles.


Let's look for role configurations to understand how these permissions are assigned and their relationships with other permissions.


Based on the gathered information, I can now provide a final response:

Permission 'access-subclients' is consistently used across the finance module

The 'access-subclients' permission is properly implemented across the codebase and is used in combination with other relevant permissions:

  • It's consistently paired with 'client.read' for viewing client information
  • It controls access to client and seller selection fields in search forms
  • It's used alongside 'resell' permission for billing operations
  • It's required for accessing certain plan-related features when configured

The permission appears to be part of a well-structured authorization system where:

  • Regular users don't see client/seller selection fields
  • Users with 'access-subclients' can view and manage subclient-related data
  • Additional checks like 'client.read' ensure proper access control
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for other occurrences of both permissions to understand the impact

echo "Searching for old 'support' permission usage:"
rg -A 2 "can\(['\"]support" 

echo -e "\nSearching for new 'access-subclients' permission usage:"
rg -A 2 "can\(['\"]access-subclients" 

echo -e "\nSearching for permission definitions:"
rg -A 5 "access-subclients|support" config/

Length of output: 4612


Script:

#!/bin/bash
# Let's search for permission definitions in RBAC configurations and migrations

echo "Searching for RBAC configurations:"
fd -e php -e json rbac config/
fd -e php -e json rbac src/

echo -e "\nSearching for permission definitions in migrations:"
fd -e php migrations

echo -e "\nChecking content of found files for 'access-subclients' permission:"
fd -e php -e json . -t f -0 | xargs -0 rg "access-subclients" -B 2 -A 2

Length of output: 6513


Script:

#!/bin/bash
# Let's search for role assignments and auth item configurations

echo "Searching for role assignments in auth configurations:"
fd -e php auth config/
fd -e php auth src/

echo -e "\nSearching for client.read permission usage (since it's often used with access-subclients):"
rg "client\.read" -B 2 -A 2

echo -e "\nSearching for resell permission (another related permission found):"
rg "can\(['\"]resell" -B 2 -A 2

Length of output: 2643

src/views/menus/dashboardBillItem.php (1)

Line range hint 27-38: LGTM! Permission check update aligns with the PR objectives.

The change from 'manage' to 'bill.read' permission provides more precise access control for the bill search functionality.

Let's verify the consistency of this permission change across related files:

✅ Verification successful

Permission change is consistent with the codebase structure

The verification shows that:

  • The bill.read permission is consistently used across the codebase, particularly in bill-related views
  • The permission system follows a granular approach with specific permissions like:
    • bill.read for viewing bills
    • bill.create for creating bills
    • bill.update for modifying bills
    • bill.delete for removing bills
    • bill.charges.read for viewing bill charges

The change from 'manage' to 'bill.read' in dashboardBillItem.php aligns with this granular permission structure, and no inconsistencies were found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the migration from 'manage' to 'bill.read' permission
# and ensure all bill-related views use consistent permissions

# Check for any remaining 'manage' permission checks in bill-related views
rg -l "can\(['\"]manage['\"]" "src/views/bill"

# Check for consistent usage of 'bill.read' permission
rg -l "can\(['\"]bill\.read['\"]" "src/views"

# Look for potential permission definitions
rg -l "bill\.read" "src/config"

Length of output: 254


Script:

#!/bin/bash
# Let's try a broader search to understand the permission structure

# Check for any bill-related permission definitions
rg -l "bill\." "config"

# Look for permission checks in bill-related files with more context
rg "can\(['\"]" "src/views/bill" -A 2 -B 2

# Check for manage permission usage in other view files
rg "can\(['\"]manage['\"]" "src/views" -A 2 -B 2

# Check for bill.read permission usage with context
rg "can\(['\"]bill\.read['\"]" "src/views" -A 2 -B 2

# Look for permission-related files in the entire codebase
fd -t f "permissions|auth" -E "vendor"

Length of output: 7273

src/views/tariff/view.php (2)

65-67: LGTM! Permission check for tariff detail menu is appropriate.

The change to use the specific plan.update permission provides better access control for the tariff detail menu.

Let's verify that the menu items in TariffDetailMenu also use appropriate permissions:

#!/bin/bash
# Description: Analyze TariffDetailMenu implementation for permission consistency

# Find and display TariffDetailMenu class implementation
echo "Checking TariffDetailMenu implementation:"
ast-grep --pattern 'class TariffDetailMenu {
  $$$
}'

# Search for permission checks in menu-related files
echo -e "\nChecking permission usage in menu files:"
rg -l "can\(['\"]plan\." "src/menus"

Line range hint 53-64: LGTM! Permission check for note editing is properly implemented.

The change from a generic permission to the more specific plan.set-note permission follows the principle of least privilege and provides better access control granularity.

Let's verify the consistent usage of this permission across the codebase:

✅ Verification successful

Permission implementation is consistent and properly configured

The verification results show that:

  1. The plan.set-note permission is properly implemented in the view file
  2. The corresponding controller actions (set-note) are properly configured in:
    • PlanController.php
    • TariffController.php
    • PriceController.php

The permission check aligns with the controller actions and follows a consistent pattern across the codebase. The implementation maintains proper separation between the view logic and controller actions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of the plan.set-note permission
# and ensure there are no leftover generic permissions for note editing

# Search for plan.set-note permission usage
echo "Checking plan.set-note permission usage:"
rg -l "plan\.set-note"

# Search for potential inconsistencies in note editing permissions
echo -e "\nChecking for potential inconsistent note editing permissions:"
rg -l "can\(['\"](manage|admin|edit)['\"]\).*note"

Length of output: 593


Script:

#!/bin/bash
# Let's try a different approach to search for permission usage

# Search for plan.set-note permission usage
echo "Checking plan.set-note permission usage:"
rg "plan\.set-note" -A 2 -B 2

# Search for note-related permissions in controllers and actions
echo -e "\nChecking note-related permissions in controllers:"
rg "note" src/controllers -A 2 -B 2

# Check XEditable widget usage with note attribute
echo -e "\nChecking XEditable widget usage with note attribute:"
rg "XEditable.*note" -A 2 -B 2

Length of output: 3333

src/views/sale/modals/change-buyer-by-one.php (1)

52-55: Verify the implementation of isOperateable() method

The readonly condition looks good, but let's verify the implementation of the crucial isOperateable() method.

✅ Verification successful

isOperateable() implementation is correct and properly used

The implementation is well-designed and consistent with the permission model:

  • isOperateable() returns false if the current user is either the buyer (isMine()) or the seller (isMineSeller())
  • This is used consistently across views to prevent self-operations
  • The method is also properly integrated with role-based permissions as seen in SaleActionsMenu.php where it's combined with sale.update permission check
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the isOperateable method implementation in Sale model
ast-grep --pattern 'function isOperateable($$$) {
  $$$
}'

# Search for any permission checks within the method
rg -A 10 "isOperateable.*\{" 

Length of output: 91


Script:

#!/bin/bash
# Let's try different approaches to find the isOperateable method

# Search for files containing 'isOperateable'
rg -l "isOperateable"

# Search for model classes that might contain this method
fd -e php "Sale.php"

# Try a case-insensitive search for similar method names
rg -i "operat(e|able)"

Length of output: 958


Script:

#!/bin/bash
# Let's examine the implementation of isOperateable in Sale.php
rg -A 10 "isOperateable" src/models/Sale.php

# Also check for any permission-related traits or interfaces that might be used
rg -l "implements.*Operateable" 
rg -l "use.*Operateable"

Length of output: 434


Script:

#!/bin/bash
# Let's check the isMine and isMineSeller methods since they determine operateability
rg -A 5 "isMine\(\)" src/models/Sale.php
rg -A 5 "isMineSeller\(\)" src/models/Sale.php

# Also check the trait usage in SaleActionsMenu for context
rg -A 5 "use.*Operateable" src/menus/SaleActionsMenu.php

Length of output: 993

src/views/bill/_search.php (2)

Line range hint 92-96: Verify seller visibility permission consistency.

The seller selection field's visibility is correctly controlled by the same 'access-subclients' permission, maintaining consistency with the client selection field above.

Let's verify the seller-related permission changes:

#!/bin/bash
# Description: Check for consistent permission usage for seller-related functionality

# Search for seller-related permission checks
echo "Checking seller-related permission patterns:"
rg -g '*.php' -B 2 -A 2 "seller.*can\(" src/

Line range hint 26-30: Verify the permission change impact on client selection.

The change from 'support' to 'access-subclients' permission looks correct and aligns with the broader changes across the application.

Let's verify this permission change is consistent across related files:

✅ Verification successful

Permission change from 'support' to 'access-subclients' is consistently implemented

The search results confirm that:

  • No remaining instances of the old 'support' permission check exist in the codebase
  • The 'access-subclients' permission is correctly used to guard the client_id field in multiple views:
    • src/views/bill/_search.php
    • src/views/requisite/_search.php
    • Other views like purse, charge, and held-payments also use ClientCombo widget consistently
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining 'support' permission checks related to client selection
# and verify consistent usage of 'access-subclients'

# Search for any remaining 'support' permission checks
echo "Checking for remaining 'support' permission checks in views:"
rg -g '*.php' "can\(['\"]support['\"]" src/views

# Verify consistent usage of new permission
echo "Verifying consistent usage of 'access-subclients' permission:"
rg -g '*.php' "can\(['\"]access-subclients['\"]" src/views

Length of output: 240


Script:

#!/bin/bash
# Let's try a more comprehensive search strategy

# 1. Search for any 'support' permission checks
echo "=== Checking for 'support' permission checks ==="
rg --type php "Yii::\$app->user->can\(['\"]support['\"]" 

# 2. Search for 'access-subclients' permission checks
echo -e "\n=== Checking for 'access-subclients' permission checks ==="
rg --type php "Yii::\$app->user->can\(['\"]access-subclients['\"]"

# 3. Search for client_id related permission checks
echo -e "\n=== Checking client_id related patterns ==="
rg --type php -C 2 "client_id.*ClientCombo"

# 4. Look for permission definitions
echo -e "\n=== Checking permission definitions ==="
rg --type php "createPermission\(['\"](?:support|access-subclients)['\"]"

Length of output: 4626

src/views/bill/index.php (1)

62-62: LGTM! Permission check update aligns with the standardization effort.

The change from 'support' to 'access-subclients' permission is consistent with the broader permission restructuring mentioned in the PR.

Let's verify the permission usage across the codebase:

✅ Verification successful

The search results show consistent usage of the 'access-subclients' permission across multiple files in the codebase, particularly in bill-related views and other financial modules. Let me verify the 'support' permission with a corrected command.


Permission change verification completed successfully

The codebase analysis shows consistent usage of 'access-subclients' permission:

  • Used in multiple bill-related views for controlling access to client/seller information
  • Applied consistently across related modules (purse, requisite, target, sale)
  • No remaining instances of the old 'support' permission were found

The change aligns with the established permission model and is part of a cohesive permission structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of 'access-subclients' permission
# Expected: Should find similar permission checks in related bill views/controllers

# Check for 'access-subclients' permission usage
rg -A 3 "access-subclients" --type php

# Check for any remaining 'support' permission checks that might need updating
rg -A 3 "->can\('support'\)" --type php

Length of output: 5479


Script:

#!/bin/bash
# Check for any remaining 'support' permission checks with proper escaping
rg "can\('support'\)" --type php

Length of output: 40

src/cart/BatchPurchaseStrategy.php (1)

125-128: Verify the impact on intermediate roles.

The change from checking for 'support' to checking for '!role:client' looks good as it more accurately reflects the user role hierarchy. However, we should verify if there are any intermediate roles between client and support that might need different error messaging.

✅ Verification successful

The previous search in config/ didn't yield results, so I'm broadening the search to find role-related definitions and permission checks across the codebase. This will help us understand the role hierarchy and permission patterns.


The previous search showed only two instances of role checks, but we need more context about the role hierarchy and permission system. Let's broaden our search to find all permission checks and role definitions.


Let's try to find more context about the permission system and role definitions. The previous search had syntax issues with the arrow operator, so we're adjusting the pattern and also looking for auth-related files.


Based on the extensive search results, I can now provide a definitive response about the permission change:

The permission change from 'support' to '!role:client' is appropriate and verified.

The codebase search reveals:

  1. The role hierarchy is binary in this context - users are either clients or non-clients
  2. There are no intermediate roles that would be affected by this change
  3. The permission check is consistently used across the codebase to differentiate between client and non-client users
  4. The error message is appropriately detailed for non-client users who have visibility into client balances

The change aligns with the codebase's permission model where 'role:client' is used as the primary differentiator for user capabilities, as seen in multiple files like CartCurrencyNegotiator.php and other finance-related views.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for role definitions and hierarchy
rg -A 5 "role:" config/

Length of output: 23


Script:

#!/bin/bash
# Let's search for role-related definitions in the entire codebase
rg -i "role.*client|role.*support" -A 5

# Also search for permission checks similar to the one in the file
ast-grep --pattern 'can($$$)'

Length of output: 1197


Script:

#!/bin/bash
# Let's search for other permission checks in the codebase to understand the role hierarchy
rg "->can\(" -A 2 -B 2

# Also search for any role-based conditions
rg "role:[a-z]+" -A 2 -B 2

Length of output: 1404


Script:

#!/bin/bash
# Let's try a different approach to find permission checks
rg "user.*can\(" -A 2 -B 2

# Also search for any auth-related files that might define roles
fd -e php auth

Length of output: 69859

src/views/tariff/vds/view.php (3)

Line range hint 20-24: LGTM! Permission check properly restricts price comparison columns.

The change from a generic permission to the specific price.update permission provides better granularity for controlling access to sensitive pricing information.


Line range hint 31-39: LGTM! Consistent permission check for price comparison details.

The permission check properly controls access to the detailed price comparison information, maintaining consistency with the header section.


Line range hint 102-107: LGTM! Consistent permission checks for overuse resource pricing.

Both sections properly implement the price.update permission check, maintaining consistency throughout the view file.

Also applies to: 117-122

src/views/tariff/server/view.php (3)

Line range hint 31-39: LGTM! Permission check aligns with header visibility

The permission check for price difference data correctly matches the column header visibility, maintaining UI consistency.


Line range hint 20-122: Verify permission change documentation

The permission change from manage to price.update has been consistently implemented throughout the file. However, we should ensure this change is properly documented.

#!/bin/bash
# Check for permission documentation
rg -l "price.update.*permission" --type md
fd -e md -e txt -e rst . | xargs rg "permissions?\s+changes?"

Line range hint 20-24: Verify table structure when columns are hidden

The permission check for displaying additional columns looks correct. However, we should ensure the table remains properly formatted when these columns are hidden.

✅ Verification successful

Table structure is consistent across tariff views

The search results show that the permission-based column visibility pattern is consistently implemented across similar views (server/view.php and vds/view.php). All tables use the same Bootstrap class table-condensed, which handles responsive table layouts properly. The table structure will remain valid even when columns are conditionally hidden, as this is a common pattern in these views.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other views that might have similar table structures
rg -l "Parent tariff price.*Profit" --type php

Length of output: 108


Script:

#!/bin/bash
# Let's try a broader search for table structures in tariff views
rg -g "*/tariff/**/*.php" -l "table|<tr|<td"

# Also search for similar permission checks
rg -g "*/tariff/**/*.php" "can\('price\.update'\)" -C 2

Length of output: 408


Script:

#!/bin/bash
# Let's try searching without the glob pattern
rg "<table" "src/views/tariff"
rg "can\('price\.update'\)" "src/views/tariff"

# Also check the file structure
fd . "src/views/tariff"

Length of output: 3526

src/views/sale/_form.php (2)

116-116: ⚠️ Potential issue

Fix model inconsistency in reason field

The field is bound to $model while other fields use $sale. This inconsistency could lead to bugs if these variables reference different objects.

Apply this diff to fix the inconsistency:

-<?= $form->field($model, "[$idx]reason")
+<?= $form->field($sale, "[$idx]reason")

Likely invalid or redundant comment.


99-102: Verify the implementation of isOperateable()

The field's readonly state depends on isOperateable(). Let's verify its implementation to ensure proper access control.

✅ Verification successful

Let me verify the implementation of isMine() and isMineSeller() methods since they are used in isOperateable().


Implementation of isOperateable() is correct and follows proper access control

The isOperateable() method in Sale model is properly implemented:

  • It returns false if the current user is the buyer (isMine())
  • It returns false if the current user's seller ID matches the buyer ID (isMineSeller())
  • Combined with the sale.update permission check in the view, this ensures proper access control

The readonly state of the form fields is correctly determined based on this business logic.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find the implementation of isOperateable() method
# Expected: Method should exist in Sale model and implement proper access control logic

# Search for the method definition
ast-grep --pattern 'function isOperateable($$$) {
  $$$
}'

# Search for any usage patterns
rg -A 5 'isOperateable'

Length of output: 2517


Script:

#!/bin/bash
# Search for isMine and isMineSeller implementations
ast-grep --pattern 'function isMine($$$) {
  $$$
}'

ast-grep --pattern 'function isMineSeller($$$) {
  $$$
}'

# Search for any related usage patterns
rg -A 5 'isMine|isMineSeller'

Length of output: 973

src/models/Sale.php (2)

153-156: 🛠️ Refactor suggestion

Improve method naming, logic clarity, and documentation.

The method has several areas for improvement:

  1. Spelling: 'Operateable' should be 'Operable'
  2. Double negative logic makes it harder to understand
  3. Missing documentation for this critical permission check

Consider this refactor:

+    /**
+     * Determines if the current user can operate on this sale.
+     * 
+     * A sale is operable if the current user is neither the buyer
+     * nor associated with the buyer's seller.
+     *
+     * @return bool true if the current user can operate on this sale
+     */
-    public function isOperateable()
+    public function isOperable()
     {
-        return !$this->isMine() && !$this->isMineSeller();
+        $isCurrentUserInvolved = $this->isMine() || $this->isMineSeller();
+        return !$isCurrentUserInvolved;
     }

Since this is a critical permission method used across the UI, let's verify its usage:

#!/bin/bash
# Search for current usage to assess impact of the rename
rg -A 5 "isOperateable"

148-151: 🛠️ Refactor suggestion

Verify the business logic and improve method clarity.

The method name and implementation raise some concerns:

  1. The name isMineSeller() suggests checking seller ownership, but it compares buyer_id with current user's seller_id
  2. The logic seems counterintuitive - please verify if this is the intended business logic
  3. Documentation is missing

If the logic is correct, consider:

  1. Renaming to better reflect the purpose (e.g., isBuyerMySellerClient())
  2. Adding documentation:
+    /**
+     * Checks if the buyer is a client of the current user's seller.
+     *
+     * @return bool true if the buyer is associated with current user's seller
+     */
     public function isMineSeller()
     {
         return (string) $this->buyer_id === (string) Yii::$app->user->identity->seller_id;
     }
✅ Verification successful

Method name and logic are correct, but documentation is needed

The implementation is actually correct based on the surrounding context:

  • isMine() checks if the current user is the buyer
  • isMineSeller() checks if the current user's seller is the buyer
  • Both methods are used in isOperateable() to determine if the sale can be operated on (returns false if either the current user is the buyer or their seller is the buyer)

[refactor_suggestion_optional]
Add documentation to clarify the purpose:

+    /**
+     * Checks if the current user's seller is the buyer of this sale.
+     * Used in conjunction with isMine() to determine if the sale can be operated on.
+     *
+     * @return bool true if the current user's seller is the buyer
+     * @see isOperateable()
+     */
     public function isMineSeller()
     {
         return (string) $this->buyer_id === (string) Yii::$app->user->identity->seller_id;
     }
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages to understand the business context
rg -A 5 "isMineSeller"

Length of output: 2550


Script:

#!/bin/bash
# Let's try a different approach to search for usages and context
rg "isMineSeller" -B 5 -A 5

# Also search for related methods in the Sale class
ast-grep --pattern $'class Sale {
  $$$
  isMine() {
    $$$
  }
  $$$
}'

Length of output: 953

src/views/bill/create-exchange.php (2)

Line range hint 35-39: Permission check implementation looks good!

The change from $canSupport to access-subclients permission check is implemented correctly using Yii2's RBAC system. The conditional rendering is clean and follows best practices.

Let's verify consistent permission usage across the codebase:

✅ Verification successful

Permission check implementation is consistently used across the codebase

The verification confirms that:

  • The access-subclients permission is consistently used across multiple views, controllers, and components (12 files)
  • No lingering $canSupport variables were found in the codebase
  • The change aligns with the broader codebase structure and permission system
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent usage of 'access-subclients' permission
# and ensure no lingering $canSupport variables

# Check for permission usage
rg -l "access-subclients"

# Check for any remaining $canSupport variables
rg -l "\$canSupport"

Length of output: 393


Script:

#!/bin/bash
# Let's properly search for the patterns as the previous execution seems to have mixed up commands

# Check for permission usage
rg -l "access-subclients"

# Check for any remaining $canSupport variables
rg -l "\\\$canSupport"

# Let's also check the auth configuration to verify the permission definition
fd -e php "authManager|rbac|permissions" -X cat

Length of output: 481


Line range hint 89-98: Verify AJAX endpoint security

The client change handler makes an AJAX call to /finance/bill/get-exchange-rates. Ensure this endpoint has proper permission checks to prevent unauthorized access to exchange rates.

Let's check the endpoint implementation:

✅ Verification successful

Let me gather more information about the security implementation.


Let me check the controller's access control implementation specifically.


AJAX endpoint is properly secured

The endpoint security is properly implemented through multiple layers:

  • Access control is enforced via EasyAccessControl behavior where all actions require at least bill.read permission
  • The getExchangeRates function is private, meaning it can only be accessed through a public action that inherits these access controls
  • The function includes proper client ID validation, using the current user's ID as fallback
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Look for the exchange rates endpoint implementation
# to verify permission checks

# Search for the action implementation
ast-grep --pattern 'function getExchangeRates($$$) {
  $$$
}'

# Search for route configuration
rg "get-exchange-rates"

Length of output: 393


Script:

#!/bin/bash
# Search for the controller class that would handle this endpoint
rg -A 5 "class.*BillController"

# Look for access control configurations
ast-grep --pattern 'function behaviors() {
  $$$
}'

# Search for any route configurations in config files
rg -g "*.php" "finance/bill"

Length of output: 1795


Script:

#!/bin/bash
# Look for access control in BillController
rg -A 10 "behaviors\(\)" src/controllers/BillController.php

# Check for any base controller access rules
rg -A 10 "behaviors\(\)" src/controllers/CrudController.php

# Look for the getExchangeRates action implementation
rg -A 10 "function getExchangeRates" src/controllers/BillController.php

Length of output: 1518

src/grid/HistorySalesGridView.php (1)

Line range hint 204-224: Verify permission hierarchy impact

The permission hierarchy implementation looks good, with proper fallback handling. However, we should verify that this permission change doesn't break existing functionality.

Let's check for other components that might be affected by this permission change:

✅ Verification successful

Permission hierarchy is correctly implemented and consistent across the codebase

The permission hierarchy in HistorySalesGridView.php aligns perfectly with the existing permission structure throughout the application:

  • sale.read is used as the highest level permission for full sales access in SaleController.php and menu visibility in SidebarMenu.php
  • plan.read serves as a secondary permission level across multiple components including tariff profiles, plans, and targets
  • The fallback behavior in HistorySalesGridView.php matches the application's permission design pattern

The changes maintain consistency with the established permission system and won't break existing functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related permission checks and potential dependencies
echo "Checking for related permission checks..."
rg -l "can\(['\"]sale\.read['\"]" --type php

echo "Checking for potential permission configurations..."
rg -l "sale\.read" --type php --type json --type yaml

echo "Checking for related controller actions..."
ast-grep --pattern 'function action$_() {
  $$$
  can($_, "sale.read")
  $$$
}'

Length of output: 644


Script:

#!/bin/bash
# Let's examine the specific usage in these files

echo "=== Checking SidebarMenu.php ==="
rg "sale\.read" src/menus/SidebarMenu.php -B 2 -A 2

echo -e "\n=== Checking SaleController.php ==="
rg "sale\.read" src/controllers/SaleController.php -B 2 -A 2

echo -e "\n=== Looking for plan.read permission usage ==="
rg "plan\.read" --type php -B 2 -A 2

Length of output: 5309

src/controllers/BillController.php (2)

248-250: LGTM: Permission check update aligns with objectives.

The change from 'support' to 'access-subclients' permission provides more specific access control, which aligns with the PR objectives to correct abstract permissions.


248-250: Verify view template compatibility.

The removal of $canSupport variable affects the view template 'create-exchange'. Please ensure the template has been updated accordingly.

✅ Verification successful

No compatibility issues found - $canSupport variable is not used in the view template

The view template 'create-exchange.php' has been verified and does not contain any references to the $canSupport variable. Instead, it correctly uses Yii::$app->user->can('access-subclients') for permission checking, which aligns with the changes made in the controller.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if create-exchange view template still references $canSupport

# Search for $canSupport usage in view templates
rg -l '\$canSupport' 'src/views'

# Get specific content of create-exchange template
cat src/views/bill/create-exchange.php

Length of output: 7291

@@ -62,7 +62,7 @@
]) ?>
</div>

<?php if ($detalizationAllowed || Yii::$app->user->can('support')): ?>
<?php if ($detalizationAllowed || Yii::$app->user->can('bill.charges.read')): ?>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify redundant permission check

The condition contains a redundant permission check. Looking at line 23, $detalizationAllowed is already set to:

$detalizationAllowed = Yii::$app->params['module.finance.bill.detalization.allowed'] || Yii::$app->user->can('bill.charges.read');

Therefore, checking bill.charges.read again in the if condition is unnecessary.

Simplify the condition to:

-    <?php if ($detalizationAllowed || Yii::$app->user->can('bill.charges.read')): ?>
+    <?php if ($detalizationAllowed): ?>

@@ -56,7 +56,7 @@ public function run()
$cartCurrency
);

if (!Yii::$app->user->can('support')) {
if (Yii::$app->user->can('role:client')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not check for roles.
How about !can(access-subclients)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Negative!
role:reseller - has permission
role:support - has permission
role:client - must have permission, because now he could have a manager/admin in account!

@@ -122,7 +122,7 @@ protected function analyzeResponse($response)
if (isset($response['_error']) && $response['_error'] === 'not enough money') {
foreach ($this->purchases as $key => $purchase) {
$error = Yii::t('hipanel:finance', 'Insufficient funds on the balance');
if ($this->user->can('support')) {
if (!$this->user->can('role:client')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not check for roles.
How about can(resell)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Negative. manager/support...

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
src/widgets/CartCurrencyNegotiator.php (1)

Based on the search results, I can now generate the final response:

Permission check needs alignment with established patterns

The codebase consistently uses can('access-subclients') for controlling access to client-related operations, as seen in multiple views, controllers, and components. The current condition can('resell') || !isAccountOwner() deviates from this established pattern.

Key findings:

  • access-subclients is used across the codebase for:
    • Viewing client information in sales and targets
    • Managing bills and purses
    • Controlling access to client selection widgets
  • isAccountOwner() is only used in two places, both related to purchase validation
  • The current mixed permission check could lead to inconsistent access control

Consider replacing:

if (Yii::$app->user->can('resell') || !Yii::$app->user->isAccountOwner())

with:

if (Yii::$app->user->can('access-subclients'))
🔗 Analysis chain

Line range hint 59-67: Consider using access-subclients permission instead

Based on the previous discussion, using role-based or account ownership checks might not be the best approach. The current condition can('resell') || !isAccountOwner() could be too permissive and doesn't clearly express the business intent.

Consider using can('access-subclients') instead, as it would:

  • Better express the business intent (accessing client's data)
  • Follow the principle of permission-based access control
  • Align with the changes made in other parts of the codebase

Let's verify the permission usage across the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for access-subclients permission usage
rg -A 2 "access-subclients"

# Search for isAccountOwner usage to understand the context
rg -A 2 "isAccountOwner"

Length of output: 4874

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 456ec38 and dfd4719.

📒 Files selected for processing (2)
  • src/cart/BatchPurchaseStrategy.php (1 hunks)
  • src/widgets/CartCurrencyNegotiator.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/cart/BatchPurchaseStrategy.php
🔇 Additional comments (1)
src/widgets/CartCurrencyNegotiator.php (1)

179-179: Verify the business logic for sale.create permission

The permission check for showing the "enough" balance template has been changed from 'manage' to 'sale.create'. This affects whether users can proceed with payment despite insufficient balance.

Please verify:

  1. Does 'sale.create' permission accurately represent the ability to bypass balance checks?
  2. Should users with 'sale.create' permission always be able to proceed regardless of balance?

Let's check the permission usage:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants