Fix FLEXIAPI-353 Validate UUIDs in the vcards-storage endpoints, complete the...

This commit is contained in:
Timothée Jaussoin 2025-07-09 14:57:48 +00:00
parent 9d98e466eb
commit 3360402a42
6 changed files with 145 additions and 105 deletions

View file

@ -62,6 +62,7 @@ v2.0
- Fix FLEXIAPI-350 Fix wrongly assigned variables in some views - Fix FLEXIAPI-350 Fix wrongly assigned variables in some views
- Fix FLEXIAPI-351 Fix import of CSV generated on Windows - Fix FLEXIAPI-351 Fix import of CSV generated on Windows
- Fix FLEXIAPI-352 Add missing errors box in the password change form - Fix FLEXIAPI-352 Add missing errors box in the password change form
* Fix FLEXIAPI-353 Validate UUIDs in the vcards-storage endpoints, complete the documentation and fix the related tests
v1.6 v1.6
---- ----

View file

@ -30,6 +30,6 @@ class VcardsStorageController extends Controller
public function destroy(Request $request, string $uuid) public function destroy(Request $request, string $uuid)
{ {
return (new AdminVcardsStorageController)->destroy($request->user()->id, $uuid); return (new AdminVcardsStorageController)->destroy($request, $request->user()->id, $uuid);
} }
} }

View file

