diff --git a/.gitignore b/.gitignore index 141c23e..d29257c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ rpmbuild/ .env.* -xmlrpc/src/vendor flexiapi/node_modules flexiapi/public/hot flexiapi/public/storage diff --git a/.gitlab-ci-files/package.yml b/.gitlab-ci-files/package.yml index 8d3b177..abf8c18 100644 --- a/.gitlab-ci-files/package.yml +++ b/.gitlab-ci-files/package.yml @@ -17,7 +17,6 @@ remi-phpredis-package: needs: - remi-igbinary-package - remi-msgpack-package - - remi-xmlrpc-package variables: PACKAGE: $PHP_REDIS_REMI_VERSION @@ -31,11 +30,6 @@ remi-msgpack-package: variables: PACKAGE: $PHP_MSGPACK_REMI_VERSION -remi-xmlrpc-package: - extends: .remi-package - variables: - PACKAGE: $PHP_XMLRPC_REMI_VERSION - .remi-package: extends: .package image: gitlab.linphone.org:4567/bc/public/docker/rocky8-php:$ROCKY_8_IMAGE_VERSION diff --git a/.gitlab-ci-files/test.yml b/.gitlab-ci-files/test.yml index 9c1558d..28add12 100644 --- a/.gitlab-ci-files/test.yml +++ b/.gitlab-ci-files/test.yml @@ -3,7 +3,6 @@ rocky8-test: image: gitlab.linphone.org:4567/bc/public/docker/rocky8-php:$ROCKY_8_IMAGE_VERSION needs: - rocky8-package - - remi-xmlrpc-package script: - yum -y localinstall build/*.rpm - cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 293c5cc..be1d1a2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,6 @@ variables: PHP_REDIS_REMI_VERSION: php-pecl-redis5-5.3.6-1 PHP_IGBINARY_REMI_VERSION: php-pecl-igbinary-3.2.14-1 PHP_MSGPACK_REMI_VERSION: php-pecl-msgpack-2.2.0-1 - PHP_XMLRPC_REMI_VERSION: php-pecl-xmlrpc-1.0.0~rc3-2 include: - '.gitlab-ci-files/package.yml' diff --git a/Makefile b/Makefile index 6c59e1e..0379a46 100644 --- a/Makefile +++ b/Makefile @@ -24,11 +24,9 @@ cleanup-package-semvers: prepare: cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis --no-dev - cd xmlrpc/src && cp ../../flexiapi/composer.phar . && php composer.phar install --ignore-platform-req=ext-redis --no-dev prepare-dev: cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis - cd xmlrpc/src && cp ../../flexiapi/composer.phar . && php composer.phar install --ignore-platform-req=ext-redis package-common: rm -rf $(OUTPUT_DIR)/flexisip-account-manager @@ -36,16 +34,10 @@ package-common: mkdir -p $(OUTPUT_DIR)/rpmbuild/SPECS mkdir -p $(OUTPUT_DIR)/rpmbuild/SOURCES - # XMLRPC - cp -R --parents xmlrpc/src/**/*.php $(OUTPUT_DIR)/flexisip-account-manager/ - cp -R --parents xmlrpc/src/vendor/**/* $(OUTPUT_DIR)/flexisip-account-manager/ - cp -R --parents xmlrpc/src/api/**/*.php $(OUTPUT_DIR)/flexisip-account-manager/ - cp -R --parents conf/*.conf $(OUTPUT_DIR)/flexisip-account-manager/ - # FlexiAPI cp -R --parents flexiapi/**/* $(OUTPUT_DIR)/flexisip-account-manager/ cp flexiapi/composer* $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/ - cp README.md $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/ + cp README.md $(OUTPUT_DIR)/flexisip-account-manager/ cp flexiapi/.env.example $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/.env.example cp flexiapi/artisan $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/ cp flexiapi/phpunit.xml $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/ @@ -53,7 +45,6 @@ package-common: cp flexiapi/phpmd.xml $(OUTPUT_DIR)/flexisip-account-manager/flexiapi/ # General - cp xmlrpc/README.md $(OUTPUT_DIR)/flexisip-account-manager/ cp -R httpd/ $(OUTPUT_DIR)/flexisip-account-manager/ cp -R cron/ $(OUTPUT_DIR)/flexisip-account-manager/ cp flexisip-account-manager.spec.run $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec diff --git a/README.md b/README.md index 33ab256..fb760f8 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ Flexisip Account Manager brings several tools in one: - a web portal, powered by FlexiAPI - a remote provisioning server, able to generate configuration files compatible with Linphone's QrCode-based or URL-based remote provisioning feature -It replaces the historical XMLRPC tool that is still available in `xmlrpc/` for retrocompatibility purpose. - # License Copyright © Belledonne Communications diff --git a/conf/accounts.conf b/conf/accounts.conf deleted file mode 100644 index ea52a5a..0000000 --- a/conf/accounts.conf +++ /dev/null @@ -1,94 +0,0 @@ -?;:[]{}\| - */ -define("GENERATED_PASSWORD_CHARACTERS", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789``-=~!@#$%^&*()_+,./<>?;:[]{}\|"); - -/* - * The length of the passwords that will be generated. - * - * Default value: 8 - */ -define("GENERATED_PASSWORD_LENGTH", 8); - -/* - * The default algorithm to use if not specified in the request - * - * Default value: MD5 - */ -define("DEFAULT_ALGORITHM", "MD5"); - -/* - * A string with each character allowed in the username generation. - * - * Default value: abcdefghijklmnopqrstuvwxyz0123456789.-_ - */ -define("GENERATED_USERNAME_CHARACTERS", "abcdefghijklmnopqrstuvwxyz0123456789.-_"); - -/* - * The length of the username that will be generated. - * - * Default value: 12 - */ -define("GENERATED_USERNAME_LENGTH", 12); - -/* - * If set to True, a created account will automatically be activated and it's expiration date set to now + TRIAL_DURATION_DAYS, - * otherwise expiration date for trial will be set when account is activated via a different xml rpc call. - */ -define('AUTO_ACTIVATE_ACCOUNT', False); - -/* - * Send an email to activate the account when it is created. - */ -define('SEND_ACTIVATION_EMAIL', True); - -/* - * Send a sms to activate the phone account when it is created. - */ -define('SEND_ACTIVATION_SMS', True); - -/* - * If false, creating an account with an email that is already used for another account will trigger an error - */ -define('ALLOW_SAME_EMAILS_ON_MULTILPLE_ACCOUNTS', True); - -/* - * If true, when an account creation request is received for an existing number, assumes recover procedure - */ -define('RECOVER_ACCOUNT_IF_EXISTS', False); - -/* - * Enabling geoloc of accounts in user_info table. - * When this option is set, the fields coutry_name and country_code will be filled - * with a call to api.ipapi.com - * - * Default value: False - */ -define("ENABLE_NEW_ACCOUNTS_GEOLOC", False); - -/* API key for geoloc. If you need geoloc and don't have a key, - * ask it on ipapi.com - */ - -define("GEOLOC_ACCESS_KEY", ""); - -?> diff --git a/conf/auth.conf b/conf/auth.conf deleted file mode 100644 index e174879..0000000 --- a/conf/auth.conf +++ /dev/null @@ -1,34 +0,0 @@ - \ No newline at end of file diff --git a/conf/db.conf b/conf/db.conf deleted file mode 100644 index a4c85c3..0000000 --- a/conf/db.conf +++ /dev/null @@ -1,126 +0,0 @@ - diff --git a/conf/emails.conf b/conf/emails.conf deleted file mode 100644 index f5acab6..0000000 --- a/conf/emails.conf +++ /dev/null @@ -1,76 +0,0 @@ -Start your sip.linphone.org service

