Web Development Blog

Magento: How to protect pages so only logged in users can view them

07.08.2009 10:03PM by Evan Johnson

There are times when you want all or part of your Magento online store to only be visible to customers who are logged in to the website. Once such example is a "wholesale" website where only approved wholesale users should be able to view products and checkout. This functionality is not built in to Magento, but it’s a just a few simple little code hacks away.

NOTE: On 8.25.09 I updated this post since I have improved the technique.

Create a redirect .phtml template

First, create a small file in the /template/page/html directory of your active theme. Call it something like auth-redirect.phtml. The contents are just:

<?php Mage::getSingleton('customer/session')->setBeforeAuthUrl($this->getRequest()->getRequestUri());  //save requested URL for later redirection
if(!Mage::getSingleton('customer/session')->isLoggedIn()) {  // if not logged in
    header("Status: 301");
    header('Location: '.Mage::helper('core/url')->getHomeUrl(customer/account/login)) ;  // send to the login page
    exit; 
} ?>

Note: Apparently, for Magento 1.4, you should use this code (but I have not tested it):

<?php Mage::getSingleton('customer/session')->setBeforeAuthUrl($this->getRequest()->getRequestUri());  //save requested URL for later redirection
if(!Mage::getSingleton('customer/session')->isLoggedIn()) {  // if not logged in
    header("Status: 301");
    header('Location: '.$this->getUrl('customer/account/login')) ;  // send to the login page
    exit; 
} ?>

Right now the 301 redirects to the login page, but it could be the homepage or somewhere else as well. The first line ensures that after logging in, the user is redirected to the page they first tried to access. Removing that line means the user gets redirected to their Account page after logging in, I believe.

Edit page.xml

Now we want to make the redirect code in auth-redirect.phtml available to all of the page templates on our website. In layout/page.xml in your active theme, add the following line of code:

<block type="page/html" name="auth-redirect" as="auth-redirect" template="page/html/auth-redirect.phtml"/>

Insert this as the first item under the "root" Block (i.e. <block type="page/html" name="root" output="toHtml">)

Edit page layout templates

Now that the redirect code in auth-redirect.phtml is available, we need to include it in all of the page templates. The "page templates" I’m referring to, in the page directory of your theme, are:

  • 1column.phtml
  • 2columns-left.phtml
  • 2columns-right.phtml
  • 3columns.phtml
  • etc etc

Insert the following line into all of them, at the top of the file just after the "<?php" tag.

echo $this->getChildHtml('auth-redirect')

This ensures that the redirect is included before any of the page HTML renders.

Add exceptions (or: public pages)

Finally, we need to add "exceptions" – public pages like the "login" page which don’t need to be protected. On a site that is only accessible to logged in users, the login page needs to be public!! To enable the login page, go to layout/customer.xml and add the following to the <customer_account_login> block:

<remove name="auth-redirect" />

If you want users to be able to create an account, another good one to make public might be <customer_account_create> in layout/customer.xml.

If you want to make the home (front) page public, add the "remove" code to the <cms_index_index> block in layout/page.xml.

You can also add this code to the custom "Layout Update XML" on any category, product or CMS page to make them public.

And your done!

That’s it. Now, if you want to protect just certain parts of a Magento store, or control access based on user Roles, you will have to get a little fancier. I’m not covering that here, but…

One way to do that might be to NOT add the auth-redirect block to the master page.xml (and then do exceptions), but instead to only place it on certain pages like the Cart and Checkout (so the catalog is visible, but you can’t purchase without logging in).

Alternatively, you can control access by placing the conditional with <?php Mage::getSingleton('customer/session')->isLoggedIn() ?> right in specific PHP of pages you want to protect. Some folks check for specific pages by URL using $_SERVER['REQUEST_URI'] with this technique. There’s more on this in the Magento forums here.

Comment

Gravatar Image
On Aug 17, 02:39 PM, (Link)
webwiseguys said:

Thanks for the post; very helpful. However, is there a way to take the user back to the page before logging in?

Gravatar Image
On Aug 17, 10:35 PM, (Link)
Yogi said:

that post i applied into my magento but i didn’t got any help from this, what i want is if any customer will open my website then he has to face a login panel , every customer have to face same thing, and website should be password protected. so nobody can touch my product without login even not directly through url. please help me to short out my problem, help will be appreciated