@ -46,14 +46,18 @@ class VcardsStorageController extends Controller
]); ]);
$vcardo = VObject\Reader::read($request->get('vcard')); $vcardo = VObject\Reader::read($request->get('vcard'));
$vcardoUID = substr($vcardo->UID, 9);
if (Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $vcardo->UID)->first()) { $request->merge(['uuid' => $vcardoUID]);
$request->validate(['uuid' => 'uuid']);
if (Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $vcardoUID)->first()) {
abort(409, 'Vcard already exists'); abort(409, 'Vcard already exists');
} }
$vcard = new VcardStorage(); $vcard = new VcardStorage();
$vcard->account_id = $accountId; $vcard->account_id = $accountId;
$vcard->uuid = $vcardo->UID; $vcard->uuid = $vcardoUID;
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize()); $vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
$vcard->save(); $vcard->save();
@ -62,13 +66,20 @@ class VcardsStorageController extends Controller
public function update(Request $request, int $accountId, string $uuid) public function update(Request $request, int $accountId, string $uuid)
{ {
$request->merge(['uuid' => $uuid]);
$request->validate([ $request->validate([
'uuid' => 'uuid',
'vcard' => ['required', new Vcard()] 'vcard' => ['required', new Vcard()]
]); ]);
$vcardo = VObject\Reader::read($request->get('vcard')); $vcardo = VObject\Reader::read($request->get('vcard'));
$vcardoUID = substr($vcardo->UID, 9);
if ($vcardo->UID != $uuid) { $request->merge(['vuuid' => $vcardoUID]);
$request->validate(['vuuid' => 'uuid']);
if ($vcardoUID != $uuid) {
abort(422, 'UUID should be the same'); abort(422, 'UUID should be the same');
} }
@ -79,8 +90,11 @@ class VcardsStorageController extends Controller
return $vcard->vcard; return $vcard->vcard;
} }
public function destroy(int $accountId, string $uuid) public function destroy(Request $request, int $accountId, string $uuid)
{ {
$request->merge(['uuid' => $uuid]);
$request->validate(['uuid' => 'uuid']);
$vcard = Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail(); $vcard = Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
return $vcard->delete(); return $vcard->delete();

171
flexiapi/composer.lock generated
View file

@ -1324,16 +1324,16 @@
}, },
{ {
"name": "giggsey/libphonenumber-for-php-lite", "name": "giggsey/libphonenumber-for-php-lite",
"version": "9.0.7", "version": "9.0.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/giggsey/libphonenumber-for-php-lite.git", "url": "https://github.com/giggsey/libphonenumber-for-php-lite.git",
"reference": "353fdd900277e8974b42c23a1f8b2c943e126791" "reference": "d7ae8dd1186b54ce1451aec437346dd772321492"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/353fdd900277e8974b42c23a1f8b2c943e126791", "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php-lite/zipball/d7ae8dd1186b54ce1451aec437346dd772321492",
"reference": "353fdd900277e8974b42c23a1f8b2c943e126791", "reference": "d7ae8dd1186b54ce1451aec437346dd772321492",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1398,7 +1398,7 @@
"issues": "https://github.com/giggsey/libphonenumber-for-php-lite/issues", "issues": "https://github.com/giggsey/libphonenumber-for-php-lite/issues",
"source": "https://github.com/giggsey/libphonenumber-for-php-lite" "source": "https://github.com/giggsey/libphonenumber-for-php-lite"
}, },
"time": "2025-06-09T07:26:43+00:00" "time": "2025-07-08T08:38:23+00:00"
}, },
{ {
"name": "graham-campbell/result-type", "name": "graham-campbell/result-type",
@ -2594,16 +2594,16 @@
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "3.29.1", "version": "3.30.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem.git", "url": "https://github.com/thephpleague/flysystem.git",
"reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" "reference": "2203e3151755d874bb2943649dae1eb8533ac93e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e",
"reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", "reference": "2203e3151755d874bb2943649dae1eb8533ac93e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2627,13 +2627,13 @@
"composer/semver": "^3.0", "composer/semver": "^3.0",
"ext-fileinfo": "*", "ext-fileinfo": "*",
"ext-ftp": "*", "ext-ftp": "*",
"ext-mongodb": "^1.3", "ext-mongodb": "^1.3|^2",
"ext-zip": "*", "ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.5", "friendsofphp/php-cs-fixer": "^3.5",
"google/cloud-storage": "^1.23", "google/cloud-storage": "^1.23",
"guzzlehttp/psr7": "^2.6", "guzzlehttp/psr7": "^2.6",
"microsoft/azure-storage-blob": "^1.1", "microsoft/azure-storage-blob": "^1.1",
"mongodb/mongodb": "^1.2", "mongodb/mongodb": "^1.2|^2",
"phpseclib/phpseclib": "^3.0.36", "phpseclib/phpseclib": "^3.0.36",
"phpstan/phpstan": "^1.10", "phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.5.11|^10.0", "phpunit/phpunit": "^9.5.11|^10.0",
@ -2671,22 +2671,22 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem/issues", "issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.29.1" "source": "https://github.com/thephpleague/flysystem/tree/3.30.0"
}, },
"time": "2024-10-08T08:58:34+00:00" "time": "2025-06-25T13:29:59+00:00"
}, },
{ {
"name": "league/flysystem-local", "name": "league/flysystem-local",
"version": "3.29.0", "version": "3.30.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem-local.git", "url": "https://github.com/thephpleague/flysystem-local.git",
"reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10",
"reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", "reference": "6691915f77c7fb69adfb87dcd550052dc184ee10",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2720,9 +2720,9 @@
"local" "local"
], ],
"support": { "support": {
"source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" "source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0"
}, },
"time": "2024-08-09T21:24:39+00:00" "time": "2025-05-21T10:34:19+00:00"
}, },
{ {
"name": "league/mime-type-detection", "name": "league/mime-type-detection",
@ -2950,16 +2950,16 @@
}, },
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
"version": "1.13.1", "version": "1.13.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/myclabs/DeepCopy.git", "url": "https://github.com/myclabs/DeepCopy.git",
"reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" "reference": "faed855a7b5f4d4637717c2b3863e277116beb36"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36",
"reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "reference": "faed855a7b5f4d4637717c2b3863e277116beb36",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2998,7 +2998,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/myclabs/DeepCopy/issues", "issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3"
}, },
"funding": [ "funding": [
{ {
@ -3006,7 +3006,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-04-29T12:36:36+00:00" "time": "2025-07-05T12:25:42+00:00"
}, },
{ {
"name": "namoshek/laravel-redis-sentinel", "name": "namoshek/laravel-redis-sentinel",
@ -4936,21 +4936,20 @@
}, },
{ {
"name": "ramsey/uuid", "name": "ramsey/uuid",
"version": "4.8.1", "version": "4.9.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ramsey/uuid.git", "url": "https://github.com/ramsey/uuid.git",
"reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "url": "https://api.github.com/repos/ramsey/uuid/zipball/4e0e23cc785f0724a0e838279a9eb03f28b092a0",
"reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "reference": "4e0e23cc785f0724a0e838279a9eb03f28b092a0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13",
"ext-json": "*",
"php": "^8.0", "php": "^8.0",
"ramsey/collection": "^1.2 || ^2.0" "ramsey/collection": "^1.2 || ^2.0"
}, },
@ -5009,9 +5008,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/ramsey/uuid/issues", "issues": "https://github.com/ramsey/uuid/issues",
"source": "https://github.com/ramsey/uuid/tree/4.8.1" "source": "https://github.com/ramsey/uuid/tree/4.9.0"
}, },
"time": "2025-06-01T06:28:46+00:00" "time": "2025-06-25T14:20:11+00:00"
}, },
{ {
"name": "react/cache", "name": "react/cache",
@ -6813,16 +6812,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v6.4.22", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3" "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93",
"reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6887,7 +6886,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v6.4.22" "source": "https://github.com/symfony/console/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -6903,7 +6902,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-07T07:05:04+00:00" "time": "2025-06-27T19:37:22+00:00"
}, },
{ {
"name": "symfony/css-selector", "name": "symfony/css-selector",
@ -7039,16 +7038,16 @@
}, },
{ {
"name": "symfony/error-handler", "name": "symfony/error-handler",
"version": "v6.4.22", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/error-handler.git", "url": "https://github.com/symfony/error-handler.git",
"reference": "ce765a2d28b3cce61de1fb916e207767a73171d1" "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/ce765a2d28b3cce61de1fb916e207767a73171d1", "url": "https://api.github.com/repos/symfony/error-handler/zipball/b088e0b175c30b4e06d8085200fa465b586f44fa",
"reference": "ce765a2d28b3cce61de1fb916e207767a73171d1", "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7094,7 +7093,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code", "description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/error-handler/tree/v6.4.22" "source": "https://github.com/symfony/error-handler/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -7110,7 +7109,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-28T12:00:15+00:00" "time": "2025-06-13T07:39:48+00:00"
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
@ -7334,16 +7333,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v6.4.22", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae" "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/452d19f945ee41345fd8a50c18b60783546b7bd3",
"reference": "6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae", "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7391,7 +7390,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v6.4.22" "source": "https://github.com/symfony/http-foundation/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -7407,20 +7406,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-11T15:36:20+00:00" "time": "2025-05-26T09:17:58+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v6.4.22", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "15c105b839a7cfa1bc0989c091bfb6477f23b673" "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/15c105b839a7cfa1bc0989c091bfb6477f23b673", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2bb2cba685aabd859f22cf6946554e8e7f3c329a",
"reference": "15c105b839a7cfa1bc0989c091bfb6477f23b673", "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7505,7 +7504,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v6.4.22" "source": "https://github.com/symfony/http-kernel/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -7521,20 +7520,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-29T07:23:40+00:00" "time": "2025-06-28T08:14:51+00:00"
}, },
{ {
"name": "symfony/mailer", "name": "symfony/mailer",
"version": "v6.4.21", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mailer.git", "url": "https://github.com/symfony/mailer.git",
"reference": "ada2809ccd4ec27aba9fc344e3efdaec624c6438" "reference": "a480322ddf8e54de262c9bca31fdcbe26b553de5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/ada2809ccd4ec27aba9fc344e3efdaec624c6438", "url": "https://api.github.com/repos/symfony/mailer/zipball/a480322ddf8e54de262c9bca31fdcbe26b553de5",
"reference": "ada2809ccd4ec27aba9fc344e3efdaec624c6438", "reference": "a480322ddf8e54de262c9bca31fdcbe26b553de5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7585,7 +7584,7 @@
"description": "Helps sending emails", "description": "Helps sending emails",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/mailer/tree/v6.4.21" "source": "https://github.com/symfony/mailer/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -7601,7 +7600,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-04-26T23:47:35+00:00" "time": "2025-06-26T21:24:02+00:00"
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
@ -8640,16 +8639,16 @@
}, },
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v6.4.22", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation.git", "url": "https://github.com/symfony/translation.git",
"reference": "7e3b3b7146c6fab36ddff304a8041174bf6e17ad" "reference": "de8afa521e04a5220e9e58a1dc99971ab7cac643"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/7e3b3b7146c6fab36ddff304a8041174bf6e17ad", "url": "https://api.github.com/repos/symfony/translation/zipball/de8afa521e04a5220e9e58a1dc99971ab7cac643",
"reference": "7e3b3b7146c6fab36ddff304a8041174bf6e17ad", "reference": "de8afa521e04a5220e9e58a1dc99971ab7cac643",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8715,7 +8714,7 @@
"description": "Provides tools to internationalize your application", "description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/translation/tree/v6.4.22" "source": "https://github.com/symfony/translation/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -8731,7 +8730,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-29T07:06:44+00:00" "time": "2025-06-26T21:24:02+00:00"
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
@ -8813,16 +8812,16 @@
}, },
{ {
"name": "symfony/uid", "name": "symfony/uid",
"version": "v6.4.13", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/uid.git", "url": "https://github.com/symfony/uid.git",
"reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007" "reference": "9c8592da78d7ee6af52011eef593350d87e814c0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/uid/zipball/18eb207f0436a993fffbdd811b5b8fa35fa5e007", "url": "https://api.github.com/repos/symfony/uid/zipball/9c8592da78d7ee6af52011eef593350d87e814c0",
"reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007", "reference": "9c8592da78d7ee6af52011eef593350d87e814c0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8867,7 +8866,7 @@
"uuid" "uuid"
], ],
"support": { "support": {
"source": "https://github.com/symfony/uid/tree/v6.4.13" "source": "https://github.com/symfony/uid/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -8883,20 +8882,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-09-25T14:18:03+00:00" "time": "2025-06-26T08:06:12+00:00"
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v6.4.21", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "22560f80c0c5cd58cc0bcaf73455ffd81eb380d5" "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/22560f80c0c5cd58cc0bcaf73455ffd81eb380d5", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600",
"reference": "22560f80c0c5cd58cc0bcaf73455ffd81eb380d5", "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8952,7 +8951,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v6.4.21" "source": "https://github.com/symfony/var-dumper/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -8968,7 +8967,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-04-09T07:34:50+00:00" "time": "2025-06-27T15:05:27+00:00"
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
@ -10046,16 +10045,16 @@
}, },
{ {
"name": "symfony/dependency-injection", "name": "symfony/dependency-injection",
"version": "v6.4.22", "version": "v6.4.23",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/dependency-injection.git", "url": "https://github.com/symfony/dependency-injection.git",
"reference": "8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9" "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9", "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0d9f24f3de0a83573fce5c9ed025d6306c6e166b",
"reference": "8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9", "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10107,7 +10106,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application", "description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/dependency-injection/tree/v6.4.22" "source": "https://github.com/symfony/dependency-injection/tree/v6.4.23"
}, },
"funding": [ "funding": [
{ {
@ -10123,7 +10122,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-05-17T07:35:26+00:00" "time": "2025-06-23T06:49:06+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",

View file

@ -347,7 +347,7 @@ Return `403` if the `max_accounts` limit of the corresponding Space is reached.
JSON parameters: JSON parameters:
* `username` unique username, minimum 6 characters * `username` unique username, minimum 6 characters
* `password` **required** minimum 6 characters * `password` **required**, minimum 6 characters
* `algorithm` **required**, values can be `SHA-256` or `MD5` * `algorithm` **required**, values can be `SHA-256` or `MD5`
* `account_creation_token` the unique `account_creation_token` * `account_creation_token` the unique `account_creation_token`
* `dtmf_protocol` optional, values must be `sipinfo`, `sipmessage` or `rfc2833` * `dtmf_protocol` optional, values must be `sipinfo`, `sipmessage` or `rfc2833`
@ -403,7 +403,7 @@ Change the account password.
JSON parameters: JSON parameters:
* `algorithm` **required**, values can be `SHA-256` or `MD5` * `algorithm` **required**, values can be `SHA-256` or `MD5`
* `old_password` **required** if the password is already set, the old password * `old_password` **required**, if the password is already set, the old password
* `password` **required**, the new password * `password` **required**, the new password
### `POST /accounts` ### `POST /accounts`
@ -416,7 +416,7 @@ Return `403` if the `max_accounts` limit of the corresponding Space is reached.
JSON parameters: JSON parameters:
* `username` unique username, minimum 6 characters * `username` unique username, minimum 6 characters
* `password` **required** minimum 6 characters * `password` **required**, minimum 6 characters
* `algorithm` **required**, values can be `SHA-256` or `MD5` * `algorithm` **required**, values can be `SHA-256` or `MD5`
* `domain` **not configurable by default**, must exist in one of the configured Spaces. Only configurable if the admin is a super admin. Otherwise the SIP domain of the corresponding space is used. * `domain` **not configurable by default**, must exist in one of the configured Spaces. Only configurable if the admin is a super admin. Otherwise the SIP domain of the corresponding space is used.
* `activated` optional, a boolean, set to `false` by default * `activated` optional, a boolean, set to `false` by default
@ -436,7 +436,7 @@ JSON parameters:
* `username` unique username, minimum 6 characters * `username` unique username, minimum 6 characters
* `domain` **not configurable by default**, must exist in one of the configured Spaces. Only configurable if the admin is a super admin. Otherwise the SIP domain of the corresponding space is used. * `domain` **not configurable by default**, must exist in one of the configured Spaces. Only configurable if the admin is a super admin. Otherwise the SIP domain of the corresponding space is used.
* `password` **required** minimum 6 characters * `password` **required**, minimum 6 characters
* `algorithm` **required**, values can be `SHA-256` or `MD5` * `algorithm` **required**, values can be `SHA-256` or `MD5`
* `display_name` optional, string * `display_name` optional, string
* `email` optional, must be an email, must be unique if `ACCOUNT_EMAIL_UNIQUE` is set to `true` * `email` optional, must be an email, must be unique if `ACCOUNT_EMAIL_UNIQUE` is set to `true`
@ -596,7 +596,7 @@ Store a vCard.
JSON parameters: JSON parameters:
* `vcard`, mandatory, a valid vCard having a mandatory `UID` parameter that is uniquelly identifying it. This `UID` parameter will then be used to manipulate the vcard through the following endpoints as `uuid`. * `vcard`, **required**, a valid vCard having a mandatory `UID` parameter that is uniquelly identifying it. This `UID` parameter will then be used to manipulate the vcard through the following endpoints as `uuid`.
### `PUT /accounts/{id/me}/vcards-storage/{uuid}` ### `PUT /accounts/{id/me}/vcards-storage/{uuid}`
<span class="badge badge-warning">Admin</span> <span class="badge badge-warning">Admin</span>
@ -606,7 +606,25 @@ Update a vCard.
JSON parameters: JSON parameters:
* `vcard`, mandatory, a valid vCard having a mandatory `UID` parameter that is uniquelly identifying it and is the same as the `uuid` parameter. * `vcard`, **required**, a valid vCard having a mandatory `UID` parameter that is uniquelly identifying it and is the same as the `uuid` parameter.
URL parameter:
* `uuid`, **required**, a valid UUID with the URN namespace
Example:
```
> PUT /accounts/me/vcards-storage/415f8219-5742-4cc5-9572-617c7f956fc5
> {
> "vcard": "BEGIN:VCARD
> VERSION:4.0
> FN:Simon Perreault
> UID:urn:uuid:415f8219-5742-4cc5-9572-617c7f956fc5
> END:VCARD"
> }
```
### `GET /accounts/{id/me}/vcards-storage` ### `GET /accounts/{id/me}/vcards-storage`
<span class="badge badge-warning">Admin</span> <span class="badge badge-warning">Admin</span>
@ -618,12 +636,20 @@ Return the list of stored vCards
<span class="badge badge-warning">Admin</span> <span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span> <span class="badge badge-info">User</span>
URL parameter:
* `uuid`, **required**, a valid UUID with the URN namespace
Return a stored vCard Return a stored vCard
### `DELETE /accounts/{id/me}/vcards-storage/{uuid}` ### `DELETE /accounts/{id/me}/vcards-storage/{uuid}`
<span class="badge badge-warning">Admin</span> <span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span> <span class="badge badge-info">User</span>
URL parameter:
* `uuid`, **required**, a valid UUID with the URN namespace
Delete a stored vCard Delete a stored vCard
## Contacts ## Contacts

View file

@ -37,28 +37,28 @@ class ApiAccountVcardsStorageTest extends TestCase
$adminRoute = '/api/accounts/' . $account->id . '/vcards-storage'; $adminRoute = '/api/accounts/' . $account->id . '/vcards-storage';
$uid = 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6'; $uid = 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6';
$lastVcard = $lastVcard =
'BEGIN:VCARD 'BEGIN:VCARD
VERSION:4.0 VERSION:4.0
FN:Jhonny English FN:Jhonny English
UID:' . $uid . ' UID:urn:uuid:' . $uid . '
END:VCARD END:VCARD
'; ';
$uid2 = 'urn:uuid:a5b33443-687c-4d19-bdd0-b30cf76bf96d'; $uid2 = 'a5b33443-687c-4d19-bdd0-b30cf76bf96d';
$secondVcard = $secondVcard =
'BEGIN:VCARD 'BEGIN:VCARD
VERSION:4.0 VERSION:4.0
FN:Simone Perreault FN:Simone Perreault
UID:' . $uid2 . ' UID:urn:uuid:' . $uid2 . '
END:VCARD END:VCARD
'; ';
$uid3 = 'urn:uuid:a5b33443-687c-4d19-bdd0-b30cf76bfc4d'; $uid3 = 'a5b33443-687c-4d19-bdd0-b30cf76bfc4d';
$thirdVcard = $thirdVcard =
'BEGIN:VCARD 'BEGIN:VCARD
VERSION:4.0 VERSION:4.0
FN:Jean Jannot FN:Jean Jannot
UID:' . $uid3 . ' UID:urn:uuid:' . $uid3 . '
END:VCARD END:VCARD
'; ';
@ -93,7 +93,7 @@ END:VCARD'
'BEGIN:VCARD 'BEGIN:VCARD
VERSION:4.0 VERSION:4.0
FN:Simon Perreault FN:Simon Perreault
UID:' . $uid . ' UID:urn:uuid:' . $uid . '
END:VCARD' END:VCARD'
])->assertStatus(200); ])->assertStatus(200);
@ -110,7 +110,7 @@ END:VCARD'
'BEGIN:VCARD 'BEGIN:VCARD
VERSION:4.0 VERSION:4.0
FN:Simon Perreault FN:Simon Perreault
UID:' . $uid . ' UID:urn:uuid:' . $uid . '
END:VCARD' END:VCARD'
])->assertStatus(409); ])->assertStatus(409);