Hello,

Activation pending for using your Linphone account.
Please use the link bellow to activate your account :

%link%

 

Regards,
The Linphone team.

'); - -/* - * The subject of the account recovery email. - */ -define("EMAIL_RECOVERY_SUBJECT", "Recover your sip.linphone.org account"); - -/* - * The body (as text) of the account recovery email. - * It must have a %key% parameter that will be replaced with the recovery code - */ -define("EMAIL_RECOVERY_BODY", "Hello,\nHere is your recovery code: %key%\n\nRegards,\nThe Linphone team.\n"); - -/* - * The body (as html) of the account recovery email. - * It must have a %key% parameter that will be replaced with the recovery code - */ -define("EMAIL_RECOVERY_BODY_HTML", 'Recover your sip.linphone.org account

Hello,

Here is your recovery code: %key%

Regards,
The Linphone team.

'); - -?> \ No newline at end of file diff --git a/conf/hooks.conf b/conf/hooks.conf deleted file mode 100644 index 50e80a0..0000000 --- a/conf/hooks.conf +++ /dev/null @@ -1,37 +0,0 @@ -sip:conference-factory@' . $request_params["domain"] . ''; -} -function provisioning_hook_on_auth_info(&$xml, $request_params) { - -} - -function provisioning_hook_on_additional_section(&$xml, $request_params) { - $xml .= '
'; - $xml .= 'sips:rls@' . $request_params["domain"] . ''; - $xml .= '
'; -} - -?> diff --git a/conf/inapp.conf b/conf/inapp.conf deleted file mode 100644 index cb7eeaf..0000000 --- a/conf/inapp.conf +++ /dev/null @@ -1,90 +0,0 @@ - \ No newline at end of file diff --git a/conf/logs.conf b/conf/logs.conf deleted file mode 100644 index 8ba157c..0000000 --- a/conf/logs.conf +++ /dev/null @@ -1,35 +0,0 @@ - diff --git a/conf/overloads.conf b/conf/overloads.conf deleted file mode 100644 index 7f38b83..0000000 --- a/conf/overloads.conf +++ /dev/null @@ -1,26 +0,0 @@ - diff --git a/conf/provisioning.conf b/conf/provisioning.conf deleted file mode 100644 index 0e8fc79..0000000 --- a/conf/provisioning.conf +++ /dev/null @@ -1,46 +0,0 @@ - \ No newline at end of file diff --git a/conf/sms.conf b/conf/sms.conf deleted file mode 100644 index 9183dab..0000000 --- a/conf/sms.conf +++ /dev/null @@ -1,124 +0,0 @@ - 'Your Linphone validation code is #CODE#', // This one isn't required but if present it MUST be equal to SMS_OVH_US_TEMPLATE - 'FR' => 'Votre code de validation Linphone est #CODE#', -); - -?> \ No newline at end of file diff --git a/conf/tests.conf b/conf/tests.conf deleted file mode 100644 index fd6d5761..0000000 --- a/conf/tests.conf +++ /dev/null @@ -1,26 +0,0 @@ - \ No newline at end of file diff --git a/flexiapi/app/Console/Commands/SetAccountAdmin.php b/flexiapi/app/Console/Commands/SetAccountAdmin.php index 09be8cd..ff53fea 100644 --- a/flexiapi/app/Console/Commands/SetAccountAdmin.php +++ b/flexiapi/app/Console/Commands/SetAccountAdmin.php @@ -39,7 +39,12 @@ class SetAccountAdmin extends Command $account = Account::withoutGlobalScopes()->where('id', $this->argument('id'))->first(); if (!$account) { - $this->error('Account not found, please use an existing SIP address'); + $this->error('Account not found, please use an existing account id'); + return 1; + } + + if ($account->admin) { + $this->error('The account is already having the admin role'); return 1; } diff --git a/flexiapi/app/Helpers/Utils.php b/flexiapi/app/Helpers/Utils.php index 4b662bc..b69cec0 100644 --- a/flexiapi/app/Helpers/Utils.php +++ b/flexiapi/app/Helpers/Utils.php @@ -132,6 +132,11 @@ function resolveDomain(Request $request): string : config('app.sip_domain'); } +function captchaConfigured(): bool +{ + return env('NOCAPTCHA_SECRET', false) != false || env('NOCAPTCHA_SITEKEY', false) != false; +} + function resolveUserContacts(Request $request) { $selected = ['id', 'username', 'domain', 'activated', 'dtmf_protocol']; diff --git a/flexiapi/app/Http/Controllers/Account/AccountController.php b/flexiapi/app/Http/Controllers/Account/AccountController.php index e88c5e9..19ebb72 100644 --- a/flexiapi/app/Http/Controllers/Account/AccountController.php +++ b/flexiapi/app/Http/Controllers/Account/AccountController.php @@ -53,6 +53,8 @@ class AccountController extends Controller public function store(CreateAccountRequest $request) { + $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']); + $account = (new AccountService(api: false))->store($request); Auth::login($account); diff --git a/flexiapi/app/Http/Controllers/Account/CreationRequestTokenController.php b/flexiapi/app/Http/Controllers/Account/CreationRequestTokenController.php index 449b37d..5e865eb 100644 --- a/flexiapi/app/Http/Controllers/Account/CreationRequestTokenController.php +++ b/flexiapi/app/Http/Controllers/Account/CreationRequestTokenController.php @@ -34,7 +34,7 @@ class CreationRequestTokenController extends Controller 'required', new RulesAccountCreationRequestToken ], - 'g-recaptcha-response' => 'required|captcha', + 'g-recaptcha-response' => captchaConfigured() ? 'required|captcha' : '', ]); $accountCreationRequestToken = AccountCreationRequestToken::where('token', $request->get('account_creation_request_token'))->firstOrFail(); diff --git a/flexiapi/app/Http/Controllers/Account/EmailController.php b/flexiapi/app/Http/Controllers/Account/EmailController.php index e61dbf7..b0528fc 100644 --- a/flexiapi/app/Http/Controllers/Account/EmailController.php +++ b/flexiapi/app/Http/Controllers/Account/EmailController.php @@ -34,7 +34,7 @@ class EmailController extends Controller public function requestChange(Request $request) { - //$request->validate(['g-recaptcha-response' => 'required|captcha']); + $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']); (new AccountService(api: false))->requestEmailChange($request); diff --git a/flexiapi/app/Http/Controllers/Account/PhoneController.php b/flexiapi/app/Http/Controllers/Account/PhoneController.php index 6e22253..c3b19bb 100644 --- a/flexiapi/app/Http/Controllers/Account/PhoneController.php +++ b/flexiapi/app/Http/Controllers/Account/PhoneController.php @@ -34,7 +34,7 @@ class PhoneController extends Controller public function requestChange(Request $request) { - //$request->validate(['g-recaptcha-response' => 'required|captcha']); + $request->validate(['g-recaptcha-response' => captchaConfigured() ? 'required|captcha': '']); (new AccountService(api: false))->requestPhoneChange($request); diff --git a/flexiapi/app/Http/Controllers/Account/RecoveryController.php b/flexiapi/app/Http/Controllers/Account/RecoveryController.php index 7de1200..1d94730 100644 --- a/flexiapi/app/Http/Controllers/Account/RecoveryController.php +++ b/flexiapi/app/Http/Controllers/Account/RecoveryController.php @@ -33,7 +33,7 @@ class RecoveryController extends Controller $rules = [ 'email' => 'required_without:phone|email|exists:accounts,email', 'phone' => 'required_without:email|starts_with:+', - //'g-recaptcha-response' => 'required|captcha', + 'g-recaptcha-response' => captchaConfigured() ? 'required|captcha' : '', ]; if ($request->get('email')) { diff --git a/flexiapi/app/Http/Controllers/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Admin/AccountController.php index 9c7571e..6f18332 100644 --- a/flexiapi/app/Http/Controllers/Admin/AccountController.php +++ b/flexiapi/app/Http/Controllers/Admin/AccountController.php @@ -109,7 +109,6 @@ 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->dtmf_protocol = $request->get('dtmf_protocol'); @@ -117,7 +116,10 @@ class AccountController extends Controller $account->save(); $account->phone = $request->get('phone'); - $account->fillPassword($request); + + if ($request->filled('password') && $request->filled('password_confirmation')) { + $account->fillPassword($request); + } $account->setRole($request->get('role')); diff --git a/flexiapi/app/Http/Controllers/Api/Account/AccountController.php b/flexiapi/app/Http/Controllers/Api/Account/AccountController.php index 1e8a1df..c149084 100644 --- a/flexiapi/app/Http/Controllers/Api/Account/AccountController.php +++ b/flexiapi/app/Http/Controllers/Api/Account/AccountController.php @@ -29,7 +29,6 @@ use Carbon\Carbon; use App\Account; use App\AccountTombstone; -use App\AccountCreationToken; use App\Alias; use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController; use App\Http\Requests\CreateAccountRequest; @@ -37,7 +36,6 @@ use App\Libraries\OvhSMS; use App\Mail\RegisterConfirmation; use App\Rules\AccountCreationToken as RulesAccountCreationToken; use App\Rules\BlacklistedUsername; -use App\Rules\IsNotPhoneNumber; use App\Rules\NoUppercase; use App\Rules\SIPUsername; use App\Rules\WithoutSpaces; diff --git a/flexiapi/app/Http/Requests/UpdateAccountRequest.php b/flexiapi/app/Http/Requests/UpdateAccountRequest.php index 5096ced..3f58367 100644 --- a/flexiapi/app/Http/Requests/UpdateAccountRequest.php +++ b/flexiapi/app/Http/Requests/UpdateAccountRequest.php @@ -44,7 +44,7 @@ class UpdateAccountRequest extends FormRequest 'phone' => [ 'nullable', Rule::unique('accounts', 'username')->where(function ($query) { - $query->where('domain', config('app.sip_domain')); + $query->where('domain', resolveDomain($this)); })->ignore($this->route('account_id'), 'id'), Rule::unique('aliases', 'alias')->ignore($this->route('account_id'), 'account_id'), new WithoutSpaces, 'starts_with:+' diff --git a/flexiapi/public/css/far.css b/flexiapi/public/css/far.css index c03963f..3854872 100644 --- a/flexiapi/public/css/far.css +++ b/flexiapi/public/css/far.css @@ -111,6 +111,19 @@ pre { color: var(--second-7); } +pre { + overflow: auto; + background-color: var(--second-8); + border-radius: 1rem; + padding: 1rem; + margin-bottom: 1rem; +} + +pre code { + color: var(--grey-1); + font-size: 1.3rem; +} + ul li { margin-left: 2rem; list-style-type: disc; @@ -138,7 +151,7 @@ p i { } code { - color: var(--second-6); + color: var(--second-7); font-family: monospace; } @@ -485,6 +498,11 @@ h4 { padding: 0.5rem 0; } +p + h1, p + h2, p + h3, p + h4, +ul + h1, ul + h2, ul + h3, ul + h4 { + margin-top: 1rem; +} + /** Badge **/ .badge { @@ -668,4 +686,19 @@ ul.pagination li:not(.disabled) .page-link:hover { select.list_toggle { display: none; +} + +/** Specific elements */ + +.table-of-contents { + max-width: 40%; + float: right; +} + +.card { + background-color: var(--grey-2); + border-radius: 1rem; + padding: 1rem; + margin-bottom: 1rem; + overflow: hidden; } \ No newline at end of file diff --git a/flexiapi/public/css/form.css b/flexiapi/public/css/form.css index 42956d5..ceb9e82 100644 --- a/flexiapi/public/css/form.css +++ b/flexiapi/public/css/form.css @@ -189,6 +189,12 @@ form div textarea[disabled] { pointer-events: none; } +form div input[readonly], +form div textarea[readonly] { + border-color: var(--grey-2); + background-color: var(--grey-2); +} + input[type=checkbox] { accent-color: var(--main-5); } diff --git a/flexiapi/resources/views/admin/account/create_edit.blade.php b/flexiapi/resources/views/admin/account/create_edit.blade.php index 0eb9d27..ab75c70 100644 --- a/flexiapi/resources/views/admin/account/create_edit.blade.php +++ b/flexiapi/resources/views/admin/account/create_edit.blade.php @@ -22,13 +22,14 @@

Connexion

+ value="{{ $account->username }}" @if ($account->id) readonly @endif> @include('parts.errors', ['name' => 'username'])
+ type="text" value="{{ $account->domain ?? config('app.sip_domain') }}" + @if ($account->id) readonly @endif>
@@ -40,7 +41,7 @@
- + @include('parts.errors', ['name' => 'password'])
@@ -188,30 +189,32 @@ Identifier: {{ $account->externalAccount->identifier }}

@else - Attach an External Account ({{ $external_accounts_count}} left) + Attach an External Account + ({{ $external_accounts_count }} left) @endif

Actions

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

To manage actions, you must configure the DTMF protocol in the account settings.

@endif diff --git a/flexiapi/resources/views/api/documentation_markdown.blade.php b/flexiapi/resources/views/api/documentation_markdown.blade.php index af7bbe6..a2588d9 100644 --- a/flexiapi/resources/views/api/documentation_markdown.blade.php +++ b/flexiapi/resources/views/api/documentation_markdown.blade.php @@ -18,7 +18,7 @@ A `content-type` and `accept` HTTP headers are REQUIRED to use the API properly Restricted endpoints are protected using a DIGEST authentication or an API Key mechanisms. -#### Access model +### Access model The endpoints are accessible using three different models: @@ -26,7 +26,7 @@ The endpoints are accessible using three different models: - User the endpoint can only be accessed by an authenticated user - Admin the endpoint can be only be accessed by an authenticated admin user -#### Using the API Key +### Using the API Key You can retrieve an API Key from @if (config('app.web_panel')) [your account panel]({{ route('account.login') }}) @else your account panel @endif or using the dedicated API endpoint. @@ -46,7 +46,7 @@ Or using a cookie: > … ``` -#### Using DIGEST +### Using DIGEST To discover the available hashing algorythm you MUST send an unauthenticated request to one of the restricted endpoints.
Only DIGEST-MD5 and DIGEST-SHA-256 are supported through the authentication layer. @@ -583,22 +583,22 @@ Return the authenticated user contacts list, in [vCard 4.0 format](https://datat Here is the format of the vCard list returned by the endpoint: ``` - BEGIN:VCARD - VERSION:4.0 - KIND:individual - IMPP:sip:schoen.tatyana@sip.linphone.org - FN:schoen.tatyana@sip.linphone.org - X-LINPHONE-ACCOUNT-DTMF-PROTOCOL:sipinfo - X-LINPHONE-ACCOUNT-TYPE:phone - X-LINPHONE-ACCOUNT-ACTION:action_key;123 - END:VCARD - BEGIN:VCARD - VERSION:4.0 - KIND:individual - IMPP:sip:dhand@sip.linphone.org - FN:dhand@sip.linphone.org - X-LINPHONE-ACCOUNT-DTMF-PROTOCOL:sipinfo - END:VCARD +BEGIN:VCARD +VERSION:4.0 +KIND:individual +IMPP:sip:schoen.tatyana@sip.linphone.org +FN:schoen.tatyana@sip.linphone.org +X-LINPHONE-ACCOUNT-DTMF-PROTOCOL:sipinfo +X-LINPHONE-ACCOUNT-TYPE:phone +X-LINPHONE-ACCOUNT-ACTION:action_key;123 +END:VCARD +BEGIN:VCARD +VERSION:4.0 +KIND:individual +IMPP:sip:dhand@sip.linphone.org +FN:dhand@sip.linphone.org +X-LINPHONE-ACCOUNT-DTMF-PROTOCOL:sipinfo +END:VCARD ``` ### `GET /contacts/vcard/{sip}` diff --git a/flexiapi/resources/views/layouts/main.blade.php b/flexiapi/resources/views/layouts/main.blade.php index e3a75d7..35f9bda 100644 --- a/flexiapi/resources/views/layouts/main.blade.php +++ b/flexiapi/resources/views/layouts/main.blade.php @@ -8,14 +8,12 @@ {{ config('app.name') }} - @if (config('instance.custom_theme')) - @if (file_exists(public_path('css/' . config('app.env') . '.style.css'))) - - @else - @endif - - - + + + + + @if (config('instance.custom_theme') & file_exists(public_path('css/' . config('app.env') . '.style.css'))) + @endif @@ -24,10 +22,12 @@
@if (config('app.web_panel'))