Skip to content

Commit

Permalink
Refactor assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdijen committed Jan 8, 2025
1 parent c582405 commit 196ab2a
Show file tree
Hide file tree
Showing 28 changed files with 60 additions and 233 deletions.
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
"psr/clock": "^1.0",
"psr/http-message": "^2.0",
"psr/log": "^2.0 || ^3.0",
"simplesamlphp/assert": "~1.7.0",
"simplesamlphp/xml-common": "~1.23.0",
"simplesamlphp/xml-security": "~1.12.0",
"simplesamlphp/xml-soap": "~1.6.0"
"simplesamlphp/assert": "~1.8.0",
"simplesamlphp/xml-common": "~1.24.0",
"simplesamlphp/xml-security": "~1.13.0",
"simplesamlphp/xml-soap": "~1.7.0"
},
"require-dev": {
"ext-intl": "*",
Expand Down
155 changes: 2 additions & 153 deletions src/Assert/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,7 @@

namespace SimpleSAML\SAML2\Assert;

use BadMethodCallException; // Requires ext-spl
use DateTime; // requires ext-date
use DateTimeImmutable; // requires ext-date
use InvalidArgumentException; // Requires ext-spl
use SimpleSAML\Assert\Assert as BaseAssert;
use SimpleSAML\Assert\AssertionFailedException;
use Throwable;

use function array_pop;
use function array_unshift;
use function call_user_func_array;
use function end;
use function enum_exists;
use function function_exists;
use function get_class;
use function is_object;
use function is_resource;
use function is_string;
use function is_subclass_of;
use function lcfirst;
use function method_exists;
use function preg_match; // Requires ext-pcre
use function strval;
use SimpleSAML\XMLSecurity\Assert\Assert as BaseAssert;

/**
* SimpleSAML\SAML2\Assert\Assert wrapper class
Expand All @@ -43,136 +21,7 @@
* @method static void allValidURI(mixed $value, string $message = '', string $exception = '')
* @method static void allValidEntityID(mixed $value, string $message = '', string $exception = '')
*/
final class Assert
class Assert extends BaseAssert
{
use CustomAssertionTrait;


/**
* @param string $name
* @param array<mixed> $arguments
*/
public static function __callStatic(string $name, array $arguments): void
{
// Handle Exception-parameter
$exception = AssertionFailedException::class;

$last = end($arguments);
if (is_string($last) && class_exists($last) && is_subclass_of($last, Throwable::class)) {
$exception = $last;
array_pop($arguments);
}

try {
if (method_exists(static::class, $name)) {
call_user_func_array([static::class, $name], $arguments);
return;
} elseif (preg_match('/^nullOr(.*)$/i', $name, $matches)) {
$method = lcfirst($matches[1]);
if (method_exists(static::class, $method)) {
call_user_func_array([static::class, 'nullOr'], [[static::class, $method], $arguments]);
} elseif (method_exists(BaseAssert::class, $method)) {
call_user_func_array([static::class, 'nullOr'], [[BaseAssert::class, $method], $arguments]);
} else {
throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $method));
}
} elseif (preg_match('/^all(.*)$/i', $name, $matches)) {
$method = lcfirst($matches[1]);
if (method_exists(static::class, $method)) {
call_user_func_array([static::class, 'all'], [[static::class, $method], $arguments]);
} elseif (method_exists(BaseAssert::class, $method)) {
call_user_func_array([static::class, 'all'], [[BaseAssert::class, $method], $arguments]);
} else {
throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $method));
}
} else {
throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $name));
}
} catch (InvalidArgumentException $e) {
throw new $exception($e->getMessage());
}
}


/**
* Handle nullOr* for either Webmozart or for our custom assertions
*
* @param callable $method
* @param array<mixed> $arguments
* @return void
*/
private static function nullOr(callable $method, array $arguments): void
{
$value = reset($arguments);
($value === null) || call_user_func_array($method, $arguments);
}