Thanks in advance..

Gravatar Image
On Aug 18, 11:31 AM, (Link)
Evan Johnson said:

@webwiseguys

Do you mean that after they log in, they are redirected to the page they were originally trying to visit?

That would be pretty slick, and much better for the user experience. If I get around to implementing that I’ll post about it here, but off of the top of my head…

I think you could do that by saving the URL they tried to visit into the getBeforeAuthUrl session variable in the auth_redirect.phtml code snippet, right before it redirects to the login page. I think loginPostAction() in Customer/controllers/AccountController.php already checks for that variable in the Session and redirects to it after the login. Most of the code is already there, I think, so it should be easy.

Try setting something like this in auth_redirect.phtml (I didn’t test it), and see how it works: Mage::getSingleton(‘customer/session’) ->setBeforeAuthUrl(Mage::getUrl().$_SERVER[‘REQUEST_URI’]);

Gravatar Image
On Aug 24, 08:54 AM, (Link)
mk said:

First of all thanks for the method, works like a charm except that like webwiseguys I would like to send the user back to where he came from, instead of showing the user account dashboard.

I’d like to add something to this:

/app/code/core/Mage/Customer/Block/Form/Register.php has a function called getBackUrl() – I suspect that by applying the method shown here (301 redirect) the supplied url is that of the login page, which in fact is part of the customer area.

What if it were possible to do a kind of “redirect” but still show the old url in the address bar via url rewriting? If this is possible the only file that needed to be modified would probably be our auth_redirect.phtml

Just a thought. Any ideas on this?

Gravatar Image
On Aug 24, 10:01 AM, (Link)
mk said:

And another note btw: Static pages like the Imprint, TOS, Legal disclaimer and the like can also be excepted from the forced login by just adding

<remove name=“auth_redirect” />

in the custom layout tab, just as well. :)

Gravatar Image
On Aug 24, 03:19 PM, (Link)
mk said:

…sorry guys… forget my last comment. The way it is now it will cause Magento to issue “Warning: SimpleXMLElement::addAttribute() [simplexmlelement.addattribute]: Attribute already exists”

Any hints on that?

Gravatar Image
On Aug 25, 01:22 PM, (Link)
Evan Johnson said:

@webwiseguys – The code in auth_redirect.phtml now saves the requested URL so the user is redirected back to the page they originally wanted after logging in.

@mk – Also, the auth_redirect.phtml code now checks if the user is logged in so the XML tag in customer.xml under <customer_logged_in> is not needed any more (I removed it from the tutorial). This was what caused the “Attribute already exists” issue mk reported. Now you CAN add exceptions to CMS pages and others through the custom Update XML.

Cheers!

Gravatar Image
On Aug 25, 01:29 PM, (Link)
Evan Johnson said:

@Yogi

This should work like you want. If you don’t add <remove name=“auth_redirect” /> exceptions anywhere, then none of the pages on your site will accessible without logging in. Every single page will send the user to the Login page.

Gravatar Image
On Aug 25, 04:07 PM, (Link)
mk said:

I’m “off duty” till september but I’ll post my feedback on this once I’m back. Thanks for the update Evan!

Gravatar Image
On Sep 2, 03:45 AM, (Link)
mk said:

Hi again Evan. Thanks for your efforts, but I’ve run into problems here.

1) The auth_redirect.phtml snippet needs some extra quotation marks in one line

header('Location: '.Mage::helper('core/url')->getHomeUrl('customer/account/login')) ; // send to the login page

else Magento will think that customer is an undefined constant. (Mind that your Blog changes my simple quotation marks into other characters as I cannot use <pre><code>…</code></pre> in comments.)

2) Furthermore both in the first version and this one I’ve found that auth_redirect.phtml does not work in my ACTIVE theme, but it actually seems to work if you put it into the DEFAULT theme instead. Which is a bit funny.

3) Somehow with the new version I’ve encountered redirect loops that I could not fix yet. It might have to do with the possible mixup of the default and active theme described in 2) ?

Cheers,
Mike

Gravatar Image
On Sep 8, 04:16 AM, (Link)
mk said:

Hi Evan, dunno if my last comment was submitted; I’ve done this again several times step by step but the way it is now I get a 301 redirect loop. Until I find a solution to this I’ve put the <remove> block into <default>.

