Fix FLEXIAPI-177 Complete vcards-storage and devices related endpoints with their User/Admin ones

This commit is contained in:
Timothée Jaussoin 2024-05-22 12:13:13 +02:00
parent c930859c6a
commit b44d6e1b25
7 changed files with 180 additions and 52 deletions

View file

@ -2,6 +2,7 @@
v1.5
----
- Fix FLEXIAPI-177 Complete vcards-storage and devices related endpoints with their User/Admin ones
- Fix FLEXIAPI-176 Improve logs for the deprecated endpoints and AccountCreationToken related serialization
- Fix FLEXIAPI-175 and FLEXISIP-231 Rewrite the Redis contacts parser to handle properly SIP uris (thanks @thibault.lemaire !)
- Fix FLEXIAPI-174 Check if the phone is valid before trying to recover it (deprecated endpoint)

View file

@ -2,69 +2,34 @@
namespace App\Http\Controllers\Api\Account;
use App\Http\Controllers\Api\Admin\VcardsStorageController as AdminVcardsStorageController;
use App\Http\Controllers\Controller;
use App\Rules\Vcard;
use App\VcardStorage;
use Illuminate\Http\Request;
use Sabre\VObject;
class VcardsStorageController extends Controller
{
public function index(Request $request)
{
return $request->user()->vcardsStorage()->get()->keyBy('uuid');
return (new AdminVcardsStorageController)->index($request->user()->id);
}
public function show(Request $request, string $uuid)
{
return $request->user()->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
return (new AdminVcardsStorageController)->show($request->user()->id, $uuid);
}
public function store(Request $request)
{
$request->validate([
'vcard' => ['required', new Vcard()]
]);
$vcardo = VObject\Reader::read($request->get('vcard'));
if ($request->user()->vcardsStorage()->where('uuid', $vcardo->UID)->first()) {
abort(409, 'Vcard already exists');
}
$vcard = new VcardStorage();
$vcard->account_id = $request->user()->id;
$vcard->uuid = $vcardo->UID;
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
$vcard->save();
return $vcard->vcard;
return (new AdminVcardsStorageController)->store($request, $request->user()->id);
}
public function update(Request $request, string $uuid)
{
$request->validate([
'vcard' => ['required', new Vcard()]
]);
$vcardo = VObject\Reader::read($request->get('vcard'));
if ($vcardo->UID != $uuid) {
abort(422, 'UUID should be the same');
}
$vcard = $request->user()->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
$vcard->save();
return $vcard->vcard;
return (new AdminVcardsStorageController)->update($request, $request->user()->id, $uuid);
}
public function destroy(Request $request, string $uuid)
{
$vcard = $request->user()->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
return $vcard->delete();
return (new AdminVcardsStorageController)->destroy($request->user()->id, $uuid);
}
}

View file

@ -0,0 +1,41 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace App\Http\Controllers\Api\Admin;
use App\Account;
use App\Http\Controllers\Controller;
use App\Libraries\FlexisipConnector;
class DeviceController extends Controller
{
public function index(int $accountId)
{
$connector = new FlexisipConnector;
return $connector->getDevices(Account::findOrFail($accountId)->identifier);
}
public function destroy(int $accountId, string $uuid)
{
$connector = new FlexisipConnector;
return $connector->deleteDevice(Account::findOrFail($accountId)->identifier, $uuid);
}
}

View file

@ -0,0 +1,71 @@
<?php
namespace App\Http\Controllers\Api\Admin;
use App\Account;
use App\Http\Controllers\Controller;
use App\Rules\Vcard;
use App\VcardStorage;
use Illuminate\Http\Request;
use Sabre\VObject;
class VcardsStorageController extends Controller
{
public function index(int $accountId)
{
return Account::findOrFail($accountId)->vcardsStorage()->get()->keyBy('uuid');
}
public function show(int $accountId, string $uuid)
{
return Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
}
public function store(Request $request, int $accountId)
{
$request->validate([
'vcard' => ['required', new Vcard()]
]);
$vcardo = VObject\Reader::read($request->get('vcard'));
if (Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $vcardo->UID)->first()) {
abort(409, 'Vcard already exists');
}
$vcard = new VcardStorage();
$vcard->account_id = $accountId;
$vcard->uuid = $vcardo->UID;
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
$vcard->save();
return $vcard->vcard;
}
public function update(Request $request, int $accountId, string $uuid)
{
$request->validate([
'vcard' => ['required', new Vcard()]
]);
$vcardo = VObject\Reader::read($request->get('vcard'));
if ($vcardo->UID != $uuid) {
abort(422, 'UUID should be the same');
}
$vcard = Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
$vcard->save();
return $vcard->vcard;
}
public function destroy(int $accountId, string $uuid)
{
$vcard = Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
return $vcard->delete();
}
}

View file

