From ad9cd4ab66aabd56c2979637195d5f6ad50c8c0a Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Tue, 24 Sep 2024 17:39:43 +1200 Subject: [PATCH] ENH Use symfony/validation logic --- src/RealMeService.php | 9 +++++--- src/Task/RealMeSetupTask.php | 45 +++++++++++++++--------------------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/RealMeService.php b/src/RealMeService.php index 54178d6..c874625 100644 --- a/src/RealMeService.php +++ b/src/RealMeService.php @@ -18,12 +18,15 @@ use SilverStripe\Core\Environment; use SilverStripe\Core\Injector\Injectable; use SilverStripe\Core\Injector\Injector; +use SilverStripe\Core\Validation\ConstraintValidator; use SilverStripe\RealMe\Exception as RealMeException; use SilverStripe\RealMe\Model\FederatedIdentity; use SilverStripe\RealMe\Model\User; use SilverStripe\Security\Member; use SilverStripe\Security\Security; use SilverStripe\View\TemplateGlobalProvider; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Url; class RealMeService implements TemplateGlobalProvider { @@ -458,11 +461,11 @@ public function enforceLogin(HTTPRequest $request, $backUrl = null) } $backUrl = $this->validSiteURL($backUrl); - + if (!$backUrl) { $backUrl = Director::absoluteBaseURL(); } - + // If not, attempt to retrieve authentication data from OneLogin (in case this is called during SAML assertion) try { if (!$session->get("RealMeErrorBackURL") && Controller::has_curr()) { @@ -800,7 +803,7 @@ public function getAssertionConsumerServiceUrlForEnvironment($env) } $domain = $this->getMetadataAssertionServiceDomainForEnvironment($env); - if (filter_var($domain, FILTER_VALIDATE_URL) === false) { + if (!ConstraintValidator::validate($domain, [new Url(), new NotBlank()])->isValid()) { return null; } diff --git a/src/Task/RealMeSetupTask.php b/src/Task/RealMeSetupTask.php index b7d2c1f..dd2c3c1 100644 --- a/src/Task/RealMeSetupTask.php +++ b/src/Task/RealMeSetupTask.php @@ -10,8 +10,11 @@ use SilverStripe\RealMe\RealMeService; use SilverStripe\Control\Director; use SilverStripe\Control\Controller; +use SilverStripe\Core\Validation\ConstraintValidator; use SilverStripe\Dev\BuildTask; use SilverStripe\Dev\Deprecation; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Url; /** * Class RealMeSetupTask @@ -276,45 +279,33 @@ private function validateEntityID($forEnv) ); } - // make sure the entityID is a valid URL - $entityId = filter_var($entityId, FILTER_VALIDATE_URL); - if ($entityId === false) { - $this->errors[] = _t( - RealMeSetupTask::class . '.ERR_CONFIG_ENTITYID', - 'The Entity ID (\'{entityId}\') must be https, not be \'localhost\', and must contain a valid ' . - 'service name and privacy realm e.g. https://my-realme-integration.govt.nz/p-realm/s-name', - array( - 'entityId' => $entityId - ) - ); - + $validationMessage = _t( + RealMeSetupTask::class . '.ERR_CONFIG_ENTITYID', + 'The Entity ID (\'{entityId}\') must be https, not be \'localhost\', and must contain a valid ' . + 'service name and privacy realm e.g. https://my-realme-integration.govt.nz/p-realm/s-name', + ['entityId' => $entityId] + ); + // make sure the entityID is a valid URL with HTTPS protocol + if (!ConstraintValidator::validate($entityId, [new Url(protocols: ['https']), new NotBlank()])->isValid()) { + $this->errors[] = $validationMessage; // invalid entity id, no point continuing. return; } - // check it's not localhost and HTTPS. and make sure we have a host / scheme + // check it's not localhost $urlParts = parse_url($entityId ?? ''); - if ($urlParts['host'] === 'localhost' || $urlParts['scheme'] === 'http') { - $this->errors[] = _t( - RealMeSetupTask::class . '.ERR_CONFIG_ENTITYID', - 'The Entity ID (\'{entityId}\') must be https, not be \'localhost\', and must contain a valid ' . - 'service name and privacy realm e.g. https://my-realme-integration.govt.nz/p-realm/s-name', - array( - 'entityId' => $entityId - ) - ); - + if ($urlParts['host'] === 'localhost') { + $this->errors[] = $validationMessage; // if there's this much wrong, we want them to fix it first. return; } $path = ltrim($urlParts['path'] ?? ''); - $urlParts = preg_split("/\\//", $path ?? ''); - + $pathParts = preg_split("/\\//", $path ?? ''); // A valid Entity ID is in the form of "https://www.domain.govt.nz//" // Validate Service Name - $serviceName = array_pop($urlParts); + $serviceName = array_pop($pathParts); if (mb_strlen($serviceName ?? '') > 20 || 0 === mb_strlen($serviceName ?? '')) { $this->errors[] = _t( RealMeSetupTask::class . '.ERR_CONFIG_ENTITYID_SERVICE_NAME', @@ -328,7 +319,7 @@ private function validateEntityID($forEnv) } // Validate Privacy Realm - $privacyRealm = array_pop($urlParts); + $privacyRealm = array_pop($pathParts); if (null === $privacyRealm || 0 === mb_strlen($privacyRealm ?? '')) { $this->errors[] = _t( RealMeSetupTask::class . '.ERR_CONFIG_ENTITYID_PRIVACY_REALM',