Skip to content

Commit

Permalink
[12.x] Validate UUID version 2 and max (#53368)
Browse files Browse the repository at this point in the history
* feat: ✨ Add support for UUID v2 and max UUID validation

* test: ✅ Add cases for every supported UUID version to data provider of UUID validation tests

* style: 🎨 Fix StyleCI errors

– Remove unused imports
– Spacing

improves: #53341

* Add missing import

* style: 🎨 Remove indent from blank line

* Add ramsey/uuid to composer suggestions

to be able to use it for UUID version constraint validation

* Update Str.php

* Update Str.php

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
shaedrich and taylorotwell authored Nov 1, 2024
1 parent 0dfeef5 commit e4fcc78
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 32 deletions.
47 changes: 26 additions & 21 deletions src/Illuminate/Support/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,12 @@
use League\CommonMark\GithubFlavoredMarkdownConverter;
use League\CommonMark\MarkdownConverter;
use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
use Ramsey\Uuid\Generator\CombGenerator;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
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 @@ -603,7 +597,7 @@ 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
* @param int<0, 8>|'max'|null $version
* @return bool
*/
public static function isUuid($value, $version = null)
Expand All @@ -616,18 +610,29 @@ public static function isUuid($value, $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,
};
$factory = new UuidFactory;

try {
$factoryUuid = $factory->fromString($value);
} catch (InvalidUuidStringException $ex) {
return false;
}

$fields = $factoryUuid->getFields();

if (! ($fields instanceof FieldsInterface)) {
return false;
}

if ($version === 0 || $version === 'nil') {
return $fields->isNil();
}

if ($version === 'max') {
return $fields->isMax();
}

return $fields->getVersion() === $version;
}

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

if ($parameters !== null && count($parameters) === 1) {
$version = $parameters[0];

if ($version !== 'max') {
$version = (int) $parameters[0];
}
}

return Str::isUuid($value, $version);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Illuminate/Validation/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
}
},
"suggest": {
"illuminate/database": "Required to use the database presence verifier (^12.0)."
"illuminate/database": "Required to use the database presence verifier (^12.0).",
"ramsey/uuid": "Required to use Validator::validateUuid() (^4.7)."
},
"config": {
"sort-packages": true
Expand Down
44 changes: 40 additions & 4 deletions tests/Support/SupportStrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1315,14 +1315,50 @@ 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],
['00000000-0000-0000-0000-000000000000', null, true],
['00000000-0000-0000-0000-000000000000', 0, true],
['00000000-0000-0000-0000-000000000000', 1, false],
['00000000-0000-0000-0000-000000000000', 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],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', null, true],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 1, false],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 2, true],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 42, false],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', null, true],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 1, false],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 3, true],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 42, false],
['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],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', null, true],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 1, false],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 5, true],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 42, false],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', null, true],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 1, false],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 6, true],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 42, false],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', null, true],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 1, false],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 7, true],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 42, false],
['07e80a1f-1629-831f-811f-c595103c91b5', null, true],
['07e80a1f-1629-831f-811f-c595103c91b5', 1, false],
['07e80a1f-1629-831f-811f-c595103c91b5', 8, true],
['07e80a1f-1629-831f-811f-c595103c91b5', 42, false],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', null, true],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 1, false],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 42, false],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'max', true],
['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],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', null, false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 1, false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 4, false],
Expand Down
40 changes: 36 additions & 4 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8488,14 +8488,46 @@ 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],
['00000000-0000-0000-0000-000000000000', 'uuid', true],
['00000000-0000-0000-0000-000000000000', 'uuid:0', true],
['00000000-0000-0000-0000-000000000000', 'uuid:1', false],
['00000000-0000-0000-0000-000000000000', '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],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid', true],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid:1', false],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid:2', true],
['ff6f8cb0-c57d-21e1-9b21-0800200c9a66', 'uuid:42', false],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid', true],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid:1', false],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid:3', true],
['76a4ba72-cc4e-3e1d-b52d-856382f408c3', 'uuid:42', false],
['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],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid', true],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid:1', false],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid:5', true],
['d3b2b5a9-d433-5c58-b038-4fa13696e357', 'uuid:42', false],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid', true],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid:1', false],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid:6', true],
['1ef97d97-b5ab-67d8-9f12-5600051f1387', 'uuid:42', false],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid', true],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid:1', false],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid:7', true],
['0192e4b9-92eb-7aec-8707-1becfb1e3eb7', 'uuid:42', false],
['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid', true],
['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid:1', false],
['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid:8', true],
['07e80a1f-1629-831f-811f-c595103c91b5', 'uuid:42', false],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid', true],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid:1', false],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid:42', false],
['FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF', 'uuid:max', true],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid', false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:1', false],
['zf6f8cb0-c57d-11e1-9b21-0800200c9a66', 'uuid:4', false],
Expand Down

0 comments on commit e4fcc78

Please sign in to comment.