mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-17 10:08:05 +00:00
Fix FLEXIAPI-155 Add a new accountServiceAccountUpdatedHook and accountServiceAccountDeletedHook
This commit is contained in:
parent
00196e5957
commit
75599dd5ab
28 changed files with 392 additions and 203 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
v1.5
|
||||
----
|
||||
- Fix FLEXIAPI-155 Add a new accountServiceAccountUpdatedHook and accountServiceAccountDeletedHook
|
||||
- Fix FLEXIAPI-153 Add phone and email to be changed in the Activity panel
|
||||
- Fix FLEXIAPI-151 Migrate to hCaptcha
|
||||
- Fix FLEXIAPI-150 Use the same account_id parameter for both API and Web routes
|
||||
|
|
|
|||
|
|
@ -120,11 +120,6 @@ class Account extends Authenticatable
|
|||
return $this->hasOne(ActivationExpiration::class);
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
return $this->hasOne(Admin::class);
|
||||
}
|
||||
|
||||
public function alias()
|
||||
{
|
||||
return $this->hasOne(Alias::class);
|
||||
|
|
@ -430,13 +425,27 @@ class Account extends Authenticatable
|
|||
$this->save();
|
||||
}
|
||||
|
||||
public function hasTombstone()
|
||||
public function hasTombstone(): bool
|
||||
{
|
||||
return AccountTombstone::where('username', $this->attributes['username'])
|
||||
->where('domain', $this->attributes['domain'])
|
||||
->exists();
|
||||
}
|
||||
|
||||
public function createTombstone(): bool
|
||||
{
|
||||
if (!$this->hasTombstone()) {
|
||||
$tombstone = new AccountTombstone();
|
||||
$tombstone->username = $this->attributes['username'];
|
||||
$tombstone->domain = $this->attributes['domain'];
|
||||
$tombstone->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function failedRecentRecovery(): bool
|
||||
{
|
||||
$oneHourAgo = Carbon::now()->subHour();
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\AccountTombstone;
|
||||
use App\Http\Requests\CreateAccountRequest;
|
||||
use App\Http\Requests\Account\Create\Web\Request as WebRequest;
|
||||
use App\Services\AccountService;
|
||||
|
||||
class AccountController extends Controller
|
||||
|
|
@ -48,11 +47,9 @@ class AccountController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function store(CreateAccountRequest $request)
|
||||
public function store(WebRequest $request)
|
||||
{
|
||||
$request->validate(['h-captcha-response' => captchaConfigured() ? 'required|HCaptcha' : '']);
|
||||
|
||||
$account = (new AccountService(api: false))->store($request);
|
||||
$account = (new AccountService())->store($request);
|
||||
|
||||
Auth::login($account);
|
||||
|
||||
|
|
@ -78,14 +75,10 @@ class AccountController extends Controller
|
|||
{
|
||||
$request->validate(['identifier' => 'required|same:identifier_confirm']);
|
||||
|
||||
if (!$request->user()->hasTombstone()) {
|
||||
$tombstone = new AccountTombstone();
|
||||
$tombstone->username = $request->user()->username;
|
||||
$tombstone->domain = $request->user()->domain;
|
||||
$tombstone->save();
|
||||
}
|
||||
$request->user()->createTombstone();
|
||||
|
||||
(new AccountService)->destroy($request, $request->user()->id);
|
||||
|
||||
$request->user()->delete();
|
||||
Auth::logout();
|
||||
|
||||
return redirect()->route('account.login');
|
||||
|
|
|
|||
|
|
@ -72,8 +72,6 @@ class AuthTokenController extends Controller
|
|||
|
||||
$authToken->delete();
|
||||
|
||||
$request->session()->flash('success', 'Successfully authenticated');
|
||||
|
||||
return redirect()->route('account.dashboard');
|
||||
}
|
||||
|
||||
|
|
@ -87,8 +85,6 @@ class AuthTokenController extends Controller
|
|||
if (!$authToken->account_id) {
|
||||
$authToken->account_id = $request->user()->id;
|
||||
$authToken->save();
|
||||
|
||||
$request->session()->flash('success', 'External device successfully authenticated');
|
||||
}
|
||||
|
||||
return redirect()->route('account.dashboard');
|
||||
|
|
|
|||
|
|
@ -103,8 +103,6 @@ class AuthenticateController extends Controller
|
|||
|
||||
$authToken->delete();
|
||||
|
||||
$request->session()->flash('success', 'Successfully authenticated');
|
||||
|
||||
return redirect()->route('account.dashboard');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,11 @@ class PasswordController extends Controller
|
|||
|
||||
if ($account->passwords()->count() > 0) {
|
||||
Log::channel('events')->info('Web: Password changed', ['id' => $account->identifier]);
|
||||
$request->session()->flash('success', 'Password successfully changed');
|
||||
|
||||
return redirect()->route('account.dashboard');
|
||||
}
|
||||
|
||||
Log::channel('events')->info('Web: Password set for the first time', ['id' => $account->identifier]);
|
||||
$request->session()->flash('success', 'Password successfully set. Your SIP account creation process is now finished.');
|
||||
|
||||
if (!empty($account->email)) {
|
||||
Mail::to($account)->send(new ConfirmedRegistration($account));
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ class AccountAccountTypeController extends Controller
|
|||
$account->types()->detach($request->get('account_type_id'));
|
||||
$account->types()->attach($request->get('account_type_id'));
|
||||
|
||||
$request->session()->flash('success', 'Type successfully added');
|
||||
Log::channel('events')->info('Web Admin: Account type attached', ['id' => $account->identifier, 'type_id' => $request->get('account_type_id')]);
|
||||
|
||||
return redirect()->route('admin.account.edit', $account);
|
||||
|
|
@ -65,7 +64,6 @@ class AccountAccountTypeController extends Controller
|
|||
|
||||
$account->types()->detach($typeId);
|
||||
|
||||
$request->session()->flash('success', 'Type successfully removed');
|
||||
Log::channel('events')->info('Web Admin: Account type detached', ['id' => $account->identifier, 'type_id' => $request->get('account_type_id')]);
|
||||
|
||||
return redirect()->route('admin.account.edit', $account);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ class AccountActionController extends Controller
|
|||
$accountAction->code = $request->get('code');
|
||||
$accountAction->save();
|
||||
|
||||
$request->session()->flash('success', 'Action successfully created');
|
||||
Log::channel('events')->info('Web Admin: Account action created', ['id' => $account->identifier, 'action' => $accountAction->key]);
|
||||
|
||||
return redirect()->route('admin.account.edit', $accountAction->account);
|
||||
|
|
@ -90,7 +89,6 @@ class AccountActionController extends Controller
|
|||
$accountAction->code = $request->get('code');
|
||||
$accountAction->save();
|
||||
|
||||
$request->session()->flash('success', 'Action successfully updated');
|
||||
Log::channel('events')->info('Web Admin: Account action updated', ['id' => $account->identifier, 'action' => $accountAction->key]);
|
||||
|
||||
return redirect()->route('admin.account.edit', $account);
|
||||
|
|
@ -116,8 +114,6 @@ class AccountActionController extends Controller
|
|||
->firstOrFail();
|
||||
$accountAction->delete();
|
||||
|
||||
$request->session()->flash('success', 'Action successfully destroyed');
|
||||
|
||||
Log::channel('events')->info('Web Admin: Account action deleted', ['id' => $accountAction->account->identifier, 'action_id' => $accountAction->key]);
|
||||
|
||||
return redirect()->route('admin.account.edit', $accountAction->account);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ class AccountContactController extends Controller
|
|||
|
||||
$account->contacts()->detach($contact->id);
|
||||
|
||||
$request->session()->flash('success', 'Type successfully removed');
|
||||
Log::channel('events')->info('Web Admin: Account contact removed', ['id' => $account->identifier, 'contact' => $contact->identifier]);
|
||||
|
||||
return redirect()->route('admin.account.edit', $account);
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Carbon\Carbon;
|
||||
|
||||
use App\Account;
|
||||
use App\ContactsList;
|
||||
use App\Http\Requests\CreateAccountWithoutUsernamePhoneCheck;
|
||||
use App\Http\Requests\Account\Create\Web\AsAdminRequest;
|
||||
use App\Http\Requests\Account\Update\Web\AsAdminRequest as WebAsAdminRequest;
|
||||
use App\Http\Requests\UpdateAccountRequest;
|
||||
use App\Services\AccountService;
|
||||
|
||||
class AccountController extends Controller
|
||||
{
|
||||
|
|
@ -79,30 +80,9 @@ class AccountController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function store(CreateAccountWithoutUsernamePhoneCheck $request)
|
||||
public function store(AsAdminRequest $request)
|
||||
{
|
||||
$request->validate([
|
||||
'password' => 'confirmed'
|
||||
]);
|
||||
|
||||
$account = new Account;
|
||||
$account->username = $request->get('username');
|
||||
$account->email = $request->get('email');
|
||||
$account->display_name = $request->get('display_name');
|
||||
$account->domain = resolveDomain($request);
|
||||
$account->ip_address = $request->ip();
|
||||
$account->created_at = Carbon::now();
|
||||
$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');
|
||||
$account->updatePassword($request->get('password'));
|
||||
|
||||
$account->refresh();
|
||||
$account->setRole($request->get('role'));
|
||||
$account = (new AccountService)->store($request);
|
||||
|
||||
Log::channel('events')->info('Web Admin: Account created', ['id' => $account->identifier]);
|
||||
|
||||
|
|
@ -122,27 +102,9 @@ class AccountController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function update(UpdateAccountRequest $request, $id)
|
||||
public function update(WebAsAdminRequest $request, int $id)
|
||||
{
|
||||
$request->validate([
|
||||
'password' => 'confirmed',
|
||||
]);
|
||||
|
||||
$account = Account::findOrFail($id);
|
||||
$account->email = $request->get('email');
|
||||
$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');
|
||||
|
||||
if ($request->get('password')) {
|
||||
$account->updatePassword($request->get('password'));
|
||||
}
|
||||
|
||||
$account->setRole($request->get('role'));
|
||||
$account = (new AccountService)->update($request, $id);
|
||||
|
||||
Log::channel('events')->info('Web Admin: Account updated', ['id' => $account->identifier]);
|
||||
|
||||
|
|
@ -172,9 +134,8 @@ class AccountController extends Controller
|
|||
public function destroy(Request $request)
|
||||
{
|
||||
$account = Account::findOrFail($request->get('account_id'));
|
||||
$account->delete();
|
||||
|
||||
$request->session()->flash('success', 'Account successfully destroyed');
|
||||
(new AccountService)->destroy($request, $request->get('account_id'));
|
||||
|
||||
Log::channel('events')->info('Web Admin: Account deleted', ['id' => $account->identifier]);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,10 @@ use Carbon\Carbon;
|
|||
|
||||
use App\Account;
|
||||
use App\AccountCreationToken;
|
||||
use App\AccountTombstone;
|
||||
use App\Alias;
|
||||
|
||||
use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController;
|
||||
use App\Http\Requests\CreateAccountRequest;
|
||||
use App\Http\Requests\Account\Create\Api\Request as ApiRequest;
|
||||
use App\Libraries\OvhSMS;
|
||||
use App\Mail\RegisterConfirmation;
|
||||
|
||||
|
|
@ -251,7 +250,7 @@ class AccountController extends Controller
|
|||
return $account;
|
||||
}
|
||||
|
||||
public function store(CreateAccountRequest $request)
|
||||
public function store(ApiRequest $request)
|
||||
{
|
||||
return (new AccountService)->store($request);
|
||||
}
|
||||
|
|
@ -334,14 +333,10 @@ class AccountController extends Controller
|
|||
|
||||
public function delete(Request $request)
|
||||
{
|
||||
if (!$request->user()->hasTombstone()) {
|
||||
$tombstone = new AccountTombstone;
|
||||
$tombstone->username = $request->user()->username;
|
||||
$tombstone->domain = $request->user()->domain;
|
||||
$tombstone->save();
|
||||
}
|
||||
$request->user()->createTombstone();
|
||||
|
||||
return Account::where('id', $request->user()->id)
|
||||
->delete();
|
||||
(new AccountService)->destroy($request, $request->user()->id);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,8 @@ use App\Account;
|
|||
use App\AccountTombstone;
|
||||
use App\AccountType;
|
||||
use App\ContactsList;
|
||||
use App\Http\Requests\CreateAccountRequest;
|
||||
use App\Http\Requests\CreateAccountWithoutUsernamePhoneCheck;
|
||||
use App\Http\Requests\UpdateAccountRequest;
|
||||
use App\Rules\PasswordAlgorithm;
|
||||
use App\Http\Requests\Account\Create\Api\AsAdminRequest;
|
||||
use App\Http\Requests\Account\Update\Api\AsAdminRequest as ApiAsAdminRequest;
|
||||
use App\Services\AccountService;
|
||||
|
||||
class AccountController extends Controller
|
||||
|
|
@ -55,7 +53,7 @@ class AccountController extends Controller
|
|||
return Account::where('email', $email)->firstOrFail();
|
||||
}
|
||||
|
||||
public function destroy($accountId)
|
||||
public function destroy(Request $request, int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
|
|
@ -66,9 +64,9 @@ class AccountController extends Controller
|
|||
$tombstone->save();
|
||||
}
|
||||
|
||||
Log::channel('events')->info('API Admin: Account destroyed', ['id' => $account->identifier]);
|
||||
(new AccountService)->destroy($request, $accountId);
|
||||
|
||||
$account->delete();
|
||||
Log::channel('events')->info('API Admin: Account destroyed', ['id' => $account->identifier]);
|
||||
}
|
||||
|
||||
public function activate(int $accountId)
|
||||
|
|
@ -126,34 +124,14 @@ class AccountController extends Controller
|
|||
return $account->makeVisible(['provisioning_token']);
|
||||
}
|
||||
|
||||
public function store(CreateAccountWithoutUsernamePhoneCheck $request)
|
||||
public function store(AsAdminRequest $request)
|
||||
{
|
||||
return (new AccountService)->store($request, asAdmin: true)->makeVisible(['confirmation_key', 'provisioning_token']);
|
||||
return (new AccountService)->store($request)->makeVisible(['confirmation_key', 'provisioning_token']);
|
||||
}
|
||||
|
||||
public function update(UpdateAccountRequest $request, int $accountId)
|
||||
public function update(ApiAsAdminRequest $request, int $accountId)
|
||||
{
|
||||
$request->validate([
|
||||
'algorithm' => ['required', new PasswordAlgorithm],
|
||||
'admin' => 'boolean|nullable',
|
||||
'activated' => 'boolean|nullable'
|
||||
]);
|
||||
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->username = $request->get('username');
|
||||
$account->email = $request->get('email');
|
||||
$account->display_name = $request->get('display_name');
|
||||
$account->dtmf_protocol = $request->get('dtmf_protocol');
|
||||
$account->domain = resolveDomain($request);
|
||||
$account->user_agent = $request->header('User-Agent') ?? config('app.name');
|
||||
$account->admin = $request->has('admin') && (bool)$request->get('admin');
|
||||
$account->save();
|
||||
|
||||
$account->updatePassword($request->get('password'), $request->get('algorithm'));
|
||||
$account->phone = $request->get('phone');
|
||||
|
||||
// Full reload
|
||||
$account = Account::withoutGlobalScopes()->find($account->id);
|
||||
$account = (new AccountService)->update($request, $accountId);
|
||||
|
||||
Log::channel('events')->info('API Admin: Account updated', ['id' => $account->identifier]);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Account\Create\Api;
|
||||
|
||||
use App\Http\Requests\Account\Create\Request;
|
||||
use App\Http\Requests\Api as RequestsApi;
|
||||
use App\Http\Requests\AsAdmin;
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
use App\Rules\PasswordAlgorithm;
|
||||
|
||||
class AsAdminRequest extends Request
|
||||
{
|
||||
use RequestsApi, AsAdmin;
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = parent::rules();
|
||||
|
||||
$rules['algorithm'] = ['required', new PasswordAlgorithm()];
|
||||
$rules['admin'] = 'boolean|nullable';
|
||||
$rules['activated'] = 'boolean|nullable';
|
||||
$rules['confirmation_key_expires'] = [
|
||||
'date_format:Y-m-d H:i:s',
|
||||
'nullable',
|
||||
];
|
||||
|
||||
if (config('app.allow_phone_number_username_admin_api') == true) {
|
||||
array_splice(
|
||||
$rules['username'],
|
||||
array_search(new IsNotPhoneNumber(), $rules['username']),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
25
flexiapi/app/Http/Requests/Account/Create/Api/Request.php
Normal file
25
flexiapi/app/Http/Requests/Account/Create/Api/Request.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Account\Create\Api;
|
||||
|
||||
use App\Http\Requests\Account\Create\Request as CreateRequest;
|
||||
use App\Http\Requests\Api as RequestsApi;
|
||||
use App\Rules\AccountCreationToken;
|
||||
|
||||
class Request extends CreateRequest
|
||||
{
|
||||
use RequestsApi;
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = parent::rules();
|
||||
$rules['account_creation_token'] = ['required', new AccountCreationToken()];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
namespace App\Http\Requests\Account\Create;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
|
@ -13,7 +13,7 @@ use App\Rules\NoUppercase;
|
|||
use App\Rules\SIPUsername;
|
||||
use App\Rules\WithoutSpaces;
|
||||
|
||||
class CreateAccountRequest extends FormRequest
|
||||
class Request extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
|
|
@ -25,10 +25,10 @@ class CreateAccountRequest extends FormRequest
|
|||
return [
|
||||
'username' => [
|
||||
'required',
|
||||
new NoUppercase,
|
||||
new IsNotPhoneNumber,
|
||||
new BlacklistedUsername,
|
||||
new SIPUsername,
|
||||
new NoUppercase(),
|
||||
new IsNotPhoneNumber(),
|
||||
new BlacklistedUsername(),
|
||||
new SIPUsername(),
|
||||
Rule::unique('accounts', 'username')->where(function ($query) {
|
||||
$query->where('domain', resolveDomain($this));
|
||||
}),
|
||||
|
|
@ -37,7 +37,7 @@ class CreateAccountRequest extends FormRequest
|
|||
}),
|
||||
'filled',
|
||||
],
|
||||
'dictionary' => [new Dictionary],
|
||||
'dictionary' => [new Dictionary()],
|
||||
'password' => 'required|min:3',
|
||||
'email' => config('app.account_email_unique')
|
||||
? 'nullable|email|unique:accounts,email'
|
||||
|
|
@ -47,7 +47,7 @@ class CreateAccountRequest extends FormRequest
|
|||
'nullable',
|
||||
'unique:aliases,alias',
|
||||
'unique:accounts,username',
|
||||
new WithoutSpaces, 'starts_with:+'
|
||||
new WithoutSpaces(), 'starts_with:+'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Account\Create\Web;
|
||||
|
||||
use App\Http\Requests\Account\Create\Request as CreateRequest;
|
||||
use App\Http\Requests\AsAdmin;
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
|
||||
class AsAdminRequest extends CreateRequest
|
||||
{
|
||||
use AsAdmin;
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = parent::rules();
|
||||
|
||||
$rules['password'] = 'confirmed';
|
||||
|
||||
if (config('app.allow_phone_number_username_admin_api') == true) {
|
||||
array_splice(
|
||||
$rules['username'],
|
||||
array_search(new IsNotPhoneNumber(), $rules['username']),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
25
flexiapi/app/Http/Requests/Account/Create/Web/Request.php
Normal file
25
flexiapi/app/Http/Requests/Account/Create/Web/Request.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Account\Create\Web;
|
||||
|
||||
use App\Http\Requests\Account\Create\Request as CreateRequest;
|
||||
|
||||
class Request extends CreateRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = parent::rules();
|
||||
|
||||
$rules['h-captcha-response'] = captchaConfigured() ? 'required|HCaptcha' : '';
|
||||
$rules['password'] = 'confirmed';
|
||||
$rules['email'] = 'confirmed';
|
||||
$rules['terms'] = 'accepted';
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Account\Update\Api;
|
||||
|
||||
use App\Http\Requests\Account\Update\Request as UpdateRequest;
|
||||
use App\Http\Requests\Api as RequestsApi;
|
||||
use App\Http\Requests\AsAdmin;
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
use App\Rules\PasswordAlgorithm;
|
||||
|
||||
class AsAdminRequest extends UpdateRequest
|
||||
{
|
||||
use RequestsApi, AsAdmin;
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = parent::rules();
|
||||
|
||||
$rules['algorithm'] = ['required', new PasswordAlgorithm()];
|
||||
$rules['admin'] = 'boolean|nullable';
|
||||
$rules['activated'] = 'boolean|nullable';
|
||||
|
||||
if (config('app.allow_phone_number_username_admin_api') == true) {
|
||||
array_splice(
|
||||
$rules['username'],
|
||||
array_search(new IsNotPhoneNumber(), $rules['username']),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
namespace App\Http\Requests\Account\Update;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
|
@ -12,7 +12,7 @@ use App\Rules\NoUppercase;
|
|||
use App\Rules\SIPUsername;
|
||||
use App\Rules\WithoutSpaces;
|
||||
|
||||
class UpdateAccountRequest extends FormRequest
|
||||
class Request extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
|
|
@ -45,7 +45,7 @@ class UpdateAccountRequest extends FormRequest
|
|||
Rule::unique('accounts', 'username')->where(function ($query) {
|
||||
$query->where('domain', resolveDomain($this));
|
||||
})->ignore($this->route('id'), 'id'),
|
||||
Rule::unique('aliases', 'alias')->ignore($this->route('id'), 'account_id'),
|
||||
Rule::unique('aliases', 'alias')->ignore($this->route('account_id'), 'account_id'),
|
||||
new WithoutSpaces, 'starts_with:+'
|
||||
]
|
||||
];
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Account\Update\Web;
|
||||
|
||||
use App\Http\Requests\Account\Update\Request as UpdateRequest;
|
||||
use App\Http\Requests\AsAdmin;
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
|
||||
class AsAdminRequest extends UpdateRequest
|
||||
{
|
||||
use AsAdmin;
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = parent::rules();
|
||||
|
||||
$rules['password'] = 'confirmed';
|
||||
|
||||
if (config('app.allow_phone_number_username_admin_api') == true) {
|
||||
array_splice(
|
||||
$rules['username'],
|
||||
array_search(new IsNotPhoneNumber(), $rules['username']),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
8
flexiapi/app/Http/Requests/Api.php
Normal file
8
flexiapi/app/Http/Requests/Api.php
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
trait Api
|
||||
{
|
||||
public $api = true;
|
||||
}
|
||||
8
flexiapi/app/Http/Requests/AsAdmin.php
Normal file
8
flexiapi/app/Http/Requests/AsAdmin.php
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
trait AsAdmin
|
||||
{
|
||||
public $asAdmin = true;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
|
||||
class CreateAccountWithoutUsernamePhoneCheck extends CreateAccountRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$parentRules = parent::rules();
|
||||
|
||||
if (config('app.allow_phone_number_username_admin_api') == true) {
|
||||
array_splice(
|
||||
$parentRules['username'],
|
||||
array_search(new IsNotPhoneNumber(), $parentRules['username']),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
return $parentRules;
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ class OvhSMS
|
|||
if (!empty($smsServices)) {
|
||||
$this->smsService = $smsServices[0];
|
||||
}
|
||||
} catch (\GuzzleHttp\Exception\ClientException $e) {
|
||||
} catch (\Exception $e) {
|
||||
Log::channel('events')->info('OVH SMS API unreachable, check the errors log');
|
||||
Log::error('OVH SMS API not reachable: ' . $e->getMessage());
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ class OvhSMS
|
|||
// One credit removed
|
||||
|
||||
$this->api->get('/sms/'. $this->smsService . '/jobs');
|
||||
} catch (\GuzzleHttp\Exception\ClientException $e) {
|
||||
} catch (\Exception $e) {
|
||||
Log::channel('events')->info('OVH SMS not sent, check the errors log');
|
||||
Log::error('OVH SMS not sent: ' . $e->getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@ use App\AccountCreationToken;
|
|||
use App\ActivationExpiration;
|
||||
use App\Alias;
|
||||
use App\EmailChangeCode;
|
||||
use App\Http\Requests\CreateAccountRequest;
|
||||
use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController;
|
||||
use App\Http\Requests\Account\Create\Request as CreateRequest;
|
||||
use App\Http\Requests\Account\Update\Request as UpdateRequest;
|
||||
use App\Libraries\OvhSMS;
|
||||
use App\Mail\NewsletterRegistration;
|
||||
use App\Mail\RecoverByCode;
|
||||
|
|
@ -33,8 +34,6 @@ use App\Mail\RegisterValidation;
|
|||
use App\PhoneChangeCode;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Rules\AccountCreationToken as RulesAccountCreationToken;
|
||||
use App\Rules\PasswordAlgorithm;
|
||||
use App\Rules\WithoutSpaces;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
|
@ -57,33 +56,8 @@ class AccountService
|
|||
/**
|
||||
* Account creation
|
||||
*/
|
||||
public function store(CreateAccountRequest $request, bool $asAdmin = false): Account
|
||||
public function store(CreateRequest $request): Account
|
||||
{
|
||||
$rules = [];
|
||||
$rules['password'] = 'confirmed';
|
||||
$rules['email'] = 'confirmed';
|
||||
$rules['terms'] = 'accepted';
|
||||
|
||||
if ($this->api) {
|
||||
$rules = [];
|
||||
$rules['account_creation_token'] = ['required', new RulesAccountCreationToken()];
|
||||
|
||||
if ($asAdmin) {
|
||||
$rules = [];
|
||||
$rules['algorithm'] = ['required', new PasswordAlgorithm()];
|
||||
$rules['admin'] = 'boolean|nullable';
|
||||
$rules['activated'] = 'boolean|nullable';
|
||||
$rules['confirmation_key_expires'] = [
|
||||
'date_format:Y-m-d H:i:s',
|
||||
'nullable',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$request->validate($rules);
|
||||
|
||||
$account = new Account();
|
||||
$account->username = $request->get('username');
|
||||
$account->activated = false;
|
||||
|
|
@ -93,7 +67,7 @@ class AccountService
|
|||
$account->user_agent = config('app.name');
|
||||
$account->dtmf_protocol = $request->get('dtmf_protocol');
|
||||
|
||||
if ($asAdmin) {
|
||||
if ($request->asAdmin) {
|
||||
$account->email = $request->get('email');
|
||||
$account->display_name = $request->get('display_name');
|
||||
$account->activated = $request->has('activated') ? (bool)$request->get('activated') : false;
|
||||
|
|
@ -108,7 +82,7 @@ class AccountService
|
|||
|
||||
$account->save();
|
||||
|
||||
if ($asAdmin) {
|
||||
if ($request->asAdmin) {
|
||||
if ((!$request->has('activated') || !(bool)$request->get('activated'))
|
||||
&& $request->has('confirmation_key_expires')) {
|
||||
$actionvationExpiration = new ActivationExpiration();
|
||||
|
|
@ -128,18 +102,23 @@ class AccountService
|
|||
|
||||
$account->updatePassword($request->get('password'), $request->get('algorithm'));
|
||||
|
||||
if ($this->api && !$asAdmin) {
|
||||
if ($request->api && !$request->asAdmin) {
|
||||
$token = AccountCreationToken::where('token', $request->get('account_creation_token'))->first();
|
||||
$token->consume();
|
||||
$token->account_id = $account->id;
|
||||
$token->save();
|
||||
|
||||
Log::channel('events')->info('API: AccountCreationToken redeemed', ['token' => $request->get('account_creation_token')]);
|
||||
}
|
||||
|
||||
Log::channel('events')->info('API: AccountCreationToken redeemed', ['token' => $request->get('account_creation_token')]);
|
||||
Log::channel('events')->info(
|
||||
$request->asAdmin
|
||||
? 'Account Service as Admin: Account created'
|
||||
: 'Account Service: Account created',
|
||||
['id' => $account->identifier]
|
||||
);
|
||||
|
||||
Log::channel('events')->info($asAdmin ? 'Account Service as Admin: Account created' : 'Account Service: Account created', ['id' => $account->identifier]);
|
||||
|
||||
if (!$this->api) {
|
||||
if (!$request->api) {
|
||||
if (!empty(config('app.newsletter_registration_address')) && $request->has('newsletter')) {
|
||||
Mail::to(config('app.newsletter_registration_address'))->send(new NewsletterRegistration($account));
|
||||
}
|
||||
|
|
@ -152,6 +131,82 @@ class AccountService
|
|||
return Account::withoutGlobalScopes()->find($account->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Account update
|
||||
*/
|
||||
public function update(UpdateRequest $request, int $accountId): ?Account
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
if ($request->asAdmin) {
|
||||
$account->username = $request->get('username') ?? $account->username;
|
||||
$account->domain = $request->has('domain') ? resolveDomain($request) : $account->domain;
|
||||
$account->email = $request->get('email');
|
||||
$account->display_name = $request->get('display_name');
|
||||
$account->dtmf_protocol = $request->get('dtmf_protocol');
|
||||
$account->user_agent = $request->header('User-Agent') ?? config('app.name');
|
||||
$account->admin = $request->has('admin') && (bool)$request->get('admin');
|
||||
|
||||
if ($request->api && $request->has('admin')) {
|
||||
$account->admin = (bool)$request->get('admin');
|
||||
}
|
||||
|
||||
if (!$request->api && $request->has('role')) {
|
||||
$account->setRole($request->get('role'));
|
||||
}
|
||||
|
||||
if (!$request->api && $request->has('activated')) {
|
||||
$account->activated = $request->get('activated') == 'true';
|
||||
}
|
||||
|
||||
if (!$request->api && $request->has('blocked')) {
|
||||
$account->blocked = $request->get('blocked') == 'true';
|
||||
}
|
||||
|
||||
if ($request->get('password')) {
|
||||
$account->updatePassword(
|
||||
$request->get('password'),
|
||||
$request->api ? $request->get('algorithm') : null
|
||||
);
|
||||
}
|
||||
|
||||
$account->save();
|
||||
|
||||
$account->phone = $request->get('phone');
|
||||
}
|
||||
|
||||
Log::channel('events')->info(
|
||||
$request->asAdmin
|
||||
? 'Account Service as Admin: Account updated'
|
||||
: 'Account Service: Account updated',
|
||||
['id' => $account->identifier]
|
||||
);
|
||||
|
||||
if (function_exists('accountServiceAccountEditedHook')) {
|
||||
accountServiceAccountEditedHook($request, $account);
|
||||
}
|
||||
|
||||
return Account::withoutGlobalScopes()->find($account->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Account destroy
|
||||
*/
|
||||
public function destroy(Request $request, int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->delete();
|
||||
|
||||
Log::channel('events')->info(
|
||||
'Account Service: Account destroyed',
|
||||
['id' => $account->identifier]
|
||||
);
|
||||
|
||||
if (function_exists('accountServiceAccountDestroyedHook')) {
|
||||
accountServiceAccountDestroyedHook($request, $account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a phone number to an account
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,3 +20,29 @@ function accountServiceAccountCreatedHook(Request $request, Account $account)
|
|||
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Run specific code if an account was edited
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
function accountServiceAccountEditedHook(Request $request, Account $account)
|
||||
{
|
||||
/*
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Run specific code if an account was destroed
|
||||
* @param Request $request
|
||||
* @param Account $account
|
||||
* @return void
|
||||
*/
|
||||
function accountServiceAccountDestroyedHook(Request $request, Account $account)
|
||||
{
|
||||
/*
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
@ -255,5 +255,4 @@
|
|||
<a class="btn" href="{{ route('admin.account.account_type.create', $account) }}">Add</a>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -310,16 +310,17 @@ JSON parameters:
|
|||
### `PUT /accounts/{id}`
|
||||
<span class="badge badge-warning">Admin</span>
|
||||
|
||||
Update an existing account.
|
||||
Update an existing account. Ensure to resend all the parameters to not reset them.
|
||||
|
||||
JSON parameters:
|
||||
|
||||
* `username` unique username, minimum 6 characters
|
||||
* `domain` **not configurable by default**. Only configurable if `APP_ADMINS_MANAGE_MULTI_DOMAINS` is set to `true` in the global configuration. Otherwise `APP_SIP_DOMAIN` is used.
|
||||
* `password` required minimum 6 characters
|
||||
* `algorithm` required, values can be `SHA-256` or `MD5`
|
||||
* `display_name` optional, string
|
||||
* `email` optional, must be an email, must be unique if `ACCOUNT_EMAIL_UNIQUE` is set to `true`
|
||||
* `admin` optional, a boolean, set to `false` by default, create an admin account
|
||||
* `admin` optional, a boolean, set to `false` by default
|
||||
* `phone` optional, a phone number, set a phone number to the account
|
||||
* `dtmf_protocol` optional, values must be `sipinfo`, `sipmessage` or `rfc2833`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue