There might be times when you do not want your catalog to be publicly visible, especially if running a B2B shop. Reasons for this are numerous but, from our experience, prices are on top of the list. Unfortunately, when it comes to Magento (at least Open Source edition), this feature is not available out of the box. Lucky for us, implementation is pretty straightforward. Let’s dig in.
The idea
When a customer tries to access the store (catalog, CMS, checkout, etc.), redirect him to login form (if he is not already logged in).
The plan
When planning this feature, good thing to know about Magento is that every route is composed of 3 parts:
- Module name
- Controller name
- Action name
We can use this piece of information on every request that comes to Magento, in order to see where the request is supposed to go.
This is only half of the information we need. Additionally, we need to know whether customer is already logged in.
Specific combination of conditions above should redirect the customer to login form.
What would be the proper way to check for those conditions? Well, hooking into Magento’s dispatching process (namely, predispatch), we can create an observer that will check what route is requested, as well as whether customer is already logged in.
- Create a 3rd party module (e.g. Inchoo_WebsiteRestriction)
- Register an observer
- Implement logic
The execution
- Done
- create file in Inchoo/WebsiteRestriction/etc/frontend/events.xml
<config xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi_noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="controller_action_predispatch"> <observer name="restrict_website" instance="InchooWebsiteRestrictionObserverRestrictWebsite" /> </event> </config>
- Create observer file at Inchoo/WebsiteRestriction/Observer/RestrictWebsite.php
<?php namespace InchooWebsiteRestrictionObserver; use MagentoCustomerModelContext; use MagentoFrameworkEventObserver; use MagentoFrameworkEventObserverInterface; use MagentoStoreModelStoreManagerInterface; class RestrictWebsite implements ObserverInterface { /** * RestrictWebsite constructor. */ public function __construct( MagentoFrameworkEventManagerInterface $eventManager, MagentoFrameworkAppResponseHttp $response, MagentoFrameworkUrlFactory $urlFactory, MagentoFrameworkAppHttpContext $context, MagentoFrameworkAppActionFlag $actionFlag ) { $this->_response = $response; $this->_urlFactory = $urlFactory; $this->_context = $context; $this->_actionFlag = $actionFlag; } /** * @param Observer $observer * @return void */ public function execute(Observer $observer) { $allowedRoutes = [ 'customer_account_login', 'customer_account_loginpost', 'customer_account_create', 'customer_account_createpost', 'customer_account_logoutsuccess', 'customer_account_confirm', 'customer_account_confirmation', 'customer_account_forgotpassword', 'customer_account_forgotpasswordpost', 'customer_account_createpassword', 'customer_account_resetpasswordpost', 'customer_section_load' ]; $request = $observer->getEvent()->getRequest(); $isCustomerLoggedIn = $this->_context->getValue(Context::CONTEXT_AUTH); $actionFullName = strtolower($request->getFullActionName()); if (!$isCustomerLoggedIn && !in_array($actionFullName, $allowedRoutes)) { $this->_response->setRedirect($this->_urlFactory->create()->getUrl('customer/account/login')); } } }
Following the execute method, we have a list of routes that are white-listed always (e.g. login, logout, create account, reset password, etc.). Reason for this is that customer should be able to access those routes regardless of him being logged in or not (i.e. there is no need to redirect customer to login form, if he is already trying to access that page).
In addition to inspecting the correct route, we need to check whether customer is already logged in. There are at least 2 ways to check this, and one of them is implemented above. The other one would be to use Magento’s customer session object (MagentoCustomerModelSession) and its isLoggedIn() method. However, according to this stackexchange question, there are some issues with it, so we’re not using it this time.
The end
To conclude, if a customer is not logged in, he is redirected to login form where he can login/register. Using this, we restrict access to the store’s catalog and CMS pages.