Skip to content

Commit

Permalink
[12.x] Validate UUID's version optionally (#53341)
Browse files Browse the repository at this point in the history
* Validate UUID's version optionally

* StyleCI fixes

* Reorder imports

* Check type before length

* Fix wrong variable

* Symfony/uid doesn't implement version 2

* fix: 🐛 Cast extracted value for identity check of match

* test: ✅ Add tests for both Str::isUuid() and the uuid validation rule

* style: 🎨 Fix StyleCI error

Suggested-by: Vano Devium <[email protected]>
cc: Vano Devium <[email protected]>
thanks-to: Vano Devium <[email protected]>
original-patch-by: Vano Devium <[email protected]>
based-on-a-patch-by: Vano Devium <[email protected]>
based-on-patch-by: Vano Devium <[email protected]>
credit-to: Vano Devium <[email protected]>
inspired-by-patch-by: Vano Devium <[email protected]>
initial-work-by: Vano Devium <[email protected]>
inspired-by: #21672

* test: ✅ Add non-existent UUID version cases to data provider

Suggested-by: Vano Devium <[email protected]>
cc: Vano Devium <[email protected]>
thanks-to: Vano Devium <[email protected]>
original-patch-by: Vano Devium <[email protected]>
based-on-a-patch-by: Vano Devium <[email protected]>
based-on-patch-by: Vano Devium <[email protected]>
credit-to: Vano Devium <[email protected]>
inspired-by-patch-by: Vano Devium <[email protected]>
initial-work-by: Vano Devium <[email protected]>
inspired-by: #21672
  • Loading branch information
shaedrich authored Oct 31, 2024
1 parent a48c542 commit 0dfeef5
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
28 changes: 26 additions & 2 deletions src/Illuminate/Support/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@
use Ramsey\Uuid\Generator\CombGenerator;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidFactory;
use Symfony\Component\Uid\NilUuid;
use Symfony\Component\Uid\Ulid;
use Symfony\Component\Uid\UuidV1;
use Symfony\Component\Uid\UuidV3;
use Symfony\Component\Uid\UuidV4;
use Symfony\Component\Uid\UuidV5;
use Symfony\Component\Uid\UuidV6;
use Symfony\Component\Uid\UuidV7;
use Symfony\Component\Uid\UuidV8;
use Throwable;
use Traversable;
use voku\helper\ASCII;
Expand Down Expand Up @@ -595,15 +603,31 @@ public static function isUrl($value, array $protocols = [])
* Determine if a given value is a valid UUID.
*
* @param mixed $value
* @param int<-1, 8>|null $version
* @return bool
*/
public static function isUuid($value)
public static function isUuid($value, $version = null)
{
if (! is_string($value)) {
return false;
}

return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0;
if ($version === null) {
return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0;
}

return match ($version) {
-1, 0 => NilUuid::isValid($value),
1 => UuidV1::isValid($value),
// 2 => UuidV2::isValid($value), // Symfony/uid doesn't implement version 2
3 => UuidV3::isValid($value),
4 => UuidV4::isValid($value),
5 => UuidV5::isValid($value),
6 => UuidV6::isValid($value),
7 => UuidV7::isValid($value),
8 => UuidV8::isValid($value),
default => false,
};
}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/Illuminate/Validation/Concerns/ValidatesAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -2550,11 +2550,12 @@ public function validateUlid($attribute, $value)
*
* @param string $attribute
* @param mixed $value
* @param array<int, int<-1, 8>> $parameters
* @return bool
*/
public function validateUuid($attribute, $value)
public function validateUuid($attribute, $value, $parameters)
{
return Str::isUuid($value);
return Str::isUuid($value, $parameters !== null && count($parameters) === 1 ? (int) $parameters[0] : null);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/Support/SupportStrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,12 @@ public function testIsUuidWithInvalidUuid($uuid)
$this->assertFalse(Str::isUuid($uuid));
}

#[DataProvider('uuidVersionList')]
public function testIsUuidWithVersion($uuid, $version, $passes)
{
$this->assertSame(Str::isUuid($uuid, $version), $passes);
}

public function testIsJson()
{
$this->assertTrue(Str::isJson('1'));
Expand Down Expand Up @@ -1306,6 +1312,24 @@ public static function invalidUuidList()
];
}

public static function uuidVersionList()
{
return [
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', null, true],
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 1, false],
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 4, true],
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 42, false],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', null, true],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 1, true],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 4, false],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 42, false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', null, false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 1, false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 4, false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 42, false],
];
}

public static function strContainsProvider()
{
return [
Expand Down
26 changes: 26 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8445,6 +8445,14 @@ public function testValidateWithInvalidUuid($uuid)
$this->assertFalse($v->passes());
}

#[DataProvider('uuidVersionList')]
public function testValidateWithUuidWithVersionConstraint($uuid, $rule, $passes)
{
$trans = $this->getIlluminateArrayTranslator();
$v = new Validator($trans, ['foo' => $uuid], ['foo' => $rule]);
$this->assertSame($v->passes(), $passes);
}

public static function validUuidList()
{
return [
Expand Down Expand Up @@ -8477,6 +8485,24 @@ public static function invalidUuidList()
];
}

public static function uuidVersionList()
{
return [
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid', true],
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:1', false],
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:4', true],
['a0a2a2d2-0b87-4a18-83f2-2529882be2de', 'uuid:42', false],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid', true],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid:1', true],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid:4', false],
['145a1e72-d11d-11e8-a8d5-f2801f1b9fd1', 'uuid:42', false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid', false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:1', false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:4', false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:42', false],
];
}

public function testValidateWithValidAscii()
{
$trans = $this->getIlluminateArrayTranslator();
Expand Down

0 comments on commit 0dfeef5

Please sign in to comment.