diff --git a/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php
index 83a0918..616d50d 100644
--- a/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php
+++ b/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php
@@ -21,11 +21,13 @@ namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
+use Illuminate\Support\Str;
use Carbon\Carbon;
use App\Account;
use App\Password;
use App\Helpers\Utils;
+use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController;
class AccountController extends Controller
{
@@ -87,6 +89,11 @@ class AccountController extends Controller
$account->ip_address = $request->ip();
$account->creation_time = Carbon::now();
$account->user_agent = config('app.name');
+
+ if (!$request->has('activated') || !(bool)$request->has('activated')) {
+ $account->confirmation_key = Str::random(WebAuthenticateController::$emailCodeSize);
+ }
+
$account->save();
$password = new Password;
diff --git a/flexiapi/app/Http/Middleware/AuthenticateDigestOrKey.php b/flexiapi/app/Http/Middleware/AuthenticateDigestOrKey.php
index 8799651..fee442a 100644
--- a/flexiapi/app/Http/Middleware/AuthenticateDigestOrKey.php
+++ b/flexiapi/app/Http/Middleware/AuthenticateDigestOrKey.php
@@ -56,6 +56,11 @@ class AuthenticateDigestOrKey
->where('domain', $domain)
->firstOrFail();
+ // Check if activated
+ if (!$account->activated) {
+ return $this->generateUnauthorizedResponse($account);
+ }
+
// Key authentication
if ($request->header('x-api-key')) {
if ($account->apiKey
diff --git a/flexiapi/database/factories/AccountFactory.php b/flexiapi/database/factories/AccountFactory.php
index 5b75dd2..86b6459 100644
--- a/flexiapi/database/factories/AccountFactory.php
+++ b/flexiapi/database/factories/AccountFactory.php
@@ -36,6 +36,7 @@ class AccountFactory extends Factory
'user_agent' => $this->faker->userAgent,
'ip_address' => $this->faker->ipv4,
'creation_time' => $this->faker->dateTime,
+ 'activated' => true
];
}
}
diff --git a/flexiapi/resources/views/documentation.blade.php b/flexiapi/resources/views/documentation.blade.php
index 2e2adb4..e26f527 100644
--- a/flexiapi/resources/views/documentation.blade.php
+++ b/flexiapi/resources/views/documentation.blade.php
@@ -48,11 +48,13 @@ For the moment only DIGEST-MD5 and DIGEST-SHA-256 are supported through the auth
Endpoints
-Ping
+Public endpoints
GET /ping
Returns pong
+Accounts
+
GET /accounts/{sip}/info
Retrieve public information about the account.
Return 404 if the account doesn't exists.
@@ -73,19 +75,23 @@ For the moment only DIGEST-MD5 and DIGEST-SHA-256 are supported through the auth
code the PIN code
-Accounts (User)
+User authenticated endpoints
+Those endpoints are authenticated and requires an activated account.
GET /accounts/me
Retrieve the account information.
-POST /accounts/email/request
+DELETE /accounts/me
+Delete the account.
+
+POST /accounts/me/email/request
Change the account email. An email will be sent to the new email address to confirm the operation.
JSON parameters:
email the new email address
-POST /accounts/password
+POST /accounts/me/password
Change the account password.
JSON parameters:
@@ -94,19 +100,22 @@ For the moment only DIGEST-MD5 and DIGEST-SHA-256 are supported through the auth
password required, the new password
-Devices
+Devices
-GET /devices
+GET /accounts/me/devices
Return the user registered devices.
-DELETE /devices/{uuid}
+DELETE /accounts/me/devices/{uuid}
Remove one of the user registered devices.
-Accounts (Administrator)
+Admin endpoints
+
Those endpoints are authenticated and requires an admin account.
POST /accounts
To create an account directly from the API.
+If activated is set to false a random generated confirmation_key will be returned to allow further activation using the public endpoints.
+
JSON parameters:
username unique username, minimum 6 characters
diff --git a/flexiapi/routes/api.php b/flexiapi/routes/api.php
index 2101cae..f0fe3fb 100644
--- a/flexiapi/routes/api.php
+++ b/flexiapi/routes/api.php
@@ -34,11 +34,11 @@ Route::group(['middleware' => ['auth.digest_or_key']], function () {
Route::get('accounts/me', 'Api\AccountController@show');
Route::delete('accounts/me', 'Api\AccountController@delete');
- Route::get('devices', 'Api\DeviceController@index');
- Route::delete('devices/{uuid}', 'Api\DeviceController@destroy');
+ Route::get('accounts/me/devices', 'Api\DeviceController@index');
+ Route::delete('accounts/me/devices/{uuid}', 'Api\DeviceController@destroy');
- Route::post('accounts/email/request', 'Api\EmailController@requestUpdate');
- Route::post('accounts/password', 'Api\PasswordController@update');
+ Route::post('accounts/me/email/request', 'Api\EmailController@requestUpdate');
+ Route::post('accounts/me/password', 'Api\PasswordController@update');
Route::group(['middleware' => ['auth.admin']], function () {
Route::get('accounts/{id}/activate', 'Api\Admin\AccountController@activate');
diff --git a/flexiapi/tests/Feature/AccountApiTest.php b/flexiapi/tests/Feature/AccountApiTest.php
index 8376bab..094d58f 100644
--- a/flexiapi/tests/Feature/AccountApiTest.php
+++ b/flexiapi/tests/Feature/AccountApiTest.php
@@ -107,8 +107,10 @@ class AccountApiTest extends TestCase
'id' => 2,
'username' => $username,
'domain' => $domain,
- 'activated' => false,
+ 'activated' => false
]);
+
+ $this->assertFalse(empty($response1['confirmation_key']));
}
public function testUsernameNoDomain()
@@ -177,12 +179,16 @@ class AccountApiTest extends TestCase
'domain' => config('app.sip_domain'),
'activated' => true,
]);
+
+ $this->assertTrue(empty($response1['confirmation_key']));
}
public function testSimpleAccount()
{
$password = Password::factory()->create();
+ $password->account->activated = false;
$password->account->generateApiKey();
+ $password->account->save();
/**
* Public information
@@ -193,6 +199,9 @@ class AccountApiTest extends TestCase
'activated' => false
]);
+ $password->account->activated = true;
+ $password->account->save();
+
/**
* Retrieve the authenticated account
*/
@@ -201,7 +210,7 @@ class AccountApiTest extends TestCase
->assertStatus(200)
->assertJson([
'username' => $password->account->username,
- 'activated' => false
+ 'activated' => true
]);
/**
@@ -224,6 +233,7 @@ class AccountApiTest extends TestCase
$password = Password::factory()->create();
$password->account->generateApiKey();
$password->account->confirmation_key = $confirmationKey;
+ $password->account->activated = false;
$password->account->save();
$this->get($this->route.'/'.$password->account->identifier.'/info')
@@ -269,6 +279,7 @@ class AccountApiTest extends TestCase
$password = Password::factory()->create();
$password->account->generateApiKey();
$password->account->confirmation_key = $confirmationKey;
+ $password->account->activated = false;
$password->account->save();
$this->get($this->route.'/'.$password->account->identifier.'/info')
@@ -298,21 +309,21 @@ class AccountApiTest extends TestCase
// Bad email
$this->keyAuthenticated($password->account)
- ->json($this->method, $this->route.'/email/request', [
+ ->json($this->method, $this->route.'/me/email/request', [
'email' => 'gnap'
])
->assertStatus(422);
// Same email
$this->keyAuthenticated($password->account)
- ->json($this->method, $this->route.'/email/request', [
+ ->json($this->method, $this->route.'/me/email/request', [
'email' => $password->account->email
])
->assertStatus(422);
// Correct email
$this->keyAuthenticated($password->account)
- ->json($this->method, $this->route.'/email/request', [
+ ->json($this->method, $this->route.'/me/email/request', [
'email' => $newEmail
])
->assertStatus(200);
@@ -339,7 +350,7 @@ class AccountApiTest extends TestCase
// Wrong algorithm
$this->keyAuthenticated($account)
- ->json($this->method, $this->route.'/password', [
+ ->json($this->method, $this->route.'/me/password', [
'algorithm' => '123',
'password' => $password
])
@@ -350,7 +361,7 @@ class AccountApiTest extends TestCase
// Fresh password without an old one
$this->keyAuthenticated($account)
- ->json($this->method, $this->route.'/password', [
+ ->json($this->method, $this->route.'/me/password', [
'algorithm' => $algorithm,
'password' => $password
])
@@ -369,7 +380,7 @@ class AccountApiTest extends TestCase
// Set new password without old one
$this->keyAuthenticated($account)
- ->json($this->method, $this->route.'/password', [
+ ->json($this->method, $this->route.'/me/password', [
'algorithm' => $newAlgorithm,
'password' => $newPassword
])
@@ -380,7 +391,7 @@ class AccountApiTest extends TestCase
// Set the new password with incorrect old password
$response = $this->keyAuthenticated($account)
- ->json($this->method, $this->route.'/password', [
+ ->json($this->method, $this->route.'/me/password', [
'algorithm' => $newAlgorithm,
'old_password' => 'blabla',
'password' => $newPassword
@@ -392,7 +403,7 @@ class AccountApiTest extends TestCase
// Set the new password
$this->keyAuthenticated($account)
- ->json($this->method, $this->route.'/password', [
+ ->json($this->method, $this->route.'/me/password', [
'algorithm' => $newAlgorithm,
'old_password' => $password,
'password' => $newPassword
diff --git a/flexisip-account-manager.spec b/flexisip-account-manager.spec
index 8939faa..ecc10c3 100644
--- a/flexisip-account-manager.spec
+++ b/flexisip-account-manager.spec
@@ -8,7 +8,7 @@
#%define _datadir %{_datarootdir}
#%define _docdir %{_datadir}/doc
-%define build_number 41
+%define build_number 42
%define var_dir /var/opt/belledonne-communications
%define opt_dir /opt/belledonne-communications/share/flexisip-account-manager
%define env_file "$RPM_BUILD_ROOT/etc/flexisip-account-manager/flexiapi.env"