mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-17 10:08:05 +00:00
Add the activated parameter in the API accounts creation command
Complete the README documentation to add the artisan commands Add an API key authentication mechanism Update the dependencies
This commit is contained in:
parent
1922ff8eac
commit
603f1a6686
16 changed files with 302 additions and 78 deletions
|
|
@ -105,3 +105,29 @@ To expire and/or clear old nonces a specific command should be called periodical
|
|||
## Usage
|
||||
|
||||
The `/api` page contains all the required documentation to authenticate and request the API.
|
||||
|
||||
## Console commands
|
||||
|
||||
FlexiAPI is shipped with several console commands that you can launch using the `artisan` executable available at the root of this project.
|
||||
|
||||
### Clear Expired Nonces for DIGEST authentication
|
||||
|
||||
This will remove the nonces stored that were not updated after `x minutes`.
|
||||
|
||||
php artisan digest:expired-nonces-clear {minutes}
|
||||
|
||||
### Remove the unconfirmed accounts
|
||||
|
||||
This request will remove the accounts that were not confirmed after `x days`. In the database an unconfirmed account is having the `activated` attribute set to `false`.
|
||||
|
||||
php artisan accounts:clear-unconfirmed {days} {--apply}
|
||||
|
||||
The base request will not delete the related accounts by default. You need to add `--apply` to remove them.
|
||||
|
||||
### Set an account admin
|
||||
|
||||
This command will set the admin role to any available FlexiSIP account (the external FlexiSIP database need to be configured beforehand). You need to use the account DB id as a parameter in this command.
|
||||
|
||||
php artisan accounts:set-admin {account_id}
|
||||
|
||||
Once one account is declared as administrator, you can directly configure the other ones using the web panel.
|
||||
|
|
@ -23,6 +23,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\ApiKey;
|
||||
|
||||
class Account extends Authenticatable
|
||||
{
|
||||
|
|
@ -60,6 +63,11 @@ class Account extends Authenticatable
|
|||
return $this->hasOne('App\Admin');
|
||||
}
|
||||
|
||||
public function apiKey()
|
||||
{
|
||||
return $this->hasOne('App\ApiKey');
|
||||
}
|
||||
|
||||
public function emailChanged()
|
||||
{
|
||||
return $this->hasOne('App\EmailChanged');
|
||||
|
|
@ -70,6 +78,16 @@ class Account extends Authenticatable
|
|||
return $this->attributes['username'].'@'.$this->attributes['domain'];
|
||||
}
|
||||
|
||||
public function generateApiKey()
|
||||
{
|
||||
$this->apiKey()->delete();
|
||||
|
||||
$apiKey = new ApiKey;
|
||||
$apiKey->account_id = $this->id;
|
||||
$apiKey->key = Str::random(40);
|
||||
$apiKey->save();
|
||||
}
|
||||
|
||||
public function isAdmin()
|
||||
{
|
||||
return ($this->admin);
|
||||
|
|
|
|||
36
flexiapi/app/ApiKey.php
Normal file
36
flexiapi/app/ApiKey.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?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 App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ApiKey extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $connection = 'local';
|
||||
protected $table = 'api_keys';
|
||||
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo('App\Account');
|
||||
}
|
||||
}
|
||||
|
|
@ -93,4 +93,12 @@ class AccountController extends Controller
|
|||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function generateApiKey(Request $request)
|
||||
{
|
||||
$account = $request->user();
|
||||
$account->generateApiKey();
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class AccountController extends Controller
|
|||
'algorithm' => 'required|in:SHA-256,MD5',
|
||||
'password' => 'required|filled',
|
||||
'domain' => 'min:3',
|
||||
'activated' => 'boolean|nullable',
|
||||
]);
|
||||
|
||||
$algorithm = $request->has('password_sha256') ? 'SHA-256' : 'MD5';
|
||||
|
|
@ -43,7 +44,9 @@ class AccountController extends Controller
|
|||
$account = new Account;
|
||||
$account->username = $request->get('username');
|
||||
$account->email = $request->get('email');
|
||||
$account->activated = true;
|
||||
$account->activated = $request->has('activated')
|
||||
? (bool)$request->get('activated')
|
||||
: false;
|
||||
$account->domain = $request->has('domain')
|
||||
? $request->get('domain')
|
||||
: config('app.sip_domain');
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class Kernel extends HttpKernel
|
|||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.admin' => \App\Http\Middleware\AuthenticateAdmin::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'auth.digest' => \App\Http\Middleware\AuthenticateDigest::class,
|
||||
'auth.digest_or_key' => \App\Http\Middleware\AuthenticateDigestOrKey::class,
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use Illuminate\Http\Response;
|
|||
use Closure;
|
||||
use Validator;
|
||||
|
||||
class AuthenticateDigest
|
||||
class AuthenticateDigestOrKey
|
||||
{
|
||||
const ALGORITHMS = [
|
||||
'MD5' => 'md5',
|
||||
|
|
@ -56,6 +56,21 @@ class AuthenticateDigest
|
|||
->where('domain', $domain)
|
||||
->firstOrFail();
|
||||
|
||||
// Key authentication
|
||||
if ($request->header('x-api-key')) {
|
||||
if ($account->apiKey
|
||||
&& $account->apiKey->key == $request->header('x-api-key')) {
|
||||
Auth::login($account);
|
||||
$response = $next($request);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->generateUnauthorizedResponse($account);
|
||||
}
|
||||
|
||||
// DIGEST authentication
|
||||
|
||||
if ($request->header('Authorization')) {
|
||||
$auth = $this->extractAuthorizationHeader($request->header('Authorization'));
|
||||
$storedNonce = $account->nonces()->where('nonce', $auth['nonce'])->first();
|
||||
135
flexiapi/composer.lock
generated
135
flexiapi/composer.lock
generated
|
|
@ -320,27 +320,27 @@
|
|||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
"version": "3.0.1",
|
||||
"version": "v3.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dragonmantank/cron-expression.git",
|
||||
"reference": "fa4e95ff5a7f1d62c3fbc05c32729b7f3ca14b52"
|
||||
"reference": "48212cdc0a79051d50d7fc2f0645c5a321caf926"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/fa4e95ff5a7f1d62c3fbc05c32729b7f3ca14b52",
|
||||
"reference": "fa4e95ff5a7f1d62c3fbc05c32729b7f3ca14b52",
|
||||
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/48212cdc0a79051d50d7fc2f0645c5a321caf926",
|
||||
"reference": "48212cdc0a79051d50d7fc2f0645c5a321caf926",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1"
|
||||
"php": "^7.1|^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"mtdowling/cron-expression": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.11",
|
||||
"phpunit/phpunit": "^6.4|^7.0"
|
||||
"phpstan/phpstan": "^0.11|^0.12",
|
||||
"phpunit/phpunit": "^7.0|^8.0|^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -370,7 +370,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-08-21T02:30:13+00:00"
|
||||
"time": "2020-10-13T01:26:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "egulias/email-validator",
|
||||
|
|
@ -900,16 +900,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v8.9.0",
|
||||
"version": "v8.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "8a6bf870bcfa1597e514a9c7ee6df44db98abb54"
|
||||
"reference": "0c80950806cd1bc6d9a7068585a12c2bfa23bdf3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/8a6bf870bcfa1597e514a9c7ee6df44db98abb54",
|
||||
"reference": "8a6bf870bcfa1597e514a9c7ee6df44db98abb54",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/0c80950806cd1bc6d9a7068585a12c2bfa23bdf3",
|
||||
"reference": "0c80950806cd1bc6d9a7068585a12c2bfa23bdf3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1059,7 +1059,7 @@
|
|||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2020-10-06T14:22:36+00:00"
|
||||
"time": "2020-10-13T14:20:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/tinker",
|
||||
|
|
@ -1195,16 +1195,16 @@
|
|||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "1.5.5",
|
||||
"version": "1.5.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "45832dfed6007b984c0d40addfac48d403dc6432"
|
||||
"reference": "a56e91e0fa1f6d0049153a9c34f63488f6b7ce61"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/45832dfed6007b984c0d40addfac48d403dc6432",
|
||||
"reference": "45832dfed6007b984c0d40addfac48d403dc6432",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/a56e91e0fa1f6d0049153a9c34f63488f6b7ce61",
|
||||
"reference": "a56e91e0fa1f6d0049153a9c34f63488f6b7ce61",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1286,7 +1286,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-13T14:44:46+00:00"
|
||||
"time": "2020-10-17T21:33:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
|
|
@ -1435,16 +1435,16 @@
|
|||
},
|
||||
{
|
||||
"name": "league/mime-type-detection",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/mime-type-detection.git",
|
||||
"reference": "ea2fbfc988bade315acd5967e6d02274086d0f28"
|
||||
"reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ea2fbfc988bade315acd5967e6d02274086d0f28",
|
||||
"reference": "ea2fbfc988bade315acd5967e6d02274086d0f28",
|
||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/353f66d7555d8a90781f6f5e7091932f9a4250aa",
|
||||
"reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1482,7 +1482,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-21T18:10:53+00:00"
|
||||
"time": "2020-10-18T11:50:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
|
|
@ -1577,16 +1577,16 @@
|
|||
},
|
||||
{
|
||||
"name": "nesbot/carbon",
|
||||
"version": "2.41.2",
|
||||
"version": "2.41.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/briannesbitt/Carbon.git",
|
||||
"reference": "35959c93ada06469107a05df6b15b65074a960cf"
|
||||
"reference": "e148788eeae9b9b7b87996520358b86faad37b52"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/35959c93ada06469107a05df6b15b65074a960cf",
|
||||
"reference": "35959c93ada06469107a05df6b15b65074a960cf",
|
||||
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e148788eeae9b9b7b87996520358b86faad37b52",
|
||||
"reference": "e148788eeae9b9b7b87996520358b86faad37b52",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1662,7 +1662,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-10T23:35:06+00:00"
|
||||
"time": "2020-10-12T20:36:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
|
|
@ -1814,20 +1814,20 @@
|
|||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v9.99.99",
|
||||
"version": "v9.99.100",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/random_compat.git",
|
||||
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95"
|
||||
"reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
|
||||
"reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
|
||||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
|
||||
"reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7"
|
||||
"php": ">= 7"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*|5.*",
|
||||
|
|
@ -1855,7 +1855,7 @@
|
|||
"pseudorandom",
|
||||
"random"
|
||||
],
|
||||
"time": "2018-07-02T15:55:56+00:00"
|
||||
"time": "2020-10-15T08:29:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "parsedown/laravel",
|
||||
|
|
@ -3133,16 +3133,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/http-client-contracts",
|
||||
"version": "v2.2.0",
|
||||
"version": "v2.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-client-contracts.git",
|
||||
"reference": "3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3"
|
||||
"reference": "41db680a15018f9c1d4b23516059633ce280ca33"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3",
|
||||
"reference": "3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3",
|
||||
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/41db680a15018f9c1d4b23516059633ce280ca33",
|
||||
"reference": "41db680a15018f9c1d4b23516059633ce280ca33",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3153,8 +3153,9 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-version": "2.3",
|
||||
"branch-alias": {
|
||||
"dev-master": "2.2-dev"
|
||||
"dev-main": "2.3-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
|
|
@ -3204,7 +3205,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-07T11:33:47+00:00"
|
||||
"time": "2020-10-14T17:08:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-foundation",
|
||||
|
|
@ -5156,16 +5157,16 @@
|
|||
},
|
||||
{
|
||||
"name": "facade/ignition",
|
||||
"version": "2.3.8",
|
||||
"version": "2.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facade/ignition.git",
|
||||
"reference": "e8fed9c382cd1d02b5606688576a35619afdf82c"
|
||||
"reference": "9fc6c3d3de5271a1b94cff19dce2c9295abf0ffa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/facade/ignition/zipball/e8fed9c382cd1d02b5606688576a35619afdf82c",
|
||||
"reference": "e8fed9c382cd1d02b5606688576a35619afdf82c",
|
||||
"url": "https://api.github.com/repos/facade/ignition/zipball/9fc6c3d3de5271a1b94cff19dce2c9295abf0ffa",
|
||||
"reference": "9fc6c3d3de5271a1b94cff19dce2c9295abf0ffa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -5224,29 +5225,29 @@
|
|||
"laravel",
|
||||
"page"
|
||||
],
|
||||
"time": "2020-10-01T23:01:14+00:00"
|
||||
"time": "2020-10-14T08:59:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/ignition-contracts",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facade/ignition-contracts.git",
|
||||
"reference": "aeab1ce8b68b188a43e81758e750151ad7da796b"
|
||||
"reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/facade/ignition-contracts/zipball/aeab1ce8b68b188a43e81758e750151ad7da796b",
|
||||
"reference": "aeab1ce8b68b188a43e81758e750151ad7da796b",
|
||||
"url": "https://api.github.com/repos/facade/ignition-contracts/zipball/3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
|
||||
"reference": "3c921a1cdba35b68a7f0ccffc6dffc1995b18267",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1"
|
||||
"php": "^7.3|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.14",
|
||||
"phpunit/phpunit": "^7.5|^8.0",
|
||||
"vimeo/psalm": "^3.12"
|
||||
"friendsofphp/php-cs-fixer": "^v2.15.8",
|
||||
"phpunit/phpunit": "^9.3.11",
|
||||
"vimeo/psalm": "^3.17.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -5273,29 +5274,29 @@
|
|||
"flare",
|
||||
"ignition"
|
||||
],
|
||||
"time": "2020-07-14T10:10:28+00:00"
|
||||
"time": "2020-10-16T08:27:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.7.3",
|
||||
"version": "2.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "5d5fe9bb3d656b514d455645b3addc5f7ba7714d"
|
||||
"reference": "fa50d9db1c0c2fae99cf988d27023effda5524a3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/5d5fe9bb3d656b514d455645b3addc5f7ba7714d",
|
||||
"reference": "5d5fe9bb3d656b514d455645b3addc5f7ba7714d",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/fa50d9db1c0c2fae99cf988d27023effda5524a3",
|
||||
"reference": "fa50d9db1c0c2fae99cf988d27023effda5524a3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9 || ^7.0",
|
||||
"php": "^5.5.9 || ^7.0 || ^8.0",
|
||||
"psr/log": "^1.0.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^0.9 || ^1.0",
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0",
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3",
|
||||
"symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
|
@ -5305,7 +5306,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.6-dev"
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
|
@ -5334,7 +5335,7 @@
|
|||
"throwable",
|
||||
"whoops"
|
||||
],
|
||||
"time": "2020-06-14T09:00:00+00:00"
|
||||
"time": "2020-10-17T09:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fzaninotto/faker",
|
||||
|
|
@ -6350,16 +6351,16 @@
|
|||
},
|
||||
{
|
||||
"name": "scrivo/highlight.php",
|
||||
"version": "v9.18.1.2",
|
||||
"version": "v9.18.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/scrivo/highlight.php.git",
|
||||
"reference": "efb6e445494a9458aa59b0af5edfa4bdcc6809d9"
|
||||
"reference": "6a1699707b099081f20a488ac1f92d682181018c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/scrivo/highlight.php/zipball/efb6e445494a9458aa59b0af5edfa4bdcc6809d9",
|
||||
"reference": "efb6e445494a9458aa59b0af5edfa4bdcc6809d9",
|
||||
"url": "https://api.github.com/repos/scrivo/highlight.php/zipball/6a1699707b099081f20a488ac1f92d682181018c",
|
||||
"reference": "6a1699707b099081f20a488ac1f92d682181018c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -6421,7 +6422,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-08-27T03:24:44+00:00"
|
||||
"time": "2020-10-16T07:43:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<?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/>.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateApiKeysTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::connection('local')->create('api_keys', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('account_id')->unsigned()->unique();
|
||||
$table->string('key')->unique();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('api_keys');
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
@if($account->isAdmin())
|
||||
<h3>Admin area</h3>
|
||||
<div class="list-group">
|
||||
<div class="list-group mb-3">
|
||||
<a href="{{ route('admin.account.index') }}" class="list-group-item list-group-item-action">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">Accounts</h5>
|
||||
|
|
@ -55,6 +55,25 @@
|
|||
<p class="mb-1">Manage the Flexisip accounts</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h5>API Key</h5>
|
||||
|
||||
<p>As an administrator you can generate an API key and use it to request the different API endpoints, <a href="{{ route('api') }}">check the related API documentation</a> to know how to use that key.</p>
|
||||
|
||||
{!! Form::open(['route' => 'admin.api_key.generate']) !!}
|
||||
<div class="form-row">
|
||||
<div class="col-8">
|
||||
<input readonly class="form-control" placeholder="No key yet, press Generate"
|
||||
@if ($account->apiKey)
|
||||
value="{{ $account->apiKey->key }}"
|
||||
@endif
|
||||
>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<button type="submit" class="btn btn-primary">Generate</button>
|
||||
</div>
|
||||
</div>
|
||||
{!! Form::close() !!}
|
||||
@endif
|
||||
|
||||
<h3 class="mt-3">Account information</h3>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,23 @@
|
|||
> accept: application/json</code></pre>
|
||||
|
||||
<h2>Authentication</h2>
|
||||
<p>Restricted endpoints are protected using a DIGEST authentication mechanism.</p>
|
||||
|
||||
<p>Restricted endpoints are protected using a DIGEST authentication or an API Key mechanisms.</p>
|
||||
|
||||
<h3>Using the API Key</h3>
|
||||
|
||||
<p>To authenticate using an API Key, you need to <a href="{{ route('account.login') }}">authenticate to your account panel</a> and being an administrator.</p>
|
||||
<p>On your panel you will then find a form to generate your personnal key.</p>
|
||||
|
||||
<p>You can then use your freshly generated key by adding a new <code>x-api-key</code> header to your API requests:</p>
|
||||
|
||||
<pre>
|
||||
<code>> GET /api/{endpoint}
|
||||
> from: sip:foobar@sip.example.org
|
||||
> x-api-key: {your-api-key}
|
||||
> …</code></pre>
|
||||
|
||||
<h3>Using DIGEST</h3>
|
||||
|
||||
<p>To discover the available hashing algorythm you MUST send an unauthenticated request to one of the restricted endpoints.<br />
|
||||
For the moment only DIGEST-MD5 and DIGEST-SHA-256 are supported through the authentication layer.</p>
|
||||
|
|
@ -43,6 +59,7 @@ For the moment only DIGEST-MD5 and DIGEST-SHA-256 are supported through the auth
|
|||
<li><code>password</code> required minimum 6 characters</li>
|
||||
<li><code>algorithm</code> required, values can be <code>SHA-256</code> or <code>MD5</code></li>
|
||||
<li><code>domain</code> optional, the value is set to the default registration domain if not set</li>
|
||||
<li><code>activated</code> optional, a boolean, set to <code>false</code> by default</li>
|
||||
</ul>
|
||||
|
||||
<p>To create an account directly from the API.<br />This endpoint is authenticated and requires an admin account.</p>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Route::middleware('auth:api')->get('/user', function (Request $request) {
|
|||
return $request->user();
|
||||
});
|
||||
|
||||
Route::group(['middleware' => ['auth.digest']], function () {
|
||||
Route::group(['middleware' => ['auth.digest_or_key']], function () {
|
||||
Route::get('ping', 'Api\PingController@ping');
|
||||
Route::get('devices', 'Api\DeviceController@index');
|
||||
Route::delete('devices/{uuid}', 'Api\DeviceController@destroy');
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ Route::group(['middleware' => 'auth.admin'], function () {
|
|||
Route::get('admin/accounts/{search?}', 'Admin\AccountController@index')->name('admin.account.index');
|
||||
Route::post('admin/search', 'Admin\AccountController@search')->name('admin.account.search');
|
||||
|
||||
Route::post('admin/api_key', 'Admin\AccountController@generateApiKey')->name('admin.api_key.generate');
|
||||
|
||||
Route::get('admin/accounts/show/{id}', 'Admin\AccountController@show')->name('admin.account.show');
|
||||
Route::get('admin/accounts/{id}/activate', 'Admin\AccountController@activate')->name('admin.account.activate');
|
||||
Route::get('admin/accounts/{id}/deactivate', 'Admin\AccountController@deactivate')->name('admin.account.deactivate');
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ class AccountApiTest extends TestCase
|
|||
->assertStatus(200)
|
||||
->assertJson([
|
||||
'id' => 2,
|
||||
'username' => $username
|
||||
'username' => $username,
|
||||
'activated' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +98,7 @@ class AccountApiTest extends TestCase
|
|||
'id' => 2,
|
||||
'username' => $username,
|
||||
'domain' => $domain,
|
||||
'activated' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +123,7 @@ class AccountApiTest extends TestCase
|
|||
'id' => 2,
|
||||
'username' => $username,
|
||||
'domain' => config('app.sip_domain'),
|
||||
'activated' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -129,8 +132,6 @@ class AccountApiTest extends TestCase
|
|||
$admin = Admin::factory()->create();
|
||||
$password = $admin->account->passwords()->first();
|
||||
|
||||
$username = 'username';
|
||||
|
||||
$response0 = $this->generateFirstResponse($password);
|
||||
$response1 = $this->generateSecondResponse($password, $response0)
|
||||
->json($this->method, $this->route, [
|
||||
|
|
@ -141,4 +142,30 @@ class AccountApiTest extends TestCase
|
|||
|
||||
$response1->assertStatus(422);
|
||||
}
|
||||
|
||||
public function testActivated()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$password = $admin->account->passwords()->first();
|
||||
|
||||
$username = 'username';
|
||||
|
||||
$response0 = $this->generateFirstResponse($password);
|
||||
$response1 = $this->generateSecondResponse($password, $response0)
|
||||
->json($this->method, $this->route, [
|
||||
'username' => $username,
|
||||
'algorithm' => 'SHA-256',
|
||||
'password' => '2',
|
||||
'activated' => true,
|
||||
]);
|
||||
|
||||
$response1
|
||||
->assertStatus(200)
|
||||
->assertJson([
|
||||
'id' => 2,
|
||||
'username' => $username,
|
||||
'domain' => config('app.sip_domain'),
|
||||
'activated' => true,
|
||||
]);;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use Illuminate\Foundation\Testing\RefreshDatabase;
|
|||
use Illuminate\Foundation\Testing\WithFaker;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AuthenticateDigestTest extends TestCase
|
||||
class AuthenticateDigestAndKeyTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
|
|
@ -58,6 +58,18 @@ class AuthenticateDigestTest extends TestCase
|
|||
$response->assertStatus(401);
|
||||
}
|
||||
|
||||
public function testAuthenticateWithKey()
|
||||
{
|
||||
$password = Password::factory()->create();
|
||||
$password->account->generateApiKey();
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'From' => 'sip:'.$password->account->identifier,
|
||||
'x-api-key' => $password->account->apiKey->key,
|
||||
])->json($this->method, $this->route);
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testMultiHash()
|
||||
{
|
||||
// Two password and we link the second to the first related account
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#%define _datadir %{_datarootdir}
|
||||
#%define _docdir %{_datadir}/doc
|
||||
|
||||
%define build_number 32
|
||||
%define build_number 34
|
||||
%define var_dir /var/opt/belledonne-communications
|
||||
%define opt_dir /opt/belledonne-communications/share/flexisip-account-manager
|
||||
%define env_file "$RPM_BUILD_ROOT/etc/flexisip-account-manager/flexiapi.env"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue