From e996a9827ccd34def7fc14081d2670fe309419f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Jaussoin?=
Date: Wed, 4 Oct 2023 15:31:11 +0200
Subject: [PATCH] Fix #125 Remove the External Accounts feature
---
README.md | 20 ----
flexiapi/app/Account.php | 31 ------
.../Commands/ExportToExternalAccounts.php | 51 ---------
.../Commands/GenerateExternalAccounts.php | 101 ------------------
.../Commands/ImportExternalAccounts.php | 68 ------------
flexiapi/app/ExternalAccount.php | 26 -----
flexiapi/app/Helpers/Utils.php | 22 +---
.../Account/ProvisioningController.php | 57 ----------
.../Controllers/Admin/AccountController.php | 14 +--
.../Admin/ContactsListContactController.php | 3 +-
flexiapi/config/app.php | 1 -
.../factories/ExternalAccountFactory.php | 25 -----
...04_132708_drop_external_accounts_table.php | 32 ++++++
.../account/documentation_markdown.blade.php | 8 --
.../views/admin/account/create_edit.blade.php | 12 ---
.../views/admin/account/index.blade.php | 3 -
.../documentation_markdown.blade.php | 1 -
flexiapi/routes/web.php | 2 -
.../tests/Feature/ApiExternalAccountTest.php | 84 ---------------
19 files changed, 35 insertions(+), 526 deletions(-)
delete mode 100644 flexiapi/app/Console/Commands/ExportToExternalAccounts.php
delete mode 100644 flexiapi/app/Console/Commands/GenerateExternalAccounts.php
delete mode 100644 flexiapi/app/Console/Commands/ImportExternalAccounts.php
delete mode 100644 flexiapi/app/ExternalAccount.php
delete mode 100644 flexiapi/database/factories/ExternalAccountFactory.php
create mode 100644 flexiapi/database/migrations/2023_10_04_132708_drop_external_accounts_table.php
delete mode 100644 flexiapi/tests/Feature/ApiExternalAccountTest.php
diff --git a/README.md b/README.md
index e101733..257a4b2 100644
--- a/README.md
+++ b/README.md
@@ -203,26 +203,6 @@ This command will set the admin role to any available Flexisip account. You need
Once one account is declared as administrator, you can directly configure the other ones using the web panel.
-### Generate External Accounts
-
-Generate `amount` accounts defined by the `group` label.
-The generated accounts will have a random username suffixed by the group name.
-
- accounts:generate-external {amount} {group}
-
-### Export External Accounts
-
-Export all the accounts defined by the `group` label.
-The command generates a JSON file containing the accounts ready to by imported as External Accounts in the current directory. A specific path can be defined using the `--o|output` optional parameter.
-
- accounts:export-to-externals {group} {--o|output=}
-
-### Import External Accounts
-
-Import accounts previously exported as a JSON file. Accounts previously imported will be skipped in the process.
-
- accounts:import-externals {file_path}
-
## Custom email templaces
Some email templates can be customized.
diff --git a/flexiapi/app/Account.php b/flexiapi/app/Account.php
index bd5e081..91d0fa8 100644
--- a/flexiapi/app/Account.php
+++ b/flexiapi/app/Account.php
@@ -77,21 +77,6 @@ class Account extends Authenticatable
$builder->where('domain', config('app.sip_domain'));
});
-
- /**
- * External account handling
- */
- static::creating(function ($account) {
- if (config('app.consume_external_account_on_create') && !getAvailableExternalAccount()) {
- abort(403, 'Accounts cannot be created on the server');
- }
- });
-
- static::created(function ($account) {
- if (config('app.consume_external_account_on_create')) {
- $account->attachExternalAccount();
- }
- });
}
public function scopeSip($query, string $sip)
@@ -138,11 +123,6 @@ class Account extends Authenticatable
return $this->hasOne(ApiKey::class);
}
- public function externalAccount()
- {
- return $this->hasOne(ExternalAccount::class);
- }
-
public function contacts()
{
return $this->belongsToMany(Account::class, 'contacts', 'account_id', 'contact_id');
@@ -284,17 +264,6 @@ class Account extends Authenticatable
return ($this->activationExpiration && $this->activationExpiration->isExpired());
}
- public function attachExternalAccount(): bool
- {
- $externalAccount = getAvailableExternalAccount();
-
- if (!$externalAccount) abort(403, 'No External Account left');
-
- $externalAccount->account_id = $this->id;
- $externalAccount->used = true;
- return $externalAccount->save();
- }
-
public function generateApiKey(): ApiKey
{
$this->apiKey()->delete();
diff --git a/flexiapi/app/Console/Commands/ExportToExternalAccounts.php b/flexiapi/app/Console/Commands/ExportToExternalAccounts.php
deleted file mode 100644
index 02467cc..0000000
--- a/flexiapi/app/Console/Commands/ExportToExternalAccounts.php
+++ /dev/null
@@ -1,51 +0,0 @@
-argument('group'))
- ->with('passwords')
- ->get();
-
- if ($accounts->count() == 0) {
- $this->error('Nothing to export');
- return;
- }
-
- $this->info('Exporting '.$accounts->count().' accounts');
-
- $data = [];
-
- foreach ($accounts as $account) {
- array_push($data, [
- 'username' => $account->username,
- 'domain' => $account->domain,
- 'group' => $account->group,
- 'password' => $account->passwords->first()->password,
- 'algorithm' => $account->passwords->first()->algorithm,
- ]);
- }
-
- file_put_contents(
- $this->option('output') ?? getcwd() . '/exported_accounts.json',
- json_encode($data)
- );
-
- $this->info('Exported');
- }
-}
diff --git a/flexiapi/app/Console/Commands/GenerateExternalAccounts.php b/flexiapi/app/Console/Commands/GenerateExternalAccounts.php
deleted file mode 100644
index 553d5c2..0000000
--- a/flexiapi/app/Console/Commands/GenerateExternalAccounts.php
+++ /dev/null
@@ -1,101 +0,0 @@
- $this->argument('amount'),
- 'group' => $this->argument('group'),
- ], [
- 'amount' => ['required', 'integer'],
- 'group' => ['required', 'alpha-dash', new NoUppercase]
- ]);
-
- if ($validator->fails()) {
- $this->info('External accounts no created:');
-
- foreach ($validator->errors()->all() as $error) {
- $this->error($error);
- }
-
- return 1;
- }
-
- $groups = Account::distinct('group')
- ->whereNotNull('group')
- ->get('group')
- ->pluck('group')
- ->toArray();
-
- if (!in_array($this->argument('group'), $groups)) {
- $this->info('Existing groups: '.implode(',', $groups));
-
- if (!$this->confirm('You are creating a new group of External Account, are you sure?', false)) {
- $this->info('Creation aborted');
- return 0;
- }
- }
-
- $accounts = collect();
- $passwords = collect();
- $algorithm = 'SHA-256';
-
- $i = 0;
-
- while ($i < $this->argument('amount')) {
- $account = new Account;
- $account->username = Str::random(12);
- $account->domain = config('app.sip_domain');
- $account->activated = 1;
- $account->ip_address = '127.0.0.1';
- $account->user_agent = 'External Account Generator';
- $account->group = $this->argument('group');
- $account->created_at = Carbon::now();
- $i++;
-
- $account->push($account->toArray());
- }
-
- Account::insert($accounts->toArray());
-
- $insertedAccounts = Account::where('group', $this->argument('group'))
- ->latest()
- ->take($this->argument('amount'))
- ->get();
-
- foreach ($insertedAccounts as $account) {
- $password = new Password;
- $password->account_id = $account->id;
- $password->password = bchash($account->username, $account->resolvedRealm, Str::random(6), $algorithm);
- $password->algorithm = $algorithm;
- $passwords->push($password->only(['account_id', 'password', 'algorithm']));
- }
-
- Password::insert($passwords->toArray());
-
- $this->info($this->argument('amount') . ' accounts created under the "' . $this->argument('group') . '" group');
-
- return 0;
- }
-}
diff --git a/flexiapi/app/Console/Commands/ImportExternalAccounts.php b/flexiapi/app/Console/Commands/ImportExternalAccounts.php
deleted file mode 100644
index 598cab1..0000000
--- a/flexiapi/app/Console/Commands/ImportExternalAccounts.php
+++ /dev/null
@@ -1,68 +0,0 @@
-argument('file_path'))) {
- $this->error('The file does not exists');
- return 1;
- }
-
- $json = json_decode(file_get_contents($this->argument('file_path')));
-
- if (empty($json)) {
- $this->error('Nothing to import or incorrect file');
- return 1;
- }
-
- $existingUsernames = ExternalAccount::select('username')
- ->from('external_accounts')
- ->get()
- ->pluck('username');
- $existingCounter = 0;
- $importedCounter = 0;
-
- $externalAccounts = collect();
- foreach ($json as $account) {
- if ($existingUsernames->contains($account->username)) {
- $existingCounter++;
- continue;
- }
-
- $externalAccount = new ExternalAccount;
- $externalAccount->username = $account->username;
- $externalAccount->domain = $account->domain;
- $externalAccount->group = $account->group;
- $externalAccount->password = $account->password;
- $externalAccount->algorithm = $account->algorithm;
-
- $externalAccounts->push($externalAccount->toArray());
- $importedCounter++;
- }
-
- ExternalAccount::insert($externalAccounts->toArray());
-
- $this->info($importedCounter . ' accounts imported');
-
- if ($existingCounter > 0) {
- $this->info($existingCounter . ' accounts already in the database');
- }
-
- return 0;
- }
-}
diff --git a/flexiapi/app/ExternalAccount.php b/flexiapi/app/ExternalAccount.php
deleted file mode 100644
index 70b4747..0000000
--- a/flexiapi/app/ExternalAccount.php
+++ /dev/null
@@ -1,26 +0,0 @@
-belongsTo('App\Account');
- }
-
- public function getIdentifierAttribute()
- {
- return $this->attributes['username'].'@'.$this->attributes['domain'];
- }
-
- public function getResolvedRealmAttribute()
- {
- return $this->attributes['domain'];
- }
-}
diff --git a/flexiapi/app/Helpers/Utils.php b/flexiapi/app/Helpers/Utils.php
index 99a2f8a..cca810a 100644
--- a/flexiapi/app/Helpers/Utils.php
+++ b/flexiapi/app/Helpers/Utils.php
@@ -21,7 +21,6 @@ use Illuminate\Support\Str;
use App\Account;
use App\DigestNonce;
-use App\ExternalAccount;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use League\CommonMark\CommonMarkConverter;
@@ -87,28 +86,9 @@ function markdownDocumentationView($view): string
);
}
-function getAvailableExternalAccount(): ?ExternalAccount
-{
- if (Schema::hasTable('external_accounts')) {
- return ExternalAccount::where('used', false)
- ->where('account_id', null)
- ->first();
- }
-
- return null;
-}
-
function publicRegistrationEnabled(): bool
{
- if (config('app.public_registration')) {
- if (config('app.consume_external_account_on_create')) {
- return (bool)getAvailableExternalAccount();
- }
-
- return true;
- }
-
- return false;
+ return (config('app.public_registration'));
}
function isRegularExpression($string): bool
diff --git a/flexiapi/app/Http/Controllers/Account/ProvisioningController.php b/flexiapi/app/Http/Controllers/Account/ProvisioningController.php
index f4cb89e..d533979 100644
--- a/flexiapi/app/Http/Controllers/Account/ProvisioningController.php
+++ b/flexiapi/app/Http/Controllers/Account/ProvisioningController.php
@@ -182,8 +182,6 @@ class ProvisioningController extends Controller
$config->appendChild($section);
if ($account) {
- $externalAccount = $account->externalAccount;
-
$section = $dom->createElement('section');
$section->setAttribute('name', 'proxy_' . $proxyConfigIndex);
@@ -204,12 +202,6 @@ class ProvisioningController extends Controller
provisioningProxyHook($section, $request, $account);
}
- if ($externalAccount) {
- $entry = $dom->createElement('entry', 'external_account');
- $entry->setAttribute('name', 'depends_on');
- $section->appendChild($entry);
- }
-
$config->appendChild($section);
$passwords = $account->passwords()->get();
@@ -249,55 +241,6 @@ class ProvisioningController extends Controller
}
$proxyConfigIndex++;
-
- // External Account handling
- if ($externalAccount) {
- $section = $dom->createElement('section');
- $section->setAttribute('name', 'proxy_' . $proxyConfigIndex);
-
- $entry = $dom->createElement('entry', 'identifier . '>');
- $entry->setAttribute('name', 'reg_identity');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', 1);
- $entry->setAttribute('name', 'reg_sendregister');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', 'push_notification');
- $entry->setAttribute('name', 'refkey');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', 'external_account');
- $entry->setAttribute('name', 'idkey');
- $section->appendChild($entry);
-
- $config->appendChild($section);
-
- $section = $dom->createElement('section');
- $section->setAttribute('name', 'auth_info_' . $authInfoIndex);
-
- $entry = $dom->createElement('entry', $externalAccount->username);
- $entry->setAttribute('name', 'username');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', $externalAccount->domain);
- $entry->setAttribute('name', 'domain');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', $externalAccount->password);
- $entry->setAttribute('name', 'ha1');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', $externalAccount->resolvedRealm);
- $entry->setAttribute('name', 'realm');
- $section->appendChild($entry);
-
- $entry = $dom->createElement('entry', $externalAccount->algorithm);
- $entry->setAttribute('name', 'algorithm');
- $section->appendChild($entry);
-
- $config->appendChild($section);
- }
}
// Complete the section with the Auth hook
diff --git a/flexiapi/app/Http/Controllers/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Admin/AccountController.php
index b9319b6..386a051 100644
--- a/flexiapi/app/Http/Controllers/Admin/AccountController.php
+++ b/flexiapi/app/Http/Controllers/Admin/AccountController.php
@@ -26,7 +26,6 @@ use Carbon\Carbon;
use App\Account;
use App\ContactsList;
-use App\ExternalAccount;
use App\Http\Requests\CreateAccountRequest;
use App\Http\Requests\UpdateAccountRequest;
@@ -39,7 +38,7 @@ class AccountController extends Controller
'order_sort' => 'in:asc,desc',
]);
- $accounts = Account::with('externalAccount', 'contactsLists')
+ $accounts = Account::with('contactsLists')
->orderBy($request->get('order_by', 'updated_at'), $request->get('order_sort', 'desc'));
if ($request->has('search')) {
@@ -110,7 +109,6 @@ class AccountController extends Controller
return view('admin.account.create_edit', [
'account' => Account::findOrFail($id),
'protocols' => [null => 'None'] + Account::$dtmfProtocols,
- 'external_accounts_count' => ExternalAccount::where('used', false)->count(),
'contacts_lists' => ContactsList::whereNotIn('id', function ($query) use ($id) {
$query->select('contacts_list_id')
->from('account_contacts_list')
@@ -145,16 +143,6 @@ class AccountController extends Controller
return redirect()->route('admin.account.edit', $id);
}
- public function attachExternalAccount(int $id)
- {
- $account = Account::findOrFail($id);
- $account->attachExternalAccount();
-
- Log::channel('events')->info('Web Admin: ExternalAccount attached', ['id' => $account->identifier]);
-
- return redirect()->back();
- }
-
public function provision(int $id)
{
$account = Account::findOrFail($id);
diff --git a/flexiapi/app/Http/Controllers/Admin/ContactsListContactController.php b/flexiapi/app/Http/Controllers/Admin/ContactsListContactController.php
index a8bb18f..5d1fb7a 100644
--- a/flexiapi/app/Http/Controllers/Admin/ContactsListContactController.php
+++ b/flexiapi/app/Http/Controllers/Admin/ContactsListContactController.php
@@ -28,8 +28,7 @@ class ContactsListContactController extends Controller
{
public function add(Request $request, int $contactsListId)
{
- $accounts = Account::orderBy('updated_at', $request->get('updated_at_order', 'desc'))
- ->with('externalAccount');
+ $accounts = Account::orderBy('updated_at', $request->get('updated_at_order', 'desc'));
if ($request->has('search')) {
$accounts = $accounts->where('username', 'like', '%' . $request->get('search') . '%');
diff --git a/flexiapi/config/app.php b/flexiapi/config/app.php
index c56dae2..45c91a1 100644
--- a/flexiapi/config/app.php
+++ b/flexiapi/config/app.php
@@ -29,7 +29,6 @@ return [
'transport_protocol_text' => env('ACCOUNT_TRANSPORT_PROTOCOL_TEXT', 'TLS (recommended), TCP or UDP'),
'account_email_unique' => env('ACCOUNT_EMAIL_UNIQUE', false),
- 'consume_external_account_on_create' => env('ACCOUNT_CONSUME_EXTERNAL_ACCOUNT_ON_CREATE', false),
'blacklisted_usernames' => env('ACCOUNT_BLACKLISTED_USERNAMES', ''),
'account_username_regex' => env('ACCOUNT_USERNAME_REGEX', '^[a-z0-9+_.-]*$'),
diff --git a/flexiapi/database/factories/ExternalAccountFactory.php b/flexiapi/database/factories/ExternalAccountFactory.php
deleted file mode 100644
index d4cbf48..0000000
--- a/flexiapi/database/factories/ExternalAccountFactory.php
+++ /dev/null
@@ -1,25 +0,0 @@
-faker->username;
- $realm = config('app.realm') ?? config('app.sip_domain');
-
- return [
- 'username' => $username,
- 'domain' => config('app.sip_domain'),
- 'group' => 'test',
- 'password' => hash('sha256', $username.':'.$realm.':testtest'),
- 'algorithm' => 'SHA-256',
- ];
- }
-}
diff --git a/flexiapi/database/migrations/2023_10_04_132708_drop_external_accounts_table.php b/flexiapi/database/migrations/2023_10_04_132708_drop_external_accounts_table.php
new file mode 100644
index 0000000..cc4879a
--- /dev/null
+++ b/flexiapi/database/migrations/2023_10_04_132708_drop_external_accounts_table.php
@@ -0,0 +1,32 @@
+id();
+ $table->string('username', 64);
+ $table->string('domain', 64);
+ $table->string('group', 16);
+ $table->string('password', 255);
+ $table->string('algorithm', 10)->default('MD5');
+ $table->boolean('used')->default(false);
+
+ $table->integer('account_id')->unsigned()->nullable();
+ $table->foreign('account_id')->references('id')
+ ->on('accounts')->onDelete('set null');
+
+ $table->timestamps();
+ });
+ }
+};
diff --git a/flexiapi/resources/views/account/documentation_markdown.blade.php b/flexiapi/resources/views/account/documentation_markdown.blade.php
index 86d0e67..f0076e7 100644
--- a/flexiapi/resources/views/account/documentation_markdown.blade.php
+++ b/flexiapi/resources/views/account/documentation_markdown.blade.php
@@ -100,14 +100,6 @@ Administrators can create and edit accounts directly from the admin panel. Durin
The deletion of an account is definitive, all the database related data (password, aliases…) will be destroyed after the deletion.
-### Attach the account to an External Account
-
-@if (config('app.consume_external_account_on_create') == false)
-*The feature is not enabled on this instance.*
-@endif
-
-It is possible to import external accounts in the application. If this feature is enabled those External Accounts can be attached during the account creation process or afterward using the Account page dedicated button.
-
### Create, edit and delete account types
An adminisator can create, edit and delete account types. Those can be used to categorize accounts in clients, they are often used for Internet of Things related devices.
diff --git a/flexiapi/resources/views/admin/account/create_edit.blade.php b/flexiapi/resources/views/admin/account/create_edit.blade.php
index 6146b85..c83f0a4 100644
--- a/flexiapi/resources/views/admin/account/create_edit.blade.php
+++ b/flexiapi/resources/views/admin/account/create_edit.blade.php
@@ -203,18 +203,6 @@
@endif
- External Account
-
- @if ($account->externalAccount)
-
- Identifier: {{ $account->externalAccount->identifier }}
-
- @else
- Attach an External Account
- ({{ $external_accounts_count }} left)
- @endif
-
Actions
@if ($account->dtmf_protocol)
diff --git a/flexiapi/resources/views/admin/account/index.blade.php b/flexiapi/resources/views/admin/account/index.blade.php
index 379abcf..dd3385c 100644
--- a/flexiapi/resources/views/admin/account/index.blade.php
+++ b/flexiapi/resources/views/admin/account/index.blade.php
@@ -98,9 +98,6 @@
@endif
- @if ($account->externalAccount)
- EA
- @endif
@if ($account->email)
Email
@endif
diff --git a/flexiapi/resources/views/provisioning/documentation_markdown.blade.php b/flexiapi/resources/views/provisioning/documentation_markdown.blade.php
index de7df5d..4f633d9 100644
--- a/flexiapi/resources/views/provisioning/documentation_markdown.blade.php
+++ b/flexiapi/resources/views/provisioning/documentation_markdown.blade.php
@@ -21,7 +21,6 @@ The general idea is to allow the clients to access a unique URL returning a cust
* Public Expose the linphonerc INI file configuration
* User Inject the authentication information to allow the application to authenticate on the server directly if a valid account is detected using the `provisioning` token
- * A similar information is also injected if an external account is linked to the main one, the application will then be able to authenticate on both accounts at the same time
* Public User Using __Custom Hooks__ an admin is also able to have access to the authenticated User internal object and inject custom XML during the provisioning. See the specific section in the `README.md` to learn more about that feature.
### Features
diff --git a/flexiapi/routes/web.php b/flexiapi/routes/web.php
index 2d03c18..fa5b68a 100644
--- a/flexiapi/routes/web.php
+++ b/flexiapi/routes/web.php
@@ -138,8 +138,6 @@ if (config('app.web_panel')) {
Route::name('account.')->prefix('accounts')->group(function () {
Route::controller(AdminAccountController::class)->group(function () {
- Route::get('{account_id}/external_account/attach', 'attachExternalAccount')->name('external_account.attach');
-
Route::get('{account_id}/provision', 'provision')->name('provision');
Route::get('create', 'create')->name('create');
diff --git a/flexiapi/tests/Feature/ApiExternalAccountTest.php b/flexiapi/tests/Feature/ApiExternalAccountTest.php
deleted file mode 100644
index 746bdcd..0000000
--- a/flexiapi/tests/Feature/ApiExternalAccountTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-.
-*/
-
-namespace Tests\Feature;
-
-use App\Admin;
-use App\Account;
-use App\ExternalAccount;
-use Illuminate\Foundation\Testing\RefreshDatabase;
-use Tests\TestCase;
-
-class ApiExternalAccountTest extends TestCase
-{
- use RefreshDatabase;
-
- protected $route = '/api/accounts';
- protected $provisioningRoute = '/provisioning/me';
- protected $method = 'POST';
-
- public function testExternalAccountAttachOnCreate()
- {
- $admin = Admin::factory()->create();
- $password = $admin->account->passwords()->first();
- $password->account->generateApiKey();
- $password->account->save();
-
- config()->set('app.consume_external_account_on_create', true);
-
- // Seed an ExternalAccount
- $externalAccount = ExternalAccount::factory()->create();
- $externalAccount->save();
-
- $response = $this->keyAuthenticated($password->account)
- ->json($this->method, $this->route, [
- 'username' => 'test',
- 'domain' => 'example.com',
- 'algorithm' => 'SHA-256',
- 'password' => '123456',
- 'activated' => true,
- ]);
-
- $response->assertStatus(200);
-
- // No ExternalAccount left
- $response = $this->keyAuthenticated($password->account)
- ->json($this->method, $this->route, [
- 'username' => 'test2',
- 'domain' => 'example.com',
- 'algorithm' => 'SHA-256',
- 'password' => '123456',
- ]);
-
- $response->assertStatus(403);
-
- $createdAccount = Account::where('username', 'test')->first();
- $createdAccount->generateApiKey();
- $createdAccount->save();
-
- $response = $this->keyAuthenticated($createdAccount)
- ->get($this->provisioningRoute)
- ->assertStatus(200)
- ->assertHeader('Content-Type', 'application/xml')
- ->assertSee($externalAccount->identifier)
- ->assertSee('ha1')
- ->assertSee('idkey')
- ->assertSee('depends_on');
- }
-}
|