(Furthermore, the last line in your .phtml is missing quotation marks around customer/account/login …)

Gravatar Image
On Sep 17, 11:34 PM, (Link)
Evan Johnson said:

@mk

Sorry for the delay in moderating and replying. I just fixed the the missing quotes (thanks), and also turned off the fancy typographic quotes on my entire blog since they just get in the way on a blog with this much code. Fixing quotes after a copy/paste sucks a lot! ;)

That’s strange that you need to put auth_redirect.php in the default theme, but thanks for the the tip in case other folks are having trouble with that.

As for the redirect issue… if the <remove name="auth_redirect" /> code is on the page that is being redirected to ('customer/account/login' in this case), that shouldn’t happen. I wonder if it’s related the "default theme" issue? Did you put <remove name="auth_redirect" /> under the <customer_account_login> section of customer.xml in the default theme as well as the active one?

Gravatar Image
On Sep 21, 07:04 AM, (Link)
mk said:

We got it to work. :-)

In our installation, the line

header('Location: '.Mage::helper('core/url')->getHomeUrl(customer/account/login)) ;

did not work, probably because "/index.php" is still part of the URL at this stage of our project.

But if I use

header('Location: http://WHATEVERDOMAIN/index.php/customer/account/login') ;

instead, it works. Seems like the fact that index.php was part of the visible URL caused the 301 loop.
So apparently your method works, but with a caveat. :-)

Thanks a lot!!

Gravatar Image
On Sep 28, 06:38 AM, (Link)
mk said:

Simply adding <remove name="auth_redirect" /> to a CMS page (like Terms of Service, Imprint) still does not work properly yet. It DOES work if I’m not logged in, but once I log in and navigate to such a page I get an XML error telling me that attribute already exists. So my idea is to add something like this

<customer_logged_out>
<remove name="auth_redirect" />
</customer_logged_out>

to those pages, so the layout update would only be carried out if the user were not logged in. But the way I’ve put it here it still doesn’t work.

Any hints?

Gravatar Image
On Sep 30, 01:21 PM, (Link)
Evan Johnson said:

@mk

That is pretty strange. I just added <remove name="auth_redirect" /> to a CMS page on my 1.3.1 site using this and it worked fine.

The only difference between the code I’m using and the code here on the blog is that instead of calling it "auth_redirect" I called it "logged-in-check". Perhaps the underscores are the problem?

The only time I ever got the "attribute already exists" error was with my previous technique, when I had <remove name="auth_redirect" /> under <customer_logged_in>. It happened when I tried to remove the auth_redirect block twice: once in <customer_logged_in> and again in the single page’s XML. I fixed it by removing the <customer_logged_in> one, and adding the IF statement to the redirect .phtml file instead for the "logged in" check.

Sorry you’re having such a hard time with this trick! Check again to make sure that you don’t have the "remove" code under <customer_logged_in> in any of your themes.

Gravatar Image
On Sep 30, 02:31 PM, (Link)
mk said:

hey please dont feel sorry man, youre the one helping me out ;) I’ll try this tomorrow.

Gravatar Image
On Oct 13, 08:37 AM, (Link)
mk said:

Hi Evan,

it works. I’ve tested it thoroughly. :-)

Don’t really know what was wrong, maybe it was due to the underscores. It started working once I removed them.

Gravatar Image
On Oct 13, 10:10 AM, (Link)
Evan Johnson said:

Huh. Well, glad it works now. My bad using an underscore in the name and not testing it. I should know better! Thanks for exposing the error so we could fix it. :)

Gravatar Image
On Dec 22, 04:32 AM, (Link)
rashid sahil said:

Thanks a lot
Nice work

Mage::getSingleton('customer/session')->setBeforeAuthUrl($this->getRequest()->getRequestUri()); //save requested URL for later redirection
if(!Mage::getSingleton('customer/session')->isLoggedIn())
{ //echo Mage::helper('core/url')->getHomeUrl('customer/account/login') ; // if not logged in header("Status: 301"); header('Location: '.Mage::helper('core/url')->getHomeUrl().'customer/account/login') ; // send to the login page //header('Location: http://bigfish.coeus-solutions.de/muhammadrashid/vinnoo/index.php/customer/account/login/') ; exit;
}

Gravatar Image
On Feb 10, 04:33 PM, (Link)
bigdog175 said:

