diff --git a/flexiapi/app/Http/Controllers/Api/Account/StatisticsCallController.php b/flexiapi/app/Http/Controllers/Api/Account/StatisticsCallController.php
new file mode 100644
index 0000000..94e9e90
--- /dev/null
+++ b/flexiapi/app/Http/Controllers/Api/Account/StatisticsCallController.php
@@ -0,0 +1,32 @@
+.
+*/
+
+namespace App\Http\Controllers\Api\Account;
+
+use App\Http\Controllers\Controller;
+use Illuminate\Http\Request;
+use App\Http\Controllers\Api\Admin\StatisticsCallController as AdminStatisticsCallController;
+
+class StatisticsCallController extends Controller
+{
+ public function index(Request $request)
+ {
+ return (new AdminStatisticsCallController)->index($request, $request->user()->id);
+ }
+}
diff --git a/flexiapi/app/Http/Controllers/Api/StatisticsCallController.php b/flexiapi/app/Http/Controllers/Api/Admin/StatisticsCallController.php
similarity index 85%
rename from flexiapi/app/Http/Controllers/Api/StatisticsCallController.php
rename to flexiapi/app/Http/Controllers/Api/Admin/StatisticsCallController.php
index c38b316..63f85ef 100644
--- a/flexiapi/app/Http/Controllers/Api/StatisticsCallController.php
+++ b/flexiapi/app/Http/Controllers/Api/Admin/StatisticsCallController.php
@@ -17,8 +17,9 @@
along with this program. If not, see .
*/
-namespace App\Http\Controllers\Api;
+namespace App\Http\Controllers\Api\Admin;
+use App\Account;
use App\Http\Controllers\Controller;
use App\StatisticsCall;
use App\StatisticsCallDevice;
@@ -27,6 +28,22 @@ use Illuminate\Support\Facades\Log;
class StatisticsCallController extends Controller
{
+ public function index(Request $request, ?int $accountId)
+ {
+ $account = Account::findOrFail($accountId);
+
+ $toQuery = StatisticsCall::query()
+ ->where('to_domain', $account->domain)
+ ->where('to_username', $account->username);
+ $calls = StatisticsCall::where('from_domain', $account->domain)
+ ->where('from_username', $account->username);
+
+ return $calls->with('devices')
+ ->union($toQuery)
+ ->orderBy('initiated_at', 'desc')
+ ->paginate(30);
+ }
+
public function store(Request $request)
{
$request->validate([
diff --git a/flexiapi/app/StatisticsCall.php b/flexiapi/app/StatisticsCall.php
index cb9b960..2198e66 100644
--- a/flexiapi/app/StatisticsCall.php
+++ b/flexiapi/app/StatisticsCall.php
@@ -34,6 +34,11 @@ class StatisticsCall extends Model
protected $casts = ['initiated_at' => 'datetime', 'ended_at' => 'datetime'];
protected $keyType = 'string';
+ public function devices()
+ {
+ return $this->hasMany(StatisticsCallDevice::class, 'call_id', 'id');
+ }
+
public function accountFrom()
{
return $this->belongsTo(Account::class, ['username', 'domain'], ['to_username', 'to_domain']);
diff --git a/flexiapi/app/StatisticsCallDevice.php b/flexiapi/app/StatisticsCallDevice.php
index 6717df2..8a220c0 100644
--- a/flexiapi/app/StatisticsCallDevice.php
+++ b/flexiapi/app/StatisticsCallDevice.php
@@ -31,6 +31,6 @@ class StatisticsCallDevice extends Model
public function call()
{
- return $this->hasOne(StatisticsCall::class, 'id', 'call_id');
+ return $this->belongsTo(StatisticsCall::class, 'id', 'call_id');
}
}
diff --git a/flexiapi/resources/views/api/documentation/statistics.blade.php b/flexiapi/resources/views/api/documentation/statistics.blade.php
index 7e31f22..e614244 100644
--- a/flexiapi/resources/views/api/documentation/statistics.blade.php
+++ b/flexiapi/resources/views/api/documentation/statistics.blade.php
@@ -2,6 +2,12 @@
FlexiAPI can record logs generated by the FlexiSIP server and compile them into statistics.
+### `GET /api/accounts/{id/me}/statistics/calls`
+Admin
+User
+
+Retrieve all the calls of an account, ordered by most recent first and paginated with their related `devices`.
+
### `POST /statistics/messages`
Admin
diff --git a/flexiapi/routes/api.php b/flexiapi/routes/api.php
index d95270a..5bb7fdc 100644
--- a/flexiapi/routes/api.php
+++ b/flexiapi/routes/api.php
@@ -41,6 +41,7 @@ use App\Http\Controllers\Api\Admin\Account\CreationTokenController as AdminCreat
use App\Http\Controllers\Api\Admin\Account\DictionaryController;
use App\Http\Controllers\Api\Admin\Account\TypeController;
use App\Http\Controllers\Api\Admin\Account\VoicemailController as AdminVoicemailController;
+use App\Http\Controllers\Api\Account\StatisticsCallController;
use App\Http\Controllers\Api\Admin\AccountController as AdminAccountController;
use App\Http\Controllers\Api\Admin\ExternalAccountController;
use App\Http\Controllers\Api\Admin\MessageController;
@@ -49,11 +50,11 @@ use App\Http\Controllers\Api\Admin\Space\CardDavServerController;
use App\Http\Controllers\Api\Admin\Space\ContactsListController;
use App\Http\Controllers\Api\Admin\Space\EmailServerController;
use App\Http\Controllers\Api\Admin\SpaceController;
+use App\Http\Controllers\Api\Admin\StatisticsCallController as AdminStatisticsCallController;
use App\Http\Controllers\Api\Admin\VcardsStorageController as AdminVcardsStorageController;
use App\Http\Controllers\Api\ApiController;
use App\Http\Controllers\Api\PhoneCountryController;
use App\Http\Controllers\Api\PingController;
-use App\Http\Controllers\Api\StatisticsCallController;
use App\Http\Controllers\Api\StatisticsMessageController;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Http\Request;
@@ -114,6 +115,10 @@ Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blo
Route::apiResource('vcards-storage', VcardsStorageController::class);
Route::apiResource('voicemails', VoicemailController::class, ['only' => ['index', 'show', 'store', 'destroy']]);
Route::apiResource('call_forwardings', CallForwardingController::class);
+
+ Route::prefix('statistics/calls')->controller(\App\Http\Controllers\Api\Account\StatisticsCallController::class)->group(function () {
+ Route::get('/', 'index');
+ });
});
Route::group(['middleware' => ['auth.admin']], function () {
@@ -208,12 +213,16 @@ Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blo
Route::delete('/', 'destroy');
});
+ Route::prefix('accounts/{id}/statistics/calls')->controller(AdminStatisticsCallController::class)->group(function () {
+ Route::get('/', 'index');
+ });
+
Route::prefix('statistics/messages')->controller(StatisticsMessageController::class)->group(function () {
Route::post('/', 'store');
Route::patch('{message_id}/to/{to}/devices/{device_id}', 'storeDevice');
});
- Route::prefix('statistics/calls')->controller(StatisticsCallController::class)->group(function () {
+ Route::prefix('statistics/calls')->controller(AdminStatisticsCallController::class)->group(function () {
Route::post('/', 'store');
Route::patch('{call_id}', 'update');
Route::patch('{call_id}/devices/{device_id}', 'storeDevice');
diff --git a/flexiapi/tests/Feature/ApiStatisticsTest.php b/flexiapi/tests/Feature/ApiStatisticsTest.php
index 93a0498..241daad 100644
--- a/flexiapi/tests/Feature/ApiStatisticsTest.php
+++ b/flexiapi/tests/Feature/ApiStatisticsTest.php
@@ -31,6 +31,7 @@ class ApiStatisticsTest extends TestCase
protected $routeMessages = '/api/statistics/messages';
protected $routeCalls = '/api/statistics/calls';
+ protected $routeAccountCalls = '/api/accounts/me/statistics/calls';
public function testMessages()
{
@@ -140,6 +141,9 @@ class ApiStatisticsTest extends TestCase
'username' => $fromUsername,
'domain' => $fromDomain,
]);
+ $account->generateUserApiKey();
+
+ $routeAdminCalls = '/api/accounts/' . $account->id . '/statistics/calls';
$this->keyAuthenticated($admin)
->json('POST', $this->routeCalls, [
@@ -150,9 +154,19 @@ class ApiStatisticsTest extends TestCase
])
->assertStatus(200);
- $this->assertDatabaseHas('statistics_calls', [
- 'id' => $id
- ]);
+ $this->keyAuthenticated($admin)
+ ->get($routeAdminCalls)
+ ->assertStatus(200)
+ ->assertJsonFragment([
+ 'id' => $id
+ ]);
+
+ $this->keyAuthenticated($account)
+ ->get($this->routeAccountCalls)
+ ->assertStatus(200)
+ ->assertJsonFragment([
+ 'id' => $id
+ ]);
$this->keyAuthenticated($admin)
->json('POST', $this->routeCalls, [
@@ -207,6 +221,13 @@ class ApiStatisticsTest extends TestCase
$this->assertSame(1, StatisticsCallDevice::count());
+ $this->keyAuthenticated($admin)
+ ->get($routeAdminCalls)
+ ->assertStatus(200)
+ ->assertJsonFragment([
+ 'device_id' => $device
+ ]);
+
// Update
$endedAt = $this->faker->iso8601();