/**
* all* for our custom assertions
*
* @param callable $method
* @param array<mixed> $arguments
* @return void
*/
private static function all(callable $method, array $arguments): void
{
$values = array_pop($arguments);
foreach ($values as $value) {
$tmp = $arguments;
array_unshift($tmp, $value);
call_user_func_array($method, $tmp);
}
}


/**
* @param mixed $value
*
* @return string
*/
protected static function valueToString(mixed $value): string
{
if (is_resource($value)) {
return 'resource';
}

if (null === $value) {
return 'null';
}

if (true === $value) {
return 'true';
}

if (false === $value) {
return 'false';
}

if (is_array($value)) {
return 'array';
}

if (is_object($value)) {
if (method_exists($value, '__toString')) {
return $value::class . ': ' . self::valueToString($value->__toString());
}

if ($value instanceof DateTime || $value instanceof DateTimeImmutable) {
return $value::class . ': ' . self::valueToString($value->format('c'));
}

if (function_exists('enum_exists') && enum_exists(get_class($value))) {
return get_class($value) . '::' . $value->name;
}

return $value::class;
}

if (is_string($value)) {
return '"' . $value . '"';
}

return strval($value);
}
}
27 changes: 9 additions & 18 deletions src/Assert/CustomAssertionTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace SimpleSAML\SAML2\Assert;

