-
Notifications
You must be signed in to change notification settings - Fork 6
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
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThe 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 Changes
Possibly related PRs
Suggested reviewers
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 checkWhile the
$model
property is typed asSale
, 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 clarityThe 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 structureThe 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 readabilityThe 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 genericmanage
permission, demonstrates good security practices by:
- Following the principle of least privilege
- Providing fine-grained access control
- 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 resultSince 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 sectionSimilar 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:
- Adding PHPDoc explaining the purpose and return value
- 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 invertedThe 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
- The
sale.create
permission is used to bypass balance validation inCartCurrencyNegotiator.php
, but there are no additional balance validations found in the payment flow.- 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 checksThe condition
Yii::$app->user->can('sale.create')
allows users to bypass balance checks. This could lead to security issues if:
- The 'sale.create' permission is too broadly assigned
- There are no additional validation steps later in the payment process
Please verify:
- The scope and assignment policy of the 'sale.create' permission
- 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 handlingThe 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 checksThe 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
📒 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 billsbill.create
for creating billsbill.update
for modifying billsbill.delete
for removing billsbill.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:
- The
plan.set-note
permission is properly implemented in the view file - 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()
returnsfalse
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 withsale.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:
- The role hierarchy is binary in this context - users are either clients or non-clients
- There are no intermediate roles that would be affected by this change
- The permission check is consistently used across the codebase to differentiate between client and non-client users
- 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
:
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:
- Spelling: 'Operateable' should be 'Operable'
- Double negative logic makes it harder to understand
- 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:
- The name
isMineSeller()
suggests checking seller ownership, but it comparesbuyer_id
with current user'sseller_id
- The logic seems counterintuitive - please verify if this is the intended business logic
- Documentation is missing
If the logic is correct, consider:
- Renaming to better reflect the purpose (e.g.,
isBuyerMySellerClient()
) - 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 buyerisMineSeller()
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 leastbill.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 inSaleController.php
and menu visibility inSidebarMenu.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')): ?> |
There was a problem hiding this comment.
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')) { |
There was a problem hiding this comment.
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)
?
There was a problem hiding this comment.
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!
src/cart/BatchPurchaseStrategy.php
Outdated
@@ -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')) { |
There was a problem hiding this comment.
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)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Negative. manager/support...
There was a problem hiding this 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 conditioncan('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 usingaccess-subclients
permission insteadBased 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
📒 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:
- Does 'sale.create' permission accurately represent the ability to bypass balance checks?
- Should users with 'sale.create' permission always be able to proceed regardless of balance?
Let's check the permission usage:
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Documentation
These changes improve user experience by ensuring that only authorized users can access certain features, enhancing security and usability.