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-351 Fix import of CSV generated on Windows
- 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
----

View file

@ -30,6 +30,6 @@ class VcardsStorageController extends Controller
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'));
$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');
}
$vcard = new VcardStorage();
$vcard->account_id = $accountId;
$vcard->uuid = $vcardo->UID;
$vcard->uuid = $vcardoUID;
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
$vcard->save();
@ -62,13 +66,20 @@ class VcardsStorageController extends Controller
public function update(Request $request, int $accountId, string $uuid)
{
$request->merge(['uuid' => $uuid]);
$request->validate([
'uuid' => 'uuid',
'vcard' => ['required', new 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');
}
@ -79,8 +90,11 @@ class VcardsStorageController extends Controller
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();
return $vcard->delete();

171
flexiapi/composer.lock generated
View file

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

View file

@ -347,7 +347,7 @@ Return `403` if the `max_accounts` limit of the corresponding Space is reached.
JSON parameters:
* `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`
* `account_creation_token` the unique `account_creation_token`
* `dtmf_protocol` optional, values must be `sipinfo`, `sipmessage` or `rfc2833`
@ -403,7 +403,7 @@ Change the account password.
JSON parameters:
* `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
### `POST /accounts`
@ -416,7 +416,7 @@ Return `403` if the `max_accounts` limit of the corresponding Space is reached.
JSON parameters:
* `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`
* `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
@ -436,7 +436,7 @@ JSON parameters:
* `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.
* `password` **required** minimum 6 characters
* `password` **required**, minimum 6 characters
* `algorithm` **required**, values can be `SHA-256` or `MD5`
* `display_name` optional, string
* `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:
* `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}`
<span class="badge badge-warning">Admin</span>
@ -606,7 +606,25 @@ Update a vCard.
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`
<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-info">User</span>
URL parameter:
* `uuid`, **required**, a valid UUID with the URN namespace
Return a stored vCard
### `DELETE /accounts/{id/me}/vcards-storage/{uuid}`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
URL parameter:
* `uuid`, **required**, a valid UUID with the URN namespace
Delete a stored vCard
## Contacts

View file

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