I have followed and retraced the steps as closely as possible but I am getting the code Mage::getSingleton….. on the webpage when accessing url follwed by the homepage content what am I missing? And also what should the file permissions be for the files?

Gravatar Image
On Feb 12, 10:27 AM, (Link)
linx said:

Thats just what I was looking for, thanks a lot, but i’m stuck on redirection problem, and I’ve checked

<remove name="auth-redirect" />

code in costumer.xml, in fact

http://www.moodywood-store.com/customer/account/login

is accessible.

I also tried to change:

header('Location: http://WHATEVERDOMAIN/index.php/customer/account/login');

but it doesn’t work:

http://www.moodywood-store.com

Gravatar Image
On Feb 13, 08:26 AM, (Link)
Subhan Habib said:

i can’t get this to work.
Could somebody please help

Gravatar Image
On Feb 18, 09:04 AM, (Link)
Benjamin said:

I had a problem with CE 1.4 and for those who also have a problem just replace in auth-redirect.php :

header('Location: '.Mage::helper('core/url')->getHomeUrl(customer/account/login)) ;

by :

header('Location: '.$this->getUrl('customer/account/login')) ;

Gravatar Image
On Feb 22, 09:24 PM, (Link)
Evan Johnson said:

@bigdog175, @linx, and @Subhan Habib – I have not tested this with 1.4. Perhaps @Benjamin has the solution? Please post back if it works, I don’t currently have the time to test it. Thanks!

@linx – Pages that have <remove name="auth-redirect" /> are the ones that are accessible. I’m not quite sure what the problem is? Again, maybe @Benjamin’s post will help.

Gravatar Image
On Mar 2, 05:23 AM, (Link)
nicolas said:

Hi,
I’m sorry but my redirection towards my
"auth-redirect.phtml" doesn’t work !!!!
I’m using Magento 1.4

I dont understand I added in page.xml :
<block type="page/html" name="auth-redirect" as="auth-redirect" template="page/html/auth-redirect.phtml" />
under the root tag : <block type="page/html" name="root" output="toHtml" template="page/3columns.phtml">

In the file 3columns.phtml : i added
<?php echo $this->getChildHtml('authRedirect') ?>

but nothing seems to be redirected to my file created in page/html !!

Thanks to help me, i’m becoming crazy !!

Gravatar Image
On Mar 3, 09:53 PM, (Link)
Evan Johnson said:

@nicolas – I really can’t tell what is going wrong from your comment. Also, I have not tested this in 1.4 so might be part of the problem. It might just be your English, but one thing to note is that you don’t redirect "towards" auth-redirect.phtml. That file gets included via the Layout XML, and the redirect is "in" it. You are redirecting "towards" the login page.

If the redirect isn’t working in 1.4, try @Benjamin’s code above.

Gravatar Image
On Mar 7, 06:24 AM, (Link)
Matthew Smith said:

Hi,

Just followed you instructions and had the same problem on v1.4 as a few users (code showing at top of page and not doing anything). After playing around with this a number of times over the past few days I’ve managed to get it to work.

You need to put php open/closing tags around the auth-redirect.phtml code as follows:

<?php
Mage::getSingleton('customer/session')->setBeforeAuthUrl($this->getRequest()->getRequestUri()); //save requested URL for later redirection
if(!Mage::getSingleton('customer/session')->isLoggedIn()) { // if not logged in header("Status: 301"); header('Location: '.$this->getUrl('customer/account/login')) ; // send to the login page exit;
}
?>

Now works great and re-directs back once logged in. Thanks for the original code – just what I needed for my site!

Gravatar Image
On Mar 8, 12:03 PM, (Link)
Marco said:

Hi
I’m a beginner, I followed the steps to insert a new block but this is not working for me and I really dont understand why !!!

Here my steps:

In design/ frontend / layout / [b]page.xml[/b]

under

<block type="page/html_breadcrumbs" name="breadcrumbs" as="breadcrumbs"/>

I added:
<block type="page/html_authredirect" name="authredirect" as="authredirect" />

In app/ code/ Mage/ Page/ Block/ Html/ [b]Authredirect.php[/b]

I added:
<?php
class Mage_Page_Block_Html_Authredirect extends Mage_Core_Block_Template
{ function __construct() { parent::__construct();

$this->setTemplate('page/html/authredirect.phtml'); }

}
?>