use SimpleSAML\Assert\Assert as BaseAssert;
use SimpleSAML\Assert\AssertionFailedException;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
Expand All @@ -30,16 +29,12 @@ trait CustomAssertionTrait
* @param string $value
* @param string $message
*/
private static function validDateTime(string $value, string $message = ''): void
protected static function validDateTime(string $value, string $message = ''): void
{
try {
BaseAssert::validDateTime($value);
} catch (AssertionFailedException $e) {
throw new SchemaViolationException($e->getMessage());
}
parent::validDateTime($value);

try {
BaseAssert::endsWith(
parent::endsWith(
$value,
'Z',
'%s is not a DateTime expressed in the UTC timezone using the \'Z\' timezone identifier.',
Expand All @@ -54,17 +49,13 @@ private static function validDateTime(string $value, string $message = ''): void
* @param string $value
* @param string $message
*/
private static function validURI(string $value, string $message = ''): void
protected static function validURI(string $value, string $message = ''): void
{
try {
BaseAssert::validURI($value);
} catch (AssertionFailedException $e) {
throw new SchemaViolationException($e->getMessage());
}
parent::validURI($value);

try {
// If it doesn't have a scheme, it's not an absolute URI
BaseAssert::regex($value, self::$scheme_regex, $message ?: '%s is not a SAML2-compliant URI');
parent::regex($value, self::$scheme_regex, $message ?: '%s is not a SAML2-compliant URI');
} catch (AssertionFailedException $e) {
throw new ProtocolViolationException($e->getMessage());
}
Expand All @@ -75,13 +66,13 @@ private static function validURI(string $value, string $message = ''): void
* @param string $value
* @param string $message
*/
private static function validEntityID(string $value, string $message = ''): void
protected static function validEntityID(string $value, string $message = ''): void
{
static::validURI($value);

try {
BaseAssert::notWhitespaceOnly($value);
BaseAssert::maxLength(
parent::notWhitespaceOnly($value);
parent::maxLength(
$value,
C::ENTITYID_MAX_LENGTH,
sprintf('An entityID cannot be longer than %d characters.', C::ENTITYID_MAX_LENGTH),
Expand Down
2 changes: 1 addition & 1 deletion src/XML/ExtensionPointTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace SimpleSAML\SAML2\XML;

use RuntimeException;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\XML\Exception\SchemaViolationException;

/**
Expand Down
2 changes: 1 addition & 1 deletion src/XML/md/AbstractMetadataDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use DateTimeImmutable;
use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\XML\ExtendableElementTrait;
use SimpleSAML\XML\Exception\SchemaViolationException;
Expand Down
5 changes: 2 additions & 3 deletions src/XML/md/AbstractRoleDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

use DateTimeImmutable;
use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Utils;
use SimpleSAML\SAML2\XML\ExtensionPointInterface;
Expand Down Expand Up @@ -136,7 +135,7 @@ public static function fromXML(DOMElement $xml): static
$protocols = self::getAttribute($xml, 'protocolSupportEnumeration');

$validUntil = self::getOptionalAttribute($xml, 'validUntil', null);
SAMLAssert::nullOrValidDateTime($validUntil);
Assert::nullOrValidDateTime($validUntil);

$orgs = Organization::getChildrenOfClass($xml);
Assert::maxCount(
Expand Down
2 changes: 1 addition & 1 deletion src/XML/saml/AbstractBaseID.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace SimpleSAML\SAML2\XML\saml;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Utils;
use SimpleSAML\SAML2\XML\EncryptableElementTrait;
Expand Down
2 changes: 1 addition & 1 deletion src/XML/saml/AbstractCondition.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace SimpleSAML\SAML2\XML\saml;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Utils;
use SimpleSAML\SAML2\XML\ExtensionPointInterface;
Expand Down
2 changes: 1 addition & 1 deletion src/XML/saml/AbstractStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace SimpleSAML\SAML2\XML\saml;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Utils;
use SimpleSAML\SAML2\XML\ExtensionPointInterface;
Expand Down
5 changes: 2 additions & 3 deletions src/XML/saml/Assertion.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

use DateTimeImmutable;
use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
use SimpleSAML\SAML2\Utils\XPath;
Expand Down Expand Up @@ -262,7 +261,7 @@ public static function fromXML(DOMElement $xml): static
// Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
$issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);

SAMLAssert::validDateTime($issueInstant, ProtocolViolationException::class);
Assert::validDateTime($issueInstant, ProtocolViolationException::class);
$issueInstant = new DateTimeImmutable($issueInstant);

$issuer = Issuer::getChildrenOfClass($xml);
Expand Down
2 changes: 1 addition & 1 deletion src/XML/saml/AssertionIDRef.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace SimpleSAML\SAML2\XML\saml;

use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\XML\StringElementTrait;
use SimpleSAML\XML\Exception\SchemaViolationException;
use SimpleSAML\XML\SchemaValidatableElementInterface;
Expand Down
7 changes: 3 additions & 4 deletions src/XML/saml/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
namespace SimpleSAML\SAML2\XML\saml;

use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\XML\EncryptableElementTrait;
use SimpleSAML\XML\Exception\InvalidDOMElementException;
Expand Down Expand Up @@ -51,13 +50,13 @@ public function __construct(
array $namespacedAttribute = [],
) {
Assert::notWhitespaceOnly($name, 'Cannot specify an empty name for an Attribute.');
SAMLAssert::nullOrValidURI($nameFormat);
Assert::nullOrValidURI($nameFormat);
Assert::nullOrNotWhitespaceOnly($friendlyName, 'FriendlyName cannot be an empty string.');
Assert::maxCount($attributeValue, C::UNBOUNDED_LIMIT);
Assert::allIsInstanceOf($attributeValue, AttributeValue::class, 'Invalid AttributeValue.');

if ($nameFormat === C::NAMEFORMAT_URI) {
SAMLAssert::validURI(
Assert::validURI(
$name,
sprintf("Attribute name `%s` does not match its declared format `%s`", $name, $nameFormat),
);
Expand Down
2 changes: 1 addition & 1 deletion src/XML/saml/AttributeValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use DateTimeImmutable;
use DateTimeInterface;
use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\XML\AbstractElement;
use SimpleSAML\XML\Chunk;
Expand Down
2 changes: 1 addition & 1 deletion src/XML/saml/SubjectConfirmationData.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use DateTimeImmutable;
use DOMElement;
use SimpleSAML\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert;
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
use SimpleSAML\SAML2\Constants as C;
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
Expand Down
Loading

0 comments on commit 196ab2a

Please sign in to comment.