From 0326f5dbbc263e08b22f30198c342965ffdca48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Najdanovic=CC=81=20Ivan?= Date: Mon, 4 Nov 2024 21:56:32 +0100 Subject: [PATCH] Settings - Decouple from shield --- composer.json | 6 +-- docs/addons/jwt.md | 2 +- docs/customization/redirect_urls.md | 8 ++-- docs/guides/mobile_apps.md | 4 +- src/Authentication/Actions/Email2FA.php | 10 ++--- src/Authentication/Actions/EmailActivator.php | 8 ++-- src/Authentication/Authenticators/Session.php | 42 +++++++++---------- src/Authorization/Groups.php | 6 +-- src/Authorization/Traits/Authorizable.php | 4 +- src/Config/Auth.php | 19 ++++++--- src/Controllers/LoginController.php | 4 +- src/Controllers/MagicLinkController.php | 18 ++++---- src/Controllers/RegisterController.php | 8 ++-- src/Entities/Group.php | 6 +-- src/Filters/ChainAuth.php | 2 +- src/Filters/HmacAuth.php | 4 +- src/Filters/JWTAuth.php | 2 +- src/Filters/SessionAuth.php | 2 +- src/Filters/TokenAuth.php | 4 +- src/Helpers/auth_helper.php | 31 ++++++++++++++ src/Helpers/email_helper.php | 42 +++++++++---------- src/Models/GroupModel.php | 2 +- src/Models/UserModel.php | 2 +- src/Traits/Activatable.php | 2 +- src/Validation/ValidationRules.php | 4 +- src/Views/login.php | 6 +-- src/Views/magic_link_message.php | 2 +- .../SessionAuthenticatorTest.php | 10 ++--- .../Authentication/Filters/HmacFilterTest.php | 6 +-- .../Filters/SessionFilterTest.php | 6 +-- .../Filters/TokenFilterTest.php | 6 +-- tests/Authorization/GroupsTest.php | 2 +- tests/Unit/UserTest.php | 6 +-- tests/_support/TestCase.php | 4 +- 34 files changed, 164 insertions(+), 126 deletions(-) diff --git a/composer.json b/composer.json index 6967d8877..6c9528202 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,7 @@ "slack": "https://codeigniterchat.slack.com" }, "require": { - "php": "^7.4.3 || ^8.0", - "codeigniter4/settings": "^2.1" + "php": "^7.4.3 || ^8.0" }, "require-dev": { "codeigniter/coding-standard": "1.7.*", @@ -46,7 +45,8 @@ }, "suggest": { "ext-curl": "Required to use the password validation rule via PwnedValidator class.", - "ext-openssl": "Required to use the JWT Authenticator." + "ext-openssl": "Required to use the JWT Authenticator.", + "codeigniter4/settings": "Required to store groups and permissions in database" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/docs/addons/jwt.md b/docs/addons/jwt.md index f9ff4b83a..ff12c0635 100644 --- a/docs/addons/jwt.md +++ b/docs/addons/jwt.md @@ -190,7 +190,7 @@ class LoginController extends BaseController } // Get the credentials for login - $credentials = $this->request->getJsonVar(setting('Auth.validFields')); + $credentials = $this->request->getJsonVar(shieldSetting('Auth.validFields')); $credentials = array_filter($credentials); $credentials['password'] = $this->request->getJsonVar('password'); diff --git a/docs/customization/redirect_urls.md b/docs/customization/redirect_urls.md index 5ecf6834b..1861670f7 100644 --- a/docs/customization/redirect_urls.md +++ b/docs/customization/redirect_urls.md @@ -9,7 +9,7 @@ public function loginRedirect(): string { $url = auth()->user()->inGroup('admin') ? '/admin' - : setting('Auth.redirects')['login']; + : shieldSetting('Auth.redirects')['login']; return $this->getUrl($url); } @@ -27,7 +27,7 @@ public function loginRedirect(): string return '/admin'; } - $url = setting('Auth.redirects')['login']; + $url = shieldSetting('Auth.redirects')['login']; return $this->getUrl($url); } @@ -40,7 +40,7 @@ You can customize where a user is redirected to after registration in the `regis ```php public function registerRedirect(): string { - $url = setting('Auth.redirects')['register']; + $url = shieldSetting('Auth.redirects')['register']; return $this->getUrl($url); } @@ -53,7 +53,7 @@ The logout redirect can also be overridden by the `logoutRedirect()` method of t ```php public function logoutRedirect(): string { - $url = setting('Auth.redirects')['logout']; + $url = shieldSetting('Auth.redirects')['logout']; return $this->getUrl($url); } diff --git a/docs/guides/mobile_apps.md b/docs/guides/mobile_apps.md index 9f1af569f..323484ca4 100644 --- a/docs/guides/mobile_apps.md +++ b/docs/guides/mobile_apps.md @@ -27,7 +27,7 @@ class LoginController extends BaseController public function mobileLogin() { // Validate credentials - $rules = setting('Validation.login') ?? [ + $rules = shieldSetting('Validation.login') ?? [ 'email' => config('Auth')->emailValidationRules, 'password' => [ 'label' => 'Auth.password', @@ -46,7 +46,7 @@ class LoginController extends BaseController } // Get the credentials for login - $credentials = $this->request->getPost(setting('Auth.validFields')); + $credentials = $this->request->getPost(shieldSetting('Auth.validFields')); $credentials = array_filter($credentials); $credentials['password'] = $this->request->getPost('password'); diff --git a/src/Authentication/Actions/Email2FA.php b/src/Authentication/Actions/Email2FA.php index 28216d8cd..a32a5a8d3 100644 --- a/src/Authentication/Actions/Email2FA.php +++ b/src/Authentication/Actions/Email2FA.php @@ -50,7 +50,7 @@ public function show(): string $this->createIdentity($user); - return $this->view(setting('Auth.views')['action_email_2fa'], ['user' => $user]); + return $this->view(shieldSetting('Auth.views')['action_email_2fa'], ['user' => $user]); } /** @@ -89,11 +89,11 @@ public function handle(IncomingRequest $request) // Send the user an email with the code helper('email'); $email = emailer(['mailType' => 'html']) - ->setFrom(setting('Email.fromEmail'), setting('Email.fromName') ?? ''); + ->setFrom(shieldSetting('Email.fromEmail'), shieldSetting('Email.fromName') ?? ''); $email->setTo($user->email); $email->setSubject(lang('Auth.email2FASubject')); $email->setMessage($this->view( - setting('Auth.views')['action_email_2fa_email'], + shieldSetting('Auth.views')['action_email_2fa_email'], ['code' => $identity->secret, 'user' => $user, 'ipAddress' => $ipAddress, 'userAgent' => $userAgent, 'date' => $date], ['debug' => false] )); @@ -105,7 +105,7 @@ public function handle(IncomingRequest $request) // Clear the email $email->clear(); - return $this->view(setting('Auth.views')['action_email_2fa_verify']); + return $this->view(shieldSetting('Auth.views')['action_email_2fa_verify']); } /** @@ -131,7 +131,7 @@ public function verify(IncomingRequest $request) if (! $authenticator->checkAction($identity, $postedToken)) { session()->setFlashdata('error', lang('Auth.invalid2FAToken')); - return $this->view(setting('Auth.views')['action_email_2fa_verify']); + return $this->view(shieldSetting('Auth.views')['action_email_2fa_verify']); } // Get our login redirect url diff --git a/src/Authentication/Actions/EmailActivator.php b/src/Authentication/Actions/EmailActivator.php index 2b47f374e..bff77020c 100644 --- a/src/Authentication/Actions/EmailActivator.php +++ b/src/Authentication/Actions/EmailActivator.php @@ -66,11 +66,11 @@ public function show(): string // Send the email helper('email'); $email = emailer(['mailType' => 'html']) - ->setFrom(setting('Email.fromEmail'), setting('Email.fromName') ?? ''); + ->setFrom(shieldSetting('Email.fromEmail'), shieldSetting('Email.fromName') ?? ''); $email->setTo($userEmail); $email->setSubject(lang('Auth.emailActivateSubject')); $email->setMessage($this->view( - setting('Auth.views')['action_email_activate_email'], + shieldSetting('Auth.views')['action_email_activate_email'], ['code' => $code, 'user' => $user, 'ipAddress' => $ipAddress, 'userAgent' => $userAgent, 'date' => $date], ['debug' => false] )); @@ -83,7 +83,7 @@ public function show(): string $email->clear(); // Display the info page - return $this->view(setting('Auth.views')['action_email_activate_show'], ['user' => $user]); + return $this->view(shieldSetting('Auth.views')['action_email_activate_show'], ['user' => $user]); } /** @@ -120,7 +120,7 @@ public function verify(IncomingRequest $request) if (! $authenticator->checkAction($identity, $postedToken)) { session()->setFlashdata('error', lang('Auth.invalidActivateToken')); - return $this->view(setting('Auth.views')['action_email_activate_show']); + return $this->view(shieldSetting('Auth.views')['action_email_activate_show']); } $user = $authenticator->getUser(); diff --git a/src/Authentication/Authenticators/Session.php b/src/Authentication/Authenticators/Session.php index 4c1b52b1a..d2ab07c98 100644 --- a/src/Authentication/Authenticators/Session.php +++ b/src/Authentication/Authenticators/Session.php @@ -196,7 +196,7 @@ public function attempt(array $credentials): Result */ public function startUpAction(string $type, User $user): bool { - $actionClass = setting('Auth.actions')[$type] ?? null; + $actionClass = shieldSetting('Auth.actions')[$type] ?? null; if ($actionClass === null) { return false; @@ -417,7 +417,7 @@ private function checkUserState(): void // No User Info in Session. // Check remember-me token. - if (setting('Auth.sessionConfig')['allowRemembering']) { + if (shieldSetting('Auth.sessionConfig')['allowRemembering']) { if ($this->checkRememberMe()) { $this->setAuthAction(); } @@ -473,7 +473,7 @@ private function setAuthAction(): bool return false; } - $authActions = setting('Auth.actions'); + $authActions = shieldSetting('Auth.actions'); foreach ($authActions as $actionClass) { if ($actionClass === null) { @@ -516,7 +516,7 @@ private function getIdentitiesForAction(User $user): array */ private function getActionTypes(): array { - $actions = setting('Auth.actions'); + $actions = shieldSetting('Auth.actions'); $types = []; foreach ($actions as $actionClass) { @@ -611,7 +611,7 @@ private function getRememberMeToken(): ?string /** @var IncomingRequest $request */ $request = service('request'); - $cookieName = setting('Cookie.prefix') . setting('Auth.sessionConfig')['rememberCookieName']; + $cookieName = shieldSetting('Cookie.prefix') . shieldSetting('Auth.sessionConfig')['rememberCookieName']; return $request->getCookie($cookieName); } @@ -682,7 +682,7 @@ public function startLogin(User $user): void */ protected function getSessionUserInfo(): array { - return session(setting('Auth.sessionConfig')['field']) ?? []; + return session(shieldSetting('Auth.sessionConfig')['field']) ?? []; } /** @@ -690,7 +690,7 @@ protected function getSessionUserInfo(): array */ protected function removeSessionUserInfo(): void { - session()->remove(setting('Auth.sessionConfig')['field']); + session()->remove(shieldSetting('Auth.sessionConfig')['field']); } /** @@ -714,7 +714,7 @@ protected function setSessionUserKey(string $key, $value): void { $sessionUserInfo = $this->getSessionUserInfo(); $sessionUserInfo[$key] = $value; - session()->set(setting('Auth.sessionConfig')['field'], $sessionUserInfo); + session()->set(shieldSetting('Auth.sessionConfig')['field'], $sessionUserInfo); } /** @@ -724,7 +724,7 @@ protected function removeSessionUserKey(string $key): void { $sessionUserInfo = $this->getSessionUserInfo(); unset($sessionUserInfo[$key]); - session()->set(setting('Auth.sessionConfig')['field'], $sessionUserInfo); + session()->set(shieldSetting('Auth.sessionConfig')['field'], $sessionUserInfo); } /** @@ -762,7 +762,7 @@ public function login(User $user): void private function issueRememberMeToken(): void { - if ($this->shouldRemember && setting('Auth.sessionConfig')['allowRemembering']) { + if ($this->shouldRemember && shieldSetting('Auth.sessionConfig')['allowRemembering']) { $this->rememberUser($this->user); // Reset so it doesn't mess up future calls. @@ -788,10 +788,10 @@ private function removeRememberCookie(): void // Remove remember-me cookie $response->deleteCookie( - setting('Auth.sessionConfig')['rememberCookieName'], - setting('Cookie.domain'), - setting('Cookie.path'), - setting('Cookie.prefix') + shieldSetting('Auth.sessionConfig')['rememberCookieName'], + shieldSetting('Cookie.domain'), + shieldSetting('Cookie.path'), + shieldSetting('Cookie.prefix') ); } @@ -930,7 +930,7 @@ protected function rememberUser(User $user): void private function calcExpires(): Time { - $timestamp = Time::now()->getTimestamp() + setting('Auth.sessionConfig')['rememberLength']; + $timestamp = Time::now()->getTimestamp() + shieldSetting('Auth.sessionConfig')['rememberLength']; return Time::createFromTimestamp($timestamp); } @@ -946,13 +946,13 @@ private function setRememberMeCookie(string $rawToken): void // Save it to the user's browser in a cookie. // Create the cookie $response->setCookie( - setting('Auth.sessionConfig')['rememberCookieName'], + shieldSetting('Auth.sessionConfig')['rememberCookieName'], $rawToken, // Value - setting('Auth.sessionConfig')['rememberLength'], // # Seconds until it expires - setting('Cookie.domain'), - setting('Cookie.path'), - setting('Cookie.prefix'), - setting('Cookie.secure'), // Only send over HTTPS? + shieldSetting('Auth.sessionConfig')['rememberLength'], // # Seconds until it expires + shieldSetting('Cookie.domain'), + shieldSetting('Cookie.path'), + shieldSetting('Cookie.prefix'), + shieldSetting('Cookie.secure'), // Only send over HTTPS? true // Hide from Javascript? ); } diff --git a/src/Authorization/Groups.php b/src/Authorization/Groups.php index eb76920c9..9b419f96a 100644 --- a/src/Authorization/Groups.php +++ b/src/Authorization/Groups.php @@ -27,7 +27,7 @@ class Groups */ public function info(string $group): ?Group { - $info = setting('AuthGroups.groups')[strtolower($group)] ?? null; + $info = shieldSetting('AuthGroups.groups')[strtolower($group)] ?? null; if (empty($info)) { return null; @@ -47,7 +47,7 @@ public function save(Group $group): void throw new RuntimeException(lang('Auth.missingTitle')); } - $groups = setting('AuthGroups.groups'); + $groups = shieldSetting('AuthGroups.groups'); $alias = $group->alias; @@ -61,6 +61,6 @@ public function save(Group $group): void ]; // Save it - setting('AuthGroups.groups', $groups); + shieldSetting('AuthGroups.groups', $groups); } } diff --git a/src/Authorization/Traits/Authorizable.php b/src/Authorization/Traits/Authorizable.php index c0b1acf2a..3e5fb3679 100644 --- a/src/Authorization/Traits/Authorizable.php +++ b/src/Authorization/Traits/Authorizable.php @@ -251,7 +251,7 @@ public function can(string ...$permissions): bool $this->populateGroups(); // Get the group matrix - $matrix = setting('AuthGroups.matrix'); + $matrix = shieldSetting('AuthGroups.matrix'); foreach ($permissions as $permission) { // Permission must contain a scope and action @@ -406,6 +406,6 @@ private function saveGroupsOrPermissions(string $type, $model, array $cache): vo */ private function getConfigPermissions(): array { - return array_keys(setting('AuthGroups.permissions')); + return array_keys(shieldSetting('AuthGroups.permissions')); } } diff --git a/src/Config/Auth.php b/src/Config/Auth.php index 9df36cd77..b9266dbd1 100644 --- a/src/Config/Auth.php +++ b/src/Config/Auth.php @@ -40,6 +40,13 @@ class Auth extends BaseConfig public const RECORD_LOGIN_ATTEMPT_FAILURE = 1; // Record only failures public const RECORD_LOGIN_ATTEMPT_ALL = 2; // Record all login attempts + /** + * -------------------------------------------------------------------- + * Use Settings + * -------------------------------------------------------------------- + */ + public bool $useSettings = true; + /** * -------------------------------------------------------------------- * View files @@ -437,7 +444,7 @@ class Auth extends BaseConfig public function loginRedirect(): string { $session = session(); - $url = $session->getTempdata('beforeLoginUrl') ?? setting('Auth.redirects')['login']; + $url = $session->getTempdata('beforeLoginUrl') ?? shieldSetting('Auth.redirects')['login']; return $this->getUrl($url); } @@ -448,7 +455,7 @@ public function loginRedirect(): string */ public function logoutRedirect(): string { - $url = setting('Auth.redirects')['logout']; + $url = shieldSetting('Auth.redirects')['logout']; return $this->getUrl($url); } @@ -459,7 +466,7 @@ public function logoutRedirect(): string */ public function registerRedirect(): string { - $url = setting('Auth.redirects')['register']; + $url = shieldSetting('Auth.redirects')['register']; return $this->getUrl($url); } @@ -470,7 +477,7 @@ public function registerRedirect(): string */ public function forcePasswordResetRedirect(): string { - $url = setting('Auth.redirects')['force_reset']; + $url = shieldSetting('Auth.redirects')['force_reset']; return $this->getUrl($url); } @@ -481,7 +488,7 @@ public function forcePasswordResetRedirect(): string */ public function permissionDeniedRedirect(): string { - $url = setting('Auth.redirects')['permission_denied']; + $url = shieldSetting('Auth.redirects')['permission_denied']; return $this->getUrl($url); } @@ -492,7 +499,7 @@ public function permissionDeniedRedirect(): string */ public function groupDeniedRedirect(): string { - $url = setting('Auth.redirects')['group_denied']; + $url = shieldSetting('Auth.redirects')['group_denied']; return $this->getUrl($url); } diff --git a/src/Controllers/LoginController.php b/src/Controllers/LoginController.php index 8c07f8b75..4bdcddae0 100644 --- a/src/Controllers/LoginController.php +++ b/src/Controllers/LoginController.php @@ -42,7 +42,7 @@ public function loginView() return redirect()->route('auth-action-show'); } - return $this->view(setting('Auth.views')['login']); + return $this->view(shieldSetting('Auth.views')['login']); } /** @@ -59,7 +59,7 @@ public function loginAction(): RedirectResponse } /** @var array $credentials */ - $credentials = $this->request->getPost(setting('Auth.validFields')) ?? []; + $credentials = $this->request->getPost(shieldSetting('Auth.validFields')) ?? []; $credentials = array_filter($credentials); $credentials['password'] = $this->request->getPost('password'); $remember = (bool) $this->request->getPost('remember'); diff --git a/src/Controllers/MagicLinkController.php b/src/Controllers/MagicLinkController.php index df77e1a4b..834c8d4ec 100644 --- a/src/Controllers/MagicLinkController.php +++ b/src/Controllers/MagicLinkController.php @@ -44,7 +44,7 @@ class MagicLinkController extends BaseController public function __construct() { /** @var class-string $providerClass */ - $providerClass = setting('Auth.userProvider'); + $providerClass = shieldSetting('Auth.userProvider'); $this->provider = new $providerClass(); } @@ -57,7 +57,7 @@ public function __construct() */ public function loginView() { - if (! setting('Auth.allowMagicLinkLogins')) { + if (! shieldSetting('Auth.allowMagicLinkLogins')) { return redirect()->route('login')->with('error', lang('Auth.magicLinkDisabled')); } @@ -65,7 +65,7 @@ public function loginView() return redirect()->to(config('Auth')->loginRedirect()); } - return $this->view(setting('Auth.views')['magic-link-login']); + return $this->view(shieldSetting('Auth.views')['magic-link-login']); } /** @@ -77,7 +77,7 @@ public function loginView() */ public function loginAction() { - if (! setting('Auth.allowMagicLinkLogins')) { + if (! shieldSetting('Auth.allowMagicLinkLogins')) { return redirect()->route('login')->with('error', lang('Auth.magicLinkDisabled')); } @@ -109,7 +109,7 @@ public function loginAction() 'user_id' => $user->id, 'type' => Session::ID_TYPE_MAGIC_LINK, 'secret' => $token, - 'expires' => Time::now()->addSeconds(setting('Auth.magicLinkLifetime')), + 'expires' => Time::now()->addSeconds(shieldSetting('Auth.magicLinkLifetime')), ]); /** @var IncomingRequest $request */ @@ -122,11 +122,11 @@ public function loginAction() // Send the user an email with the code helper('email'); $email = emailer(['mailType' => 'html']) - ->setFrom(setting('Email.fromEmail'), setting('Email.fromName') ?? ''); + ->setFrom(shieldSetting('Email.fromEmail'), shieldSetting('Email.fromName') ?? ''); $email->setTo($user->email); $email->setSubject(lang('Auth.magicLinkSubject')); $email->setMessage($this->view( - setting('Auth.views')['magic-link-email'], + shieldSetting('Auth.views')['magic-link-email'], ['token' => $token, 'user' => $user, 'ipAddress' => $ipAddress, 'userAgent' => $userAgent, 'date' => $date], ['debug' => false] )); @@ -148,7 +148,7 @@ public function loginAction() */ protected function displayMessage(): string { - return $this->view(setting('Auth.views')['magic-link-message']); + return $this->view(shieldSetting('Auth.views')['magic-link-message']); } /** @@ -156,7 +156,7 @@ protected function displayMessage(): string */ public function verify(): RedirectResponse { - if (! setting('Auth.allowMagicLinkLogins')) { + if (! shieldSetting('Auth.allowMagicLinkLogins')) { return redirect()->route('login')->with('error', lang('Auth.magicLinkDisabled')); } diff --git a/src/Controllers/RegisterController.php b/src/Controllers/RegisterController.php index 7b310b1f8..fb306c7ec 100644 --- a/src/Controllers/RegisterController.php +++ b/src/Controllers/RegisterController.php @@ -60,7 +60,7 @@ public function registerView() } // Check if registration is allowed - if (! setting('Auth.allowRegistration')) { + if (! shieldSetting('Auth.allowRegistration')) { return redirect()->back()->withInput() ->with('error', lang('Auth.registerDisabled')); } @@ -73,7 +73,7 @@ public function registerView() return redirect()->route('auth-action-show'); } - return $this->view(setting('Auth.views')['register']); + return $this->view(shieldSetting('Auth.views')['register']); } /** @@ -86,7 +86,7 @@ public function registerAction(): RedirectResponse } // Check if registration is allowed - if (! setting('Auth.allowRegistration')) { + if (! shieldSetting('Auth.allowRegistration')) { return redirect()->back()->withInput() ->with('error', lang('Auth.registerDisabled')); } @@ -151,7 +151,7 @@ public function registerAction(): RedirectResponse */ protected function getUserProvider(): UserModel { - $provider = model(setting('Auth.userProvider')); + $provider = model(shieldSetting('Auth.userProvider')); assert($provider instanceof UserModel, 'Config Auth.userProvider is not a valid UserProvider.'); diff --git a/src/Entities/Group.php b/src/Entities/Group.php index b63707929..74a439985 100644 --- a/src/Entities/Group.php +++ b/src/Entities/Group.php @@ -41,11 +41,11 @@ public function setPermissions(array $permissions): void { $this->permissions = $permissions; - $matrix = setting('AuthGroups.matrix'); + $matrix = shieldSetting('AuthGroups.matrix'); $matrix[$this->alias] = $permissions; - setting('AuthGroups.matrix', $matrix); + shieldSetting('AuthGroups.matrix', $matrix); } /** @@ -99,6 +99,6 @@ private function populatePermissions(): void return; } - $this->permissions = setting('AuthGroups.matrix')[$this->alias] ?? []; + $this->permissions = shieldSetting('AuthGroups.matrix')[$this->alias] ?? []; } } diff --git a/src/Filters/ChainAuth.php b/src/Filters/ChainAuth.php index 469ac0fe1..05e68402e 100644 --- a/src/Filters/ChainAuth.php +++ b/src/Filters/ChainAuth.php @@ -54,7 +54,7 @@ public function before(RequestInterface $request, $arguments = null) $authenticator = $auth->getAuthenticator(); - if (setting('Auth.recordActiveDate')) { + if (shieldSetting('Auth.recordActiveDate')) { $authenticator->recordActiveDate(); } diff --git a/src/Filters/HmacAuth.php b/src/Filters/HmacAuth.php index fd2123c04..ca3c4769c 100644 --- a/src/Filters/HmacAuth.php +++ b/src/Filters/HmacAuth.php @@ -33,7 +33,7 @@ public function before(RequestInterface $request, $arguments = null) $authenticator = auth('hmac')->getAuthenticator(); $requestParams = [ - 'token' => $request->getHeaderLine(setting('AuthToken.authenticatorHeader')['hmac'] ?? 'Authorization'), + 'token' => $request->getHeaderLine(shieldSetting('AuthToken.authenticatorHeader')['hmac'] ?? 'Authorization'), 'body' => $request->getBody() ?? '', ]; @@ -45,7 +45,7 @@ public function before(RequestInterface $request, $arguments = null) ->setJSON(['message' => lang('Auth.badToken')]); } - if (setting('Auth.recordActiveDate')) { + if (shieldSetting('Auth.recordActiveDate')) { $authenticator->recordActiveDate(); } diff --git a/src/Filters/JWTAuth.php b/src/Filters/JWTAuth.php index c85bcc308..b4f4338e7 100644 --- a/src/Filters/JWTAuth.php +++ b/src/Filters/JWTAuth.php @@ -55,7 +55,7 @@ public function before(RequestInterface $request, $arguments = null) ->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED); } - if (setting('Auth.recordActiveDate')) { + if (shieldSetting('Auth.recordActiveDate')) { $authenticator->recordActiveDate(); } } diff --git a/src/Filters/SessionAuth.php b/src/Filters/SessionAuth.php index 2063f240d..1b73e5cd0 100644 --- a/src/Filters/SessionAuth.php +++ b/src/Filters/SessionAuth.php @@ -52,7 +52,7 @@ public function before(RequestInterface $request, $arguments = null) $authenticator = auth('session')->getAuthenticator(); if ($authenticator->loggedIn()) { - if (setting('Auth.recordActiveDate')) { + if (shieldSetting('Auth.recordActiveDate')) { $authenticator->recordActiveDate(); } diff --git a/src/Filters/TokenAuth.php b/src/Filters/TokenAuth.php index 473d5cc8d..fb43390af 100644 --- a/src/Filters/TokenAuth.php +++ b/src/Filters/TokenAuth.php @@ -52,7 +52,7 @@ public function before(RequestInterface $request, $arguments = null) $authenticator = auth('tokens')->getAuthenticator(); $result = $authenticator->attempt([ - 'token' => $request->getHeaderLine(setting('AuthToken.authenticatorHeader')['tokens'] ?? 'Authorization'), + 'token' => $request->getHeaderLine(shieldSetting('AuthToken.authenticatorHeader')['tokens'] ?? 'Authorization'), ]); if (! $result->isOK() || (! empty($arguments) && $result->extraInfo()->tokenCant($arguments[0]))) { @@ -61,7 +61,7 @@ public function before(RequestInterface $request, $arguments = null) ->setJSON(['message' => lang('Auth.badToken')]); } - if (setting('Auth.recordActiveDate')) { + if (shieldSetting('Auth.recordActiveDate')) { $authenticator->recordActiveDate(); } diff --git a/src/Helpers/auth_helper.php b/src/Helpers/auth_helper.php index b05accb86..b393b9ccd 100644 --- a/src/Helpers/auth_helper.php +++ b/src/Helpers/auth_helper.php @@ -12,6 +12,7 @@ */ use CodeIgniter\Shield\Auth; +use CodeIgniter\Shield\Config\Auth as AuthConfig; if (! function_exists('auth')) { /** @@ -43,3 +44,33 @@ function user_id() return $auth->id(); } } + +if (! function_exists('shieldSetting')) { + /** + * Provides a wrapper function for settings module. + * + * @param mixed $value + * + * @return array|bool|float|int|object|string|void|null + * @phpstan-return ($value is null ? array|bool|float|int|object|string|null : void) + */ + function shieldSetting(?string $key = null, $value = null) + { + /** @var AuthConfig $config */ + $config = config('Auth'); + if($config->useSettings) { + return setting($key, $value); + } + + // Getting the value? + if (!empty($key) && count(func_get_args()) === 1) { + $parts = explode('.', $key); + if (count($parts) === 1) { + throw new InvalidArgumentException('$key must contain both the class and field name, i.e. Foo.bar'); + } + return config($parts[0])?->{$parts[1]} ?? null; + } + + throw new InvalidArgumentException('Settings library is not being used for shield'); + } +} diff --git a/src/Helpers/email_helper.php b/src/Helpers/email_helper.php index 8fd51c6ba..3e582e8bd 100644 --- a/src/Helpers/email_helper.php +++ b/src/Helpers/email_helper.php @@ -24,27 +24,27 @@ function emailer(array $overrides = []): Email { $config = [ - 'userAgent' => setting('Email.userAgent'), - 'protocol' => setting('Email.protocol'), - 'mailPath' => setting('Email.mailPath'), - 'SMTPHost' => setting('Email.SMTPHost'), - 'SMTPUser' => setting('Email.SMTPUser'), - 'SMTPPass' => setting('Email.SMTPPass'), - 'SMTPPort' => setting('Email.SMTPPort'), - 'SMTPTimeout' => setting('Email.SMTPTimeout'), - 'SMTPKeepAlive' => setting('Email.SMTPKeepAlive'), - 'SMTPCrypto' => setting('Email.SMTPCrypto'), - 'wordWrap' => setting('Email.wordWrap'), - 'wrapChars' => setting('Email.wrapChars'), - 'mailType' => setting('Email.mailType'), - 'charset' => setting('Email.charset'), - 'validate' => setting('Email.validate'), - 'priority' => setting('Email.priority'), - 'CRLF' => setting('Email.CRLF'), - 'newline' => setting('Email.newline'), - 'BCCBatchMode' => setting('Email.BCCBatchMode'), - 'BCCBatchSize' => setting('Email.BCCBatchSize'), - 'DSN' => setting('Email.DSN'), + 'userAgent' => shieldSetting('Email.userAgent'), + 'protocol' => shieldSetting('Email.protocol'), + 'mailPath' => shieldSetting('Email.mailPath'), + 'SMTPHost' => shieldSetting('Email.SMTPHost'), + 'SMTPUser' => shieldSetting('Email.SMTPUser'), + 'SMTPPass' => shieldSetting('Email.SMTPPass'), + 'SMTPPort' => shieldSetting('Email.SMTPPort'), + 'SMTPTimeout' => shieldSetting('Email.SMTPTimeout'), + 'SMTPKeepAlive' => shieldSetting('Email.SMTPKeepAlive'), + 'SMTPCrypto' => shieldSetting('Email.SMTPCrypto'), + 'wordWrap' => shieldSetting('Email.wordWrap'), + 'wrapChars' => shieldSetting('Email.wrapChars'), + 'mailType' => shieldSetting('Email.mailType'), + 'charset' => shieldSetting('Email.charset'), + 'validate' => shieldSetting('Email.validate'), + 'priority' => shieldSetting('Email.priority'), + 'CRLF' => shieldSetting('Email.CRLF'), + 'newline' => shieldSetting('Email.newline'), + 'BCCBatchMode' => shieldSetting('Email.BCCBatchMode'), + 'BCCBatchSize' => shieldSetting('Email.BCCBatchSize'), + 'DSN' => shieldSetting('Email.DSN'), ]; if ($overrides !== []) { diff --git a/src/Models/GroupModel.php b/src/Models/GroupModel.php index d08c8774d..4320c8e8a 100644 --- a/src/Models/GroupModel.php +++ b/src/Models/GroupModel.php @@ -79,7 +79,7 @@ public function deleteNotIn($userId, $cache): void */ public function isValidGroup(string $group): bool { - $allowedGroups = array_keys(setting('AuthGroups.groups')); + $allowedGroups = array_keys(shieldSetting('AuthGroups.groups')); return in_array($group, $allowedGroups, true); } diff --git a/src/Models/UserModel.php b/src/Models/UserModel.php index 0fede61ec..2fb95ca9a 100644 --- a/src/Models/UserModel.php +++ b/src/Models/UserModel.php @@ -153,7 +153,7 @@ private function assignIdentities(array $data, array $identities): array */ public function addToDefaultGroup(User $user): void { - $defaultGroup = setting('AuthGroups.defaultGroup'); + $defaultGroup = shieldSetting('AuthGroups.defaultGroup'); /** @var GroupModel $groupModel */ $groupModel = model(GroupModel::class); diff --git a/src/Traits/Activatable.php b/src/Traits/Activatable.php index b75808076..e34eebea4 100644 --- a/src/Traits/Activatable.php +++ b/src/Traits/Activatable.php @@ -60,6 +60,6 @@ public function deactivate(): void */ private function shouldActivate(): bool { - return strpos(setting('Auth.actions')['register'] ?? '', 'Activator') !== false; + return strpos(shieldSetting('Auth.actions')['register'] ?? '', 'Activator') !== false; } } diff --git a/src/Validation/ValidationRules.php b/src/Validation/ValidationRules.php index 4e1284fb7..676eef142 100644 --- a/src/Validation/ValidationRules.php +++ b/src/Validation/ValidationRules.php @@ -36,7 +36,7 @@ public function __construct() public function getRegistrationRules(): array { - $setting = setting('Validation.registration'); + $setting = shieldSetting('Validation.registration'); if ($setting !== null) { return $setting; } @@ -66,7 +66,7 @@ public function getRegistrationRules(): array public function getLoginRules(): array { - return setting('Validation.login') ?? [ + return shieldSetting('Validation.login') ?? [ // 'username' => $this->config->usernameValidationRules, 'email' => $this->config->emailValidationRules, 'password' => $this->getPasswordRules(), diff --git a/src/Views/login.php b/src/Views/login.php index 4fd0232cb..d284bec46 100644 --- a/src/Views/login.php +++ b/src/Views/login.php @@ -44,7 +44,7 @@ - +
- +

