diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ff6883..054408e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ v1.5 - Fix #133 Make the MySQL connection unstrict - Fix #132 Move the provisioning_tokens and recovery_codes to dedicated table - Fix #130 Drop the group column in the Accounts table +- Fix FLEXIAPI-132 Refactor the Provisioning to remove proxy_default_values +- Fix FLEXIAPI-134 Add a system to detect and block abusive accounts v1.4.4 ------ diff --git a/flexiapi/.env.example b/flexiapi/.env.example index 5e6edd5..0876614 100644 --- a/flexiapi/.env.example +++ b/flexiapi/.env.example @@ -33,6 +33,10 @@ ACCOUNT_PROVISIONING_RC_FILE= ACCOUNT_PROVISIONING_OVERWRITE_ALL= ACCOUNT_PROVISIONING_USE_X_LINPHONE_PROVISIONING_HEADER=true +# Blocking service +BLOCKING_TIME_PERIOD_CHECK=30 # Time span on which the blocking service will proceed, in minutes +BLOCKING_AMOUNT_EVENTS_AUTHORIZED_DURING_PERIOD=5 # Amount of account events authorized during this period + # Instance specific parameters INSTANCE_COPYRIGHT= # Simple text displayed in the page footer INSTANCE_INTRO_REGISTRATION= # Markdown text displayed in the home page diff --git a/flexiapi/app/Http/Controllers/Account/AccountController.php b/flexiapi/app/Http/Controllers/Account/AccountController.php index 4eedec1..1ee14f6 100644 --- a/flexiapi/app/Http/Controllers/Account/AccountController.php +++ b/flexiapi/app/Http/Controllers/Account/AccountController.php @@ -36,6 +36,11 @@ class AccountController extends Controller ]); } + public function blocked(Request $request) + { + return view('account.blocked'); + } + public function panel(Request $request) { return view('account.dashboard', [ @@ -47,7 +52,7 @@ class AccountController extends Controller { $account = (new AccountService(api: false))->store($request); - $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']); + $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha' : '']); Auth::login($account); @@ -74,7 +79,7 @@ class AccountController extends Controller $request->validate(['identifier' => 'required|same:identifier_confirm']); if (!$request->user()->hasTombstone()) { - $tombstone = new AccountTombstone; + $tombstone = new AccountTombstone(); $tombstone->username = $request->user()->username; $tombstone->domain = $request->user()->domain; $tombstone->save(); diff --git a/flexiapi/app/Http/Controllers/Account/EmailController.php b/flexiapi/app/Http/Controllers/Account/EmailController.php index 904de2d..44e962c 100644 --- a/flexiapi/app/Http/Controllers/Account/EmailController.php +++ b/flexiapi/app/Http/Controllers/Account/EmailController.php @@ -36,6 +36,10 @@ class EmailController extends Controller { $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']); + if ((new BlockingService($request->user()))->checkBlock()) { + return redirect()->route('account.blocked'); + } + (new AccountService(api: false))->requestEmailChange($request); return redirect()->route('account.email.validate'); diff --git a/flexiapi/app/Http/Controllers/Account/PhoneController.php b/flexiapi/app/Http/Controllers/Account/PhoneController.php index 3b6b12c..669baef 100644 --- a/flexiapi/app/Http/Controllers/Account/PhoneController.php +++ b/flexiapi/app/Http/Controllers/Account/PhoneController.php @@ -36,6 +36,10 @@ class PhoneController extends Controller { $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']); + if ((new BlockingService($request->user()))->checkBlock()) { + return redirect()->route('account.blocked'); + } + (new AccountService(api: false))->requestPhoneChange($request); return redirect()->route('account.phone.validate'); diff --git a/flexiapi/app/Http/Controllers/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Admin/AccountController.php index 39f2371..f7e3a15 100644 --- a/flexiapi/app/Http/Controllers/Admin/AccountController.php +++ b/flexiapi/app/Http/Controllers/Admin/AccountController.php @@ -95,6 +95,7 @@ class AccountController extends Controller $account->user_agent = config('app.name'); $account->dtmf_protocol = $request->get('dtmf_protocol'); $account->activated = $request->get('activated') == 'true'; + $account->blocked = $request->get('blocked') == 'true'; $account->save(); $account->phone = $request->get('phone'); @@ -132,6 +133,7 @@ class AccountController extends Controller $account->display_name = $request->get('display_name'); $account->dtmf_protocol = $request->get('dtmf_protocol'); $account->activated = $request->get('activated') == 'true'; + $account->blocked = $request->get('blocked') == 'true'; $account->save(); $account->phone = $request->get('phone'); diff --git a/flexiapi/app/Http/Controllers/Api/Account/EmailController.php b/flexiapi/app/Http/Controllers/Api/Account/EmailController.php index bb78298..d61a92c 100644 --- a/flexiapi/app/Http/Controllers/Api/Account/EmailController.php +++ b/flexiapi/app/Http/Controllers/Api/Account/EmailController.php @@ -21,12 +21,18 @@ namespace App\Http\Controllers\Api\Account; use App\Http\Controllers\Controller; use App\Services\AccountService; +use App\Services\BlockingService; + use Illuminate\Http\Request; class EmailController extends Controller { public function requestUpdate(Request $request) { + if ((new BlockingService($request->user()))->checkBlock()) { + return abort(403, 'Account blocked'); + } + (new AccountService)->requestEmailChange($request); } } diff --git a/flexiapi/app/Http/Controllers/Api/Account/PhoneController.php b/flexiapi/app/Http/Controllers/Api/Account/PhoneController.php index beb81fc..e0bd025 100644 --- a/flexiapi/app/Http/Controllers/Api/Account/PhoneController.php +++ b/flexiapi/app/Http/Controllers/Api/Account/PhoneController.php @@ -19,15 +19,20 @@ namespace App\Http\Controllers\Api\Account; -use Illuminate\Http\Request; use App\Http\Controllers\Controller; - use App\Services\AccountService; +use App\Services\BlockingService; + +use Illuminate\Http\Request; class PhoneController extends Controller { public function requestUpdate(Request $request) { + if ((new BlockingService($request->user()))->checkBlock()) { + return abort(403, 'Account blocked'); + } + return (new AccountService)->requestPhoneChange($request); } diff --git a/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php index e3635a6..2f269e3 100644 --- a/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php +++ b/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php @@ -96,6 +96,28 @@ class AccountController extends Controller return $account; } + public function block(int $id) + { + $account = Account::findOrFail($id); + $account->blocked = true; + $account->save(); + + Log::channel('events')->info('API Admin: Account blocked', ['id' => $account->identifier]); + + return $account; + } + + public function unblock(int $id) + { + $account = Account::findOrFail($id); + $account->blocked = false; + $account->save(); + + Log::channel('events')->info('API Admin: Account unblocked', ['id' => $account->identifier]); + + return $account; + } + public function provision(int $id) { $account = Account::findOrFail($id); diff --git a/flexiapi/app/Http/Kernel.php b/flexiapi/app/Http/Kernel.php index d7a3602..9530eed 100644 --- a/flexiapi/app/Http/Kernel.php +++ b/flexiapi/app/Http/Kernel.php @@ -72,6 +72,7 @@ class Kernel extends HttpKernel 'auth.admin' => \App\Http\Middleware\AuthenticateAdmin::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'auth.digest_or_key' => \App\Http\Middleware\AuthenticateDigestOrKey::class, + 'auth.check_blocked' => \App\Http\Middleware\CheckBlocked::class, 'web_panel_enabled' => \App\Http\Middleware\IsWebPanelEnabled::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, diff --git a/flexiapi/app/Http/Middleware/CheckBlocked.php b/flexiapi/app/Http/Middleware/CheckBlocked.php new file mode 100644 index 0000000..098b1ff --- /dev/null +++ b/flexiapi/app/Http/Middleware/CheckBlocked.php @@ -0,0 +1,35 @@ +. +*/ + +namespace App\Http\Middleware; + +use Closure; +use Illuminate\Http\Request; + +class CheckBlocked +{ + public function handle(Request $request, Closure $next) + { + if ($request->user()->blocked) { + abort(403, 'Account blocked'); + } + + return $next($request); + } +} diff --git a/flexiapi/app/Services/BlockingService.php b/flexiapi/app/Services/BlockingService.php new file mode 100644 index 0000000..b391a54 --- /dev/null +++ b/flexiapi/app/Services/BlockingService.php @@ -0,0 +1,86 @@ +. +*/ + +namespace App\Services; + +use App\Account; + +use Carbon\Carbon; + +class BlockingService +{ + public function __construct(public Account $account) + { + } + + public function checkBlock(): bool + { + if ($this->account->blocked) { + return true; + } + + $isBlockable = $this->isBlockable(); + + if ($isBlockable) { + $this->account->blocked = true; + $this->account->save(); + } + + return $isBlockable; + } + + public function isBlockable(): bool + { + if (config('app.blocking_amount_events_authorized_during_period') == 0) { + return false; + } + + return $this->countEvents() >= config('app.blocking_amount_events_authorized_during_period'); + } + + private function countEvents(): int + { + $events = 0; + + $events += $this->account->recoveryCodes()->where( + 'created_at', + '>', + Carbon::now()->subMinutes(config('app.blocking_time_period_check'))->toDateTimeString() + )->count(); + + $events += $this->account->phoneChangeCodes()->where( + 'created_at', + '>', + Carbon::now()->subMinutes(config('app.blocking_time_period_check'))->toDateTimeString() + )->count(); + + $events += $this->account->emailChangeCodes()->where( + 'created_at', + '>', + Carbon::now()->subMinutes(config('app.blocking_time_period_check'))->toDateTimeString() + )->count(); + + // Deprecated, also detect if the account itself was updated recently, might be because of the confirmation_key change + if (Carbon::now()->subMinutes(config('app.blocking_time_period_check'))->isBefore($this->account->updated_at)) { + $events++; + } + + return $events; + } +} diff --git a/flexiapi/config/app.php b/flexiapi/config/app.php index 2e6149f..cfbf626 100644 --- a/flexiapi/config/app.php +++ b/flexiapi/config/app.php @@ -51,6 +51,12 @@ return [ 'flexisip_pusher_firebase_key' => env('APP_FLEXISIP_PUSHER_FIREBASE_KEY', null), 'linphone_daemon_unix_pipe' => env('APP_LINPHONE_DAEMON_UNIX_PATH', null), + /** + * Blocking service + */ + 'blocking_time_period_check' => env('BLOCKING_TIME_PERIOD_CHECK', 30), + 'blocking_amount_events_authorized_during_period' => env('BLOCKING_AMOUNT_EVENTS_AUTHORIZED_DURING_PERIOD', 5), + /** * Account provisioning */ diff --git a/flexiapi/database/migrations/2024_01_22_151512_add_blocked_to_accounts_table.php b/flexiapi/database/migrations/2024_01_22_151512_add_blocked_to_accounts_table.php new file mode 100644 index 0000000..29bb216 --- /dev/null +++ b/flexiapi/database/migrations/2024_01_22_151512_add_blocked_to_accounts_table.php @@ -0,0 +1,22 @@ +boolean('blocked')->default(false)->index(); + }); + } + + public function down() + { + Schema::table('accounts', function (Blueprint $table) { + $table->dropColumn('blocked'); + }); + } +}; diff --git a/flexiapi/resources/views/account/blocked.blade.php b/flexiapi/resources/views/account/blocked.blade.php new file mode 100644 index 0000000..99040d8 --- /dev/null +++ b/flexiapi/resources/views/account/blocked.blade.php @@ -0,0 +1,7 @@ +@extends('layouts.main', ['welcome' => true]) + +@section('content') +
+