@ -428,12 +428,14 @@ Return the updated account.
## Accounts devices
### `GET /accounts/me/devices`
### `GET /accounts/{id/me}/devices`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Return the user registered devices.
### `DELETE /accounts/me/devices/{uuid}`
### `DELETE /accounts/{id/me}/devices/{uuid}`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Remove one of the user registered devices.
@ -450,9 +452,10 @@ Return the user contacts.
Return a user contact.
## Account vCards storage
## vCards storage
### `POST /accounts/me/vcards-storage`
### `POST /accounts/{id/me}/vcards-storage`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Store a vCard.
@ -461,7 +464,8 @@ 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`.
### `PUT /accounts/me/vcards-storage/{uuid}`
### `PUT /accounts/{id/me}/vcards-storage/{uuid}`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Update a vCard.
@ -470,17 +474,20 @@ 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.
### `GET /accounts/me/vcards-storage`
### `GET /accounts/{id/me}/vcards-storage`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Return the list of stored vCards
### `GET /accounts/me/vcards-storage/{uuid}`
### `GET /accounts/{id/me}/vcards-storage/{uuid}`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Return a stored vCard
### `DELETE /accounts/me/vcards-storage/{uuid}`
### `DELETE /accounts/{id/me}/vcards-storage/{uuid}`
<span class="badge badge-warning">Admin</span>
<span class="badge badge-info">User</span>
Delete a stored vCard

View file

@ -24,6 +24,7 @@ use App\Http\Controllers\Api\Admin\AccountController as AdminAccountController;
use App\Http\Controllers\Api\Admin\AccountDictionaryController;
use App\Http\Controllers\Api\Admin\AccountTypeController;
use App\Http\Controllers\Api\Admin\ContactsListController;
use App\Http\Controllers\Api\Admin\VcardsStorageController as AdminVcardsStorageController;
use App\Http\Controllers\Api\StatisticsMessageController;
use App\Http\Controllers\Api\StatisticsCallController;
use Illuminate\Http\Request;
@ -108,6 +109,9 @@ Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blo
Route::get('{sip}/search', 'search');
Route::get('{email}/search-by-email', 'searchByEmail');
Route::get('{account_id}/devices', 'Api\Admin\DeviceController@index');
Route::delete('{account_id}/devices/{uuid}', 'Api\Admin\DeviceController@destroy');
Route::post('{account_id}/types/{type_id}', 'typeAdd');
Route::delete('{account_id}/types/{type_id}', 'typeRemove');
@ -125,6 +129,7 @@ Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blo
Route::apiResource('accounts/{id}/actions', AccountActionController::class);
Route::apiResource('account_types', AccountTypeController::class);
Route::apiResource('accounts/{account_id}/vcards-storage', AdminVcardsStorageController::class);
Route::apiResource('contacts_lists', ContactsListController::class);
Route::prefix('contacts_lists')->controller(ContactsListController::class)->group(function () {

View file

@ -22,21 +22,26 @@ namespace Tests\Feature;
use App\Account;
use Tests\TestCase;
class ApiAccountVcardsStorageTest extends TestCase
class ApiVcardsStorageTest extends TestCase
{
protected $route = '/api/accounts/me/vcards-storage';
protected $method = 'POST';
public function testCrud()
public function testAccountCrud()
{
$admin = Account::factory()->admin()->create();
$admin->generateApiKey();
$account = Account::factory()->create();
$account->generateApiKey();
$adminRoute = '/api/accounts/' . $account->id . '/vcards-storage';
$uid = 'urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6';
$lastVcard =
'BEGIN:VCARD
VERSION:4.0
FN:Simone Perreault
FN:Jhonny English
UID:' . $uid . '
END:VCARD
';
@ -47,6 +52,14 @@ VERSION:4.0
FN:Simone Perreault
UID:' . $uid2 . '
END:VCARD
';
$uid3 = 'urn:uuid:a5b33443-687c-4d19-bdd0-b30cf76bfc4d';
$thirdVcard =
'BEGIN:VCARD
VERSION:4.0
FN:Jean Jannot
UID:' . $uid3 . '
END:VCARD
';
// Missing vcard
@ -56,6 +69,13 @@ END:VCARD
])
->assertJsonValidationErrors(['vcard']);
// Admin vcard
$this->keyAuthenticated($admin)
->json($this->method, $adminRoute, [
'foo' => 'bar'
])
->assertJsonValidationErrors(['vcard']);
// Missing UID
$this->keyAuthenticated($account)
->json($this->method, $this->route, [
@ -77,6 +97,12 @@ UID:' . $uid . '
END:VCARD'
])->assertStatus(200);
// Admin create
$this->keyAuthenticated($admin)
->json($this->method, $adminRoute, [
'vcard' => $thirdVcard])
->assertStatus(200);
// Again...
$this->keyAuthenticated($account)
->json($this->method, $this->route, [
@ -101,6 +127,10 @@ END:VCARD'
'uuid' => $uid2
]);
$this->assertDatabaseHas('vcards_storage', [
'uuid' => $uid3
]);
// Update
$this->keyAuthenticated($account)
->json('PUT', $this->route . '/' . $uid, [
@ -135,6 +165,14 @@ END:VCARD'
'vcard' => $lastVcard
]);
// Admin get
$this->keyAuthenticated($admin)
->get($adminRoute . '/' . $uid)
->assertStatus(200)
->assertJson([
'vcard' => $lastVcard
]);
// Vcard format endpoints
/*$this->keyAuthenticated($account)
->get('vcards-storage')