- +

diff --git a/src/Views/magic_link_message.php b/src/Views/magic_link_message.php index 0855272f3..797c3e56f 100644 --- a/src/Views/magic_link_message.php +++ b/src/Views/magic_link_message.php @@ -11,7 +11,7 @@

-

+

diff --git a/tests/Authentication/Authenticators/SessionAuthenticatorTest.php b/tests/Authentication/Authenticators/SessionAuthenticatorTest.php index 3fb04a386..1e028167d 100644 --- a/tests/Authentication/Authenticators/SessionAuthenticatorTest.php +++ b/tests/Authentication/Authenticators/SessionAuthenticatorTest.php @@ -92,7 +92,7 @@ public function testLoggedInWithRememberCookie(): void unset($_SESSION['user']); // Set Cookie.prefix $cookiePrefix = 'prefix_'; - setting('Cookie.prefix', $cookiePrefix); + shieldSetting('Cookie.prefix', $cookiePrefix); $this->user->createEmailIdentity(['email' => 'foo@example.com', 'password' => 'secret']); @@ -101,12 +101,12 @@ public function testLoggedInWithRememberCookie(): void $rememberModel = model(RememberModel::class); $selector = 'selector'; $validator = 'validator'; - $expires = date('Y-m-d H:i:s', time() + setting('Auth.sessionConfig')['rememberLength']); + $expires = date('Y-m-d H:i:s', time() + shieldSetting('Auth.sessionConfig')['rememberLength']); $rememberModel->rememberUser($this->user, $selector, hash('sha256', $validator), $expires); // Set Cookie value for remember-me. $token = $selector . ':' . $validator; - $cookieName = $cookiePrefix . setting('Auth.sessionConfig')['rememberCookieName']; + $cookieName = $cookiePrefix . shieldSetting('Auth.sessionConfig')['rememberCookieName']; $_COOKIE[$cookieName] = $token; $this->assertTrue($this->auth->loggedIn()); @@ -117,7 +117,7 @@ public function testLoggedInWithRememberCookie(): void $this->assertSame($this->user->id, $authUser->id); // Forget Cookie.prefix - setting()->forget('Cookie.prefix'); + shieldSetting()->forget('Cookie.prefix'); } public function testLoggedInAsDeletedUserWithRememberCookie(): void @@ -131,7 +131,7 @@ public function testLoggedInAsDeletedUserWithRememberCookie(): void $rememberModel = model(RememberModel::class); $selector = 'selector'; $validator = 'validator'; - $expires = date('Y-m-d H:i:s', time() + setting('Auth.sessionConfig')['rememberLength']); + $expires = date('Y-m-d H:i:s', time() + shieldSetting('Auth.sessionConfig')['rememberLength']); $rememberModel->rememberUser($this->user, $selector, hash('sha256', $validator), $expires); // Set Cookie value for remember-me. diff --git a/tests/Authentication/Filters/HmacFilterTest.php b/tests/Authentication/Filters/HmacFilterTest.php index ffb516313..63b6afcd7 100644 --- a/tests/Authentication/Filters/HmacFilterTest.php +++ b/tests/Authentication/Filters/HmacFilterTest.php @@ -118,7 +118,7 @@ public function testBlocksInactiveUsers(): void $token = $user->generateHmacToken('foo'); // Activation only required with email activation - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, '')]) ->get('protected-route'); @@ -127,14 +127,14 @@ public function testBlocksInactiveUsers(): void $result->assertSee('Protected'); // Now require user activation and try again - setting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); + shieldSetting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); $result = $this->withHeaders(['Authorization' => 'HMAC-SHA256 ' . $this->generateRawHeaderToken($token->secret, $token->rawSecretKey, '')]) ->get('protected-route'); $result->assertStatus(403); - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); } protected function generateRawHeaderToken(string $secret, string $secretKey, string $body): string diff --git a/tests/Authentication/Filters/SessionFilterTest.php b/tests/Authentication/Filters/SessionFilterTest.php index 10c8c21b9..247ae1f1c 100644 --- a/tests/Authentication/Filters/SessionFilterTest.php +++ b/tests/Authentication/Filters/SessionFilterTest.php @@ -73,7 +73,7 @@ public function testBlocksInactiveUsersAndRedirectsToAuthAction(): void $user = fake(UserModel::class, ['active' => false]); // Activation only required with email activation - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); $result = $this->actingAs($user) ->get('protected-route'); @@ -82,7 +82,7 @@ public function testBlocksInactiveUsersAndRedirectsToAuthAction(): void $result->assertSee('Protected'); // Now require user activation and try again - setting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); + shieldSetting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); $result = $this->actingAs($user) ->get('protected-route'); @@ -91,7 +91,7 @@ public function testBlocksInactiveUsersAndRedirectsToAuthAction(): void // User should be logged out $this->assertNull(auth('session')->id()); - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); } public function testStoreRedirectsToEntraceUrlIntoSession(): void diff --git a/tests/Authentication/Filters/TokenFilterTest.php b/tests/Authentication/Filters/TokenFilterTest.php index c080be2df..78401dbde 100644 --- a/tests/Authentication/Filters/TokenFilterTest.php +++ b/tests/Authentication/Filters/TokenFilterTest.php @@ -103,7 +103,7 @@ public function testBlocksInactiveUsers(): void $token = $user->generateAccessToken('foo'); // Activation only required with email activation - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); $result = $this->withHeaders(['Authorization' => 'Bearer ' . $token->raw_token]) ->get('protected-route'); @@ -112,13 +112,13 @@ public function testBlocksInactiveUsers(): void $result->assertSee('Protected'); // Now require user activation and try again - setting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); + shieldSetting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); $result = $this->withHeaders(['Authorization' => 'Bearer ' . $token->raw_token]) ->get('protected-route'); $result->assertStatus(403); - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); } } diff --git a/tests/Authorization/GroupsTest.php b/tests/Authorization/GroupsTest.php index b4b1ba32f..ac56c588e 100644 --- a/tests/Authorization/GroupsTest.php +++ b/tests/Authorization/GroupsTest.php @@ -52,7 +52,7 @@ public function testGroupInfo(): void $this->assertInstanceOf(Group::class, $group); $this->assertSame('Admin', $group->title); - $this->assertSame(setting('AuthGroups.groups')['admin']['description'], $group->description); + $this->assertSame(shieldSetting('AuthGroups.groups')['admin']['description'], $group->description); $this->assertSame('admin', $group->alias); } diff --git a/tests/Unit/UserTest.php b/tests/Unit/UserTest.php index 9c4d3ccda..bc5d92bde 100644 --- a/tests/Unit/UserTest.php +++ b/tests/Unit/UserTest.php @@ -345,14 +345,14 @@ public function testIsActivatedSuccessWhenNotRequired(): void $this->user->active = false; model(UserModel::class)->save($this->user); - setting('Auth.actions', ['register' => null]); + shieldSetting('Auth.actions', ['register' => null]); $this->assertTrue($this->user->isActivated()); } public function testIsActivatedWhenRequired(): void { - setting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); + shieldSetting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); $user = $this->user; $user->deactivate(); @@ -370,7 +370,7 @@ public function testIsActivatedWhenRequired(): void public function testIsNotActivated(): void { - setting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); + shieldSetting('Auth.actions', ['register' => '\CodeIgniter\Shield\Authentication\Actions\EmailActivator']); $user = $this->user; $user->active = false; diff --git a/tests/_support/TestCase.php b/tests/_support/TestCase.php index a7af822ea..ea5971748 100644 --- a/tests/_support/TestCase.php +++ b/tests/_support/TestCase.php @@ -39,8 +39,8 @@ protected function setUp(): void helper(['auth', 'setting']); // Ensure from email is available anywhere during Tests - setting('Email.fromEmail', 'foo@example.com'); - setting('Email.fromName', 'John Smith'); + shieldSetting('Email.fromEmail', 'foo@example.com'); + shieldSetting('Email.fromName', 'John Smith'); // Clear any actions $config = config('Auth');