In design/ frontend / template/ page/ html/ [b]authredirect.phtml[/b]

I added:
<h1>Hello World !</h1>

In design/ frontend / template/ page/ [b]3columns.phtml[/b]
under this line
<?php echo $this->getChildHtml('breadcrumbs') ?>

i added:
<?php echo $this->getChildHtml('authredirect') ?>

Can you please help me to understand why this is not working ??
I tried to follow exactly the right method but nothing !!

If you copy my codes in your own, do you have the same problem ??

Thank you !

Gravatar Image
On Mar 10, 09:50 AM, (Link)
Evan Johnson said:

@Matthew Smith – It’s true, I did leave out the PHP tags, thanks. I added them above for anyone else who is confused.

@Marco – The first thing I see wrong is that you don’t need to create a Block Class and import the template like you are doing. This could probably work, but that is now how I am doing it in this tutorial. I am just putting the redirect code in a block type="page/html", not creating a new type type="page/html_authredirect". Try it again the way I show above if you can’t get it to work your way.

Gravatar Image
On Mar 10, 02:10 PM, (Link)
Marco said:

Yes I know I tried different ways !
All the ways were goods but what I didn’t know is that I had to refresh the cache via Magento admin !! :) the joke lol
So now it’s good I rewrote your method with

<block type="page/html" name="authredirect" template="authredirect/authredirect.phtml" />

directly without creating a special class…

Gravatar Image
On Apr 20, 08:15 PM, (Link)
Monique said:

Hi

I just installed this on my site and now my site wont work, it just continues to load with a blank page. Any suggestions on what ive done wrong?

Monique

Gravatar Image
On Apr 23, 11:13 AM, (Link)
Evan Johnson said:

@Marco – Glad you got it working! The cache will always get ya :p

@Monique – I can't tell from that what is going wrong. Also, it's been a while since I posted this so my ability to help troubleshoot has diminished greatly...

Gravatar Image
On Apr 29, 11:33 AM, (Link)
Rolando Galindo said:

hey. thank you for your solution. it works in my store (1.3.4) after the "redirect" adjustment.

ps. do you have any step by step links about "How to upgrade your magento version" without loosing your DB. thanks

Gravatar Image
On May 5, 07:00 PM, (Link)
Evan Johnson said:

@Rolando – Glad it works for you! And no, sorry I don’t have any instructions for upgrading Magento as I am not currently maintaining any of the stores I set up. Good luck with the upgrade!

Gravatar Image
On May 24, 01:48 AM, (Link)
Darshana said:

It works fine with Magento ver. 1.4.0.1 also. But when I add the "echo $this->getChildHtml('auth-redirect');" line at the top of temaplte/page/1column.phtml, it shows me the following error:

'The page isn’t redirecting properly'

when I remove that line from 1column.phtml it works fine.

What can be the reason? I am using the 2 column layout with right sidebar.

I am following the instructions carefully. Then can you help me out to get the solution of that problem.

Thanks.

Gravatar Image
On Jun 10, 10:47 PM, (Link)
Adam said:

Have you seen any issues with IE 8. Im seeing it redirect back to the login page. Other browsers seems fine. Thoughts?

Thanks

Adam

Gravatar Image
On Jul 4, 02:47 AM, (Link)
Arti said:

Well that works for me. But what to do if I want to let some of the pages created im Magento CMS stay public. There is no file for them, they use standart 2-column templates. There are also other pages made with this template, that need to be private. How can I add the redirect code, dynamicaly to some of the content pages made in CMS.

Gravatar Image
On Jul 6, 11:53 AM, (Link)
Evan Johnson said:

