From 48323477cf40fa472d02be44fff38ef7345419f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Jaussoin?= Date: Tue, 26 Oct 2021 15:08:31 +0200 Subject: [PATCH] Complete the authenticated account contacts tests and fix the related documentation Cleanup the returned Vcard 4.0 formats Implement the recently introducted REST endpoints in the admin panels Add account actions logs to the new Controllers --- flexiapi/app/AccountAction.php | 12 + .../Admin/AccountAccountTypeController.php | 67 ++++++ .../Admin/AccountActionController.php | 119 ++++++++++ .../Admin/AccountContactController.php | 78 ++++++ .../Controllers/Admin/AccountController.php | 2 + .../Admin/AccountTypeController.php | 104 ++++++++ .../Api/Admin/AccountActionController.php | 4 +- flexiapi/composer.lock | 223 +++++++++--------- flexiapi/composer.phar | Bin 2268732 -> 2283840 bytes ...7_150641_make_account_types_key_unique.php | 24 ++ flexiapi/database/seeds/AccountTypeSeeder.php | 6 +- flexiapi/public/css/style.css | 5 + .../resources/views/account/panel.blade.php | 6 + .../account/account_type/create.blade.php | 41 ++++ .../account/action/create_edit.blade.php | 49 ++++ .../admin/account/action/delete.blade.php | 31 +++ .../admin/account/contact/create.blade.php | 33 +++ .../admin/account/contact/delete.blade.php | 31 +++ .../views/admin/account/create_edit.blade.php | 5 + .../views/admin/account/delete.blade.php | 2 +- .../views/admin/account/index.blade.php | 2 - .../views/admin/account/show.blade.php | 62 ++++- .../admin/account/type/create_edit.blade.php | 38 +++ .../views/admin/account/type/delete.blade.php | 28 +++ .../views/admin/account/type/index.blade.php | 44 ++++ .../resources/views/parts/errors.blade.php | 7 + flexiapi/routes/web.php | 28 +++ flexisip-account-manager.spec | 2 +- 28 files changed, 930 insertions(+), 123 deletions(-) create mode 100644 flexiapi/app/Http/Controllers/Admin/AccountAccountTypeController.php create mode 100644 flexiapi/app/Http/Controllers/Admin/AccountActionController.php create mode 100644 flexiapi/app/Http/Controllers/Admin/AccountContactController.php create mode 100644 flexiapi/app/Http/Controllers/Admin/AccountTypeController.php create mode 100644 flexiapi/database/migrations/2021_10_27_150641_make_account_types_key_unique.php create mode 100644 flexiapi/resources/views/admin/account/account_type/create.blade.php create mode 100644 flexiapi/resources/views/admin/account/action/create_edit.blade.php create mode 100644 flexiapi/resources/views/admin/account/action/delete.blade.php create mode 100644 flexiapi/resources/views/admin/account/contact/create.blade.php create mode 100644 flexiapi/resources/views/admin/account/contact/delete.blade.php create mode 100644 flexiapi/resources/views/admin/account/type/create_edit.blade.php create mode 100644 flexiapi/resources/views/admin/account/type/delete.blade.php create mode 100644 flexiapi/resources/views/admin/account/type/index.blade.php diff --git a/flexiapi/app/AccountAction.php b/flexiapi/app/AccountAction.php index af1d4ae..327cafd 100644 --- a/flexiapi/app/AccountAction.php +++ b/flexiapi/app/AccountAction.php @@ -9,6 +9,18 @@ class AccountAction extends Model { use HasFactory; + public static $protocols = ['sipinfo' => 'SIPInfo', 'rfc2833' => 'RFC2833']; + + public static function protocolsRule() + { + return implode(',', array_keys(self::$protocols)); + } + + public function getResolvedProtocolAttribute() + { + return self::$protocols[$this->attributes['protocol']]; + } + public function account() { return $this->belongsTo('App\Account'); diff --git a/flexiapi/app/Http/Controllers/Admin/AccountAccountTypeController.php b/flexiapi/app/Http/Controllers/Admin/AccountAccountTypeController.php new file mode 100644 index 0000000..4665c72 --- /dev/null +++ b/flexiapi/app/Http/Controllers/Admin/AccountAccountTypeController.php @@ -0,0 +1,67 @@ +. +*/ + +namespace App\Http\Controllers\Admin; + +use App\Http\Controllers\Controller; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; + +use App\Account; +use App\AccountType; + +class AccountAccountTypeController extends Controller +{ + public function create(Account $account) + { + return view('admin.account.account_type.create', [ + 'account' => $account, + 'account_types' => AccountType::whereNotIn('id', function($query) use ($account) { + $query->select('account_type_id') + ->from('account_account_type') + ->where('account_id', $account->id); + })->pluck('key', 'id') + ]); + } + + public function store(Request $request, Account $account) + { + $request->validate([ + 'account_type_id' => ['required', 'exists:account_types,id'], + ]); + + $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.show', $account); + } + + public function destroy(Request $request, Account $account, int $typeId) + { + $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.show', $account); + } +} diff --git a/flexiapi/app/Http/Controllers/Admin/AccountActionController.php b/flexiapi/app/Http/Controllers/Admin/AccountActionController.php new file mode 100644 index 0000000..3b21605 --- /dev/null +++ b/flexiapi/app/Http/Controllers/Admin/AccountActionController.php @@ -0,0 +1,119 @@ +. +*/ + +namespace App\Http\Controllers\Admin; + +use App\Http\Controllers\Controller; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; + +use App\Account; +use App\AccountAction; +use App\Rules\NoUppercase; + +class AccountActionController extends Controller +{ + public function create(Account $account) + { + return view('admin.account.action.create_edit', [ + 'action' => new AccountAction, + 'account' => $account, + 'protocols' => AccountAction::$protocols + ]); + } + + public function store(Request $request, Account $account) + { + $request->validate([ + 'key' => ['required', 'alpha_dash', new NoUppercase], + 'code' => ['required', 'alpha_num', new NoUppercase], + 'protocol' => 'required|in:' . AccountAction::protocolsRule() + ]); + + $accountAction = new AccountAction; + $accountAction->account_id = $account->id; + $accountAction->key = $request->get('key'); + $accountAction->code = $request->get('code'); + $accountAction->protocol = $request->get('protocol'); + $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.show', $accountAction->account); + } + + public function edit(Account $account, int $actionId) + { + $accountAction = $account->actions() + ->where('id', $actionId) + ->firstOrFail(); + + return view('admin.account.action.create_edit', [ + 'action' => $accountAction, + 'account' => $account, + 'protocols' => AccountAction::$protocols + ]); + } + + public function update(Request $request, Account $account, int $actionId) + { + $request->validate([ + 'key' => ['alpha_dash', new NoUppercase], + 'code' => ['alpha_num', new NoUppercase], + 'protocol' => 'in:' . AccountAction::protocolsRule() + ]); + + $accountAction = $account->actions() + ->where('id', $actionId) + ->firstOrFail(); + $accountAction->key = $request->get('key'); + $accountAction->code = $request->get('code'); + $accountAction->protocol = $request->get('protocol'); + $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.show', $account); + } + + public function delete(Account $account, int $actionId) + { + return view('admin.account.action.delete', [ + 'action' => $account->actions() + ->where('id', $actionId) + ->firstOrFail() + ]); + } + + public function destroy(Request $request, Account $account, int $actionId) + { + $accountAction = $account->actions() + ->where('id', $actionId) + ->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.show', $accountAction->account); + } +} diff --git a/flexiapi/app/Http/Controllers/Admin/AccountContactController.php b/flexiapi/app/Http/Controllers/Admin/AccountContactController.php new file mode 100644 index 0000000..a2b2de4 --- /dev/null +++ b/flexiapi/app/Http/Controllers/Admin/AccountContactController.php @@ -0,0 +1,78 @@ +. +*/ + +namespace App\Http\Controllers\Admin; + +use App\Http\Controllers\Controller; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; + +use App\Account; + +class AccountContactController extends Controller +{ + public function create(Account $account) + { + return view('admin.account.contact.create', [ + 'account' => $account + ]); + } + + public function store(Request $request, Account $account) + { + $contact = Account::sip($request->get('sip'))->first(); + + if (!$contact) { + $request->session()->flash('error', 'The contact SIP address doesn\'t exists'); + + return redirect()->route('admin.account.contact.create', $account); + } + + $account->contacts()->detach($contact->id); + $account->contacts()->attach($contact->id); + + $request->session()->flash('success', 'Contact successfully added'); + + Log::channel('events')->info('Web Admin: Account contact added', ['id' => $account->identifier, 'contact' => $contact->identifier]); + + return redirect()->route('admin.account.show', $account); + } + + public function delete(Account $account, int $contactId) + { + $contact = $account->contacts()->where('id', $contactId)->firstOrFail(); + + return view('admin.account.contact.delete', [ + 'account' => $account, + 'contact' => $contact + ]); + } + + public function destroy(Request $request, Account $account) + { + $contact = $account->contacts()->where('id', $request->get('contact_id'))->firstOrFail(); + + $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.show', $account); + } +} diff --git a/flexiapi/app/Http/Controllers/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Admin/AccountController.php index a89fa27..13dcfa8 100644 --- a/flexiapi/app/Http/Controllers/Admin/AccountController.php +++ b/flexiapi/app/Http/Controllers/Admin/AccountController.php @@ -67,6 +67,7 @@ class AccountController extends Controller $account = new Account; $account->username = $request->get('username'); $account->email = $request->get('email'); + $account->display_name = $request->get('display_name'); $account->domain = config('app.sip_domain'); $account->ip_address = $request->ip(); $account->creation_time = Carbon::now(); @@ -93,6 +94,7 @@ class AccountController extends Controller $account = Account::findOrFail($id); $account->username = $request->get('username'); $account->email = $request->get('email'); + $account->display_name = $request->get('display_name'); $account->save(); $this->fillPassword($request, $account); diff --git a/flexiapi/app/Http/Controllers/Admin/AccountTypeController.php b/flexiapi/app/Http/Controllers/Admin/AccountTypeController.php new file mode 100644 index 0000000..0d71660 --- /dev/null +++ b/flexiapi/app/Http/Controllers/Admin/AccountTypeController.php @@ -0,0 +1,104 @@ +. +*/ + +namespace App\Http\Controllers\Admin; + +use App\Http\Controllers\Controller; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; +use Illuminate\Validation\Rule; + +use App\AccountType; +use App\Rules\NoUppercase; + +class AccountTypeController extends Controller +{ + public function index() + { + return view('admin.account.type.index', ['types' => AccountType::all()]); + } + + public function create() + { + return view('admin.account.type.create_edit', [ + 'type' => new AccountType + ]); + } + + public function store(Request $request) + { + $request->validate([ + 'key' => ['required', 'alpha_dash', new NoUppercase, 'unique:account_types,key'], + ]); + + $accountType = new AccountType; + $accountType->key = $request->get('key'); + $accountType->save(); + + $request->session()->flash('success', 'Type successfully created'); + + return redirect()->route('admin.account.type.index'); + } + + public function edit(int $typeId) + { + return view('admin.account.type.create_edit', [ + 'type' => AccountType::findOrFail($typeId) + ]); + } + + public function update(Request $request, int $typeId) + { + $request->validate([ + 'key' => [ + 'required', + 'alpha_dash', + new NoUppercase, + Rule::unique('account_types')->ignore($typeId) + ] + ]); + + $accountType = AccountType::findOrFail($typeId); + $accountType->key = $request->get('key'); + $accountType->save(); + + $request->session()->flash('success', 'Type successfully updated'); + + return redirect()->route('admin.account.type.index'); + } + + public function delete(int $typeId) + { + return view('admin.account.type.delete', [ + 'type' => AccountType::findOrFail($typeId) + ]); + } + + public function destroy(Request $request, int $typeId) + { + $type = AccountType::findOrFail($typeId); + $type->delete(); + + $request->session()->flash('success', 'Type successfully destroyed'); + + Log::channel('events')->info('Web Admin: Account type deleted', ['type' => $type->key]); + + return redirect()->route('admin.account.type.index'); + } +} diff --git a/flexiapi/app/Http/Controllers/Api/Admin/AccountActionController.php b/flexiapi/app/Http/Controllers/Api/Admin/AccountActionController.php index d6a2e01..e3dca69 100644 --- a/flexiapi/app/Http/Controllers/Api/Admin/AccountActionController.php +++ b/flexiapi/app/Http/Controllers/Api/Admin/AccountActionController.php @@ -46,7 +46,7 @@ class AccountActionController extends Controller $request->validate([ 'key' => ['required', 'alpha_dash', new NoUppercase], 'code' => ['required', 'alpha_num', new NoUppercase], - 'protocol' => 'required|in:sipinfo,rfc2833' + 'protocol' => 'required|in:' . AccountAction::protocolsRule() ]); $accountAction = new AccountAction; @@ -64,7 +64,7 @@ class AccountActionController extends Controller $request->validate([ 'key' => ['alpha_dash', new NoUppercase], 'code' => ['alpha_num', new NoUppercase], - 'protocol' => 'in:sipinfo,rfc2833' + 'protocol' => 'in:' . AccountAction::protocolsRule() ]); $accountAction = Account::findOrFail($id) diff --git a/flexiapi/composer.lock b/flexiapi/composer.lock index 182c0cd..e988d13 100644 --- a/flexiapi/composer.lock +++ b/flexiapi/composer.lock @@ -232,34 +232,30 @@ }, { "name": "doctrine/inflector", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210" + "reference": "8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/9cf661f4eb38f7c881cac67c75ea9b00bf97b210", - "reference": "9cf661f4eb38f7c881cac67c75ea9b00bf97b210", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89", + "reference": "8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^7.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-strict-rules": "^0.11", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "doctrine/coding-standard": "^8.2", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "vimeo/psalm": "^4.10" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" @@ -307,7 +303,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.x" + "source": "https://github.com/doctrine/inflector/tree/2.0.4" }, "funding": [ { @@ -323,7 +319,7 @@ "type": "tidelift" } ], - "time": "2020-05-29T15:13:26+00:00" + "time": "2021-10-22T20:16:43+00:00" }, { "name": "doctrine/lexer", @@ -848,16 +844,16 @@ }, { "name": "guzzlehttp/promises", - "version": "1.5.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0" + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0", - "reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0", + "url": "https://api.github.com/repos/guzzle/promises/zipball/fe752aedc9fd8fcca3fe7ad05d419d32998a06da", + "reference": "fe752aedc9fd8fcca3fe7ad05d419d32998a06da", "shasum": "" }, "require": { @@ -912,7 +908,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.0" + "source": "https://github.com/guzzle/promises/tree/1.5.1" }, "funding": [ { @@ -928,7 +924,7 @@ "type": "tidelift" } ], - "time": "2021-10-07T13:05:22+00:00" + "time": "2021-10-22T20:56:57+00:00" }, { "name": "guzzlehttp/psr7", @@ -1042,16 +1038,16 @@ }, { "name": "laravel/framework", - "version": "v8.64.0", + "version": "v8.68.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "3337c029e1bb31d9712d27437cc27010ba302c9e" + "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/3337c029e1bb31d9712d27437cc27010ba302c9e", - "reference": "3337c029e1bb31d9712d27437cc27010ba302c9e", + "url": "https://api.github.com/repos/laravel/framework/zipball/abe985ff1fb82dd04aab03bc1dc56e83fe61a59f", + "reference": "abe985ff1fb82dd04aab03bc1dc56e83fe61a59f", "shasum": "" }, "require": { @@ -1065,14 +1061,14 @@ "league/commonmark": "^1.3|^2.0.2", "league/flysystem": "^1.1", "monolog/monolog": "^2.0", - "nesbot/carbon": "^2.31", + "nesbot/carbon": "^2.53.1", "opis/closure": "^3.6", "php": "^7.3|^8.0", "psr/container": "^1.0", "psr/log": "^1.0 || ^2.0", "psr/simple-cache": "^1.0", "ramsey/uuid": "^4.2.2", - "swiftmailer/swiftmailer": "^6.0", + "swiftmailer/swiftmailer": "^6.3", "symfony/console": "^5.1.4", "symfony/error-handler": "^5.1.4", "symfony/finder": "^5.1.4", @@ -1127,22 +1123,23 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "^3.189.0", + "aws/aws-sdk-php": "^3.198.1", "doctrine/dbal": "^2.13.3|^3.1.2", - "filp/whoops": "^2.8", + "filp/whoops": "^2.14.3", "guzzlehttp/guzzle": "^6.5.5|^7.0.1", "league/flysystem-cached-adapter": "^1.0", "mockery/mockery": "^1.4.4", "orchestra/testbench-core": "^6.23", "pda/pheanstalk": "^4.0", "phpunit/phpunit": "^8.5.19|^9.5.8", - "predis/predis": "^1.1.2", + "predis/predis": "^1.1.9", "symfony/cache": "^5.1.4" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.189.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.198.1).", "brianium/paratest": "Required to run tests in parallel (^6.0).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.2).", + "ext-bcmath": "Required to use the multiple_of validation rule.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", "ext-memcached": "Required to use the memcache cache driver.", @@ -1150,7 +1147,7 @@ "ext-posix": "Required to use all features of the queue worker.", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", - "filp/whoops": "Required for friendly error pages in development (^2.8).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", @@ -1160,7 +1157,7 @@ "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", "phpunit/phpunit": "Required to use assertions and run tests (^8.5.19|^9.5.8).", - "predis/predis": "Required to use the predis connector (^1.1.2).", + "predis/predis": "Required to use the predis connector (^1.1.9).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0|^6.0).", "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).", @@ -1209,7 +1206,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-10-12T13:43:13+00:00" + "time": "2021-10-27T12:31:46+00:00" }, { "name": "laravel/serializable-closure", @@ -2695,16 +2692,16 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "15f7faf8508e04471f666633addacf54c0ab5933" + "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/15f7faf8508e04471f666633addacf54c0ab5933", - "reference": "15f7faf8508e04471f666633addacf54c0ab5933", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/8a5d5072dca8f48460fce2f4131fcc495eec654c", + "reference": "8a5d5072dca8f48460fce2f4131fcc495eec654c", "shasum": "" }, "require": { @@ -2716,7 +2713,7 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "symfony/phpunit-bridge": "^4.4|^5.0" + "symfony/phpunit-bridge": "^4.4|^5.4" }, "suggest": { "ext-intl": "Needed to support internationalized email addresses" @@ -2754,7 +2751,7 @@ ], "support": { "issues": "https://github.com/swiftmailer/swiftmailer/issues", - "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.7" + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.3.0" }, "funding": [ { @@ -2766,20 +2763,20 @@ "type": "tidelift" } ], - "time": "2021-03-09T12:30:35+00:00" + "time": "2021-10-18T15:26:12+00:00" }, { "name": "symfony/console", - "version": "v5.3.7", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a" + "reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a", - "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a", + "url": "https://api.github.com/repos/symfony/console/zipball/d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3", + "reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3", "shasum": "" }, "require": { @@ -2849,7 +2846,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.3.7" + "source": "https://github.com/symfony/console/tree/v5.3.10" }, "funding": [ { @@ -2865,7 +2862,7 @@ "type": "tidelift" } ], - "time": "2021-08-25T20:02:16+00:00" + "time": "2021-10-26T09:30:15+00:00" }, { "name": "symfony/css-selector", @@ -3374,16 +3371,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.3.7", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5" + "reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e36c8e5502b4f3f0190c675f1c1f1248a64f04e5", - "reference": "e36c8e5502b4f3f0190c675f1c1f1248a64f04e5", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9f34f02e8a5fdc7a56bafe011cea1ce97300e54c", + "reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c", "shasum": "" }, "require": { @@ -3427,7 +3424,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.3.7" + "source": "https://github.com/symfony/http-foundation/tree/v5.3.10" }, "funding": [ { @@ -3443,20 +3440,20 @@ "type": "tidelift" } ], - "time": "2021-08-27T11:20:35+00:00" + "time": "2021-10-11T15:41:55+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.3.9", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ceaf46a992f60e90645e7279825a830f733a17c5" + "reference": "703e4079920468e9522b72cf47fd76ce8d795e86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ceaf46a992f60e90645e7279825a830f733a17c5", - "reference": "ceaf46a992f60e90645e7279825a830f733a17c5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/703e4079920468e9522b72cf47fd76ce8d795e86", + "reference": "703e4079920468e9522b72cf47fd76ce8d795e86", "shasum": "" }, "require": { @@ -3539,7 +3536,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.3.9" + "source": "https://github.com/symfony/http-kernel/tree/v5.3.10" }, "funding": [ { @@ -3555,7 +3552,7 @@ "type": "tidelift" } ], - "time": "2021-09-28T10:25:11+00:00" + "time": "2021-10-29T08:36:48+00:00" }, { "name": "symfony/mime", @@ -4681,16 +4678,16 @@ }, { "name": "symfony/string", - "version": "v5.3.7", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5" + "reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5", - "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5", + "url": "https://api.github.com/repos/symfony/string/zipball/d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c", + "reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c", "shasum": "" }, "require": { @@ -4744,7 +4741,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.3.7" + "source": "https://github.com/symfony/string/tree/v5.3.10" }, "funding": [ { @@ -4760,20 +4757,20 @@ "type": "tidelift" } ], - "time": "2021-08-26T08:00:08+00:00" + "time": "2021-10-27T18:21:46+00:00" }, { "name": "symfony/translation", - "version": "v5.3.9", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886" + "reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", - "reference": "6e69f3551c1a3356cf6ea8d019bf039a0f8b6886", + "url": "https://api.github.com/repos/symfony/translation/zipball/6ef197aea2ac8b9cd63e0da7522b3771714035aa", + "reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa", "shasum": "" }, "require": { @@ -4839,7 +4836,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.3.9" + "source": "https://github.com/symfony/translation/tree/v5.3.10" }, "funding": [ { @@ -4855,7 +4852,7 @@ "type": "tidelift" } ], - "time": "2021-08-26T08:22:53+00:00" + "time": "2021-10-10T06:43:24+00:00" }, { "name": "symfony/translation-contracts", @@ -4937,16 +4934,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.3.8", + "version": "v5.3.10", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da" + "reference": "875432adb5f5570fff21036fd22aee244636b7d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/eaaea4098be1c90c8285543e1356a09c8aa5c8da", - "reference": "eaaea4098be1c90c8285543e1356a09c8aa5c8da", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/875432adb5f5570fff21036fd22aee244636b7d1", + "reference": "875432adb5f5570fff21036fd22aee244636b7d1", "shasum": "" }, "require": { @@ -5005,7 +5002,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.3.8" + "source": "https://github.com/symfony/var-dumper/tree/v5.3.10" }, "funding": [ { @@ -5021,7 +5018,7 @@ "type": "tidelift" } ], - "time": "2021-09-24T15:59:58+00:00" + "time": "2021-10-26T09:30:15+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -5290,23 +5287,23 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.6.2", + "version": "v3.6.4", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "70b89754913fd89fef16d0170a91dbc2a5cd633a" + "reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/70b89754913fd89fef16d0170a91dbc2a5cd633a", - "reference": "70b89754913fd89fef16d0170a91dbc2a5cd633a", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3c2d678269ba60e178bcd93e36f6a91c36b727f1", + "reference": "3c2d678269ba60e178bcd93e36f6a91c36b727f1", "shasum": "" }, "require": { "illuminate/routing": "^6|^7|^8", "illuminate/session": "^6|^7|^8", "illuminate/support": "^6|^7|^8", - "maximebf/debugbar": "^1.16.3", + "maximebf/debugbar": "^1.17.2", "php": ">=7.2", "symfony/debug": "^4.3|^5", "symfony/finder": "^4.3|^5" @@ -5320,7 +5317,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.5-dev" + "dev-master": "3.6-dev" }, "laravel": { "providers": [ @@ -5359,7 +5356,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.2" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.6.4" }, "funding": [ { @@ -5371,7 +5368,7 @@ "type": "github" } ], - "time": "2021-06-14T14:29:26+00:00" + "time": "2021-10-21T10:57:31+00:00" }, { "name": "doctrine/instantiator", @@ -5509,16 +5506,16 @@ }, { "name": "facade/ignition", - "version": "2.15.0", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "3ee6e94815462bcf09bca0efc1c9069685df8da3" + "reference": "23400e6cc565c9dcae2c53704b4de1c4870c0697" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/3ee6e94815462bcf09bca0efc1c9069685df8da3", - "reference": "3ee6e94815462bcf09bca0efc1c9069685df8da3", + "url": "https://api.github.com/repos/facade/ignition/zipball/23400e6cc565c9dcae2c53704b4de1c4870c0697", + "reference": "23400e6cc565c9dcae2c53704b4de1c4870c0697", "shasum": "" }, "require": { @@ -5582,7 +5579,7 @@ "issues": "https://github.com/facade/ignition/issues", "source": "https://github.com/facade/ignition" }, - "time": "2021-10-11T15:24:06+00:00" + "time": "2021-10-28T11:47:23+00:00" }, { "name": "facade/ignition-contracts", @@ -5816,21 +5813,21 @@ }, { "name": "maximebf/debugbar", - "version": "v1.17.1", + "version": "v1.17.3", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "0a3532556be0145603f8a9de23e76dc28eed7054" + "reference": "e8ac3499af0ea5b440908e06cc0abe5898008b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/0a3532556be0145603f8a9de23e76dc28eed7054", - "reference": "0a3532556be0145603f8a9de23e76dc28eed7054", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e8ac3499af0ea5b440908e06cc0abe5898008b3c", + "reference": "e8ac3499af0ea5b440908e06cc0abe5898008b3c", "shasum": "" }, "require": { "php": "^7.1|^8", - "psr/log": "^1.0", + "psr/log": "^1|^2|^3", "symfony/var-dumper": "^2.6|^3|^4|^5" }, "require-dev": { @@ -5875,9 +5872,9 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.1" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.3" }, - "time": "2021-08-01T09:19:02+00:00" + "time": "2021-10-19T12:33:27+00:00" }, { "name": "mockery/mockery", @@ -6262,16 +6259,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { @@ -6282,7 +6279,8 @@ "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -6312,9 +6310,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" }, - "time": "2020-09-03T19:13:55+00:00" + "time": "2021-10-19T17:43:47+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -6435,23 +6433,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.7", + "version": "9.2.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" + "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cf04e88a2e3c56fc1a65488afd493325b4c1bc3e", + "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.12.0", + "nikic/php-parser": "^4.13.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -6500,7 +6498,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.8" }, "funding": [ { @@ -6508,7 +6506,7 @@ "type": "github" } ], - "time": "2021-09-17T05:39:03+00:00" + "time": "2021-10-30T08:01:38+00:00" }, { "name": "phpunit/php-file-iterator", @@ -7707,7 +7705,6 @@ "type": "github" } ], - "abandoned": true, "time": "2020-09-28T06:45:17+00:00" }, { diff --git a/flexiapi/composer.phar b/flexiapi/composer.phar index 0e7ab8212c170ea286a13f6113154981bc8b7a85..208773a73cb74970133b9d748d27954c8063bb84 100755 GIT binary patch delta 36060 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�V8DjLo4<17l;T4l;(4PtJ*3 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 zFhunique('key'); + }); + + } + + public function down() + { + Schema::table('account_types', function (Blueprint $table) { + $table->dropUnique('account_types_key_unique'); + }); + + } +} diff --git a/flexiapi/database/seeds/AccountTypeSeeder.php b/flexiapi/database/seeds/AccountTypeSeeder.php index 09253fc..4f49405 100644 --- a/flexiapi/database/seeds/AccountTypeSeeder.php +++ b/flexiapi/database/seeds/AccountTypeSeeder.php @@ -9,7 +9,9 @@ class AccountTypeSeeder extends Seeder { public function run() { - AccountType::create(['key' => 'phone']); - AccountType::create(['key' => 'door']); + AccountType::create(['key' => 'device_audio_intercom']); + AccountType::create(['key' => 'device_video_intercom']); + AccountType::create(['key' => 'device_security_camera']); + AccountType::create(['key' => 'device_internal_unit']); } } diff --git a/flexiapi/public/css/style.css b/flexiapi/public/css/style.css index 8fe3cf9..39e16df 100644 --- a/flexiapi/public/css/style.css +++ b/flexiapi/public/css/style.css @@ -99,6 +99,11 @@ input.form-control { padding: 0 1.5rem; } +.btn.btn-sm { + padding: 0 0.75rem; + line-height: 1.75rem; +} + .btn.btn-centered { display: block; margin: 1rem auto; diff --git a/flexiapi/resources/views/account/panel.blade.php b/flexiapi/resources/views/account/panel.blade.php index 909853f..acc4027 100644 --- a/flexiapi/resources/views/account/panel.blade.php +++ b/flexiapi/resources/views/account/panel.blade.php @@ -54,6 +54,12 @@

Manage the Flexisip accounts

+ +
+
Account types
+
+

Manage the account types

+
Statistics
diff --git a/flexiapi/resources/views/admin/account/account_type/create.blade.php b/flexiapi/resources/views/admin/account/account_type/create.blade.php new file mode 100644 index 0000000..d71f5cc --- /dev/null +++ b/flexiapi/resources/views/admin/account/account_type/create.blade.php @@ -0,0 +1,41 @@ +@extends('layouts.account') + +@section('breadcrumb') +
+ + +@endsection + +@section('content') + +

Add a Type to the Account

+ +@if ($account_types->count() == 0) + +@else + +{!! Form::model($account, [ + 'route' => ['admin.account.account_type.store', $account->id], + 'method' => 'post' +]) !!} +
+
+ {!! Form::label('account_type_id', 'Account Type') !!} + {!! Form::select('account_type_id', $account_types, null, ['class' => 'form-control']); !!} +
+
+ +{!! Form::submit('Add', ['class' => 'btn btn-success btn-centered']) !!} +{!! Form::close() !!} + +@endif + +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/action/create_edit.blade.php b/flexiapi/resources/views/admin/account/action/create_edit.blade.php new file mode 100644 index 0000000..7370897 --- /dev/null +++ b/flexiapi/resources/views/admin/account/action/create_edit.blade.php @@ -0,0 +1,49 @@ +@extends('layouts.account') + +@section('breadcrumb') + + + +@endsection + +@section('content') + +@if ($action->id) +

Edit an account action

+@else +

Create an account action

+@endif + +{!! Form::model($action, [ + 'route' => $action->id + ? ['admin.account.action.update', $action->account->id, $action->id] + : ['admin.account.action.store', $account->id], + 'method' => $action->id + ? 'put' + : 'post' +]) !!} +
+
+ {!! Form::label('key', 'Key') !!} + {!! Form::text('key', $action->key, ['class' => 'form-control', 'placeholder' => 'action_key']); !!} +
+
+ {!! Form::label('code', 'Code') !!} + {!! Form::text('code', $action->code, ['class' => 'form-control', 'placeholder' => '12ab45']); !!} +
+
+ {!! Form::label('protocol', 'Protocol') !!} + {!! Form::select('protocol', $protocols, $action->protocol, ['class' => 'form-control']); !!} +
+
+ +{!! Form::submit(($action->id) ? 'Update' : 'Create', ['class' => 'btn btn-success btn-centered']) !!} +{!! Form::close() !!} + +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/action/delete.blade.php b/flexiapi/resources/views/admin/account/action/delete.blade.php new file mode 100644 index 0000000..bf960b3 --- /dev/null +++ b/flexiapi/resources/views/admin/account/action/delete.blade.php @@ -0,0 +1,31 @@ +@extends('layouts.account') + +@section('breadcrumb') + + + + +@endsection + +@section('content') + +

Delete an account action

+ +{!! Form::open(['route' => ['admin.account.action.destroy', $action->account, $action], 'method' => 'delete']) !!} + +

You are going to permanently delete the following account action. Please confirm your action.

+

{{ $action->key }}

+ +{!! Form::hidden('account_id', $action->account->id) !!} +{!! Form::hidden('action_id', $action->id) !!} + +{!! Form::submit('Delete', ['class' => 'btn btn-danger btn-centered']) !!} +{!! Form::close() !!} + +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/contact/create.blade.php b/flexiapi/resources/views/admin/account/contact/create.blade.php new file mode 100644 index 0000000..2022203 --- /dev/null +++ b/flexiapi/resources/views/admin/account/contact/create.blade.php @@ -0,0 +1,33 @@ +@extends('layouts.account') + +@section('breadcrumb') + + + +@endsection + +@section('content') + +

Add a Contact to the Account

+ +{!! Form::model($account, [ + 'route' => ['admin.account.contact.store', $account->id], + 'method' => 'post' +]) !!} +
+
+ {!! Form::label('sip', 'Adresse SIP') !!} + {!! Form::text('sip', null, ['class' => 'form-control', 'placeholder' => 'username@server.com']); !!} +
+
+ +{!! Form::submit('Add', ['class' => 'btn btn-success btn-centered']) !!} +{!! Form::close() !!} + +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/contact/delete.blade.php b/flexiapi/resources/views/admin/account/contact/delete.blade.php new file mode 100644 index 0000000..a8aded1 --- /dev/null +++ b/flexiapi/resources/views/admin/account/contact/delete.blade.php @@ -0,0 +1,31 @@ +@extends('layouts.account') + +@section('breadcrumb') + + + + +@endsection + +@section('content') + +

Delete an account contact

+ +{!! Form::open(['route' => ['admin.account.contact.destroy', $account], 'method' => 'delete']) !!} + +

You are going to remove the following contact from the contact list. Please confirm your action.

+

{{ $contact->identifier }}

+ +{!! Form::hidden('account_id', $account->id) !!} +{!! Form::hidden('contact_id', $contact->id) !!} + +{!! Form::submit('Remove', ['class' => 'btn btn-danger btn-centered']) !!} +{!! Form::close() !!} + +@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 123f585..6dc5808 100644 --- a/flexiapi/resources/views/admin/account/create_edit.blade.php +++ b/flexiapi/resources/views/admin/account/create_edit.blade.php @@ -68,6 +68,11 @@ {!! Form::email('email', $account->email, ['class' => 'form-control', 'placeholder' => 'Email']); !!}
+
+ {!! Form::label('display_name', 'Display Name') !!} + {!! Form::text('display_name', $account->display_name, ['class' => 'form-control', 'placeholder' => 'John Doe']); !!} +
+
{!! Form::label('phone', 'Phone') !!} {!! Form::text('phone', $account->phone, ['class' => 'form-control', 'placeholder' => '+12123123']); !!} diff --git a/flexiapi/resources/views/admin/account/delete.blade.php b/flexiapi/resources/views/admin/account/delete.blade.php index cab8592..184df86 100644 --- a/flexiapi/resources/views/admin/account/delete.blade.php +++ b/flexiapi/resources/views/admin/account/delete.blade.php @@ -16,7 +16,7 @@ {!! Form::open(['route' => 'admin.account.destroy', 'method' => 'delete']) !!} -

You are going to permanently delete the following account account. Please confirm your action.

+

You are going to permanently delete the following account. Please confirm your action.

{{ $account->identifier }}

{!! Form::hidden('account_id', $account->id) !!} diff --git a/flexiapi/resources/views/admin/account/index.blade.php b/flexiapi/resources/views/admin/account/index.blade.php index 0894104..6342c3f 100644 --- a/flexiapi/resources/views/admin/account/index.blade.php +++ b/flexiapi/resources/views/admin/account/index.blade.php @@ -25,7 +25,6 @@
- @@ -59,7 +58,6 @@ @endforeach -
{{ $account->creation_time}}
diff --git a/flexiapi/resources/views/admin/account/show.blade.php b/flexiapi/resources/views/admin/account/show.blade.php index 209b8ca..217f8e0 100644 --- a/flexiapi/resources/views/admin/account/show.blade.php +++ b/flexiapi/resources/views/admin/account/show.blade.php @@ -20,7 +20,8 @@ Id: {{ $account->id }}
Identifier: {{ $account->identifier }}
Email: {{ $account->email }}
- Phone number:@if ($account->alias) {{ $account->phone }} @else No number @endif + @if ($account->alias)Phone number: {{ $account->phone }}
@endif + @if ($account->display_name)Display name: {{ $account->display_name }}
@endif

@if ($account->sha256Password) @@ -43,8 +44,65 @@ Not Admin Add admin role @endif +

Contacts

+ + + + @foreach ($account->contacts as $contact) + + + + + @endforeach + +
{{ $contact->identifier }} + Delete +
+ +Add + +

Actions

+ + + + @foreach ($account->actions as $action) + + + + + + + @endforeach + +
{{ $action->key }}{{ $action->code }}{{ $action->resolvedProtocol }} + Edit + Delete +
+ +Add + +

Types

+ + + + @foreach ($account->types as $type) + + + + + @endforeach + +
{{ $type->key }} + {!! Form::open(['route' => ['admin.account.account_type.destroy', $account, $type->id], 'method' => 'delete']) !!} + {!! Form::submit('Delete', ['class' => 'btn btn-sm mr-2']) !!} + {!! Form::close() !!} +
+ +Add + +

Provisioning

+ @if ($account->confirmation_key) -

Provisioning

Share the following picture with the user or the one-time-use link bellow.


diff --git a/flexiapi/resources/views/admin/account/type/create_edit.blade.php b/flexiapi/resources/views/admin/account/type/create_edit.blade.php new file mode 100644 index 0000000..d2afee3 --- /dev/null +++ b/flexiapi/resources/views/admin/account/type/create_edit.blade.php @@ -0,0 +1,38 @@ +@extends('layouts.account') + +@section('breadcrumb') + + +@endsection + +@section('content') + +@if ($type->id) +

Edit an account type

+@else +

Create an account type

+@endif + +{!! Form::model($type, [ + 'route' => $type->id + ? ['admin.account.type.update', $type->id] + : ['admin.account.type.store'], + 'method' => $type->id + ? 'put' + : 'post' +]) !!} +
+
+ {!! Form::label('key', 'Key') !!} + {!! Form::text('key', $type->key, ['class' => 'form-control', 'placeholder' => 'type_key']); !!} +
+
+ +{!! Form::submit(($type->id) ? 'Update' : 'Create', ['class' => 'btn btn-success btn-centered']) !!} +{!! Form::close() !!} + +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/type/delete.blade.php b/flexiapi/resources/views/admin/account/type/delete.blade.php new file mode 100644 index 0000000..5de1b04 --- /dev/null +++ b/flexiapi/resources/views/admin/account/type/delete.blade.php @@ -0,0 +1,28 @@ +@extends('layouts.account') + +@section('breadcrumb') + + + + +@endsection + +@section('content') + +

Delete an account type

+ +{!! Form::open(['route' => ['admin.account.type.destroy', $type->id], 'method' => 'delete']) !!} + +

You are going to permanently delete the following type. Please confirm your action.

+

{{ $type->key }}

+ +{!! Form::submit('Delete', ['class' => 'btn btn-danger btn-centered']) !!} +{!! Form::close() !!} + +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/admin/account/type/index.blade.php b/flexiapi/resources/views/admin/account/type/index.blade.php new file mode 100644 index 0000000..6fbc740 --- /dev/null +++ b/flexiapi/resources/views/admin/account/type/index.blade.php @@ -0,0 +1,44 @@ +@extends('layouts.account') + +@section('breadcrumb') + + +@endsection + +@section('content') + +
+
+ Create +

Types

+
+
+ + + + + + + + + + @foreach ($types as $type) + + + + + @endforeach + + +
Key
+ {{ $type->key }} + + Edit + Delete +
+ +@endsection \ No newline at end of file diff --git a/flexiapi/resources/views/parts/errors.blade.php b/flexiapi/resources/views/parts/errors.blade.php index 63f37d5..63c0144 100644 --- a/flexiapi/resources/views/parts/errors.blade.php +++ b/flexiapi/resources/views/parts/errors.blade.php @@ -8,6 +8,13 @@ @endif +@if (Session::has('error')) +
+ {{Session::get('error')}} +
+@endif + + @if (Session::has('success'))
{{Session::get('success')}} diff --git a/flexiapi/routes/web.php b/flexiapi/routes/web.php index 8da7081..d82a546 100644 --- a/flexiapi/routes/web.php +++ b/flexiapi/routes/web.php @@ -79,6 +79,26 @@ Route::group(['middleware' => 'auth.admin'], function () { Route::get('admin/statistics/week', 'Admin\StatisticsController@showWeek')->name('admin.statistics.show.week'); Route::get('admin/statistics/month', 'Admin\StatisticsController@showMonth')->name('admin.statistics.show.month'); + // Account types + Route::get('admin/accounts/types', 'Admin\AccountTypeController@index')->name('admin.account.type.index'); + Route::get('admin/accounts/types/create', 'Admin\AccountTypeController@create')->name('admin.account.type.create'); + Route::post('admin/accounts/types', 'Admin\AccountTypeController@store')->name('admin.account.type.store'); + Route::get('admin/accounts/types/{type_id}/edit', 'Admin\AccountTypeController@edit')->name('admin.account.type.edit'); + Route::put('admin/accounts/types/{type_id}', 'Admin\AccountTypeController@update')->name('admin.account.type.update'); + Route::get('admin/accounts/types/{type_id}/delete', 'Admin\AccountTypeController@delete')->name('admin.account.type.delete'); + Route::delete('admin/accounts/types/{type_id}', 'Admin\AccountTypeController@destroy')->name('admin.account.type.destroy'); + + Route::get('admin/accounts/{account}/types/create', 'Admin\AccountAccountTypeController@create')->name('admin.account.account_type.create'); + Route::post('admin/accounts/{account}/types', 'Admin\AccountAccountTypeController@store')->name('admin.account.account_type.store'); + Route::delete('admin/accounts/{account}/types/{type_id}', 'Admin\AccountAccountTypeController@destroy')->name('admin.account.account_type.destroy'); + + // Contacts + Route::get('admin/accounts/{account}/contacts/create', 'Admin\AccountContactController@create')->name('admin.account.contact.create'); + Route::post('admin/accounts/{account}/contacts', 'Admin\AccountContactController@store')->name('admin.account.contact.store'); + Route::get('admin/accounts/{account}/contacts/{contact_id}/delete', 'Admin\AccountContactController@delete')->name('admin.account.contact.delete'); + Route::delete('admin/accounts/{account}/contacts', 'Admin\AccountContactController@destroy')->name('admin.account.contact.destroy'); + + // Accounts Route::get('admin/accounts/{account}/show', 'Admin\AccountController@show')->name('admin.account.show'); Route::get('admin/accounts/{account}/activate', 'Admin\AccountController@activate')->name('admin.account.activate'); @@ -100,4 +120,12 @@ Route::group(['middleware' => 'auth.admin'], function () { Route::get('admin/accounts/{search?}', 'Admin\AccountController@index')->name('admin.account.index'); Route::post('admin/accounts/search', 'Admin\AccountController@search')->name('admin.account.search'); + + // Account actions + Route::get('admin/accounts/{account}/actions/create', 'Admin\AccountActionController@create')->name('admin.account.action.create'); + Route::post('admin/accounts/{account}/actions', 'Admin\AccountActionController@store')->name('admin.account.action.store'); + Route::get('admin/accounts/{account}/actions/{action_id}/edit', 'Admin\AccountActionController@edit')->name('admin.account.action.edit'); + Route::put('admin/accounts/{account}/actions/{action_id}', 'Admin\AccountActionController@update')->name('admin.account.action.update'); + Route::get('admin/accounts/{account}/actions/{action_id}/delete', 'Admin\AccountActionController@delete')->name('admin.account.action.delete'); + Route::delete('admin/accounts/{account}/actions/{action_id}', 'Admin\AccountActionController@destroy')->name('admin.account.action.destroy'); }); \ No newline at end of file diff --git a/flexisip-account-manager.spec b/flexisip-account-manager.spec index c98f9fb..8bb279d 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 109 +%define build_number 110 %define var_dir /var/opt/belledonne-communications %define opt_dir /opt/belledonne-communications/share/flexisip-account-manager