├── docs └── EditRole.png ├── app ├── locale │ └── de_DE │ │ └── MagentoHackathon_AdvancedAcl.csv ├── etc │ └── modules │ │ └── MagentoHackathon_AdvancedAcl.xml └── code │ └── community │ └── MagentoHackathon │ └── AdvancedAcl │ ├── Model │ └── Observer │ │ ├── Access.php │ │ ├── Customer.php │ │ ├── Abstract.php │ │ ├── Url.php │ │ ├── Config.php │ │ ├── Catalog.php │ │ ├── Sales.php │ │ └── Role.php │ ├── Test │ ├── Config │ │ ├── ObserverUrlConfigTests.php │ │ └── ObserverRoleConfigTests.php │ └── Helper │ │ └── DataTests.php │ ├── sql │ └── magentohackathon_advancedacl_setup │ │ └── install-1.0.0.php │ ├── Block │ └── Adminhtml │ │ ├── System │ │ └── Config │ │ │ └── Switcher.php │ │ ├── Store │ │ └── Switcher.php │ │ └── Permissions │ │ └── Tab │ │ └── Stores.php │ ├── Helper │ └── Data.php │ └── etc │ └── config.xml ├── modman ├── .travis.yml ├── composer.json └── README.md /docs/EditRole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magento-hackathon/AdvancedAcl/HEAD/docs/EditRole.png -------------------------------------------------------------------------------- /app/locale/de_DE/MagentoHackathon_AdvancedAcl.csv: -------------------------------------------------------------------------------- 1 | "Advanced ACL","Erweiterte Zugriffsbeschränkung" 2 | "Restrict store view access","StoreView-Zugriff einschränken" 3 | -------------------------------------------------------------------------------- /modman: -------------------------------------------------------------------------------- 1 | app/etc/modules/MagentoHackathon_AdvancedAcl.xml app/etc/modules/MagentoHackathon_AdvancedAcl.xml 2 | app/code/community/MagentoHackathon/AdvancedAcl app/code/community/MagentoHackathon/AdvancedAcl 3 | app/locale/de_DE/MagentoHackathon_AdvancedAcl.csv app/locale/de_DE/MagentoHackathon_AdvancedAcl.csv 4 | -------------------------------------------------------------------------------- /app/etc/modules/MagentoHackathon_AdvancedAcl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | community 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.4 4 | - 5.5 5 | env: 6 | matrix: 7 | - MAGENTO_VERSION=magento-ce-1.9.1.0 8 | - MAGENTO_VERSION=magento-ce-1.9.0.1 9 | - MAGENTO_VERSION=magento-ce-1.8.1.0 10 | - MAGENTO_VERSION=magento-ce-1.8.0.0 11 | before_script: 12 | - curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar 13 | - phpenv rehash 14 | - git clone https://github.com/AOEpeople/magento-coding-standard $(pear config-get php_dir)/PHP/CodeSniffer/Standards/Ecg 15 | script: 16 | # Code Style 17 | - php phpcs.phar --config-set ignore_warnings_on_exit --standard=$(pear config-get php_dir)/PHP/CodeSniffer/Standards/Ecg --encoding=utf-8 --report-width=180 ./app 18 | # Unit Tests 19 | - curl -sSL https://raw.githubusercontent.com/AOEpeople/MageTestStand/master/setup.sh | bash 20 | notifications: 21 | email: false -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "magento-hackathon/advanced-acl", 3 | "type": "magento-module", 4 | "license": "OSL-3.0", 5 | "homepage": "https://github.com/magento-hackathon/AdvancedAcl.git", 6 | "description": "Restrict Magento admin permissions to specific websites or storeviews", 7 | "authors": [ 8 | { 9 | "name": "Thomas Birke", 10 | "email": "tbirke@netextreme.de" 11 | }, 12 | { 13 | "name": "Michael Lühr", 14 | "email": "ml@luehr-software.de" 15 | }, 16 | { 17 | "name": "Andre Flitsch", 18 | "email": "andre@pixelperfect.at" 19 | }, 20 | { 21 | "name": "Andreas Penz", 22 | "email": "testa.peta@gmail.com" 23 | } 24 | ], 25 | "require":{ 26 | "magento-hackathon/magento-composer-installer":"*" 27 | } 28 | } -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Access.php: -------------------------------------------------------------------------------- 1 | getControllerAction(); 18 | 19 | $storeId = $controller->getRequest()->getParam('store'); 20 | 21 | if (!$this->getHelper()->hasStoreViewAccess($storeId)) { 22 | $this->deniedAction($controller, self::CATALOG_PRODUCT_INDEX_ROUTE_PATH); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Test/Config/ObserverUrlConfigTests.php: -------------------------------------------------------------------------------- 1 | assertEventObserverDefined( 15 | 'adminhtml', 16 | 'controller_action_predispatch_adminhtml_catalog_product_edit', 17 | 'magentohackathon_advancedacl/observer_url', 18 | 'catalogProductEdit' 19 | ); 20 | 21 | $this->assertEventObserverDefined( 22 | 'adminhtml', 23 | 'controller_action_predispatch_adminhtml_catalog_category_edit', 24 | 'magentohackathon_advancedacl/observer_url', 25 | 'catalogCategoryEdit' 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Customer.php: -------------------------------------------------------------------------------- 1 | getCollection(); 14 | if ($collection instanceof Mage_Customer_Model_Resource_Customer_Collection) { 15 | $storeIds = $this->getStoreIds(); 16 | 17 | if ( ! empty($storeIds)) { 18 | $collection->addAttributeToFilter('store_id', array('in' => $storeIds)); 19 | } 20 | } 21 | } 22 | 23 | /** 24 | * retrieves allowed store ids 25 | * 26 | * @return mixed 27 | */ 28 | protected function getStoreIds() 29 | { 30 | return Mage::helper('magentohackathon_advancedacl/data')->getActiveRole()->getStoreIds(); 31 | } 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Abstract.php: -------------------------------------------------------------------------------- 1 | deniedAction(); 26 | return $controller->setFlag('', Mage_Adminhtml_System_ConfigController::FLAG_NO_DISPATCH, true); 27 | return false; 28 | } 29 | 30 | /** 31 | * @param Mage_Core_Controller_Varien_Action $controller 32 | * @param $routePath 33 | */ 34 | public function deniedAction($controller, $routePath) 35 | { 36 | /** @var Mage_Core_Model_Url $urlModel */ 37 | $urlModel = Mage::helper('adminhtml'); 38 | $controller->getResponse()->setRedirect($urlModel->getUrl($routePath)); 39 | return; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Test/Config/ObserverRoleConfigTests.php: -------------------------------------------------------------------------------- 1 | assertEventObserverDefined( 15 | 'adminhtml', 16 | 'admin_permissions_role_prepare_save', 17 | 'magentohackathon_advancedacl/observer_role', 18 | 'addStoresToRoleModel' 19 | ); 20 | 21 | $this->assertEventObserverDefined( 22 | 'adminhtml', 23 | 'admin_roles_save_after', 24 | 'magentohackathon_advancedacl/observer_role', 25 | 'saveAfter' 26 | ); 27 | 28 | $this->assertEventObserverDefined( 29 | 'adminhtml', 30 | 'admin_roles_load_after', 31 | 'magentohackathon_advancedacl/observer_role', 32 | 'afterLoad' 33 | ); 34 | 35 | $this->assertEventObserverDefined( 36 | 'adminhtml', 37 | 'admin_roles_delete_before', 38 | 'magentohackathon_advancedacl/observer_role', 39 | 'beforeDelete' 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/sql/magentohackathon_advancedacl_setup/install-1.0.0.php: -------------------------------------------------------------------------------- 1 | startSetup(); 7 | 8 | $table = $installer->getConnection() 9 | ->newTable($installer->getTable('magentohackathon_advancedacl/role_store')) 10 | ->addColumn('role_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( 11 | 'nullable' => false, 12 | 'primary' => true, 13 | ), 'Role ID') 14 | ->addColumn('store_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array( 15 | 'unsigned' => true, 16 | 'nullable' => false, 17 | 'primary' => true, 18 | ), 'Store ID') 19 | ->addIndex($installer->getIdxName('magentohackathon_advancedacl/role_store', array('store_id')), 20 | array('store_id')) 21 | ->addForeignKey($installer->getFkName('magentohackathon_advancedacl/role_store', 'role_id', 'admin/role', 'role_id'), 22 | 'role_id', $installer->getTable('admin/role'), 'role_id', 23 | Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE) 24 | ->addForeignKey($installer->getFkName('magentohackathon_advancedacl/role_store', 'store_id', 'core/store', 'store_id'), 25 | 'store_id', $installer->getTable('core/store'), 'store_id', 26 | Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE) 27 | ->setComment('Admin Role To Store Linkage Table'); 28 | $installer->getConnection()->createTable($table); 29 | 30 | $installer->endSetup(); -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Url.php: -------------------------------------------------------------------------------- 1 | getRequest()->getParam(self::STORE_PARAM_KEY); 24 | $defaultStoreId = $this->getHelper()->getDefaultStoreId(); 25 | $allowedStoreIds = $this->getHelper()->getAllowedStoreIds(); 26 | 27 | if (is_null($storeId) && !empty($allowedStoreIds) && !in_array($defaultStoreId, $allowedStoreIds)) { 28 | $storeId = current($allowedStoreIds); 29 | $controller->getRequest()->setParam(self::STORE_PARAM_KEY, $storeId); 30 | } 31 | } 32 | 33 | /** 34 | * @param Varien_Event_Observer $observer 35 | */ 36 | public function catalogProductEdit(Varien_Event_Observer $observer) 37 | { 38 | $this->_appendFirstStoreId($observer->getControllerAction()); 39 | } 40 | 41 | /** 42 | * @param Varien_Event_Observer $observer 43 | */ 44 | public function catalogCategoryEdit(Varien_Event_Observer $observer) 45 | { 46 | $this->_appendFirstStoreId($observer->getControllerAction()); 47 | } 48 | 49 | /** 50 | * @param Varien_Event_Observer $observer 51 | */ 52 | public function cmsPageIndex(Varien_Event_Observer $observer) 53 | { 54 | $this->_appendFirstStoreId($observer->getControllerAction()); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Block/Adminhtml/System/Config/Switcher.php: -------------------------------------------------------------------------------- 1 | hasFullAccess()) { 44 | unset($options['default']); 45 | foreach ($options as $key=>$option) { 46 | if (preg_match('/^website_(.+)$/', $key, $matches)) { 47 | if (false === $helper->hasFullWebsiteAccess($matches[1])) { 48 | unset($options[$key]); 49 | } 50 | } elseif (preg_match('/^group_(.+)_(open|close)$/', $key, $matches)) { 51 | if (false === $helper->hasFullStoreGroupAccess($matches[1])) { 52 | unset($options[$key]); 53 | } 54 | } elseif (preg_match('/^store_(.+)$/', $key, $matches)) { 55 | if (false === $helper->hasStoreViewAccess($matches[1])) { 56 | unset($options[$key]); 57 | } 58 | } 59 | } 60 | } 61 | 62 | return $options; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Config.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | 35 | 36 | /** 37 | * Class MagentoHackathon_AdvancedAcl_Model_Observer_Config 38 | */ 39 | class MagentoHackathon_AdvancedAcl_Model_Observer_Config 40 | extends MagentoHackathon_AdvancedAcl_Model_Observer_Abstract 41 | { 42 | public function beforeLoad($observer) 43 | { 44 | $controller = $observer->getControllerAction(); 45 | if ($controller instanceof Mage_Adminhtml_System_ConfigController) { 46 | switch ($controller->getRequest()->getActionName()) { 47 | case 'edit': 48 | case 'save': 49 | return $this->_checkScopeAccess($controller); 50 | } 51 | } 52 | } 53 | 54 | protected function _checkScopeAccess($controller) 55 | { 56 | $website = $controller->getRequest()->getParam('website'); 57 | $store = $controller->getRequest()->getParam('store'); 58 | 59 | if ($this->getHelper()->hasFullAccess() || $this->getHelper()->isSingleStoreMode()) { 60 | // there is no restriction for this user 61 | return; 62 | } 63 | 64 | if ($store) { 65 | if (false === $this->getHelper()->hasStoreViewAccess($store)) { 66 | return $this->denyAccess($controller); 67 | } 68 | } elseif ($website) { 69 | if (false === $this->getHelper()->hasFullWebsiteAccess($website)) { 70 | return $this->denyAccess($controller); 71 | } 72 | } else { 73 | return $this->denyAccess($controller); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Build Status 2 | --- 3 | [![Build Status](https://travis-ci.org/magento-hackathon/AdvancedAcl.svg?branch=master)](https://travis-ci.org/magento-hackathon/AdvancedAcl) 4 | 5 | # Extended Access Control List for Magento 6 | 7 | This extension allows merchants to restrict admin users to specific store views, 8 | so it makes your Magento multitenant. 9 | 10 | ![image](https://raw.github.com/magento-hackathon/AdvancedAcl/master/docs/EditRole.png) 11 | 12 | ### What we can do 13 | 14 | We currently support restrictions of Magento Core: 15 | 16 | * system configuration, 17 | * customers 18 | * catalog, and 19 | * sales 20 | 21 | ### What we can't do 22 | 23 | There are lots of third party extensions for Magento and we can't support every 24 | single of them, so we focused on Magento Core, allowing you (or your developer) 25 | to extend it according to your needs. 26 | 27 | ## Installation 28 | 29 | We recommend to use [Composer](http://getcomposer.org) to install this into your 30 | Magento store, but you may also use 31 | [modman](https://github.com/colinmollenhour/modman) or just copy the extension 32 | into your Magento root. 33 | 34 | Most of our code uses event/observer pattern to gain maximum compatibility, but 35 | there are few rewrites, too (namely store switcher blocks). So make sure, your 36 | other extensions do not override the same blocks. 37 | 38 | Clean cache after installation. 39 | 40 | ## Usage 41 | 42 | Open System → Permissions → Roles and select a role without full system access. 43 | There you will find a new tab "Advanced ACL" in there, where you will be able to 44 | restrict the role to some specific store views. 45 | 46 | *If none is selected, the role access won't get limited.* 47 | 48 | Regarding system configuration, users will be able to enter website level, if 49 | they have access to all stores of the website. Furthermore, users will be able 50 | to enter default level, if they have access to all stores of your Magento 51 | installation. 52 | 53 | ## Extending 54 | 55 | Your shop probably contains lots of modules and you might want to restrict 56 | access to these, too. 57 | 58 | Our helper provides three methods to determine access: 59 | 60 | * ``Mage::helper('magentohackathon_advancedacl')->hasStoreViewAccess($store)`` 61 | to request access to a specific store (given as Mage_Core_Model_Store, store 62 | id or store code), 63 | * ``Mage::helper('magentohackathon_advancedacl')->hasFullStoreGroupAccess($storegroup)`` 64 | to request access to a whole storegroup (given as Mage_Core_Model_Store, store 65 | id or store code), that means, the user is allowed to 66 | access all stores of this store group, 67 | * ``Mage::helper('magentohackathon_advancedacl')->hasFullWebsiteAccess($website)`` 68 | to request access to a whole website (given as Mage_Core_Model_Website, 69 | website id or website code), that means, the user is allowed to 70 | access all stores of this website, 71 | * ``Mage::helper('magentohackathon_advancedacl')->hasFullAccess()`` 72 | to request access to the whole shop, that means, the user is allowed to 73 | access all stores of the shop 74 | 75 | Licence 76 | ------- 77 | [OSL - Open Software Licence 3.0](http://opensource.org/licenses/osl-3.0.php) 78 | 79 | Copyright 80 | --------- 81 | (c) 2015 82 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Catalog.php: -------------------------------------------------------------------------------- 1 | getCollection(); 14 | if ($collection instanceof Mage_Catalog_Model_Resource_Product_Collection) { 15 | $storeIds = $this->getStoreIds(); 16 | 17 | if (!empty($storeIds)) { 18 | $collection->addStoreFilter(current($storeIds)); 19 | } 20 | } 21 | } 22 | 23 | /** 24 | * filter url rewrite collection by allowed stores 25 | * 26 | * @param Varien_Event_Observer $observer 27 | */ 28 | public function filterUrlRewriteCollection(Varien_Event_Observer $observer) 29 | { 30 | $collection = $observer->getCollection(); 31 | if ($collection instanceof Mage_Core_Model_Resource_Url_Rewrite_Collection) { 32 | $storeIds = $this->getStoreIds(); 33 | if (!empty($storeIds)) { 34 | $collection->addStoreFilter($storeIds); 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * filter search terms by allowed stores 41 | * 42 | * @param Varien_Event_Observer $observer 43 | */ 44 | public function filterSearchTermsGrid(Varien_Event_Observer $observer) 45 | { 46 | $collection = $observer->getCollection(); 47 | if ($collection instanceof Mage_CatalogSearch_Model_Resource_Query_Collection) { 48 | $storeIds = $this->getStoreIds(); 49 | if (!empty($storeIds)) { 50 | $collection->addStoreFilter($storeIds); 51 | } 52 | } 53 | } 54 | /** 55 | * filter search terms by allowed stores 56 | * 57 | * @param Varien_Event_Observer $observer 58 | */ 59 | public function filterTagGrid(Varien_Event_Observer $observer) 60 | { 61 | $collection = $observer->getCollection(); 62 | if ($collection instanceof Mage_Tag_Model_Resource_Tag_Collection) { 63 | $storeIds = $this->getStoreIds(); 64 | if (!empty($storeIds)) { 65 | $collection->addStoreFilter($storeIds); 66 | } 67 | } 68 | } 69 | 70 | /** 71 | * filter out categories by allowed stores 72 | * 73 | * @param Varien_Event_Observer $observer 74 | */ 75 | public function filterCategories(Varien_Event_Observer $observer) 76 | { 77 | /** @var Mage_Catalog_Model_Resource_Category_Collection $collection */ 78 | $collection = $observer->getCategoryCollection(); 79 | $storeIds = $this->getStoreIds(); 80 | $oldStoreId = $collection->getStoreId(); 81 | // setting the first allowed store if the current store is not allowed for user 82 | if (!empty($storeIds) && !in_array($oldStoreId, $storeIds)) { 83 | $allowedStoreId = current($storeIds); 84 | $collection 85 | ->setProductStoreId($allowedStoreId) 86 | ->setStoreId($allowedStoreId); 87 | } 88 | } 89 | 90 | /** 91 | * retrieves allowed store ids 92 | * 93 | * @return mixed 94 | */ 95 | protected function getStoreIds() 96 | { 97 | return Mage::helper('magentohackathon_advancedacl/data')->getActiveRole()->getStoreIds(); 98 | } 99 | } -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Block/Adminhtml/Store/Switcher.php: -------------------------------------------------------------------------------- 1 | hasFullAccess()) { 43 | $this->_hasDefaultOption = false; 44 | } 45 | } 46 | 47 | public function isShow() 48 | { 49 | $helper = Mage::helper('magentohackathon_advancedacl'); 50 | if (false === $helper->isSingleStoreMode()) { 51 | return true; 52 | } 53 | return parent::isShow(); 54 | } 55 | 56 | /** 57 | * Get websites 58 | * 59 | * @return array 60 | */ 61 | public function getWebsites() 62 | { 63 | $helper = Mage::helper('magentohackathon_advancedacl'); 64 | $websites = parent::getWebsites(); 65 | $result = array(); 66 | foreach($websites as $website) { 67 | foreach ($website->getStores() as $store) { 68 | if ($helper->hasStoreViewAccess($store)) { 69 | $result[] = $website; 70 | break; 71 | } 72 | } 73 | } 74 | return $result; 75 | } 76 | 77 | /** 78 | * Get store groups for specified website 79 | * 80 | * @param Mage_Core_Model_Website $website 81 | * @return array 82 | */ 83 | public function getStoreGroups($website) 84 | { 85 | $helper = Mage::helper('magentohackathon_advancedacl'); 86 | $storeGroups = parent::getStoreGroups($website); 87 | $result = array(); 88 | foreach($storeGroups as $key=>$storeGroup) { 89 | foreach ($storeGroups->getStores() as $store) { 90 | if ($helper->hasStoreViewAccess($store)) { 91 | $result[$key] = $storeGroup; 92 | break; 93 | } 94 | } 95 | } 96 | return $result; 97 | } 98 | 99 | /** 100 | * Get store views for specified store group 101 | * 102 | * @param Mage_Core_Model_Store_Group $group 103 | * @return array 104 | */ 105 | public function getStores($group) 106 | { 107 | $helper = Mage::helper('magentohackathon_advancedacl'); 108 | $stores = parent::getStores($group); 109 | $result = array(); 110 | foreach($stores as $key=>$store) { 111 | if ($helper->hasStoreViewAccess($store)) { 112 | $result[$key] = $store; 113 | } 114 | } 115 | return $result; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Sales.php: -------------------------------------------------------------------------------- 1 | getOrderGridCollection(); 14 | $this->filterCollection($collection); 15 | 16 | } 17 | 18 | /** 19 | * filter sales order invoices collection by allowed stores 20 | * 21 | * @param Varien_Event_Observer $observer 22 | */ 23 | public function filterInvoiceGrid(Varien_Event_Observer $observer) 24 | { 25 | $collection = $observer->getOrderInvoiceGridCollection(); 26 | $this->filterCollection($collection); 27 | } 28 | 29 | /** 30 | * filters shipment grid by allowed stores 31 | * 32 | * @param Varien_Event_Observer $observer 33 | */ 34 | public function filterShipmentsGrid(Varien_Event_Observer $observer) 35 | { 36 | $collection = $observer->getOrderShipmentGridCollection(); 37 | $this->filterCollection($collection); 38 | } 39 | 40 | 41 | /** 42 | * filters credit memos grid by allowed stores 43 | * 44 | * @param Varien_Event_Observer $observer 45 | */ 46 | public function filterCreditMemoGrid(Varien_Event_Observer $observer) 47 | { 48 | $collection = $observer->getOrderCreditmemoGridCollection(); 49 | $this->filterCollection($collection); 50 | } 51 | 52 | public function filterAgreements(Varien_Event_Observer $observer) 53 | { 54 | $collection = $observer->getOrderCreditmemoGridCollection(); 55 | $this->filterCollection($collection); 56 | } 57 | 58 | /** 59 | * filters agreements grid by allowed stores 60 | * 61 | * @param Varien_Event_Observer $observer 62 | */ 63 | public function filterAgreementsGrid(Varien_Event_Observer $observer) 64 | { 65 | $collection = $observer->getCollection(); 66 | if ($collection instanceof Mage_Checkout_Model_Resource_Agreement_Collection) { 67 | // getStoreIds() includes a DB query, so only execute this if this is the correct collection! 68 | $storeIds = $this->getStoreIds(); 69 | if (! empty($storeIds) && ! in_array(Mage_Core_Model_App::ADMIN_STORE_ID, $storeIds)) { 70 | $collection->setIsStoreFilterWithAdmin(false); 71 | $collection->addStoreFilter($storeIds); 72 | } 73 | } 74 | if ($collection instanceof Mage_Sales_Model_Resource_Order_Payment_Transaction_Collection) { 75 | // getStoreIds() includes a DB query, so only execute this if this is the correct collection! 76 | $storeIds = $this->getStoreIds(); 77 | $collection->addStoreFilter($storeIds); 78 | } 79 | } 80 | 81 | 82 | /** 83 | * filters recurring profile grid by allowed stores 84 | * 85 | * @param Varien_Event_Observer $observer 86 | */ 87 | public function filterRecurringProfilesGrid(Varien_Event_Observer $observer) 88 | { 89 | /** @var Mage_Sales_Model_Resource_Recurring_Profile_Collection $collection */ 90 | $collection = $observer->getRecurringProfileCollection(); 91 | $storeIds = $this->getStoreIds(); 92 | if (0 < count($storeIds)) { 93 | $collection->addFieldToFilter('store_id', array('in' => $storeIds)); 94 | } 95 | } 96 | 97 | 98 | /** 99 | * retrieves allowed store ids 100 | * 101 | * @return mixed 102 | */ 103 | protected function getStoreIds() 104 | { 105 | return Mage::helper('magentohackathon_advancedacl/data')->getActiveRole()->getStoreIds(); 106 | } 107 | 108 | /** 109 | * @param $collection 110 | */ 111 | public function filterCollection($collection) 112 | { 113 | $storeIds = $this->getStoreIds(); 114 | if (0 < count($storeIds)) { 115 | $collection->addAttributeToFilter('store_id', array('in' => $storeIds)); 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Block/Adminhtml/Permissions/Tab/Stores.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | 35 | class MagentoHackathon_AdvancedAcl_Block_Adminhtml_Permissions_Tab_Stores 36 | extends Mage_Adminhtml_Block_Widget_Form 37 | implements Mage_Adminhtml_Block_Widget_Tab_Interface 38 | { 39 | /** 40 | * @return MagentoHackathon_AdvancedAcl_Helper_Data 41 | */ 42 | protected function _getHelper() 43 | { 44 | return Mage::helper('magentohackathon_advancedacl'); 45 | } 46 | 47 | protected function _initForm() 48 | { 49 | $form = new Varien_Data_Form(); 50 | $fieldset = $form->addFieldset('base_fieldset', array( 51 | 'legend' => Mage::helper('adminhtml')->__('Restrict store view access')) 52 | ); 53 | 54 | /** 55 | * Check is single store mode 56 | */ 57 | if (!$this->_getHelper()->isSingleStoreMode()) { 58 | $field = $fieldset->addField('store_ids', 'multiselect', array( 59 | 'name' => 'stores[]', 60 | 'label' => Mage::helper('cms')->__('Store View'), 61 | 'title' => Mage::helper('cms')->__('Store View'), 62 | 'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(), 63 | )); 64 | $renderer = $this->getLayout()->createBlock('adminhtml/store_switcher_form_renderer_fieldset_element'); 65 | $field->setRenderer($renderer); 66 | } 67 | else { 68 | $fieldset->addField('store_ids', 'hidden', array( 69 | 'name' => 'stores[]', 70 | 'value' => Mage::app()->getStore(true)->getId() 71 | )); 72 | } 73 | 74 | $form->setValues($this->getRole()->getData()); 75 | $this->setForm($form); 76 | } 77 | 78 | /** 79 | * 80 | */ 81 | protected function _beforeToHtml() 82 | { 83 | $this->_initForm(); 84 | parent::_beforeToHtml(); 85 | } 86 | 87 | /** 88 | * 89 | * @return Mage_Admin_Model_Roles 90 | */ 91 | protected function getRole() 92 | { 93 | return Mage::registry('current_role'); 94 | } 95 | 96 | /** 97 | * 98 | * @return Mage_Admin_Model_Roles 99 | */ 100 | protected function getRoles() 101 | { 102 | return $this->getRole(); 103 | } 104 | 105 | /** 106 | * 107 | * @return MagentoHackathon_AdvancedAcl_Helper_Data 108 | */ 109 | protected function _helper() 110 | { 111 | return Mage::helper('magentohackathon_advancedacl'); 112 | } 113 | 114 | 115 | public function canShowTab() 116 | { 117 | return true; 118 | } 119 | 120 | public function getTabLabel() 121 | { 122 | return Mage::helper('magentohackathon_advancedacl')->__('Advanced ACL'); 123 | } 124 | 125 | public function getTabTitle() 126 | { 127 | return $this->getTabLabel(); 128 | } 129 | 130 | public function isHidden() 131 | { 132 | return false; 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Model/Observer/Role.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | 35 | 36 | /** 37 | * Class MagentoHackathon_AdvancedAcl_Model_Observer_Role 38 | */ 39 | class MagentoHackathon_AdvancedAcl_Model_Observer_Role 40 | { 41 | 42 | /** 43 | * Add store restriction tab 44 | * 45 | * @param Varien_Event $event 46 | */ 47 | public function addTabToRoles($event) 48 | { 49 | $block = $event->getBlock(); 50 | 51 | /* @var Mage_Adminhtml_Block_Permissions_Editroles $block */ 52 | if ($block instanceof Mage_Adminhtml_Block_Permissions_Editroles 53 | && Mage::helper('magentohackathon_advancedacl')->isAdmin() 54 | ) { 55 | $tab = $block->getLayout()->createBlock( 56 | 'magentohackathon_advancedacl/adminhtml_permissions_tab_stores', 57 | 'adminhtml.permissions.tab.magentohackathon_advancedacl' 58 | ); 59 | $block->addTab('magentohackathon_advancedacl', $tab); 60 | } 61 | } 62 | 63 | /** 64 | * @param $roleId 65 | * @return mixed 66 | */ 67 | public function lookupStoreIds($roleId) 68 | { 69 | $adapter = $this->_getReadAdapter(); 70 | 71 | $select = $adapter->select() 72 | ->from($this->_getTable('magentohackathon_advancedacl/role_store'), 'store_id') 73 | ->where('role_id = ?',(int)$roleId); 74 | 75 | return $adapter->fetchCol($select); 76 | } 77 | 78 | /** 79 | * @return mixed 80 | */ 81 | protected function _getReadAdapter() 82 | { 83 | return Mage::getSingleton('core/resource')->getConnection('core_read'); 84 | } 85 | 86 | /** 87 | * @return mixed 88 | */ 89 | protected function _getWriteAdapter() 90 | { 91 | return Mage::getSingleton('core/resource')->getConnection('core_write'); 92 | } 93 | 94 | /** 95 | * @param $tableName 96 | * @return mixed 97 | */ 98 | protected function _getTable($tableName) 99 | { 100 | return Mage::getSingleton('core/resource')->getTableName($tableName); 101 | } 102 | 103 | /** 104 | * @param Varien_Event_Observer $observer 105 | */ 106 | public function addStoresToRoleModel(Varien_Event_Observer $observer) 107 | { 108 | /** @var Mage_Admin_Model_Roles $role */ 109 | $role = $observer->getObject(); 110 | /** @var Mage_Core_Controller_Request_Http $request */ 111 | $request = $observer->getRequest(); 112 | 113 | if ($stores = $request->getParam('stores')) { 114 | $role->setStores($stores); 115 | } 116 | } 117 | 118 | /** 119 | * @param Varien_Event_Observer $observer 120 | */ 121 | public function saveAfter(Varien_Event_Observer $observer) 122 | { 123 | $object = $observer->getDataObject(); 124 | 125 | if ($object instanceof Mage_Admin_Model_Roles) { 126 | if ($object->getStores()) { 127 | $oldStores = $this->lookupStoreIds($object->getId()); 128 | $newStores = (array)$object->getStores(); 129 | if (empty($newStores)) { 130 | $newStores = (array)$object->getStoreId(); 131 | } 132 | $table = $this->_getTable('magentohackathon_advancedacl/role_store'); 133 | $insert = array_diff($newStores, $oldStores); 134 | $delete = array_diff($oldStores, $newStores); 135 | 136 | if ($delete) { 137 | $where = array( 138 | 'role_id = ?' => (int) $object->getId(), 139 | 'store_id IN (?)' => $delete 140 | ); 141 | 142 | $this->_getWriteAdapter()->delete($table, $where); 143 | } 144 | 145 | if ($insert) { 146 | $data = array(); 147 | 148 | foreach ($insert as $storeId) { 149 | $data[] = array( 150 | 'role_id' => (int) $object->getId(), 151 | 'store_id' => (int) $storeId 152 | ); 153 | } 154 | $this->_getWriteAdapter()->insertMultiple($table, $data); 155 | } 156 | } 157 | } 158 | } 159 | 160 | /** 161 | * @param Varien_Event_Observer $observer 162 | */ 163 | public function afterLoad(Varien_Event_Observer $observer) 164 | { 165 | $object = $observer->getDataObject(); 166 | if ($object->getId()) { 167 | $stores = $this->lookupStoreIds($object->getId()); 168 | $object->setData('store_ids', $stores); 169 | } 170 | } 171 | 172 | /** 173 | * @param Varien_Event_Observer $observer 174 | */ 175 | public function beforeDelete(Varien_Event_Observer $observer) 176 | { 177 | $object = $observer->getDataObject(); 178 | 179 | if ($object->getId()) { 180 | $condition = array( 181 | 'role_id = ?' => (int)$object->getId(), 182 | ); 183 | $this->_getWriteAdapter()->delete($this->_getTable('magentohackathon_advancedacl/role_store'), $condition); 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Helper/Data.php: -------------------------------------------------------------------------------- 1 | 33 | * @author Thomas Birke 34 | */ 35 | 36 | class MagentoHackathon_AdvancedAcl_Helper_Data 37 | extends Mage_Core_Helper_Abstract 38 | { 39 | 40 | protected $_websites = null; 41 | 42 | /** 43 | * @var null|boolean 44 | */ 45 | protected $_isSingleStoreMode = null; 46 | 47 | /** 48 | * if customer is allowed to access given store 49 | * 50 | * @param int|string|Mage_Core_Model_Store $store store id, store code, or store 51 | * @return bool 52 | */ 53 | public function hasStoreViewAccess($store = null) 54 | { 55 | if (is_null($store)) { 56 | $store = $this->getDefaultStoreId(); 57 | } 58 | if (is_object($store) && $store instanceof Mage_Core_Model_Store) { 59 | $storeId = $store->getId(); 60 | } elseif (is_numeric($store)) { 61 | $storeId = $store; 62 | } else { 63 | $storeId = Mage::getModel('core/store')->load($store)->getId(); 64 | } 65 | $allowedStores = $this->getActiveRole()->getStoreIds(); 66 | 67 | return empty($allowedStores) || in_array($storeId, $allowedStores); 68 | } 69 | 70 | /** 71 | * get stores the customer is restricted to 72 | * 73 | * @return array 74 | * @codeCoverageIgnore 75 | */ 76 | public function getAllowedStoreIds() 77 | { 78 | return $this->getActiveRole()->getStoreIds(); 79 | } 80 | 81 | /** 82 | * if customer is restricted to specific stores 83 | * 84 | * @return bool 85 | */ 86 | public function hasFullAccess() 87 | { 88 | $allowedStoreIds = $this->getAllowedStoreIds(); 89 | 90 | return empty($allowedStoreIds) 91 | || Mage::getModel('core/store')->getCollection()->getAllIds() === $allowedStoreIds; 92 | } 93 | 94 | /** 95 | * if customer can access all stores of a website 96 | * 97 | * @param Mage_Core_Model_Website|string $website Website to check stores of 98 | * @return bool 99 | */ 100 | public function hasFullWebsiteAccess($website) 101 | { 102 | if (is_string($website)) { 103 | $website = Mage::getModel('core/website')->load($website); 104 | } 105 | 106 | $diff = array_diff($website->getStoreIds(), $this->getAllowedStoreIds()); 107 | return empty($diff); 108 | } 109 | 110 | /** 111 | * if customer can access all stores of a store group 112 | * 113 | * @param Mage_Core_Model_Store_Group|string $group Group to check stores of 114 | * @return bool 115 | */ 116 | public function hasFullStoreGroupAccess($storeGroup) 117 | { 118 | if (is_string($storeGroup)) { 119 | $storeGroup = Mage::getModel('core/store_group')->load($storeGroup); 120 | } 121 | 122 | $diff = array_diff($storeGroup->getStoreIds(), $this->getAllowedStoreIds()); 123 | return empty($diff); 124 | } 125 | 126 | /** 127 | * @param int $roleid role_id from admin/role 128 | * @return boolean 129 | * @codeCoverageIgnore 130 | */ 131 | public function isAdmin() 132 | { 133 | $collection = Mage::getModel('admin/rules') 134 | ->getCollection() 135 | ->addFieldToFilter('role_id', $this->getActiveRole()->getId()) 136 | ->addFieldToFilter('resource_id', 'all') 137 | ->addFieldToFilter('permission', 'allow'); 138 | if($collection->count() > 0) 139 | { 140 | return true; 141 | } 142 | return false; 143 | } 144 | 145 | /** 146 | * 147 | * @return Mage_Admin_Model_Role 148 | * @codeCoverageIgnore 149 | */ 150 | public function getActiveRole() 151 | { 152 | $user = Mage::getSingleton('admin/session')->getUser(); 153 | if ($user === null) { 154 | // this can happen on API calls - make sure to use an administrator with all rights then! 155 | // we should not filter any collection for API calls since our restrictions are defined per admin-user 156 | // we currently do not have any restrictions for API users 157 | $adminRoleId = Mage::getModel('admin/rules') 158 | ->getCollection() 159 | ->addFieldToFilter('resource_id', Mage_Admin_Model_Resource_Acl::ACL_ALL_RULES) 160 | ->addFieldToFilter('permission', Mage_Admin_Model_Rules::RULE_PERMISSION_ALLOWED) 161 | ->setPageSize(1) 162 | ->setCurPage(1) 163 | ->getFirstItem() 164 | ->getData('role_id'); 165 | 166 | return Mage::getModel('admin/role')->load($adminRoleId); 167 | } 168 | 169 | return $user->getRole(); 170 | } 171 | 172 | /** 173 | * Is single Store mode (only one store without default) 174 | * 175 | * @return bool|null 176 | * @codeCoverageIgnore 177 | */ 178 | public function isSingleStoreMode() 179 | { 180 | if (is_null($this->_isSingleStoreMode)) { 181 | $this->_isSingleStoreMode = Mage::app()->isSingleStoreMode(); 182 | } 183 | return $this->_isSingleStoreMode; 184 | } 185 | 186 | /** 187 | * get the default store-id 188 | * 189 | * @return mixed 190 | * @throws Mage_Core_Exception 191 | * @codeCoverageIgnore 192 | */ 193 | public function getDefaultStoreId() 194 | { 195 | return Mage::app() 196 | ->getWebsite(true) 197 | ->getDefaultGroup() 198 | ->getDefaultStoreId(); 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/Test/Helper/DataTests.php: -------------------------------------------------------------------------------- 1 | getModelMock('admin/roles', array('__call')); 18 | 19 | $rolesMock->expects($this->once()) 20 | ->method('__call') 21 | ->with('getStoreIds') 22 | ->will($this->returnValue(array(1))); 23 | 24 | $this->replaceByMock('model', 'admin/roles', $rolesMock); 25 | 26 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getDefaultStoreId', 'getActiveRole')); 27 | 28 | $helperMock->expects($this->once()) 29 | ->method('getDefaultStoreId') 30 | ->will($this->returnValue(1)); 31 | 32 | $helperMock->expects($this->once()) 33 | ->method('getActiveRole') 34 | ->will($this->returnValue($rolesMock)); 35 | 36 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 37 | 38 | $this->assertTrue( 39 | Mage::helper(self::HELPER_ALIAS)->hasStoreViewAccess() 40 | ); 41 | 42 | $rolesMock = $this->getModelMock('admin/roles', array('__call')); 43 | 44 | $rolesMock->expects($this->once()) 45 | ->method('__call') 46 | ->with('getStoreIds') 47 | ->will($this->returnValue(array(2))); 48 | 49 | $this->replaceByMock('model', 'admin/roles', $rolesMock); 50 | 51 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getDefaultStoreId', 'getActiveRole')); 52 | 53 | $helperMock->expects($this->once()) 54 | ->method('getDefaultStoreId') 55 | ->will($this->returnValue(1)); 56 | 57 | $helperMock->expects($this->once()) 58 | ->method('getActiveRole') 59 | ->will($this->returnValue($rolesMock)); 60 | 61 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 62 | 63 | $this->assertFalse( 64 | Mage::helper(self::HELPER_ALIAS)->hasStoreViewAccess() 65 | ); 66 | 67 | } 68 | 69 | public function testIsAllowedAccessForStoreWithStoreParam() 70 | { 71 | $rolesMock = $this->getModelMock('admin/roles', array('__call')); 72 | 73 | $rolesMock->expects($this->once()) 74 | ->method('__call') 75 | ->with('getStoreIds') 76 | ->will($this->returnValue(array(1))); 77 | 78 | $this->replaceByMock('model', 'admin/roles', $rolesMock); 79 | 80 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getDefaultStoreId', 'getActiveRole')); 81 | 82 | $helperMock->expects($this->once()) 83 | ->method('getActiveRole') 84 | ->will($this->returnValue($rolesMock)); 85 | 86 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 87 | 88 | $this->assertTrue( 89 | Mage::helper(self::HELPER_ALIAS)->hasStoreViewAccess(1) 90 | ); 91 | 92 | $rolesMock = $this->getModelMock('admin/roles', array('__call')); 93 | 94 | $rolesMock->expects($this->once()) 95 | ->method('__call') 96 | ->with('getStoreIds') 97 | ->will($this->returnValue(array(1))); 98 | 99 | $this->replaceByMock('model', 'admin/roles', $rolesMock); 100 | 101 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getDefaultStoreId', 'getActiveRole')); 102 | 103 | $helperMock->expects($this->once()) 104 | ->method('getActiveRole') 105 | ->will($this->returnValue($rolesMock)); 106 | 107 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 108 | 109 | $this->assertFalse( 110 | Mage::helper(self::HELPER_ALIAS)->hasStoreViewAccess(2) 111 | ); 112 | } 113 | 114 | public function testHasFullAccess() 115 | { 116 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds', 'getActiveRole')); 117 | 118 | $helperMock->expects($this->once()) 119 | ->method('getAllowedStoreIds') 120 | ->will($this->returnValue(array(3,4))); 121 | 122 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 123 | 124 | $coreStoreCollectionMock = $this->getResourceModelMock('core/store_collection', array('getAllIds')); 125 | 126 | $coreStoreCollectionMock->expects($this->once()) 127 | ->method('getAllIds') 128 | ->will($this->returnValue(array(3,4))); 129 | 130 | $this->replaceByMock('resource_model', 'core/store_collection', $coreStoreCollectionMock); 131 | 132 | $this->assertTrue( 133 | Mage::helper(self::HELPER_ALIAS)->hasFullAccess() 134 | ); 135 | 136 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds', 'getActiveRole')); 137 | 138 | $helperMock->expects($this->once()) 139 | ->method('getAllowedStoreIds') 140 | ->will($this->returnValue(array(3,4))); 141 | 142 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 143 | 144 | $coreStoreCollectionMock = $this->getResourceModelMock('core/store_collection', array('getAllIds')); 145 | 146 | $coreStoreCollectionMock->expects($this->once()) 147 | ->method('getAllIds') 148 | ->will($this->returnValue(array(1,2,3,4,5))); 149 | 150 | $this->replaceByMock('resource_model', 'core/store_collection', $coreStoreCollectionMock); 151 | 152 | $this->assertFalse( 153 | Mage::helper(self::HELPER_ALIAS)->hasFullAccess() 154 | ); 155 | 156 | } 157 | 158 | public function testHasFullWebsiteAccess() 159 | { 160 | $coreWebsiteModelMock = $this->getModelMock('core/website', array('getStoreIds')); 161 | 162 | $coreWebsiteModelMock->expects($this->once()) 163 | ->method('getStoreIds') 164 | ->will($this->returnValue(array(13))); 165 | 166 | $this->replaceByMock('model', 'core/website', $coreWebsiteModelMock); 167 | 168 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 169 | 170 | $helperMock->expects($this->once()) 171 | ->method('getAllowedStoreIds') 172 | ->will($this->returnValue(array(13))); 173 | 174 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 175 | 176 | $this->assertTrue( 177 | Mage::helper(self::HELPER_ALIAS)->hasFullWebsiteAccess('dummy') 178 | ); 179 | 180 | $coreWebsiteModelMock = $this->getModelMock('core/website', array('getStoreIds')); 181 | 182 | $coreWebsiteModelMock->expects($this->once()) 183 | ->method('getStoreIds') 184 | ->will($this->returnValue(array(13))); 185 | 186 | $this->replaceByMock('model', 'core/website', $coreWebsiteModelMock); 187 | 188 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 189 | 190 | $helperMock->expects($this->once()) 191 | ->method('getAllowedStoreIds') 192 | ->will($this->returnValue(array(12))); 193 | 194 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 195 | 196 | $this->assertFalse( 197 | Mage::helper(self::HELPER_ALIAS)->hasFullWebsiteAccess('dummy') 198 | ); 199 | 200 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 201 | 202 | $helperMock->expects($this->once()) 203 | ->method('getAllowedStoreIds') 204 | ->will($this->returnValue(array(12))); 205 | 206 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 207 | 208 | $this->assertTrue( 209 | Mage::helper(self::HELPER_ALIAS)->hasFullWebsiteAccess( 210 | (new Varien_Object())->setStoreIds(array(12)) 211 | ) 212 | ); 213 | 214 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 215 | 216 | $helperMock->expects($this->once()) 217 | ->method('getAllowedStoreIds') 218 | ->will($this->returnValue(array(12))); 219 | 220 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 221 | 222 | $this->assertFalse( 223 | Mage::helper(self::HELPER_ALIAS)->hasFullWebsiteAccess( 224 | (new Varien_Object())->setStoreIds(array(2)) 225 | ) 226 | ); 227 | } 228 | 229 | public function testHasFullStoreGroupAccess() 230 | { 231 | $coreStoreGroupModelMock = $this->getModelMock('core/store_group', array('getStoreIds')); 232 | 233 | $coreStoreGroupModelMock->expects($this->once()) 234 | ->method('getStoreIds') 235 | ->will($this->returnValue(array(4,5,6))); 236 | 237 | $this->replaceByMock('model', 'core/store_group', $coreStoreGroupModelMock); 238 | 239 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 240 | 241 | $helperMock->expects($this->once()) 242 | ->method('getAllowedStoreIds') 243 | ->will($this->returnValue(array(4,5,6))); 244 | 245 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 246 | 247 | $this->assertTrue( 248 | Mage::helper(self::HELPER_ALIAS)->hasFullStoreGroupAccess('dummy') 249 | ); 250 | 251 | $coreStoreGroupModelMock = $this->getModelMock('core/store_group', array('getStoreIds')); 252 | 253 | $coreStoreGroupModelMock->expects($this->once()) 254 | ->method('getStoreIds') 255 | ->will($this->returnValue(array(5))); 256 | 257 | $this->replaceByMock('model', 'core/store_group', $coreStoreGroupModelMock); 258 | 259 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 260 | 261 | $helperMock->expects($this->once()) 262 | ->method('getAllowedStoreIds') 263 | ->will($this->returnValue(array(30))); 264 | 265 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 266 | 267 | $this->assertFalse( 268 | Mage::helper(self::HELPER_ALIAS)->hasFullStoreGroupAccess('dummy') 269 | ); 270 | 271 | $this->replaceByMock('model', 'core/store_group', $coreStoreGroupModelMock); 272 | 273 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 274 | 275 | $helperMock->expects($this->once()) 276 | ->method('getAllowedStoreIds') 277 | ->will($this->returnValue(array(5))); 278 | 279 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 280 | 281 | $this->assertTrue( 282 | Mage::helper(self::HELPER_ALIAS)->hasFullStoreGroupAccess( 283 | (new Varien_Object())->setStoreIds(array(5)) 284 | ) 285 | ); 286 | 287 | $this->replaceByMock('model', 'core/store_group', $coreStoreGroupModelMock); 288 | 289 | $helperMock = $this->getHelperMock(self::HELPER_ALIAS, array('getAllowedStoreIds')); 290 | 291 | $helperMock->expects($this->once()) 292 | ->method('getAllowedStoreIds') 293 | ->will($this->returnValue(array(9))); 294 | 295 | $this->replaceByMock('helper', self::HELPER_ALIAS, $helperMock); 296 | 297 | $this->assertFalse( 298 | Mage::helper(self::HELPER_ALIAS)->hasFullStoreGroupAccess( 299 | (new Varien_Object())->setStoreIds(array(5)) 300 | ) 301 | ); 302 | 303 | } 304 | 305 | } -------------------------------------------------------------------------------- /app/code/community/MagentoHackathon/AdvancedAcl/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1.0.0 6 | 7 | 8 | 9 | 10 | 11 | MagentoHackathon_AdvancedAcl_Model 12 | magentohackathon_advancedacl_resource 13 | 14 | 15 | MagentoHackathon_AdvancedAcl_Model_Resource 16 | 17 | 18 | admin_role_store
19 |
20 |
21 |
22 |
23 | 24 | 25 | MagentoHackathon_AdvancedAcl_Helper 26 | 27 | 28 | 29 | 30 | MagentoHackathon_AdvancedAcl_Block 31 | 32 | 33 | 34 | MagentoHackathon_AdvancedAcl_Block_Adminhtml_Store_Switcher 35 | MagentoHackathon_AdvancedAcl_Block_Adminhtml_System_Config_Switcher 36 | 37 | 38 | 39 | 40 | 41 | 42 | MagentoHackathon_AdvancedAcl 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | 51 | 52 | MagentoHackathon_AdvancedAcl.csv 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | singleton 62 | magentohackathon_advancedacl/observer_role 63 | addStoresToRoleModel 64 | 65 | 66 | 67 | 68 | 69 | 70 | singleton 71 | magentohackathon_advancedacl/observer_role 72 | saveAfter 73 | 74 | 75 | 76 | 77 | 78 | 79 | singleton 80 | magentohackathon_advancedacl/observer_role 81 | afterLoad 82 | 83 | 84 | 85 | 86 | 87 | 88 | singleton 89 | magentohackathon_advancedacl/observer_role 90 | beforeDelete 91 | 92 | 93 | 94 | 95 | 96 | 97 | singleton 98 | magentohackathon_advancedacl/observer_role 99 | addTabToRoles 100 | 101 | 102 | 103 | 104 | 105 | 106 | singleton 107 | magentohackathon_advancedacl/observer_sales 108 | filterOrderGrid 109 | 110 | 111 | 112 | 113 | 114 | 115 | singleton 116 | magentohackathon_advancedacl/observer_sales 117 | filterInvoiceGrid 118 | 119 | 120 | 121 | 122 | 123 | 124 | singleton 125 | magentohackathon_advancedacl/observer_sales 126 | filterShipmentsGrid 127 | 128 | 129 | 130 | 131 | 132 | 133 | singleton 134 | magentohackathon_advancedacl/observer_sales 135 | filterCreditMemoGrid 136 | 137 | 138 | 139 | 140 | 141 | 142 | singleton 143 | magentohackathon_advancedacl/observer_sales 144 | filterRecurringProfilesGrid 145 | 146 | 147 | 148 | 149 | 150 | 151 | singleton 152 | magentohackathon_advancedacl/observer_sales 153 | filterAgreementsGrid 154 | 155 | 156 | singleton 157 | magentohackathon_advancedacl/observer_catalog 158 | filterUrlRewriteCollection 159 | 160 | 161 | singleton 162 | magentohackathon_advancedacl/observer_catalog 163 | filterSearchTermsGrid 164 | 165 | 166 | singleton 167 | magentohackathon_advancedacl/observer_catalog 168 | filterTagGrid 169 | 170 | 171 | 172 | 173 | 174 | 175 | singleton 176 | magentohackathon_advancedacl/observer_catalog 177 | filterCategories 178 | 179 | 180 | 181 | 182 | 183 | 184 | singleton 185 | magentohackathon_advancedacl/observer_catalog 186 | filterProductGrid 187 | 188 | 189 | singleton 190 | magentohackathon_advancedacl/observer_customer 191 | filterCustomerGrid 192 | 193 | 194 | 195 | 196 | 197 | 198 | singleton 199 | magentohackathon_advancedacl/observer_config 200 | beforeLoad 201 | 202 | 203 | 204 | 205 | 206 | 207 | singleton 208 | magentohackathon_advancedacl/observer_access 209 | productEditAccessAllowed 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | singleton 218 | magentohackathon_advancedacl/observer_url 219 | catalogProductEdit 220 | 221 | 222 | 223 | 224 | 225 | 226 | singleton 227 | magentohackathon_advancedacl/observer_url 228 | catalogCategoryEdit 229 | 230 | 231 | 232 | 233 | 234 | 235 | singleton 236 | magentohackathon_advancedacl/observer_url 237 | cmsPageIndex 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 |
252 | --------------------------------------------------------------------------------