diff --git a/components/ILIAS/CmiXapi/classes/class.ilCmiXapiAuthToken.php b/components/ILIAS/CmiXapi/classes/class.ilCmiXapiAuthToken.php index 2898c0430c76..3f7100f0cd1d 100755 --- a/components/ILIAS/CmiXapi/classes/class.ilCmiXapiAuthToken.php +++ b/components/ILIAS/CmiXapi/classes/class.ilCmiXapiAuthToken.php @@ -248,7 +248,7 @@ public static function selectCurrentTimestamp(): string public static function createToken(): string { - return (new \Ramsey\Uuid\UuidFactory())->uuid4()->toString(); + return (new \ILIAS\Data\UUID\Factory())->uuid4AsString(); } public static function fillToken(int $usrId, int $refId, int $objId, int $lrsTypeId = 0): string diff --git a/components/ILIAS/CmiXapi/classes/class.ilCmiXapiContentUploadImporter.php b/components/ILIAS/CmiXapi/classes/class.ilCmiXapiContentUploadImporter.php index ac9ff45ef5ef..1dda53609647 100755 --- a/components/ILIAS/CmiXapi/classes/class.ilCmiXapiContentUploadImporter.php +++ b/components/ILIAS/CmiXapi/classes/class.ilCmiXapiContentUploadImporter.php @@ -460,6 +460,6 @@ private function generateActivityId(string $publisherId): string { global $DIC; $objId = $this->object->getId(); - return "https://ilias.de/cmi5/activityid/" . (new \Ramsey\Uuid\UuidFactory())->uuid3(ilCmiXapiUser::getIliasUuid(), $objId . '-' . $publisherId); + return "https://ilias.de/cmi5/activityid/" . (new \ILIAS\Data\UUID\Factory())->uuid3AsString(ilCmiXapiUser::getIliasUuid(), $objId . '-' . $publisherId); } } diff --git a/components/ILIAS/CmiXapi/classes/class.ilCmiXapiUser.php b/components/ILIAS/CmiXapi/classes/class.ilCmiXapiUser.php index 528d288bf11e..79585d2521b5 100755 --- a/components/ILIAS/CmiXapi/classes/class.ilCmiXapiUser.php +++ b/components/ILIAS/CmiXapi/classes/class.ilCmiXapiUser.php @@ -18,6 +18,9 @@ declare(strict_types=1); +use ILIAS\Data\UUID\Factory as UuidFactory; +use ILIAS\Data\UUID\Uuid; + /** * Class ilCmiXapiUser * @@ -123,7 +126,6 @@ public static function getIliasUuid(): ?string $setting = new ilSetting('cmix'); // Fallback if (null == $setting->get('ilias_uuid', null)) { - // $uuid = (new \Ramsey\Uuid\UuidFactory())->uuid4()->toString(); $uuid = self::getUUID(32); $setting->set('ilias_uuid', $uuid); } @@ -583,24 +585,24 @@ private static function userObjectUniqueIdExists(string $id): bool return $result->numRows() != 0; } - public static function generateCMI5Registration(int $objId, int $usrId): \Ramsey\Uuid\UuidInterface + public static function generateCMI5Registration(int $objId, int $usrId): Uuid { - return (new \Ramsey\Uuid\UuidFactory())->uuid3(self::getIliasUuid(), $objId . '-' . $usrId); + return (new UuidFactory())->uuid3(self::getIliasUuid(), $objId . '-' . $usrId); } - public static function generateRegistration(ilObjCmiXapi $obj, ilObjUser $user): \Ramsey\Uuid\UuidInterface + public static function generateRegistration(ilObjCmiXapi $obj, ilObjUser $user): Uuid { - return (new \Ramsey\Uuid\UuidFactory())->uuid3(self::getIliasUuid(), $obj->getRefId() . '-' . $user->getId()); + return (new UuidFactory())->uuid3(self::getIliasUuid(), $obj->getRefId() . '-' . $user->getId()); } - public static function getCMI5RegistrationFromAuthToken(ilCmiXapiAuthToken $authToken): \Ramsey\Uuid\UuidInterface + public static function getCMI5RegistrationFromAuthToken(ilCmiXapiAuthToken $authToken): Uuid { - return (new \Ramsey\Uuid\UuidFactory())->uuid3(self::getIliasUuid(), $authToken->getObjId() . '-' . $authToken->getUsrId()); + return (new UuidFactory())->uuid3(self::getIliasUuid(), $authToken->getObjId() . '-' . $authToken->getUsrId()); } - public static function getRegistrationFromAuthToken(ilCmiXapiAuthToken $authToken): \Ramsey\Uuid\UuidInterface + public static function getRegistrationFromAuthToken(ilCmiXapiAuthToken $authToken): Uuid { - return (new \Ramsey\Uuid\UuidFactory())->uuid3(self::getIliasUuid(), $authToken->getRefId() . '-' . $authToken->getUsrId()); + return (new UuidFactory())->uuid3(self::getIliasUuid(), $authToken->getRefId() . '-' . $authToken->getUsrId()); } public static function getUsrIdForObjectAndUsrIdent(int $objId, string $userIdent): ?int diff --git a/components/ILIAS/Data/src/UUID/Factory.php b/components/ILIAS/Data/src/UUID/Factory.php index 8b037ca7d60b..bcd85c2778a0 100755 --- a/components/ILIAS/Data/src/UUID/Factory.php +++ b/components/ILIAS/Data/src/UUID/Factory.php @@ -48,6 +48,23 @@ public function uuid4AsString(): string return $this->uuid4()->toString(); } + /** + * Name-based UUID (version 3, MD5): the same namespace and name always result in the same UUID. + * + * @param Uuid|string $namespace a UUID, with or without hyphens + */ + public function uuid3(Uuid|string $namespace, string $name): Uuid + { + return new RamseyUuidWrapper( + $this->uuid_factory->uuid3($namespace instanceof Uuid ? $namespace->toString() : $namespace, $name) + ); + } + + public function uuid3AsString(Uuid|string $namespace, string $name): string + { + return $this->uuid3($namespace, $name)->toString(); + } + public function fromString(string $uuid): Uuid { return new RamseyUuidWrapper($this->uuid_factory->fromString($uuid)); diff --git a/components/ILIAS/Data/tests/UuidTest.php b/components/ILIAS/Data/tests/UuidTest.php index f1eea3b7bd8b..01a2813a32b0 100755 --- a/components/ILIAS/Data/tests/UuidTest.php +++ b/components/ILIAS/Data/tests/UuidTest.php @@ -57,6 +57,30 @@ public function test_uuid4_string(): void $this->assertMatchesRegularExpression(self::VALID_UUID4, $uuid); } + /** + * Name-based UUIDs must never change: they are stored and compared, e.g. as cmi5 registrations. + * Expected values cross-checked with Python's uuid.uuid3(). + */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] + public function test_uuid3_is_stable(): void + { + $factory = new Factory(); + + $this->assertSame( + 'cdefba47-4fc6-3904-99e9-989195f87f2c', + $factory->uuid3AsString('6ba7b810-9dad-11d1-80b4-00c04fd430c8', 'www.ilias.de') + ); + // namespace without hyphens, as stored by CmiXapi + $this->assertSame( + 'd60304bc-9cb8-3988-9fa1-e6953cc506e7', + $factory->uuid3AsString('0123456789abcdef0123456789abcdef', '12-34') + ); + $this->assertSame( + 'cdefba47-4fc6-3904-99e9-989195f87f2c', + $factory->uuid3($factory->fromString('6ba7b810-9dad-11d1-80b4-00c04fd430c8'), 'www.ilias.de')->toString() + ); + } + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_from_string(): void {