From 100822e5a136fdeb6a316f288fae7f9119e7b60d Mon Sep 17 00:00:00 2001 From: Mohammad Jamil Asfihani Date: Wed, 13 Jul 2022 02:56:48 +0700 Subject: [PATCH] Re-work the filters & Set the route name for routing in config (#444) * Update LoginFilter.php * Update LoginFilter.php * Update LoginFilter.php use `uri_string()` to get the string from current url * uri_string is a bad idea I use `current_url()` and at line 51 I add an extra script in case if user use index.php :) * Update LoginFilter.php * use url_is() function for better solution NOTE : Since url_is() is available start from CodeIgniter 4.0.5, user must update their application. * a little re work for another filters I remove the helper('auth) since it's no use in there (performance reason) and put the session check at the begin of code, because we need a session data right? * fix * Update PermissionFilter.php * Candidate for BaseFilter & the reserved routes I add defaultLandingRoute to store the default route name after user success to login (depend on the real case) or fail in Permission & Role Filters too * Candidate for the new Filters * Update BaseFilter.php * extend the BaseFilter sorry my mistake * rename $defaultLandingRoute to $landingRoute * just rename some strings * Run CodeIgniter4 Coding Standards * Update Routes.php The Routes.php now will use reserved routing from Auth.php * Fix typo * Apply analysis fixes Co-authored-by: MGatner --- src/Config/Auth.php | 37 +++++++++++++++++++++++ src/Config/Routes.php | 28 ++++++++++------- src/Filters/BaseFilter.php | 52 ++++++++++++++++++++++++++++++++ src/Filters/LoginFilter.php | 33 ++++++-------------- src/Filters/PermissionFilter.php | 31 ++++++------------- src/Filters/RoleFilter.php | 30 ++++++------------ 6 files changed, 134 insertions(+), 77 deletions(-) create mode 100644 src/Filters/BaseFilter.php diff --git a/src/Config/Auth.php b/src/Config/Auth.php index d520d30..2b951d9 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -18,6 +18,43 @@ class Auth extends BaseConfig */ public $defaultUserGroup; + /** + * -------------------------------------------------------------------- + * Landing Route + * -------------------------------------------------------------------- + * + * This is your landing page (route name) after user success to login, + * i.e $landingRoute = 'dashboard'. + * + * If you set $silent = true the Permission and Role filters will + * use this config too for the routing. + * + * @var string + */ + public $landingRoute = '/'; + + /** + * -------------------------------------------------------------------- + * Reserverd Routes + * -------------------------------------------------------------------- + * + * The auth routes config is listed in here and you can customize it, + * i.e. $reservedRoutes = ['forgot' => 'forgot-password']. + * + * Do Not Change The Key!!! Because it's the identity for routing. + * + * @var array + */ + public $reservedRoutes = [ + 'login' => 'login', + 'logout' => 'logout', + 'register' => 'register', + 'activate-account' => 'activate-account', + 'resend-activate-account' => 'resend-activate-account', + 'forgot' => 'forgot', + 'reset-password' => 'reset-password', + ]; + /** * -------------------------------------------------------------------- * Libraries diff --git a/src/Config/Routes.php b/src/Config/Routes.php index 442dcc3..251a25b 100644 --- a/src/Config/Routes.php +++ b/src/Config/Routes.php @@ -3,26 +3,32 @@ namespace Myth\Auth\Config; use CodeIgniter\Router\RouteCollection; +use Myth\Auth\Config\Auth as AuthConfig; /** @var RouteCollection $routes */ + // Myth:Auth routes file. $routes->group('', ['namespace' => 'Myth\Auth\Controllers'], static function ($routes) { + // Load the reserved routes from Auth.php + $config = config(AuthConfig::class); + $reservedRoutes = $config->reservedRoutes; + // Login/out - $routes->get('login', 'AuthController::login', ['as' => 'login']); - $routes->post('login', 'AuthController::attemptLogin'); - $routes->get('logout', 'AuthController::logout'); + $routes->get($reservedRoutes['login'], 'Auth::login', ['as' => $reservedRoutes['login']]); + $routes->post($reservedRoutes['login'], 'Auth::attemptLogin'); + $routes->get($reservedRoutes['logout'], 'Auth::logout'); // Registration - $routes->get('register', 'AuthController::register', ['as' => 'register']); - $routes->post('register', 'AuthController::attemptRegister'); + $routes->get($reservedRoutes['register'], 'Auth::register', ['as' => $reservedRoutes['register']]); + $routes->post($reservedRoutes['register'], 'Auth::attemptRegister'); // Activation - $routes->get('activate-account', 'AuthController::activateAccount', ['as' => 'activate-account']); - $routes->get('resend-activate-account', 'AuthController::resendActivateAccount', ['as' => 'resend-activate-account']); + $routes->get($reservedRoutes['activate-account'], 'Auth::activateAccount', ['as' => $reservedRoutes['activate-account']]); + $routes->get($reservedRoutes['resend-activate-account'], 'Auth::resendActivateAccount', ['as' => $reservedRoutes['resend-activate-account']]); // Forgot/Resets - $routes->get('forgot', 'AuthController::forgotPassword', ['as' => 'forgot']); - $routes->post('forgot', 'AuthController::attemptForgot'); - $routes->get('reset-password', 'AuthController::resetPassword', ['as' => 'reset-password']); - $routes->post('reset-password', 'AuthController::attemptReset'); + $routes->get($reservedRoutes['forgot'], 'Auth::forgotPassword', ['as' => $reservedRoutes['forgot']]); + $routes->post($reservedRoutes['forgot'], 'Auth::attemptForgot'); + $routes->get($reservedRoutes['reset-password'], 'Auth::resetPassword', ['as' => $reservedRoutes['reset-password']]); + $routes->post($reservedRoutes['reset-password'], 'Auth::attemptReset'); }); diff --git a/src/Filters/BaseFilter.php b/src/Filters/BaseFilter.php new file mode 100644 index 0000000..bca7aab --- /dev/null +++ b/src/Filters/BaseFilter.php @@ -0,0 +1,52 @@ +landingRoute = $config->landingRoute; + $this->reservedRoutes = $config->reservedRoutes; + + // Load the authenticate service + $this->authenticate = service('authentication'); + + // Load the authorize service + $this->authorize = service('authorization'); + + // Load the helper + if (! function_exists('logged_in')) { + helper('auth'); + } + } +} diff --git a/src/Filters/LoginFilter.php b/src/Filters/LoginFilter.php index 516734a..542dccb 100644 --- a/src/Filters/LoginFilter.php +++ b/src/Filters/LoginFilter.php @@ -6,9 +6,8 @@ use CodeIgniter\HTTP\RedirectResponse; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; -use Config\App; -class LoginFilter implements FilterInterface +class LoginFilter extends BaseFilter implements FilterInterface { /** * Verifies that a user is logged in, or redirects to login. @@ -19,32 +18,18 @@ class LoginFilter implements FilterInterface */ public function before(RequestInterface $request, $arguments = null) { - if (! function_exists('logged_in')) { - helper('auth'); + // Make sure this isn't already a Myth\Auth routes. + foreach ($this->reservedRoutes as $reservedRoute) { + if (url_is(route_to($reservedRoute))) { + return; + } } - $current = (string) current_url(true) - ->setHost('') - ->setScheme('') - ->stripQuery('token'); - - $config = config(App::class); - if ($config->forceGlobalSecureRequests) { - // Remove "https:/" - $current = substr($current, 7); - } - - // Make sure this isn't already a login route - if (in_array($current, [route_to('login'), route_to('forgot'), route_to('reset-password'), route_to('register'), route_to('activate-account')], true)) { - return; - } - - // if no user is logged in then send to the login form - $authenticate = service('authentication'); - if (! $authenticate->check()) { + // If no user is logged in then send them to the login form. + if (! $this->authenticate->check()) { session()->set('redirect_url', current_url()); - return redirect('login'); + return redirect($this->reservedRoutes['login']); } } diff --git a/src/Filters/PermissionFilter.php b/src/Filters/PermissionFilter.php index dc2ab38..20decf9 100644 --- a/src/Filters/PermissionFilter.php +++ b/src/Filters/PermissionFilter.php @@ -8,7 +8,7 @@ use CodeIgniter\HTTP\ResponseInterface; use Myth\Auth\Exceptions\PermissionException; -class PermissionFilter implements FilterInterface +class PermissionFilter extends BaseFilter implements FilterInterface { /** * @param array|null $arguments @@ -17,34 +17,27 @@ class PermissionFilter implements FilterInterface */ public function before(RequestInterface $request, $arguments = null) { - if (! function_exists('logged_in')) { - helper('auth'); + // If no user is logged in then send them to the login form. + if (! $this->authenticate->check()) { + session()->set('redirect_url', current_url()); + + return redirect($this->reservedRoutes['login']); } if (empty($arguments)) { return; } - $authenticate = service('authentication'); - - // if no user is logged in then send to the login form - if (! $authenticate->check()) { - session()->set('redirect_url', current_url()); - - return redirect('login'); - } - - $authorize = service('authorization'); - $result = true; + $result = true; // Check each requested permission foreach ($arguments as $permission) { - $result = $result && $authorize->hasPermission($permission, $authenticate->id()); + $result = ($result && $this->authorize->hasPermission($permission, $this->authenticate->id())); } if (! $result) { - if ($authenticate->silent()) { - $redirectURL = session('redirect_url') ?? '/'; + if ($this->authenticate->silent()) { + $redirectURL = session('redirect_url') ?? route_to($this->landingRoute); unset($_SESSION['redirect_url']); return redirect()->to($redirectURL)->with('error', lang('Auth.notEnoughPrivilege')); @@ -54,8 +47,6 @@ public function before(RequestInterface $request, $arguments = null) } } - //-------------------------------------------------------------------- - /** * Allows After filters to inspect and modify the response * object as needed. This method does not allow any way @@ -69,6 +60,4 @@ public function before(RequestInterface $request, $arguments = null) public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } - - //-------------------------------------------------------------------- } diff --git a/src/Filters/RoleFilter.php b/src/Filters/RoleFilter.php index 09e0e61..537a5c7 100644 --- a/src/Filters/RoleFilter.php +++ b/src/Filters/RoleFilter.php @@ -8,7 +8,7 @@ use CodeIgniter\HTTP\ResponseInterface; use Myth\Auth\Exceptions\PermissionException; -class RoleFilter implements FilterInterface +class RoleFilter extends BaseFilter implements FilterInterface { /** * @param array|null $arguments @@ -17,34 +17,26 @@ class RoleFilter implements FilterInterface */ public function before(RequestInterface $request, $arguments = null) { - if (! function_exists('logged_in')) { - helper('auth'); + // If no user is logged in then send them to the login form. + if (! $this->authenticate->check()) { + session()->set('redirect_url', current_url()); + + return redirect($this->reservedRoutes['login']); } if (empty($arguments)) { return; } - $authenticate = service('authentication'); - - // if no user is logged in then send to the login form - if (! $authenticate->check()) { - session()->set('redirect_url', current_url()); - - return redirect('login'); - } - - $authorize = service('authorization'); - // Check each requested permission foreach ($arguments as $group) { - if ($authorize->inGroup($group, $authenticate->id())) { + if ($this->authorize->inGroup($group, $this->authenticate->id())) { return; } } - if ($authenticate->silent()) { - $redirectURL = session('redirect_url') ?? '/'; + if ($this->authenticate->silent()) { + $redirectURL = session('redirect_url') ?? route_to($this->landingRoute); unset($_SESSION['redirect_url']); return redirect()->to($redirectURL)->with('error', lang('Auth.notEnoughPrivilege')); @@ -53,8 +45,6 @@ public function before(RequestInterface $request, $arguments = null) throw new PermissionException(lang('Auth.notEnoughPrivilege')); } - //-------------------------------------------------------------------- - /** * Allows After filters to inspect and modify the response * object as needed. This method does not allow any way @@ -68,6 +58,4 @@ public function before(RequestInterface $request, $arguments = null) public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) { } - - //-------------------------------------------------------------------- }