@everyone – I am sorry, but this post is a year old now and I have not worked with Magento in a while. I really don’t know what the cause of some of your problems are :(. I have not seen that IE8 issue, and I am not sure about the best way to handle individual CMS pages.

But even though I cannot help, feel free to post solutions here as I will continue to approve comments on this post. Good luck!

Gravatar Image
On Jul 6, 12:25 PM, (Link)
Adam said:

Thanks for the post and the reply, its is still very useful..cheers

Gravatar Image
On Jul 26, 11:57 AM, (Link)
JW said:

I’ve done this tutorial and it works great!! However, I would like to restrict the pages to specific user groups. I know that you’re not covering it, but could you give me an idea on how to do it or point me in the right direction? I really appreciate your tutorials!

Gravatar Image
On Jul 27, 10:19 AM, (Link)
Evan Johnson said:

It probably wouldn’t be too hard to check for a user’s group in auth-redirect.phtml, instead of just checking if they are logged in like it does now. Something like this?

$groupId = Mage::getSingleton('customer/session')->getCustomerGroupId();

Gravatar Image
On Aug 19, 02:35 PM, (Link)
Ryan McCarthy said:

I was having some huge issues with this until I noticed my <block> was wrong…

I had the template location wrong! Check to make sure your template location is pointing to the correct file. This was mine:

<block type="page/html" name="auth-redirect" as="auth-redirect" template="page/auth-redirect.phtml"/>

Thanks for some amazing work on this! Now it works like a charm!

Gravatar Image
On Jan 8, 12:59 PM, (Link)
cmw said:

I credited Evan for a solution. Just to let you know.
http://www.magentocommerce.com/boards/viewthread/202860/#t292537

Gravatar Image
On Jan 9, 04:35 PM, (Link)
Evan Johnson said:

Thanks cmw!

Gravatar Image
On Jan 14, 08:58 AM, (Link)
brendan said:

Hi,

I would like to use the above solution, however I want to just redirect to the homepage or www.example.com/

When I try changing the code
from
$this->getUrl('customer/account/login')

to
$this->getUrl('')
i just get a redirection loop. Can anyone suggest a work around.

I just dont want to goto the login page. As I would prefer to see at least the homepage

Gravatar Image
On Jan 14, 10:25 AM, (Link)
Evan Johnson said:

@brendan
You should be able to ditch the getUrl() method and just enter a URL like so:

header('Location: http://www.example.com/');

Gravatar Image
On Jan 17, 03:39 AM, (Link)
Brendan said:

Thanks,

found the issue. Because I wanted to redirect to the home page I needed to ensure I removed the block that was stopping this. Essentially I had a redirection loop happening.

Once I added in the code to ignore the homepage I was ok

thanks

Gravatar Image
On Mar 19, 04:47 PM, (Link)
Dino said:

Nothing works for me… only a blank page. Magento 1.5

Gravatar Image
On Apr 22, 06:37 AM, (Link)
Joejoe said:

This DOES work on Magento 1.5… it works fine … BUT one this is missing from this article… it seems to disable magento’s ability to show error messages/warnings… e.g. if someone tries to login with the wrong password…. there’s no error message – anyone know how I can get these to work alongside this method?

Gravatar Image
On Apr 22, 11:40 AM, (Link)
Joejoe said:

Ahh, solution was some more exceptions needed in the customer.xml ….they are further down in the code. Logout success and what-not.

Gravatar Image
On Apr 28, 07:31 AM, (Link)
Joejoe said:

Arrrrrrrg. Everything was sweet and then it just stopped working… not updated anything… just one day it worked and then two days later it didn’t… tried removing all customisation and replacing it but nothing… no idea why… incredibly frustrating… anyone know why this might suddenly stop working? :S

Gravatar Image
On May 6, 04:57 AM, (Link)
Joejoe said:

So… I couldn’t work out what could possibly be wrong… why it should work then stop working and so after trying to delete files/return to normal/try again, and it still never working… I tried this…

I renamed auth-redirect.phtml to auth-redirect-url.phtml (no special reason for the name) and repeated all steps… and it worked…

Is there any reason why this should have worked for a new name?! I cannot understand why it should… something to do with the cache?!

Gravatar Image
On May 6, 05:00 AM, (Link)
Joejoe said:

Just realised, instantly after posting that!

I had two templates for different websites which had their own files except that they shared the same base template for customer.xml and some others…

…basically, on one website I wanted more exceptions than the other and therefore I had cancelled the script on pages on the other website too….

Solution = some websites use auth-redirect-url.phtml and others use auth-redirect-main.phtml …so exceptions can properly be customised for each site using different names!

Gravatar Image
On Aug 14, 10:34 PM, (Link)
MagePsycho said:

Hi

I have developed the extension that does the same thing, please find the url as:
http://www.magentocommerce.com/magento-connect/MagePsycho/extension/3954/store_restriction

Happy E-Commerce!!
MagePsycho

  Subscribe to article comments