Your account was blocked due to its recent activity, please contact support to unblock it

+
+@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/create_edit.blade.php b/flexiapi/resources/views/admin/account/create_edit.blade.php index 0428825..dbe3ed0 100644 --- a/flexiapi/resources/views/admin/account/create_edit.blade.php +++ b/flexiapi/resources/views/admin/account/create_edit.blade.php @@ -39,7 +39,7 @@

Connexion

id) readonly @endif> @include('parts.errors', ['name' => 'username']) @@ -53,7 +53,7 @@
+ value="@if ($account->id){{ $account->display_name }}@else{{ old('display_name') }} @endif"> @include('parts.errors', ['name' => 'display_name'])
@@ -97,6 +97,14 @@
+
+ blocked) checked @endif> +

Unblocked

+ blocked) checked @endif> +

Blocked

+ +
+
admin) checked @endif>

Admin

diff --git a/flexiapi/resources/views/admin/account/index.blade.php b/flexiapi/resources/views/admin/account/index.blade.php index 7c02052..64b1cb1 100644 --- a/flexiapi/resources/views/admin/account/index.blade.php +++ b/flexiapi/resources/views/admin/account/index.blade.php @@ -104,9 +104,6 @@ @endif - @if ($account->email) - Email - @endif @if ($account->activated) Act. @endif @@ -116,6 +113,9 @@ @if ($account->sha256Password) SHA256 @endif + @if ($account->blocked) + Blocked + @endif {{ $account->updated_at }} diff --git a/flexiapi/resources/views/api/documentation_markdown.blade.php b/flexiapi/resources/views/api/documentation_markdown.blade.php index 241692b..97b3f7b 100644 --- a/flexiapi/resources/views/api/documentation_markdown.blade.php +++ b/flexiapi/resources/views/api/documentation_markdown.blade.php @@ -386,18 +386,30 @@ Search for a specific account by email. Delete a specific account and its related information. -### `GET /accounts/{id}/activate` +### `POST /accounts/{id}/activate` Admin Activate an account. -### `GET /accounts/{id}/deactivate` +### `POST /accounts/{id}/deactivate` Admin Deactivate an account. +### `POST /accounts/{id}/block` + +Admin + +Block an account. + +### `POST /accounts/{id}/unblock` + +Admin + +Unblock an account. + ### `GET /accounts/{id}/provision` Admin diff --git a/flexiapi/routes/api.php b/flexiapi/routes/api.php index 3c6dee9..8d6b3b7 100644 --- a/flexiapi/routes/api.php +++ b/flexiapi/routes/api.php @@ -56,7 +56,7 @@ Route::post('accounts/auth_token', 'Api\Account\AuthTokenController@store'); Route::get('accounts/me/api_key/{auth_token}', 'Api\Account\ApiKeyController@generateFromToken')->middleware('cookie', 'cookie.encrypt'); -Route::group(['middleware' => ['auth.digest_or_key']], function () { +Route::group(['middleware' => ['auth.digest_or_key', 'auth.check_blocked']], function () { Route::get('accounts/auth_token/{auth_token}/attach', 'Api\Account\AuthTokenController@attach'); Route::prefix('accounts/me')->group(function () { @@ -90,8 +90,10 @@ Route::group(['middleware' => ['auth.digest_or_key']], function () { // Accounts Route::prefix('accounts')->controller(AdminAccountController::class)->group(function () { - Route::get('{id}/activate', 'activate'); - Route::get('{id}/deactivate', 'deactivate'); + Route::post('{id}/activate', 'activate'); + Route::post('{id}/deactivate', 'deactivate'); + Route::post('{id}/block', 'block'); + Route::post('{id}/unblock', 'unblock'); Route::get('{id}/provision', 'provision'); Route::post('/', 'store'); diff --git a/flexiapi/routes/web.php b/flexiapi/routes/web.php index 276040d..f68e64d 100644 --- a/flexiapi/routes/web.php +++ b/flexiapi/routes/web.php @@ -91,6 +91,12 @@ Route::middleware(['web_panel_enabled'])->group(function () { }); Route::middleware(['auth'])->group(function () { + Route::get('logout', 'Account\AuthenticateController@logout')->name('account.logout'); + }); + + Route::middleware(['auth', 'auth.check_blocked'])->group(function () { + Route::get('blocked', 'Account\AccountController@blocked')->name('account.blocked'); + // Email change and validation Route::prefix('email')->controller(EmailController::class)->group(function () { Route::get('change', 'change')->name('account.email.change'); @@ -114,8 +120,6 @@ Route::middleware(['web_panel_enabled'])->group(function () { Route::delete('delete', 'destroy')->name('account.destroy'); }); - Route::get('logout', 'Account\AuthenticateController@logout')->name('account.logout'); - Route::prefix('password')->controller(PasswordController::class)->group(function () { Route::get('/', 'show')->name('account.password.show'); Route::post('/', 'update')->name('account.password.update'); @@ -134,7 +138,7 @@ Route::middleware(['web_panel_enabled'])->group(function () { Route::get('auth_tokens/qrcode/{token}', 'Account\AuthTokenController@qrcode')->name('auth_tokens.qrcode'); Route::get('auth_tokens/auth/{token}', 'Account\AuthTokenController@auth')->name('auth_tokens.auth'); - Route::name('admin.')->prefix('admin')->middleware(['auth.admin'])->group(function () { + Route::name('admin.')->prefix('admin')->middleware(['auth.admin', 'auth.check_blocked'])->group(function () { Route::name('statistics.')->controller(StatisticsController::class)->prefix('statistics')->group(function () { Route::get('/', 'index')->name('index'); Route::post('call_logs', 'editCallLogs')->name('edit_call_logs'); diff --git a/flexiapi/tests/Feature/AccountBlockingTest.php b/flexiapi/tests/Feature/AccountBlockingTest.php new file mode 100644 index 0000000..9ef585c --- /dev/null +++ b/flexiapi/tests/Feature/AccountBlockingTest.php @@ -0,0 +1,75 @@ +. +*/ + +namespace Tests\Feature; + +use App\Admin; +use App\Password; + +use Tests\TestCase; + +class AccountBlockingTest extends TestCase +{ + protected $route = '/api/accounts'; + protected $method = 'POST'; + + public function testBlocking() + { + $password = Password::factory()->create(); + $password->account->generateApiKey(); + + config()->set('app.blocking_amount_events_authorized_during_period', 2); + + $this->keyAuthenticated($password->account) + ->json($this->method, $this->route . '/me/phone/request', [ + 'phone' => '+331234' + ])->assertStatus(200); + + $this->keyAuthenticated($password->account) + ->json($this->method, $this->route . '/me/email/request', [ + 'email' => 'foo@bar.com' + ])->assertStatus(403); + } + + public function testAdminBlocking() + { + $password = Password::factory()->create(); + $password->account->generateApiKey(); + + $admin = Admin::factory()->create(); + $admin->account->generateApiKey(); + + $this->keyAuthenticated($password->account) + ->get($this->route . '/me')->assertStatus(200); + + $this->keyAuthenticated($admin->account) + ->json($this->method, $this->route . '/' . $password->account->id .'/block') + ->assertStatus(200); + + $this->keyAuthenticated($password->account) + ->get($this->route . '/me')->assertStatus(403); + + $this->keyAuthenticated($admin->account) + ->json($this->method, $this->route . '/' . $password->account->id .'/unblock') + ->assertStatus(200); + + $this->keyAuthenticated($password->account) + ->get($this->route . '/me')->assertStatus(200); + } +} diff --git a/flexiapi/tests/Feature/AccountProvisioningTest.php b/flexiapi/tests/Feature/AccountProvisioningTest.php index 0c62ee1..859b60a 100644 --- a/flexiapi/tests/Feature/AccountProvisioningTest.php +++ b/flexiapi/tests/Feature/AccountProvisioningTest.php @@ -19,7 +19,6 @@ namespace Tests\Feature; -use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; use App\Password; @@ -29,8 +28,6 @@ use App\AuthToken; class AccountProvisioningTest extends TestCase { - use RefreshDatabase; - protected $route = '/provisioning'; protected $accountRoute = '/provisioning/me'; protected $method = 'GET'; diff --git a/flexiapi/tests/Feature/ApiAccountActionTest.php b/flexiapi/tests/Feature/ApiAccountActionTest.php index 7c17053..4d164ba 100644 --- a/flexiapi/tests/Feature/ApiAccountActionTest.php +++ b/flexiapi/tests/Feature/ApiAccountActionTest.php @@ -23,13 +23,10 @@ use App\Password; use App\AccountAction; use App\Admin; -use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ApiAccountActionTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts'; protected $method = 'POST'; diff --git a/flexiapi/tests/Feature/ApiAccountApiKeyTest.php b/flexiapi/tests/Feature/ApiAccountApiKeyTest.php index 026b478..567700e 100644 --- a/flexiapi/tests/Feature/ApiAccountApiKeyTest.php +++ b/flexiapi/tests/Feature/ApiAccountApiKeyTest.php @@ -19,15 +19,11 @@ namespace Tests\Feature; -use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; - use App\Password; class ApiAccountApiKeyTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts/me/api_key'; protected $method = 'GET'; diff --git a/flexiapi/tests/Feature/ApiAccountContactsTest.php b/flexiapi/tests/Feature/ApiAccountContactsTest.php index 3da417b..ebf6c52 100644 --- a/flexiapi/tests/Feature/ApiAccountContactsTest.php +++ b/flexiapi/tests/Feature/ApiAccountContactsTest.php @@ -23,14 +23,11 @@ use App\Password; use App\AccountType; use App\Admin; use App\ContactsList; -use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\DB; use Tests\TestCase; class ApiAccountContactTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts'; protected $contactsListsRoute = '/api/contacts_lists'; protected $method = 'POST'; diff --git a/flexiapi/tests/Feature/ApiAccountCreationTokenTest.php b/flexiapi/tests/Feature/ApiAccountCreationTokenTest.php index 470e497..5c00c37 100644 --- a/flexiapi/tests/Feature/ApiAccountCreationTokenTest.php +++ b/flexiapi/tests/Feature/ApiAccountCreationTokenTest.php @@ -21,17 +21,13 @@ namespace Tests\Feature; use App\Account; use App\AccountCreationRequestToken; -use Illuminate\Foundation\Testing\RefreshDatabase; -use Tests\TestCase; - use App\AccountCreationToken; use App\Admin; +use Tests\TestCase; use Carbon\Carbon; class ApiAccountCreationTokenTest extends TestCase { - use RefreshDatabase; - protected $tokenRoute = '/api/account_creation_tokens/send-by-push'; protected $tokenRequestRoute = '/api/account_creation_request_tokens'; protected $tokenUsingCreationTokenRoute = '/api/account_creation_tokens/using-account-creation-request-token'; diff --git a/flexiapi/tests/Feature/ApiAccountDictionaryTest.php b/flexiapi/tests/Feature/ApiAccountDictionaryTest.php index 7db725b..78e287e 100644 --- a/flexiapi/tests/Feature/ApiAccountDictionaryTest.php +++ b/flexiapi/tests/Feature/ApiAccountDictionaryTest.php @@ -23,14 +23,11 @@ use App\Password; use App\AccountType; use App\Admin; use App\ContactsList; -use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\DB; use Tests\TestCase; class ApiAccountDictionaryTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts'; protected $method = 'POST'; @@ -49,7 +46,7 @@ class ApiAccountDictionaryTest extends TestCase // First key $this->keyAuthenticated($admin->account) - ->json($this->method, $this->route . '/' . $account->id . ' /dictionary/' . $key , [ + ->json($this->method, $this->route . '/' . $account->id . ' /dictionary/' . $key, [ 'value' => $value ])->assertStatus(201); @@ -71,7 +68,7 @@ class ApiAccountDictionaryTest extends TestCase // Update $this->keyAuthenticated($admin->account) - ->json($this->method, $this->route . '/' . $account->id . ' /dictionary/' . $key , [ + ->json($this->method, $this->route . '/' . $account->id . ' /dictionary/' . $key, [ 'value' => $newValue ])->assertStatus(200); @@ -84,7 +81,7 @@ class ApiAccountDictionaryTest extends TestCase // Second key $this->keyAuthenticated($admin->account) - ->json($this->method, $this->route . '/' . $account->id . ' /dictionary/' . $secondKey , [ + ->json($this->method, $this->route . '/' . $account->id . ' /dictionary/' . $secondKey, [ 'value' => $newValue ])->assertStatus(201); diff --git a/flexiapi/tests/Feature/ApiAccountMessageTest.php b/flexiapi/tests/Feature/ApiAccountMessageTest.php index 55a46eb..a2714f8 100644 --- a/flexiapi/tests/Feature/ApiAccountMessageTest.php +++ b/flexiapi/tests/Feature/ApiAccountMessageTest.php @@ -21,14 +21,11 @@ namespace Tests\Feature; use App\Admin; -use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Testing\Fluent\AssertableJson; use Tests\TestCase; class ApiAccountMessageTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/messages'; protected $method = 'POST'; diff --git a/flexiapi/tests/Feature/ApiAccountPhoneChangeTest.php b/flexiapi/tests/Feature/ApiAccountPhoneChangeTest.php index bfc0f0b..c61eebf 100644 --- a/flexiapi/tests/Feature/ApiAccountPhoneChangeTest.php +++ b/flexiapi/tests/Feature/ApiAccountPhoneChangeTest.php @@ -21,14 +21,10 @@ namespace Tests\Feature; use App\Password; use App\PhoneChangeCode; - -use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ApiAccountPhoneChangeTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts/me/phone'; protected $method = 'POST'; diff --git a/flexiapi/tests/Feature/ApiAccountTest.php b/flexiapi/tests/Feature/ApiAccountTest.php index 7a7b109..48445ad 100644 --- a/flexiapi/tests/Feature/ApiAccountTest.php +++ b/flexiapi/tests/Feature/ApiAccountTest.php @@ -27,14 +27,10 @@ use App\ActivationExpiration; use App\Admin; use App\Alias as AppAlias; use Carbon\Carbon; -use Illuminate\Foundation\Testing\RefreshDatabase; - use Tests\TestCase; class ApiAccountTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts'; protected $method = 'POST'; @@ -380,14 +376,14 @@ class ApiAccountTest extends TestCase ] ])->assertJsonValidationErrors(['dictionary']); - $response = $this->keyAuthenticated($password->account) - ->json($this->method, $this->route, [ - 'username' => 'john2', - 'domain' => 'lennon.com', - 'password' => 'password123', - 'algorithm' => 'SHA-256', - 'dictionary' => 'hop' - ])->assertJsonValidationErrors(['dictionary']); + $response = $this->keyAuthenticated($password->account) + ->json($this->method, $this->route, [ + 'username' => 'john2', + 'domain' => 'lennon.com', + 'password' => 'password123', + 'algorithm' => 'SHA-256', + 'dictionary' => 'hop' + ])->assertJsonValidationErrors(['dictionary']); } public function testActivated() @@ -506,7 +502,7 @@ class ApiAccountTest extends TestCase $password->account->activated = false; $password->account->save(); - $expiration = new ActivationExpiration; + $expiration = new ActivationExpiration(); $expiration->account_id = $password->account->id; $expiration->expires = Carbon::now()->subYear(); $expiration->save(); @@ -698,7 +694,7 @@ class ApiAccountTest extends TestCase $phone = '+1234'; - $alias = new AppAlias; + $alias = new AppAlias(); $alias->alias = $phone; $alias->domain = $password->account->domain; $alias->account_id = $password->account->id; @@ -743,7 +739,7 @@ class ApiAccountTest extends TestCase config()->set('app.dangerous_endpoints', true); - $alias = new AppAlias; + $alias = new AppAlias(); $alias->alias = $phone; $alias->domain = $password->account->domain; $alias->account_id = $password->account->id; @@ -949,7 +945,7 @@ class ApiAccountTest extends TestCase $password->account->activated = false; $password->account->save(); - $expiration = new ActivationExpiration; + $expiration = new ActivationExpiration(); $expiration->account_id = $password->account->id; $expiration->expires = Carbon::now()->subYear(); $expiration->save(); @@ -984,6 +980,8 @@ class ApiAccountTest extends TestCase public function testChangeEmail() { + $this->disableBlockingService(); + $password = Password::factory()->create(); $otherAccount = Password::factory()->create(); $password->account->generateApiKey(); @@ -1109,7 +1107,7 @@ class ApiAccountTest extends TestCase // deactivate $this->keyAuthenticated($admin->account) - ->get($this->route . '/' . $password->account->id . '/deactivate') + ->post($this->route . '/' . $password->account->id . '/deactivate') ->assertStatus(200) ->assertJson([ 'activated' => false @@ -1123,7 +1121,7 @@ class ApiAccountTest extends TestCase ]); $this->keyAuthenticated($admin->account) - ->get($this->route . '/' . $password->account->id . '/activate') + ->post($this->route . '/' . $password->account->id . '/activate') ->assertStatus(200) ->assertJson([ 'activated' => true @@ -1225,7 +1223,8 @@ class ApiAccountTest extends TestCase ->assertStatus(200) ->assertJson([ 'confirmation_key_expires' => '2040-12-12 12:12:12' - ]);; + ]); + ; } public function testDelete() diff --git a/flexiapi/tests/Feature/ApiAccountTypeTest.php b/flexiapi/tests/Feature/ApiAccountTypeTest.php index 29071e9..bce894f 100644 --- a/flexiapi/tests/Feature/ApiAccountTypeTest.php +++ b/flexiapi/tests/Feature/ApiAccountTypeTest.php @@ -23,14 +23,11 @@ use App\Password; use App\AccountType; use App\Admin; -use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\DB; use Tests\TestCase; class ApiAccountTypeTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/account_types'; protected $method = 'POST'; diff --git a/flexiapi/tests/Feature/ApiAuthenticationTest.php b/flexiapi/tests/Feature/ApiAuthenticationTest.php index 4b3db3a..635a546 100644 --- a/flexiapi/tests/Feature/ApiAuthenticationTest.php +++ b/flexiapi/tests/Feature/ApiAuthenticationTest.php @@ -21,13 +21,10 @@ namespace Tests\Feature; use App\Password; -use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ApiAuthenticationTest extends TestCase { - use RefreshDatabase; - protected $route = '/api/accounts/me'; protected $method = 'GET'; diff --git a/flexiapi/tests/Feature/ApiStatisticsTest.php b/flexiapi/tests/Feature/ApiStatisticsTest.php index 9fcea97..d1d38ee 100644 --- a/flexiapi/tests/Feature/ApiStatisticsTest.php +++ b/flexiapi/tests/Feature/ApiStatisticsTest.php @@ -23,13 +23,12 @@ use App\Account; use App\Admin; use App\StatisticsCallDevice; use App\StatisticsMessageDevice; -use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Tests\TestCase; class ApiStatisticsTest extends TestCase { - use WithFaker, RefreshDatabase; + use WithFaker; protected $routeMessages = '/api/statistics/messages'; protected $routeCalls = '/api/statistics/calls'; diff --git a/flexiapi/tests/TestCase.php b/flexiapi/tests/TestCase.php index df74a88..f2044e3 100644 --- a/flexiapi/tests/TestCase.php +++ b/flexiapi/tests/TestCase.php @@ -23,14 +23,21 @@ use App\Password; use App\Account; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; +use Illuminate\Foundation\Testing\RefreshDatabase; abstract class TestCase extends BaseTestCase { use CreatesApplication; + use RefreshDatabase; protected $route = '/api/accounts/me'; protected $method = 'GET'; + protected function disableBlockingService() + { + config()->set('app.blocking_amount_events_authorized_during_period', 0); + } + protected function keyAuthenticated(Account $account) { return $this->withHeaders([ @@ -41,14 +48,14 @@ abstract class TestCase extends BaseTestCase protected function generateFirstResponse(Password $password, ?string $method = null, ?string $route = null) { return $this->withHeaders([ - 'From' => 'sip:'.$password->account->identifier + 'From' => 'sip:' . $password->account->identifier ])->json($method ?? $this->method, $route ?? $this->route); } protected function generateSecondResponse(Password $password, $firstResponse) { return $this->withHeaders([ - 'From' => 'sip:'.$password->account->identifier, + 'From' => 'sip:' . $password->account->identifier, 'Authorization' => $this->generateDigest($password, $firstResponse), ]); }