Got straight method for redirecting user to login page, 404 page (Not Found) and 401 page (Unauthorized Access) without having to configure anonymous user and/or add snippet to protected resources.
1. Add login_page key to system setting or context setting.
2. Make sure we provide different page for error_page (404) and unauthorized_page (401) in system setting.
3. Create a new plugin "checkPolicy" and attach 2 system event: OnWebPageInit and OnPageNotFound.
After looking into modResource (/core/model/modx/modresource.class.php), I found that modx->resourceIdentifier may changes on the process.
On
OnWebPageInit event, modx->resourceIdentifier has just been set and provide the authentic value of the resource id. If the resource does not exist, it's simply return string value of the $PHP_SELF (only available when FURL is enabled); otherwise will be numeric value of resource id. On the process, when the resource not available for user, modRequest then forward the resource to 404 error_page (this process also changed modx->resourceIdentifier to error_page ID).
So if we store resourceIdentifier value on
OnWebPageInit, then we can use and compare it at the next event,
OnPageNotFound. Then make a decision whether will be redirected to the login page or return 401 unauthorized_page instead of 404 error_page.
Below the plugin code...
<?php
/**
* checkPolicy plugin
* ------------------
* A general purpose for checking resource permission
* and redirect user to login_page if required
*
* Requirement:
* - Attach system event "OnWebPageInit" and "OnPageNotFound" onto this plugin
* - Create new context/system setting: login_page (resource ID for login page)
* or set it on this plugin as scriptproperties, klik tab Properties > create property: login_page.
**/
//don't process this plugin on manager context or any context we want
$excludeContext = array('mgr');
if (in_array($modx->context->get('key'), $excludeContext)) return;
global $checkResourceIdentifier;
if (!isset($checkResourceIdentifier)) {
//invoked on "OnWebPageInit" when $modx->resourceIdentifier has been set properly
//and save "default" resource ID on GLOBAL $checkResourceIdentifier
$checkResourceIdentifier = $modx->resourceIdentifier;
} elseif (isset($checkResourceIdentifier) && intval($checkResourceIdentifier) > 0 && intval($checkResourceIdentifier) == $checkResourceIdentifier) {
//invoked on "OnPageNotFound" after modRequest send 404 error
//and check $checkResourceIdentifier > 0 (resource exist but no privilege)
//get login_page, unauthorized_page and error_page
$E401 = $modx->getOption('unauthorized_page', $scriptProperties, 0);
$E404 = $modx->getOption('error_page', $scriptProperties, 0);
$login_page = $modx->getOption('login_page', $scriptProperties, 0);
//don't process if "default" resource ID was error_page, unauthorized_page or login_page
if ($checkResourceIdentifier == $E401 || $checkResourceIdentifier == $E404 || $checkResourceIdentifier == $login_page) return '';
//set $checkResourceIdentifier to 0, to make sure the plugin don't make any looping process
$checkResourceIdentifier = 0;
if (!$modx->user->hasSessionContext($modx->context->get('key')) && $login_page > 0) {
//if not logged in? redirect to login page
$modx->sendRedirect($modx->makeUrl($login_page, "", "", 'full'));
} else {
//if logged in but have no privilege? send 401 unauthorized_page instead of 404 error_page
$modx->sendUnauthorizedPage();
}
}
Cheers,
@zaenal
[ed. note: lokamaya last edited this post 12 years, 6 months ago.]