mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-17 10:08:05 +00:00
Fix FLEXIAPI-196 Add a phone validation system by country code with configuration panels and related tests and documentation
This commit is contained in:
parent
f6c5562201
commit
08ff1b8675
26 changed files with 933 additions and 71 deletions
|
|
@ -3,6 +3,7 @@
|
|||
v1.6
|
||||
----
|
||||
- Fix FLEXIAPI-192 Add DotEnv configuration to allow the expiration of tokens and codes in the app
|
||||
- Fix FLEXIAPI-196 Add a phone validation system by country code with configuration panels and related tests and documentation
|
||||
|
||||
v1.5
|
||||
---
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ function generateNonce(): string
|
|||
|
||||
function generateValidNonce(Account $account): string
|
||||
{
|
||||
$nonce = new DigestNonce;
|
||||
$nonce = new DigestNonce();
|
||||
$nonce->account_id = $account->id;
|
||||
$nonce->nonce = generateNonce();
|
||||
$nonce->save();
|
||||
|
|
@ -62,7 +62,9 @@ function generatePin(): int
|
|||
|
||||
function percent($value, $max): float
|
||||
{
|
||||
if ($max == 0) $max = 1;
|
||||
if ($max == 0) {
|
||||
$max = 1;
|
||||
}
|
||||
return round(($value * 100) / $max, 2);
|
||||
}
|
||||
|
||||
|
|
@ -81,8 +83,8 @@ function markdownDocumentationView(string $view): string
|
|||
],
|
||||
]);
|
||||
|
||||
$converter->getEnvironment()->addExtension(new HeadingPermalinkExtension);
|
||||
$converter->getEnvironment()->addExtension(new TableOfContentsExtension);
|
||||
$converter->getEnvironment()->addExtension(new HeadingPermalinkExtension());
|
||||
$converter->getEnvironment()->addExtension(new TableOfContentsExtension());
|
||||
|
||||
return (string) $converter->convert(
|
||||
(string)view($view, [
|
||||
|
|
@ -162,3 +164,247 @@ function validateIsoDate($attribute, $value, $parameters, $validator): bool
|
|||
|
||||
return (bool)preg_match($regex, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This list was got from the Internet
|
||||
*
|
||||
* @see https://gist.github.com/vxnick/380904
|
||||
* @return array
|
||||
*/
|
||||
function getCountryCodes()
|
||||
{
|
||||
return [
|
||||
'AF' => 'Afghanistan',
|
||||
'AX' => 'Åland Islands',
|
||||
'AL' => 'Albania',
|
||||
'DZ' => 'Algeria',
|
||||
'AS' => 'American Samoa',
|
||||
'AD' => 'Andorra',
|
||||
'AO' => 'Angola',
|
||||
'AI' => 'Anguilla',
|
||||
'AG' => 'Antigua & Barbuda',
|
||||
'AR' => 'Argentina',
|
||||
'AU' => 'Australia',
|
||||
'AT' => 'Austria',
|
||||
'AZ' => 'Azerbaijan',
|
||||
'BS' => 'Bahamas',
|
||||
'BH' => 'Bahrain',
|
||||
'BD' => 'Bangladesh',
|
||||
'BB' => 'Barbados',
|
||||
'BY' => 'Belarus',
|
||||
'BE' => 'Belgium',
|
||||
'BZ' => 'Belize',
|
||||
'BJ' => 'Benin',
|
||||
'BM' => 'Bermuda',
|
||||
'BT' => 'Bhutan',
|
||||
'BO' => 'Bolivia',
|
||||
'BA' => 'Bosnia & Herzegovina',
|
||||
'BW' => 'Botswana',
|
||||
'BR' => 'Brazil',
|
||||
'IO' => 'British Indian Ocean Territory',
|
||||
'BN' => 'Brunei',
|
||||
'BG' => 'Bulgaria',
|
||||
'BF' => 'Burkina Faso',
|
||||
'BI' => 'Burundi',
|
||||
'KH' => 'Cambodia',
|
||||
'CM' => 'Cameroon',
|
||||
'CA' => 'Canada',
|
||||
'CV' => 'Cape Verde',
|
||||
'KY' => 'Cayman Islands',
|
||||
'CF' => 'Central African Republic',
|
||||
'TD' => 'Chad',
|
||||
'CL' => 'Chile',
|
||||
'CN' => 'China',
|
||||
'CX' => 'Christmas Island',
|
||||
'CC' => 'Cocos (Keeling) Islands',
|
||||
'CO' => 'Colombia',
|
||||
'KM' => 'Comoros',
|
||||
'CG' => 'Congo - Brazzaville',
|
||||
'CD' => 'Congo - Kinshasa',
|
||||
'CK' => 'Cook Islands',
|
||||
'CR' => 'Costa Rica',
|
||||
'CI' => 'Côte d’Ivoire',
|
||||
'HR' => 'Croatia',
|
||||
'CU' => 'Cuba',
|
||||
'CY' => 'Cyprus',
|
||||
'CZ' => 'Czechia',
|
||||
'DK' => 'Denmark',
|
||||
'DJ' => 'Djibouti',
|
||||
'DM' => 'Dominica',
|
||||
'DO' => 'Dominican Republic',
|
||||
'EC' => 'Ecuador',
|
||||
'EG' => 'Egypt',
|
||||
'SV' => 'El Salvador',
|
||||
'GQ' => 'Equatorial Guinea',
|
||||
'ER' => 'Eritrea',
|
||||
'EE' => 'Estonia',
|
||||
'ET' => 'Ethiopia',
|
||||
'FK' => 'Falkland Islands',
|
||||
'FO' => 'Faroe Islands',
|
||||
'FJ' => 'Fiji',
|
||||
'FI' => 'Finland',
|
||||
'FR' => 'France',
|
||||
'GF' => 'French Guiana',
|
||||
'PF' => 'French Polynesia',
|
||||
'GA' => 'Gabon',
|
||||
'GM' => 'Gambia',
|
||||
'GE' => 'Georgia',
|
||||
'DE' => 'Germany',
|
||||
'GH' => 'Ghana',
|
||||
'GI' => 'Gibraltar',
|
||||
'GR' => 'Greece',
|
||||
'GL' => 'Greenland',
|
||||
'GD' => 'Grenada',
|
||||
'GP' => 'Guadeloupe',
|
||||
'GU' => 'Guam',
|
||||
'GT' => 'Guatemala',
|
||||
'GG' => 'Guernsey',
|
||||
'GN' => 'Guinea',
|
||||
'GW' => 'Guinea-Bissau',
|
||||
'GY' => 'Guyana',
|
||||
'HT' => 'Haiti',
|
||||
'HN' => 'Honduras',
|
||||
'HK' => 'Hong Kong SAR China',
|
||||
'HU' => 'Hungary',
|
||||
'IS' => 'Iceland',
|
||||
'IN' => 'India',
|
||||
'ID' => 'Indonesia',
|
||||
'IR' => 'Iran',
|
||||
'IQ' => 'Iraq',
|
||||
'IE' => 'Ireland',
|
||||
'IM' => 'Isle of Man',
|
||||
'IL' => 'Israel',
|
||||
'IT' => 'Italy',
|
||||
'JM' => 'Jamaica',
|
||||
'JP' => 'Japan',
|
||||
'JE' => 'Jersey',
|
||||
'JO' => 'Jordan',
|
||||
'KZ' => 'Kazakhstan',
|
||||
'KE' => 'Kenya',
|
||||
'KI' => 'Kiribati',
|
||||
'KP' => 'North Korea',
|
||||
'KR' => 'South Korea',
|
||||
'KW' => 'Kuwait',
|
||||
'KG' => 'Kyrgyzstan',
|
||||
'LA' => 'Laos',
|
||||
'LV' => 'Latvia',
|
||||
'LB' => 'Lebanon',
|
||||
'LS' => 'Lesotho',
|
||||
'LR' => 'Liberia',
|
||||
'LY' => 'Libya',
|
||||
'LI' => 'Liechtenstein',
|
||||
'LT' => 'Lithuania',
|
||||
'LU' => 'Luxembourg',
|
||||
'MO' => 'Macao SAR China',
|
||||
'MK' => 'North Macedonia',
|
||||
'MG' => 'Madagascar',
|
||||
'MW' => 'Malawi',
|
||||
'MY' => 'Malaysia',
|
||||
'MV' => 'Maldives',
|
||||
'ML' => 'Mali',
|
||||
'MT' => 'Malta',
|
||||
'MH' => 'Marshall Islands',
|
||||
'MQ' => 'Martinique',
|
||||
'MR' => 'Mauritania',
|
||||
'MU' => 'Mauritius',
|
||||
'YT' => 'Mayotte',
|
||||
'MX' => 'Mexico',
|
||||
'FM' => 'Micronesia',
|
||||
'MD' => 'Moldova',
|
||||
'MC' => 'Monaco',
|
||||
'MN' => 'Mongolia',
|
||||
'ME' => 'Montenegro',
|
||||
'MS' => 'Montserrat',
|
||||
'MA' => 'Morocco',
|
||||
'MZ' => 'Mozambique',
|
||||
'MM' => 'Myanmar (Burma)',
|
||||
'NA' => 'Namibia',
|
||||
'NR' => 'Nauru',
|
||||
'NP' => 'Nepal',
|
||||
'NL' => 'Netherlands',
|
||||
'NC' => 'New Caledonia',
|
||||
'NZ' => 'New Zealand',
|
||||
'NI' => 'Nicaragua',
|
||||
'NE' => 'Niger',
|
||||
'NG' => 'Nigeria',
|
||||
'NU' => 'Niue',
|
||||
'NF' => 'Norfolk Island',
|
||||
'MP' => 'Northern Mariana Islands',
|
||||
'NO' => 'Norway',
|
||||
'OM' => 'Oman',
|
||||
'PK' => 'Pakistan',
|
||||
'PW' => 'Palau',
|
||||
'PS' => 'Palestinian Territories',
|
||||
'PA' => 'Panama',
|
||||
'PG' => 'Papua New Guinea',
|
||||
'PY' => 'Paraguay',
|
||||
'PE' => 'Peru',
|
||||
'PH' => 'Philippines',
|
||||
'PL' => 'Poland',
|
||||
'PT' => 'Portugal',
|
||||
'PR' => 'Puerto Rico',
|
||||
'QA' => 'Qatar',
|
||||
'RE' => 'Réunion',
|
||||
'RO' => 'Romania',
|
||||
'RU' => 'Russia',
|
||||
'RW' => 'Rwanda',
|
||||
'SH' => 'St. Helena',
|
||||
'KN' => 'St. Kitts & Nevis',
|
||||
'LC' => 'St. Lucia',
|
||||
'PM' => 'St. Pierre & Miquelon',
|
||||
'VC' => 'St. Vincent & Grenadines',
|
||||
'WS' => 'Samoa',
|
||||
'SM' => 'San Marino',
|
||||
'ST' => 'São Tomé & Príncipe',
|
||||
'SA' => 'Saudi Arabia',
|
||||
'SN' => 'Senegal',
|
||||
'RS' => 'Serbia',
|
||||
'SC' => 'Seychelles',
|
||||
'SL' => 'Sierra Leone',
|
||||
'SG' => 'Singapore',
|
||||
'SK' => 'Slovakia',
|
||||
'SI' => 'Slovenia',
|
||||
'SB' => 'Solomon Islands',
|
||||
'SO' => 'Somalia',
|
||||
'ZA' => 'South Africa',
|
||||
'ES' => 'Spain',
|
||||
'LK' => 'Sri Lanka',
|
||||
'SD' => 'Sudan',
|
||||
'SR' => 'Suriname',
|
||||
'SJ' => 'Svalbard & Jan Mayen',
|
||||
'SZ' => 'Eswatini',
|
||||
'SE' => 'Sweden',
|
||||
'CH' => 'Switzerland',
|
||||
'SY' => 'Syria',
|
||||
'TW' => 'Taiwan',
|
||||
'TJ' => 'Tajikistan',
|
||||
'TZ' => 'Tanzania',
|
||||
'TH' => 'Thailand',
|
||||
'TL' => 'Timor-Leste',
|
||||
'TG' => 'Togo',
|
||||
'TK' => 'Tokelau',
|
||||
'TO' => 'Tonga',
|
||||
'TT' => 'Trinidad & Tobago',
|
||||
'TN' => 'Tunisia',
|
||||
'TM' => 'Turkmenistan',
|
||||
'TC' => 'Turks & Caicos Islands',
|
||||
'TV' => 'Tuvalu',
|
||||
'UG' => 'Uganda',
|
||||
'UA' => 'Ukraine',
|
||||
'AE' => 'United Arab Emirates',
|
||||
'GB' => 'United Kingdom',
|
||||
'US' => 'United States',
|
||||
'UY' => 'Uruguay',
|
||||
'UZ' => 'Uzbekistan',
|
||||
'VU' => 'Vanuatu',
|
||||
'VE' => 'Venezuela',
|
||||
'VN' => 'Vietnam',
|
||||
'VG' => 'British Virgin Islands',
|
||||
'VI' => 'U.S. Virgin Islands',
|
||||
'WF' => 'Wallis & Futuna',
|
||||
'EH' => 'Western Sahara',
|
||||
'YE' => 'Yemen',
|
||||
'ZM' => 'Zambia',
|
||||
'ZW' => 'Zimbabwe',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\PhoneCountry;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PhoneCountryController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('admin.phone_country.index', [
|
||||
'phone_countries' => PhoneCountry::all()
|
||||
]);
|
||||
}
|
||||
|
||||
public function activateAll()
|
||||
{
|
||||
PhoneCountry::query()->update(['activated' => true]);
|
||||
|
||||
return redirect()->route('admin.phone_countries.index');
|
||||
}
|
||||
|
||||
public function deactivateAll()
|
||||
{
|
||||
PhoneCountry::query()->update(['activated' => false]);
|
||||
|
||||
return redirect()->route('admin.phone_countries.index');
|
||||
}
|
||||
|
||||
public function activate(string $code)
|
||||
{
|
||||
$phoneCountry = PhoneCountry::where('code', $code)->firstOrFail();
|
||||
|
||||
PhoneCountry::where('country_code', $phoneCountry->country_code)->update(['activated' => true]);
|
||||
|
||||
return redirect()->route('admin.phone_countries.index');
|
||||
}
|
||||
|
||||
public function deactivate(string $code)
|
||||
{
|
||||
$phoneCountry = PhoneCountry::where('code', $code)->firstOrFail();
|
||||
|
||||
PhoneCountry::where('country_code', $phoneCountry->country_code)->update(['activated' => false]);
|
||||
|
||||
return redirect()->route('admin.phone_countries.index');
|
||||
}
|
||||
}
|
||||
|
|
@ -38,9 +38,9 @@ use App\Mail\RegisterConfirmation;
|
|||
use App\Rules\AccountCreationToken as RulesAccountCreationToken;
|
||||
use App\Rules\AccountCreationTokenNotExpired;
|
||||
use App\Rules\BlacklistedUsername;
|
||||
use App\Rules\FilteredPhone;
|
||||
use App\Rules\NoUppercase;
|
||||
use App\Rules\SIPUsername;
|
||||
use App\Rules\WithoutSpaces;
|
||||
use App\Rules\PasswordAlgorithm;
|
||||
|
||||
use App\Services\AccountService;
|
||||
|
|
@ -69,7 +69,7 @@ class AccountController extends Controller
|
|||
|
||||
$request->merge(['phone' => $phone]);
|
||||
$request->validate([
|
||||
'phone' => ['required', new WithoutSpaces, 'starts_with:+']
|
||||
'phone' => ['required', 'phone', new FilteredPhone]
|
||||
]);
|
||||
|
||||
$account = Account::where('domain', config('app.sip_domain'))
|
||||
|
|
@ -116,9 +116,10 @@ class AccountController extends Controller
|
|||
'phone' => [
|
||||
'required_without:email',
|
||||
'required_without:username',
|
||||
'phone',
|
||||
new FilteredPhone,
|
||||
'unique:accounts,phone',
|
||||
'unique:accounts,username',
|
||||
new WithoutSpaces, 'starts_with:+'
|
||||
],
|
||||
'account_creation_token' => [
|
||||
'required',
|
||||
|
|
@ -189,7 +190,7 @@ class AccountController extends Controller
|
|||
|
||||
$request->validate([
|
||||
'phone' => [
|
||||
'required', new WithoutSpaces, 'starts_with:+', 'exists:accounts,phone'
|
||||
'required', 'phone', new FilteredPhone, 'exists:accounts,phone'
|
||||
],
|
||||
'account_creation_token' => [
|
||||
'required',
|
||||
|
|
|
|||
14
flexiapi/app/Http/Controllers/Api/PhoneCountryController.php
Normal file
14
flexiapi/app/Http/Controllers/Api/PhoneCountryController.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\PhoneCountry;
|
||||
|
||||
class PhoneCountryController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return PhoneCountry::all();
|
||||
}
|
||||
}
|
||||
|
|
@ -25,10 +25,10 @@ use Illuminate\Validation\Rule;
|
|||
use App\Account;
|
||||
use App\Rules\BlacklistedUsername;
|
||||
use App\Rules\Dictionary;
|
||||
use App\Rules\FilteredPhone;
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
use App\Rules\NoUppercase;
|
||||
use App\Rules\SIPUsername;
|
||||
use App\Rules\WithoutSpaces;
|
||||
|
||||
class Request extends FormRequest
|
||||
{
|
||||
|
|
@ -65,7 +65,8 @@ class Request extends FormRequest
|
|||
'nullable',
|
||||
'unique:accounts,phone',
|
||||
'unique:accounts,username',
|
||||
new WithoutSpaces(), 'starts_with:+'
|
||||
'phone',
|
||||
new FilteredPhone
|
||||
]
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ use Illuminate\Validation\Rule;
|
|||
|
||||
use App\Account;
|
||||
use App\Rules\BlacklistedUsername;
|
||||
use App\Rules\FilteredPhone;
|
||||
use App\Rules\IsNotPhoneNumber;
|
||||
use App\Rules\NoUppercase;
|
||||
use App\Rules\SIPUsername;
|
||||
use App\Rules\WithoutSpaces;
|
||||
|
||||
class Request extends FormRequest
|
||||
{
|
||||
|
|
@ -60,11 +60,12 @@ class Request extends FormRequest
|
|||
'dtmf_protocol' => 'nullable|in:' . Account::dtmfProtocolsRule(),
|
||||
'phone' => [
|
||||
'nullable',
|
||||
'phone',
|
||||
new FilteredPhone,
|
||||
Rule::unique('accounts', 'username')->where(function ($query) {
|
||||
$query->where('domain', resolveDomain($this));
|
||||
})->ignore($this->route('id'), 'id'),
|
||||
Rule::unique('accounts', 'phone')->ignore($this->route('account_id'), 'id'),
|
||||
new WithoutSpaces, 'starts_with:+'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
|
|
|||
22
flexiapi/app/PhoneCountry.php
Normal file
22
flexiapi/app/PhoneCountry.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PhoneCountry extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public $incrementing = false;
|
||||
protected $visible = ['code', 'country_code', 'activated'];
|
||||
protected $casts = [
|
||||
'activated' => 'boolean',
|
||||
];
|
||||
|
||||
public function getNameAttribute(): ?string
|
||||
{
|
||||
return getCountryCodes()[$this->attributes['code']];
|
||||
}
|
||||
}
|
||||
24
flexiapi/app/Rules/FilteredPhone.php
Normal file
24
flexiapi/app/Rules/FilteredPhone.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use App\PhoneCountry;
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use Propaganistas\LaravelPhone\PhoneNumber;
|
||||
|
||||
class FilteredPhone implements Rule
|
||||
{
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
if (!PhoneCountry::where('code', (new PhoneNumber($value))->getCountry())
|
||||
->where('activated', true)
|
||||
->exists()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function message()
|
||||
{
|
||||
return 'The phone number must belong to an authorized country.';
|
||||
}
|
||||
}
|
||||
|
|
@ -31,9 +31,9 @@ use App\Mail\NewsletterRegistration;
|
|||
use App\Mail\RecoverByCode;
|
||||
use App\Mail\RegisterValidation;
|
||||
use App\PhoneChangeCode;
|
||||
use App\Rules\FilteredPhone;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Rules\WithoutSpaces;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -223,9 +223,10 @@ class AccountService
|
|||
{
|
||||
$request->validate([
|
||||
'phone' => [
|
||||
'phone',
|
||||
new FilteredPhone,
|
||||
'required', 'unique:accounts,phone',
|
||||
'unique:accounts,username',
|
||||
new WithoutSpaces(), 'starts_with:+'
|
||||
]
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
"ovh/ovh": "^3.2",
|
||||
"parsedown/laravel": "^1.2",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"propaganistas/laravel-phone": "^5.1",
|
||||
"react/socket": "^1.14",
|
||||
"respect/validation": "^2.2",
|
||||
"sabre/vobject": "^4.5",
|
||||
|
|
|
|||
285
flexiapi/composer.lock
generated
285
flexiapi/composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e9d79f33a899fd2dcde3de88c243e800",
|
||||
"content-hash": "075490b395def258891e92f9518e7a03",
|
||||
"packages": [
|
||||
{
|
||||
"name": "awobaz/compoships",
|
||||
|
|
@ -298,16 +298,16 @@
|
|||
},
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"version": "v3.0.2",
|
||||
"version": "v3.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dflydev/dflydev-dot-access-data.git",
|
||||
"reference": "f41715465d65213d644d3141a6a93081be5d3549"
|
||||
"reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549",
|
||||
"reference": "f41715465d65213d644d3141a6a93081be5d3549",
|
||||
"url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f",
|
||||
"reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -367,9 +367,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
|
||||
"source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2"
|
||||
"source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3"
|
||||
},
|
||||
"time": "2022-10-27T11:44:00+00:00"
|
||||
"time": "2024-07-08T12:26:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
|
|
@ -1389,6 +1389,135 @@
|
|||
],
|
||||
"time": "2023-10-12T05:21:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "giggsey/libphonenumber-for-php",
|
||||
"version": "8.13.40",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
|
||||
"reference": "795e0b760e5c439b6fa1ffa787c1d90c2face1ff"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/795e0b760e5c439b6fa1ffa787c1d90c2face1ff",
|
||||
"reference": "795e0b760e5c439b6fa1ffa787c1d90c2face1ff",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"giggsey/locale": "^1.7|^2.0",
|
||||
"php": ">=5.3.2",
|
||||
"symfony/polyfill-mbstring": "^1.17"
|
||||
},
|
||||
"replace": {
|
||||
"giggsey/libphonenumber-for-php-lite": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"pear/pear-core-minimal": "^1.9",
|
||||
"pear/pear_exception": "^1.0",
|
||||
"pear/versioncontrol_git": "^0.5",
|
||||
"phing/phing": "^2.7",
|
||||
"php-coveralls/php-coveralls": "^1.0|^2.0",
|
||||
"symfony/console": "^2.8|^3.0|^v4.4|^v5.2",
|
||||
"symfony/phpunit-bridge": "^4.2 || ^5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"libphonenumber\\": "src/"
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/src/data/",
|
||||
"/src/carrier/data/",
|
||||
"/src/geocoding/data/",
|
||||
"/src/timezone/data/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Joshua Gigg",
|
||||
"email": "giggsey@gmail.com",
|
||||
"homepage": "https://giggsey.com/"
|
||||
}
|
||||
],
|
||||
"description": "PHP Port of Google's libphonenumber",
|
||||
"homepage": "https://github.com/giggsey/libphonenumber-for-php",
|
||||
"keywords": [
|
||||
"geocoding",
|
||||
"geolocation",
|
||||
"libphonenumber",
|
||||
"mobile",
|
||||
"phonenumber",
|
||||
"validation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
|
||||
"source": "https://github.com/giggsey/libphonenumber-for-php"
|
||||
},
|
||||
"time": "2024-07-01T11:38:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "giggsey/locale",
|
||||
"version": "2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/giggsey/Locale.git",
|
||||
"reference": "37874fa473131247c348059fb7b8985efc18b5ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/giggsey/Locale/zipball/37874fa473131247c348059fb7b8985efc18b5ea",
|
||||
"reference": "37874fa473131247c348059fb7b8985efc18b5ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"pear/pear-core-minimal": "^1.9",
|
||||
"pear/pear_exception": "^1.0",
|
||||
"pear/versioncontrol_git": "^0.5",
|
||||
"phing/phing": "^2.7",
|
||||
"php-coveralls/php-coveralls": "^2.0",
|
||||
"phpunit/phpunit": "^8.5|^9.5",
|
||||
"symfony/console": "^5.0|^6.0",
|
||||
"symfony/filesystem": "^5.0|^6.0",
|
||||
"symfony/finder": "^5.0|^6.0",
|
||||
"symfony/process": "^5.0|^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Giggsey\\Locale\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Joshua Gigg",
|
||||
"email": "giggsey@gmail.com",
|
||||
"homepage": "https://giggsey.com/"
|
||||
}
|
||||
],
|
||||
"description": "Locale functions required by libphonenumber-for-php",
|
||||
"support": {
|
||||
"issues": "https://github.com/giggsey/Locale/issues",
|
||||
"source": "https://github.com/giggsey/Locale/tree/2.6"
|
||||
},
|
||||
"time": "2024-04-18T19:31:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "graham-campbell/result-type",
|
||||
"version": "v1.1.2",
|
||||
|
|
@ -3177,16 +3306,16 @@
|
|||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v5.0.2",
|
||||
"version": "v5.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13"
|
||||
"reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
||||
"reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1",
|
||||
"reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3197,7 +3326,7 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"ircmaxell/php-yacc": "^0.0.7",
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
|
||||
"phpunit/phpunit": "^9.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/php-parse"
|
||||
|
|
@ -3229,9 +3358,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nikic/PHP-Parser/issues",
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2"
|
||||
"source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0"
|
||||
},
|
||||
"time": "2024-03-05T20:51:40+00:00"
|
||||
"time": "2024-07-01T20:03:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/termwind",
|
||||
|
|
@ -3945,45 +4074,45 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.6.19",
|
||||
"version": "9.6.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "a1a54a473501ef4cdeaae4e06891674114d79db8"
|
||||
"reference": "49d7820565836236411f5dc002d16dd689cde42f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8",
|
||||
"reference": "a1a54a473501ef4cdeaae4e06891674114d79db8",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f",
|
||||
"reference": "49d7820565836236411f5dc002d16dd689cde42f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.3.1 || ^2",
|
||||
"doctrine/instantiator": "^1.5.0 || ^2",
|
||||
"ext-dom": "*",
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.10.1",
|
||||
"phar-io/manifest": "^2.0.3",
|
||||
"phar-io/version": "^3.0.2",
|
||||
"myclabs/deep-copy": "^1.12.0",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=7.3",
|
||||
"phpunit/php-code-coverage": "^9.2.28",
|
||||
"phpunit/php-file-iterator": "^3.0.5",
|
||||
"phpunit/php-code-coverage": "^9.2.31",
|
||||
"phpunit/php-file-iterator": "^3.0.6",
|
||||
"phpunit/php-invoker": "^3.1.1",
|
||||
"phpunit/php-text-template": "^2.0.3",
|
||||
"phpunit/php-timer": "^5.0.2",
|
||||
"sebastian/cli-parser": "^1.0.1",
|
||||
"sebastian/code-unit": "^1.0.6",
|
||||
"phpunit/php-text-template": "^2.0.4",
|
||||
"phpunit/php-timer": "^5.0.3",
|
||||
"sebastian/cli-parser": "^1.0.2",
|
||||
"sebastian/code-unit": "^1.0.8",
|
||||
"sebastian/comparator": "^4.0.8",
|
||||
"sebastian/diff": "^4.0.3",
|
||||
"sebastian/environment": "^5.1.3",
|
||||
"sebastian/exporter": "^4.0.5",
|
||||
"sebastian/global-state": "^5.0.1",
|
||||
"sebastian/object-enumerator": "^4.0.3",
|
||||
"sebastian/resource-operations": "^3.0.3",
|
||||
"sebastian/type": "^3.2",
|
||||
"sebastian/diff": "^4.0.6",
|
||||
"sebastian/environment": "^5.1.5",
|
||||
"sebastian/exporter": "^4.0.6",
|
||||
"sebastian/global-state": "^5.0.7",
|
||||
"sebastian/object-enumerator": "^4.0.4",
|
||||
"sebastian/resource-operations": "^3.0.4",
|
||||
"sebastian/type": "^3.2.1",
|
||||
"sebastian/version": "^3.0.2"
|
||||
},
|
||||
"suggest": {
|
||||
|
|
@ -4028,7 +4157,7 @@
|
|||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -4044,7 +4173,79 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-05T04:35:58+00:00"
|
||||
"time": "2024-07-10T11:45:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "propaganistas/laravel-phone",
|
||||
"version": "5.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Propaganistas/Laravel-Phone.git",
|
||||
"reference": "d8c0e5fbde9820e026595616a7a36074233a09c6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Propaganistas/Laravel-Phone/zipball/d8c0e5fbde9820e026595616a7a36074233a09c6",
|
||||
"reference": "d8c0e5fbde9820e026595616a7a36074233a09c6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"giggsey/libphonenumber-for-php": "^7.0|^8.0",
|
||||
"illuminate/contracts": "^9.0|^10.0",
|
||||
"illuminate/support": "^9.0|^10.0",
|
||||
"illuminate/validation": "^9.0|^10.0",
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "^1.4",
|
||||
"nunomaduro/larastan": "^2.4",
|
||||
"orchestra/testbench": "*",
|
||||
"phpunit/phpunit": "^9.5.10"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Propaganistas\\LaravelPhone\\PhoneServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Propaganistas\\LaravelPhone\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Propaganistas",
|
||||
"email": "Propaganistas@users.noreply.github.com"
|
||||
}
|
||||
],
|
||||
"description": "Adds phone number functionality to Laravel based on Google's libphonenumber API.",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"libphonenumber",
|
||||
"phone",
|
||||
"validation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Propaganistas/Laravel-Phone/issues",
|
||||
"source": "https://github.com/Propaganistas/Laravel-Phone/tree/5.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/Propaganistas",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-01-15T09:23:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
|
|
@ -5446,16 +5647,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sabre/vobject",
|
||||
"version": "4.5.4",
|
||||
"version": "4.5.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sabre-io/vobject.git",
|
||||
"reference": "a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772"
|
||||
"reference": "7148cf57d25aaba0a49f6656d37c35e8175b3087"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sabre-io/vobject/zipball/a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772",
|
||||
"reference": "a6d53a3e5bec85ed3dd78868b7de0f5b4e12f772",
|
||||
"url": "https://api.github.com/repos/sabre-io/vobject/zipball/7148cf57d25aaba0a49f6656d37c35e8175b3087",
|
||||
"reference": "7148cf57d25aaba0a49f6656d37c35e8175b3087",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -5546,7 +5747,7 @@
|
|||
"issues": "https://github.com/sabre-io/vobject/issues",
|
||||
"source": "https://github.com/fruux/sabre-vobject"
|
||||
},
|
||||
"time": "2023-11-09T12:54:37+00:00"
|
||||
"time": "2024-07-02T08:48:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabre/xml",
|
||||
|
|
|
|||
70
flexiapi/database/factories/PhoneCountryFactory.php
Normal file
70
flexiapi/database/factories/PhoneCountryFactory.php
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
|
||||
class PhoneCountryFactory extends Factory
|
||||
{
|
||||
public function definition()
|
||||
{
|
||||
$phoneNumberUtils = PhoneNumberUtil::getInstance();
|
||||
|
||||
$codes = ['AF', 'AX', 'AL', 'DZ', 'AS', 'AD'];
|
||||
$code = $codes[array_rand($codes)];
|
||||
|
||||
return [
|
||||
'code' => $code,
|
||||
'country_code' => $phoneNumberUtils->getMetadataForRegion($code)->getCountryCode(),
|
||||
'activated' => false,
|
||||
];
|
||||
}
|
||||
|
||||
public function france()
|
||||
{
|
||||
$code = 'FR';
|
||||
$phoneNumberUtils = PhoneNumberUtil::getInstance();
|
||||
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'code' => $code,
|
||||
'country_code' => $phoneNumberUtils->getMetadataForRegion($code)->getCountryCode()
|
||||
]);
|
||||
}
|
||||
|
||||
public function netherlands()
|
||||
{
|
||||
$code = 'NL';
|
||||
$phoneNumberUtils = PhoneNumberUtil::getInstance();
|
||||
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'code' => $code,
|
||||
'country_code' => $phoneNumberUtils->getMetadataForRegion($code)->getCountryCode()
|
||||
]);
|
||||
}
|
||||
|
||||
public function activated()
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'activated' => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use App\PhoneCountry;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('phone_countries', function (Blueprint $table) {
|
||||
$table->string('code', 2)->primary();
|
||||
$table->string('country_code', 3);
|
||||
$table->boolean('activated')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
$phoneNumberUtils = PhoneNumberUtil::getInstance();
|
||||
foreach (getCountryCodes() as $code => $name) {
|
||||
$phoneCountry = new PhoneCountry();
|
||||
$phoneCountry->code = $code;
|
||||
$phoneCountry->country_code = $phoneNumberUtils->getMetadataForRegion($code)->getCountryCode();
|
||||
$phoneCountry->save();
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('phone_countries');
|
||||
}
|
||||
};
|
||||
4
flexiapi/public/css/style.css
vendored
4
flexiapi/public/css/style.css
vendored
|
|
@ -432,6 +432,7 @@ content>nav a {
|
|||
margin: 1rem 0;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
content>nav a.current {
|
||||
|
|
@ -446,8 +447,7 @@ content>nav a.current i {
|
|||
}
|
||||
|
||||
content>nav a i {
|
||||
margin: 0 1rem;
|
||||
margin-left: 2rem;
|
||||
margin-right: 0.75rem;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
|
|
|
|||
52
flexiapi/resources/views/admin/phone_country/index.blade.php
Normal file
52
flexiapi/resources/views/admin/phone_country/index.blade.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item" aria-current="page">
|
||||
Phone Countries
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
<header>
|
||||
<h1><i class="material-symbols-outlined">flag</i> Phone Countries</h1>
|
||||
<a class="btn btn-secondary oppose" href="{{ route('admin.phone_countries.activate_all') }}">
|
||||
<i class="material-symbols-outlined">add_circle</i>
|
||||
Activate All
|
||||
</a>
|
||||
<a class="btn btn-secondary" href="{{ route('admin.phone_countries.deactivate_all') }}">
|
||||
<i class="material-symbols-outlined">remove_circle</i>
|
||||
Deactivate All
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Name</th>
|
||||
<th>Country code</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($phone_countries as $phone_country)
|
||||
<tr>
|
||||
<td>{{ $phone_country->code }}</td>
|
||||
<td>{{ $phone_country->name }}</td>
|
||||
<td>{{ $phone_country->country_code }}</td>
|
||||
<td>
|
||||
@if ($phone_country->activated)
|
||||
<span class="badge badge-success" title="Activated">Activated</span>
|
||||
<a href="{{ route('admin.phone_countries.deactivate', $phone_country->code) }}">Desactivate</a>
|
||||
@else
|
||||
<span class="badge badge-error" title="Deactivated">Deactivated</span>
|
||||
<a href="{{ route('admin.phone_countries.activate', $phone_country->code) }}">Activate</a>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@endsection
|
||||
|
|
@ -243,7 +243,7 @@ JSON parameters:
|
|||
* `algorithm` required, values can be `SHA-256` or `MD5`
|
||||
* `domain` if not set the value is enforced to the default registration domain set in the global configuration
|
||||
* `email` optional if `phone` set, an email, set an email to the account, must be unique if `ACCOUNT_EMAIL_UNIQUE` is set to `true`
|
||||
* `phone` required if `username` not set, optional if `email` set, a phone number, set a phone number to the account
|
||||
* `phone` required if `username` not set, optional if `email` set, a valid phone number, set a phone number to the account
|
||||
* `account_creation_token` the unique `account_creation_token`
|
||||
|
||||
### `POST /accounts/with-account-creation-token`
|
||||
|
|
@ -284,7 +284,7 @@ Can only be used once, a new `recover_key` need to be requested to be called aga
|
|||
|
||||
JSON parameters:
|
||||
|
||||
* `phone` required the phone number to send the SMS to
|
||||
* `phone` required, the phone number to send the SMS to
|
||||
* `account_creation_token` the unique `account_creation_token`
|
||||
|
||||
### `GET /accounts/{sip}/recover/{recover_key}`
|
||||
|
|
@ -380,7 +380,7 @@ JSON parameters:
|
|||
* `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
|
||||
* `phone` optional, a phone number, set a phone number to the account
|
||||
* `phone` optional, a valid phone number, set a phone number to the account
|
||||
* `dtmf_protocol` optional, values must be `sipinfo`, `sipmessage` or `rfc2833`
|
||||
* `dictionary` optional, an associative array attached to the account, <a href="#dictionary">see also the related endpoints</a>.
|
||||
* <span class="badge badge-message">Deprecated</span> `confirmation_key_expires` optional, a datetime of this format: Y-m-d H:i:s. Only used when `activated` is not used or `false`. Enforces an expiration date on the returned `confirmation_key`. After that datetime public email or phone activation endpoints will return `403`.
|
||||
|
|
@ -399,7 +399,7 @@ JSON parameters:
|
|||
* `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
|
||||
* `phone` optional, a phone number, set a phone number to the account
|
||||
* `phone` optional, a valid phone number, set a phone number to the account
|
||||
* `dtmf_protocol` optional, values must be `sipinfo`, `sipmessage` or `rfc2833`
|
||||
|
||||
Using this endpoint you can also set a fresh dictionnary if the parameter is set. The existing dictionary entries will be destroyed.
|
||||
|
|
@ -765,6 +765,17 @@ JSON parameters:
|
|||
* `to` required, SIP address of the receiver
|
||||
* `body` required, content of the message
|
||||
|
||||
## Phone Countries
|
||||
|
||||
The phone numbers managed by FlexiAPI are validated against a list of countries that can be managed in the admin web panels.
|
||||
|
||||
### `GET /phones_countries`
|
||||
<span class="badge badge-success">Public</span>
|
||||
|
||||
Return the list of Phone Countries and their current status.
|
||||
|
||||
If a country is deactivated all the new submitted phones submitted on the platform will be blocked.
|
||||
|
||||
## Statistics
|
||||
|
||||
FlexiAPI can record logs generated by the FlexiSIP server and compile them into statistics.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
if (auth()->user()->superAdmin) {
|
||||
$items['admin.sip_domains.index'] = ['title' => 'SIP Domains', 'icon' => 'dns'];
|
||||
$items['admin.phone_countries.index'] = ['title' => 'Phone Countries', 'icon' => 'flag'];
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ Route::post('accounts/auth_token', 'Api\Account\AuthTokenController@store');
|
|||
|
||||
Route::get('accounts/me/api_key/{auth_token}', 'Api\Account\ApiKeyController@generateFromToken')->middleware('cookie', 'cookie.encrypt');
|
||||
|
||||
Route::get('phone_countries', 'Api\PhoneCountryController@index');
|
||||
|
||||
Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blocked']], function () {
|
||||
Route::get('accounts/auth_token/{auth_token}/attach', 'Api\Account\AuthTokenController@attach');
|
||||
Route::post('account_creation_tokens/consume', 'Api\Account\CreationTokenController@consume');
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ use App\Http\Controllers\Admin\AccountController as AdminAccountController;
|
|||
use App\Http\Controllers\Admin\AccountStatisticsController;
|
||||
use App\Http\Controllers\Admin\ContactsListController;
|
||||
use App\Http\Controllers\Admin\ContactsListContactController;
|
||||
use App\Http\Controllers\Admin\PhoneCountryController;
|
||||
use App\Http\Controllers\Admin\SipDomainController;
|
||||
use App\Http\Controllers\Admin\StatisticsController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
|
@ -157,6 +158,14 @@ Route::group(['middleware' => 'web_panel_enabled'], function () {
|
|||
Route::middleware(['auth.super_admin'])->group(function () {
|
||||
Route::resource('sip_domains', SipDomainController::class);
|
||||
Route::get('sip_domains/delete/{id}', 'Admin\SipDomainController@delete')->name('sip_domains.delete');
|
||||
|
||||
Route::name('phone_countries.')->controller(PhoneCountryController::class)->prefix('phone_countries')->group(function () {
|
||||
Route::get('/', 'index')->name('index');
|
||||
Route::get('/activate_all', 'activateAll')->name('activate_all');
|
||||
Route::get('/deactivate_all', 'deactivateAll')->name('deactivate_all');
|
||||
Route::get('/{code}/activate', 'activate')->name('activate');
|
||||
Route::get('/{code}/deactivate', 'deactivate')->name('deactivate');
|
||||
});
|
||||
});
|
||||
|
||||
Route::name('statistics.')->controller(StatisticsController::class)->prefix('statistics')->group(function () {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class AccountBlockingTest extends TestCase
|
|||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->route . '/me/phone/request', [
|
||||
'phone' => '+331234'
|
||||
'phone' => '+33612312312'
|
||||
])->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ class ApiAccountCreationTokenTest extends TestCase
|
|||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, '/api/accounts/me/phone/request', [
|
||||
'phone' => '+33123'
|
||||
'phone' => '+33612312312'
|
||||
])
|
||||
->assertStatus(200);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
namespace Tests\Feature;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountCreationToken;
|
||||
use App\PhoneChangeCode;
|
||||
use App\PhoneCountry;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ApiAccountPhoneChangeTest extends TestCase
|
||||
|
|
@ -55,7 +55,7 @@ class ApiAccountPhoneChangeTest extends TestCase
|
|||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->route.'/request', [
|
||||
'phone' => '+123123'
|
||||
'phone' => '+33612312312'
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
|
|
@ -71,6 +71,35 @@ class ApiAccountPhoneChangeTest extends TestCase
|
|||
->assertStatus(410);
|
||||
}
|
||||
|
||||
public function testCreatePhoneByCountry()
|
||||
{
|
||||
$account = Account::factory()->withConsumedAccountCreationToken()->create();
|
||||
$account->generateApiKey();
|
||||
|
||||
$frenchPhoneNumber = '+33612121212';
|
||||
$dutchPhoneNumber = '+31612121212';
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->route.'/request', [
|
||||
'phone' => $frenchPhoneNumber
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->route.'/request', [
|
||||
'phone' => $dutchPhoneNumber
|
||||
])
|
||||
->assertJsonValidationErrors(['phone']);
|
||||
|
||||
PhoneCountry::where('code', 'NL')->update(['activated' => true]);
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->route.'/request', [
|
||||
'phone' => $dutchPhoneNumber
|
||||
])
|
||||
->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testUnvalidatedAccount()
|
||||
{
|
||||
$account = Account::factory()->create();
|
||||
|
|
|
|||
|
|
@ -869,7 +869,7 @@ class ApiAccountTest extends TestCase
|
|||
*/
|
||||
public function testRecoverPhone()
|
||||
{
|
||||
$phone = '+3361234';
|
||||
$phone = '+33612312312';
|
||||
|
||||
$password = Password::factory()->create();
|
||||
$password->account->generateApiKey();
|
||||
|
|
@ -892,7 +892,7 @@ class ApiAccountTest extends TestCase
|
|||
|
||||
// Wrong phone
|
||||
$this->json($this->method, $this->route . '/recover-by-phone', [
|
||||
'phone' => '+331234', // wrong phone number
|
||||
'phone' => '+33612312313', // wrong phone number
|
||||
'account_creation_token' => $token->token
|
||||
])->assertJsonValidationErrors(['phone']);
|
||||
|
||||
|
|
@ -923,7 +923,10 @@ class ApiAccountTest extends TestCase
|
|||
]);
|
||||
|
||||
$this->get($this->route . '/+1234/info-by-phone')
|
||||
->assertStatus(404);
|
||||
->assertStatus(302);
|
||||
|
||||
$this->get($this->route . '/+33612312312/info-by-phone')
|
||||
->assertStatus(200);
|
||||
|
||||
$this->json('GET', $this->route . '/' . $password->account->identifier . '/info-by-phone')
|
||||
->assertJsonValidationErrors(['phone']);
|
||||
|
|
@ -1030,7 +1033,7 @@ class ApiAccountTest extends TestCase
|
|||
|
||||
public function testCreatePublicPhone()
|
||||
{
|
||||
$phone = '+12345';
|
||||
$phone = '+33612312312';
|
||||
|
||||
config()->set('app.dangerous_endpoints', true);
|
||||
|
||||
|
|
|
|||
79
flexiapi/tests/Feature/ApiPhoneCountryTest.php
Normal file
79
flexiapi/tests/Feature/ApiPhoneCountryTest.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Account;
|
||||
use App\PhoneCountry;
|
||||
use App\SipDomain;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ApiPhoneCountryTest extends TestCase
|
||||
{
|
||||
protected $route = '/api/phone_countries';
|
||||
protected $method = 'POST';
|
||||
protected $routeChangePhone = '/api/accounts/me/phone';
|
||||
|
||||
public function testCreatePhoneByCountry()
|
||||
{
|
||||
$account = Account::factory()->withConsumedAccountCreationToken()->create();
|
||||
$account->generateApiKey();
|
||||
|
||||
$frenchPhoneNumber = '+33612121212';
|
||||
$dutchPhoneNumber = '+31612121212';
|
||||
|
||||
$this->get($this->route)
|
||||
->assertStatus(200)
|
||||
->assertJsonFragment([
|
||||
'code' => 'FR',
|
||||
'activated' => true
|
||||
])
|
||||
->assertJsonFragment([
|
||||
'code' => 'NL',
|
||||
'activated' => false
|
||||
]);
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->routeChangePhone.'/request', [
|
||||
'phone' => $frenchPhoneNumber
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->routeChangePhone.'/request', [
|
||||
'phone' => $dutchPhoneNumber
|
||||
])
|
||||
->assertJsonValidationErrors(['phone']);
|
||||
|
||||
PhoneCountry::where('code', 'NL')->update(['activated' => true]);
|
||||
|
||||
$this->get($this->route)
|
||||
->assertStatus(200)
|
||||
->assertJsonFragment([
|
||||
'code' => 'NL',
|
||||
'activated' => true
|
||||
]);
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json($this->method, $this->routeChangePhone.'/request', [
|
||||
'phone' => $dutchPhoneNumber
|
||||
])
|
||||
->assertStatus(200);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ namespace Tests;
|
|||
|
||||
use App\Password;
|
||||
use App\Account;
|
||||
|
||||
use App\PhoneCountry;
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
|
|
@ -33,6 +33,15 @@ abstract class TestCase extends BaseTestCase
|
|||
protected $route = '/api/accounts/me';
|
||||
protected $method = 'GET';
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
PhoneCountry::truncate();
|
||||
PhoneCountry::factory()->france()->activated()->create();
|
||||
PhoneCountry::factory()->netherlands()->create();
|
||||
}
|
||||
|
||||
protected function disableBlockingService()
|
||||
{
|
||||
config()->set('app.blocking_amount_events_authorized_during_period', 0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue