mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-17 10:08:05 +00:00
Add AccountAction model, CRUD and tests
Add AccountType model, CRUD and tests Add AccountContact model, CRUD and tests Allow users to retreive their contacts in JSON and VCARD4.0 format Update the dependencies Complete the documentation Improve the messages displayed when removing accounts in RemoveUnconfirmedAccounts Fix a bug in DeviceController Fix README
This commit is contained in:
parent
146e655bb6
commit
75a98c0949
25 changed files with 1256 additions and 93 deletions
|
|
@ -116,7 +116,7 @@ If you are planning to send emails using your account manager:
|
|||
|
||||
## Usage
|
||||
|
||||
For the web panel, a generale documentation is available under the `\documentation` page.
|
||||
For the web panel, a generale documentation is available under the `/documentation` page.
|
||||
For the REST API, the `/api` page contains all the required documentation to authenticate and request the API.
|
||||
|
||||
## Console commands
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class Account extends Authenticatable
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $with = ['passwords', 'admin', 'emailChanged', 'alias', 'activationExpiration'];
|
||||
protected $hidden = ['alias', 'expire_time', 'confirmation_key'];
|
||||
protected $with = ['passwords', 'admin', 'emailChanged', 'alias', 'activationExpiration', 'types', 'actions'];
|
||||
protected $hidden = ['alias', 'expire_time', 'confirmation_key', 'pivot'];
|
||||
protected $dateTimes = ['creation_time'];
|
||||
protected $appends = ['realm', 'phone', 'confirmation_key_expires'];
|
||||
protected $casts = [
|
||||
|
|
@ -44,6 +44,9 @@ class Account extends Authenticatable
|
|||
];
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* Scopes
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::addGlobalScope('domain', function (Builder $builder) {
|
||||
|
|
@ -63,36 +66,12 @@ class Account extends Authenticatable
|
|||
return $query->where('id', '<', 0);
|
||||
}
|
||||
|
||||
public function phoneChangeCode()
|
||||
/**
|
||||
* Relations
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return $this->hasOne('App\PhoneChangeCode');
|
||||
}
|
||||
|
||||
public function passwords()
|
||||
{
|
||||
return $this->hasMany('App\Password');
|
||||
}
|
||||
|
||||
public function alias()
|
||||
{
|
||||
return $this->hasOne('App\Alias');
|
||||
}
|
||||
|
||||
public function nonces()
|
||||
{
|
||||
return $this->hasMany('App\DigestNonce');
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
return $this->hasOne('App\Admin');
|
||||
}
|
||||
|
||||
public function hasTombstone()
|
||||
{
|
||||
return AccountTombstone::where('username', $this->attributes['username'])
|
||||
->where('domain', $this->attributes['domain'])
|
||||
->exists();
|
||||
return $this->hasMany('App\AccountAction');
|
||||
}
|
||||
|
||||
public function activationExpiration()
|
||||
|
|
@ -100,16 +79,54 @@ class Account extends Authenticatable
|
|||
return $this->hasOne('App\ActivationExpiration');
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
return $this->hasOne('App\Admin');
|
||||
}
|
||||
|
||||
public function alias()
|
||||
{
|
||||
return $this->hasOne('App\Alias');
|
||||
}
|
||||
|
||||
public function apiKey()
|
||||
{
|
||||
return $this->hasOne('App\ApiKey');
|
||||
}
|
||||
|
||||
public function contacts()
|
||||
{
|
||||
return $this->belongsToMany('App\Account', 'contacts', 'account_id', 'contact_id');
|
||||
}
|
||||
|
||||
public function emailChanged()
|
||||
{
|
||||
return $this->hasOne('App\EmailChanged');
|
||||
}
|
||||
|
||||
public function nonces()
|
||||
{
|
||||
return $this->hasMany('App\DigestNonce');
|
||||
}
|
||||
|
||||
public function passwords()
|
||||
{
|
||||
return $this->hasMany('App\Password');
|
||||
}
|
||||
|
||||
public function phoneChangeCode()
|
||||
{
|
||||
return $this->hasOne('App\PhoneChangeCode');
|
||||
}
|
||||
|
||||
public function types()
|
||||
{
|
||||
return $this->belongsToMany('App\AccountType');
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes
|
||||
*/
|
||||
public function getIdentifierAttribute()
|
||||
{
|
||||
return $this->attributes['username'].'@'.$this->attributes['domain'];
|
||||
|
|
@ -148,6 +165,9 @@ class Account extends Authenticatable
|
|||
return $this->passwords()->where('algorithm', 'SHA-256')->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
public function activationExpired(): bool
|
||||
{
|
||||
return ($this->activationExpiration && $this->activationExpiration->isExpired());
|
||||
|
|
@ -188,6 +208,13 @@ class Account extends Authenticatable
|
|||
return ($this->admin);
|
||||
}
|
||||
|
||||
public function hasTombstone()
|
||||
{
|
||||
return AccountTombstone::where('username', $this->attributes['username'])
|
||||
->where('domain', $this->attributes['domain'])
|
||||
->exists();
|
||||
}
|
||||
|
||||
public function updatePassword($newPassword, $algorithm)
|
||||
{
|
||||
$this->passwords()->delete();
|
||||
|
|
@ -198,4 +225,32 @@ class Account extends Authenticatable
|
|||
$password->algorithm = $algorithm;
|
||||
$password->save();
|
||||
}
|
||||
|
||||
public function toVcard4()
|
||||
{
|
||||
$vcard = '
|
||||
BEGIN:VCARD
|
||||
VERSION:4.0
|
||||
KIND:individual
|
||||
MEMBER:'.$this->getIdentifierAttribute();
|
||||
|
||||
if (!empty($this->attributes['display_name'])) {
|
||||
$vcard . '
|
||||
NAME:'.$this->attributes['display_name'];
|
||||
}
|
||||
|
||||
if ($this->types) {
|
||||
$vcard .= '
|
||||
X-LINPHONE-ACCOUNT-TYPE:'.$this->types->implode('key', ',');
|
||||
}
|
||||
|
||||
foreach ($this->actions as $action) {
|
||||
$vcard .= '
|
||||
X-LINPHONE-ACCOUNT-ACTION:'.$action->key.';'.$action->code.';'.$action->protocol;
|
||||
}
|
||||
|
||||
return $vcard . '
|
||||
END:VCARD
|
||||
';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
flexiapi/app/AccountAction.php
Normal file
16
flexiapi/app/AccountAction.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountAction extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo('App\Account');
|
||||
}
|
||||
}
|
||||
18
flexiapi/app/AccountType.php
Normal file
18
flexiapi/app/AccountType.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountType extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $hidden = ['pivot', 'created_at', 'updated_at'];
|
||||
|
||||
public function accounts()
|
||||
{
|
||||
return $this->belongsToMany('App\Account');
|
||||
}
|
||||
}
|
||||
|
|
@ -44,11 +44,14 @@ class RemoveUnconfirmedAccounts extends Command
|
|||
$accounts = $accounts->where('activated', false);
|
||||
}
|
||||
|
||||
$count = $accounts->count();
|
||||
|
||||
if ($this->option('apply')) {
|
||||
$this->info($accounts->count() . ' accounts deleted');
|
||||
$this->info($count . ' accounts in deletion…');
|
||||
$accounts->delete();
|
||||
$this->info($count . ' accounts deleted');
|
||||
} else {
|
||||
$this->info($accounts->count() . ' accounts to delete');
|
||||
$this->info($count . ' accounts to delete');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
flexiapi/app/Contact.php
Normal file
11
flexiapi/app/Contact.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Contact extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2021 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\Http\Controllers\Account;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class ContactVcardController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return response(
|
||||
$request->user()->contacts->map(function ($contact) {
|
||||
return $contact->toVcard4();
|
||||
})->implode('
|
||||
')
|
||||
);
|
||||
}
|
||||
|
||||
public function show(Request $request, string $sip)
|
||||
{
|
||||
return $request->user()
|
||||
->contacts()
|
||||
->sip($sip)
|
||||
->firstOrFail()
|
||||
->toVcard4();
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ class DeviceController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function destroy(string $uuid)
|
||||
public function destroy(Request $request, string $uuid)
|
||||
{
|
||||
$connector = new FlexisipConnector;
|
||||
$connector->deleteDevice($request->user()->identifier, $uuid);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2021 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\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class AccountContactController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$contacts = $request->user()->contacts;
|
||||
|
||||
return $request->has('vcard')
|
||||
? response($contacts->map(function ($contact) {
|
||||
return $contact->toVcard4();
|
||||
})->implode('
|
||||
')
|
||||
)
|
||||
: $contacts;
|
||||
}
|
||||
|
||||
public function show(Request $request, string $sip)
|
||||
{
|
||||
$contact = $request->user()
|
||||
->contacts()
|
||||
->sip($sip)
|
||||
->firstOrFail();
|
||||
|
||||
return $request->has('vcard')
|
||||
? $contact->toVcard4()
|
||||
: $contact;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2021 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\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountAction;
|
||||
use App\Rules\NoUppercase;
|
||||
|
||||
class AccountActionController extends Controller
|
||||
{
|
||||
public function index(int $id)
|
||||
{
|
||||
return Account::findOrFail($id)->actions;
|
||||
}
|
||||
|
||||
public function get(int $id, int $actionId)
|
||||
{
|
||||
return Account::findOrFail($id)
|
||||
->actions()
|
||||
->where('id', $actionId)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
public function store(Request $request, int $id)
|
||||
{
|
||||
$request->validate([
|
||||
'key' => ['required', 'alpha_dash', new NoUppercase],
|
||||
'code' => ['required', 'alpha_num', new NoUppercase],
|
||||
'protocol' => 'required|in:sipinfo,rfc2833'
|
||||
]);
|
||||
|
||||
$accountAction = new AccountAction;
|
||||
$accountAction->account_id = Account::findOrFail($id)->id;
|
||||
$accountAction->key = $request->get('key');
|
||||
$accountAction->code = $request->get('code');
|
||||
$accountAction->protocol = $request->get('protocol');
|
||||
$accountAction->save();
|
||||
|
||||
return $accountAction;
|
||||
}
|
||||
|
||||
public function update(Request $request, int $id, int $actionId)
|
||||
{
|
||||
$request->validate([
|
||||
'key' => ['alpha_dash', new NoUppercase],
|
||||
'code' => ['alpha_num', new NoUppercase],
|
||||
'protocol' => 'in:sipinfo,rfc2833'
|
||||
]);
|
||||
|
||||
$accountAction = Account::findOrFail($id)
|
||||
->actions()
|
||||
->where('id', $actionId)
|
||||
->firstOrFail();
|
||||
$accountAction->key = $request->get('key');
|
||||
$accountAction->code = $request->get('code');
|
||||
$accountAction->protocol = $request->get('protocol');
|
||||
$accountAction->save();
|
||||
|
||||
return $accountAction;
|
||||
}
|
||||
|
||||
public function destroy(int $id, int $actionId)
|
||||
{
|
||||
return Account::findOrFail($id)
|
||||
->actions()
|
||||
->where('id', $actionId)
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2021 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\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
use App\Account;
|
||||
|
||||
class AccountContactController extends Controller
|
||||
{
|
||||
public function index(int $id)
|
||||
{
|
||||
return Account::findOrFail($id)->contacts;
|
||||
}
|
||||
|
||||
public function show(int $id, int $contactId)
|
||||
{
|
||||
return Account::findOrFail($id)
|
||||
->contacts()
|
||||
->where('id', $contactId)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
public function add(int $id, int $contactId)
|
||||
{
|
||||
if (Account::findOrFail($id)->contacts()->pluck('id')->contains($contactId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (Account::findOrFail($contactId)) {
|
||||
return Account::findOrFail($id)->contacts()->attach($contactId);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(int $id, int $contactId)
|
||||
{
|
||||
if (!Account::findOrFail($id)->contacts()->pluck('id')->contains($contactId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return Account::findOrFail($id)->contacts()->detach($contactId);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ use Carbon\Carbon;
|
|||
|
||||
use App\Account;
|
||||
use App\AccountTombstone;
|
||||
use App\AccountType;
|
||||
use App\ActivationExpiration;
|
||||
use App\Admin;
|
||||
use App\Alias;
|
||||
|
|
@ -116,6 +117,7 @@ class AccountController extends Controller
|
|||
$account = new Account;
|
||||
$account->username = $request->get('username');
|
||||
$account->email = $request->get('email');
|
||||
$account->display_name = $request->get('display_name');
|
||||
$account->activated = $request->has('activated')
|
||||
? (bool)$request->get('activated')
|
||||
: false;
|
||||
|
|
@ -163,4 +165,24 @@ class AccountController extends Controller
|
|||
|
||||
return response()->json($account->makeVisible(['confirmation_key']));
|
||||
}
|
||||
|
||||
public function typeAdd(int $id, int $typeId)
|
||||
{
|
||||
if (Account::findOrFail($id)->types()->pluck('id')->contains($typeId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (AccountType::findOrFail($typeId)) {
|
||||
return Account::findOrFail($id)->types()->attach($typeId);
|
||||
}
|
||||
}
|
||||
|
||||
public function typeRemove(int $id, int $typeId)
|
||||
{
|
||||
if (!Account::findOrFail($id)->types()->pluck('id')->contains($typeId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return Account::findOrFail($id)->types()->detach($typeId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2021 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\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\NoUppercase;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\AccountType;
|
||||
|
||||
class AccountTypeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return AccountType::all();
|
||||
}
|
||||
|
||||
public function get(int $accountTypeId)
|
||||
{
|
||||
return AccountType::where('id', $accountTypeId)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'key' => ['required', 'alpha_dash', new NoUppercase],
|
||||
]);
|
||||
|
||||
$accountType = new AccountType;
|
||||
$accountType->key = $request->get('key');
|
||||
$accountType->save();
|
||||
|
||||
return $accountType;
|
||||
}
|
||||
|
||||
public function update(Request $request, int $accountTypeId)
|
||||
{
|
||||
$request->validate([
|
||||
'key' => ['alpha_dash', new NoUppercase],
|
||||
]);
|
||||
|
||||
$accountType = AccountType::where('id', $accountTypeId)
|
||||
->firstOrFail();
|
||||
$accountType->key = $request->get('key');
|
||||
$accountType->save();
|
||||
|
||||
return $accountType;
|
||||
}
|
||||
|
||||
public function destroy(int $accountTypeId)
|
||||
{
|
||||
return AccountType::where('id', $accountTypeId)
|
||||
->delete();
|
||||
}
|
||||
}
|
||||
158
flexiapi/composer.lock
generated
158
flexiapi/composer.lock
generated
|
|
@ -716,16 +716,16 @@
|
|||
},
|
||||
{
|
||||
"name": "graham-campbell/result-type",
|
||||
"version": "v1.0.2",
|
||||
"version": "v1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/GrahamCampbell/Result-Type.git",
|
||||
"reference": "84afea85c6841deeea872f36249a206e878a5de0"
|
||||
"reference": "296c015dc30ec4322168c5ad3ee5cc11dae827ac"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/84afea85c6841deeea872f36249a206e878a5de0",
|
||||
"reference": "84afea85c6841deeea872f36249a206e878a5de0",
|
||||
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/296c015dc30ec4322168c5ad3ee5cc11dae827ac",
|
||||
"reference": "296c015dc30ec4322168c5ad3ee5cc11dae827ac",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -761,7 +761,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
|
||||
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.2"
|
||||
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -773,7 +773,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-08-28T21:34:50+00:00"
|
||||
"time": "2021-10-17T19:48:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
|
|
@ -848,16 +848,16 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "1.4.1",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d"
|
||||
"reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d",
|
||||
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/136a635e2b4a49b9d79e9c8fee267ffb257fdba0",
|
||||
"reference": "136a635e2b4a49b9d79e9c8fee267ffb257fdba0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -869,7 +869,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
"dev-master": "1.5-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
|
@ -885,10 +885,25 @@
|
|||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "hello@gjcampbell.co.uk",
|
||||
"homepage": "https://github.com/GrahamCampbell"
|
||||
},
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com",
|
||||
"homepage": "https://github.com/Nyholm"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"email": "webmaster@tubo-world.de",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle promises library",
|
||||
|
|
@ -897,22 +912,36 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/promises/issues",
|
||||
"source": "https://github.com/guzzle/promises/tree/1.4.1"
|
||||
"source": "https://github.com/guzzle/promises/tree/1.5.0"
|
||||
},
|
||||
"time": "2021-03-07T09:25:29+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/GrahamCampbell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Nyholm",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-07T13:05:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.8.2",
|
||||
"version": "1.8.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "dc960a912984efb74d0a90222870c72c87f10c91"
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
|
||||
"reference": "dc960a912984efb74d0a90222870c72c87f10c91",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -949,13 +978,34 @@
|
|||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "hello@gjcampbell.co.uk",
|
||||
"homepage": "https://github.com/GrahamCampbell"
|
||||
},
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "George Mponos",
|
||||
"email": "gmponos@gmail.com",
|
||||
"homepage": "https://github.com/gmponos"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com",
|
||||
"homepage": "https://github.com/Nyholm"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com",
|
||||
"homepage": "https://github.com/sagikazarmark"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"email": "webmaster@tubo-world.de",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
|
|
@ -972,22 +1022,36 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.2"
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.3"
|
||||
},
|
||||
"time": "2021-04-26T09:17:50+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/GrahamCampbell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Nyholm",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-10-05T13:56:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v8.62.0",
|
||||
"version": "v8.64.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "60a7e00488167ce2babf3a2aeb3677e48aaf39be"
|
||||
"reference": "3337c029e1bb31d9712d27437cc27010ba302c9e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/60a7e00488167ce2babf3a2aeb3677e48aaf39be",
|
||||
"reference": "60a7e00488167ce2babf3a2aeb3677e48aaf39be",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/3337c029e1bb31d9712d27437cc27010ba302c9e",
|
||||
"reference": "3337c029e1bb31d9712d27437cc27010ba302c9e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1145,20 +1209,20 @@
|
|||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-09-28T13:30:25+00:00"
|
||||
"time": "2021-10-12T13:43:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v1.0.2",
|
||||
"version": "v1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/serializable-closure.git",
|
||||
"reference": "679e24d36ff8b9be0e36f5222244ec8602e18867"
|
||||
"reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/679e24d36ff8b9be0e36f5222244ec8602e18867",
|
||||
"reference": "679e24d36ff8b9be0e36f5222244ec8602e18867",
|
||||
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/6cfc678735f22ccedad761b8cae2bab14c3d8e5b",
|
||||
"reference": "6cfc678735f22ccedad761b8cae2bab14c3d8e5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1204,7 +1268,7 @@
|
|||
"issues": "https://github.com/laravel/serializable-closure/issues",
|
||||
"source": "https://github.com/laravel/serializable-closure"
|
||||
},
|
||||
"time": "2021-09-29T13:25:52+00:00"
|
||||
"time": "2021-10-07T14:00:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/tinker",
|
||||
|
|
@ -2335,16 +2399,16 @@
|
|||
},
|
||||
{
|
||||
"name": "psy/psysh",
|
||||
"version": "v0.10.8",
|
||||
"version": "v0.10.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bobthecow/psysh.git",
|
||||
"reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3"
|
||||
"reference": "01281336c4ae557fe4a994544f30d3a1bc204375"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/e4573f47750dd6c92dca5aee543fa77513cbd8d3",
|
||||
"reference": "e4573f47750dd6c92dca5aee543fa77513cbd8d3",
|
||||
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/01281336c4ae557fe4a994544f30d3a1bc204375",
|
||||
"reference": "01281336c4ae557fe4a994544f30d3a1bc204375",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2404,9 +2468,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/bobthecow/psysh/issues",
|
||||
"source": "https://github.com/bobthecow/psysh/tree/v0.10.8"
|
||||
"source": "https://github.com/bobthecow/psysh/tree/v0.10.9"
|
||||
},
|
||||
"time": "2021-04-10T16:23:39+00:00"
|
||||
"time": "2021-10-10T13:37:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
|
|
@ -2454,16 +2518,16 @@
|
|||
},
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa"
|
||||
"reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/eaca1dc1054ddd10cbd83c1461907bee6fb528fa",
|
||||
"reference": "eaca1dc1054ddd10cbd83c1461907bee6fb528fa",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/cccc74ee5e328031b15640b51056ee8d3bb66c0a",
|
||||
"reference": "cccc74ee5e328031b15640b51056ee8d3bb66c0a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2517,7 +2581,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/collection/issues",
|
||||
"source": "https://github.com/ramsey/collection/tree/1.2.1"
|
||||
"source": "https://github.com/ramsey/collection/tree/1.2.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -2529,7 +2593,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2021-08-06T03:41:06+00:00"
|
||||
"time": "2021-10-10T03:01:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
|
|
@ -5445,19 +5509,20 @@
|
|||
},
|
||||
{
|
||||
"name": "facade/ignition",
|
||||
"version": "2.14.0",
|
||||
"version": "2.15.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facade/ignition.git",
|
||||
"reference": "c6126e291bd44ad3fe482537a145fc70e3320598"
|
||||
"reference": "3ee6e94815462bcf09bca0efc1c9069685df8da3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/facade/ignition/zipball/c6126e291bd44ad3fe482537a145fc70e3320598",
|
||||
"reference": "c6126e291bd44ad3fe482537a145fc70e3320598",
|
||||
"url": "https://api.github.com/repos/facade/ignition/zipball/3ee6e94815462bcf09bca0efc1c9069685df8da3",
|
||||
"reference": "3ee6e94815462bcf09bca0efc1c9069685df8da3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"facade/flare-client-php": "^1.9.1",
|
||||
|
|
@ -5517,7 +5582,7 @@
|
|||
"issues": "https://github.com/facade/ignition/issues",
|
||||
"source": "https://github.com/facade/ignition"
|
||||
},
|
||||
"time": "2021-10-01T12:58:45+00:00"
|
||||
"time": "2021-10-11T15:24:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/ignition-contracts",
|
||||
|
|
@ -7642,6 +7707,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2020-09-28T06:45:17+00:00"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateContactsTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('accounts', function (Blueprint $table) {
|
||||
$table->string('display_name')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('contacts', function (Blueprint $table) {
|
||||
$table->integer('account_id')->unsigned();
|
||||
$table->integer('contact_id')->unsigned();
|
||||
$table->foreign('account_id')->references('id')
|
||||
->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('contact_id')->references('id')
|
||||
->on('accounts')->onDelete('cascade');
|
||||
$table->unique(['account_id', 'contact_id']);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('account_types', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('key');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('account_account_type', function (Blueprint $table) {
|
||||
$table->integer('account_id')->unsigned();
|
||||
$table->integer('account_type_id')->unsigned();
|
||||
$table->foreign('account_id')->references('id')
|
||||
->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('account_type_id')->references('id')
|
||||
->on('account_types')->onDelete('cascade');
|
||||
$table->unique(['account_id', 'account_type_id']);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('account_actions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('account_id')->unsigned();
|
||||
$table->foreign('account_id')->references('id')
|
||||
->on('accounts')->onDelete('cascade');
|
||||
$table->string('key');
|
||||
$table->string('code');
|
||||
$table->string('protocol');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::disableForeignKeyConstraints();
|
||||
|
||||
Schema::table('accounts', function (Blueprint $table) {
|
||||
$table->dropColumn('display_name');
|
||||
});
|
||||
|
||||
Schema::dropIfExists('contacts');
|
||||
Schema::dropIfExists('account_types');
|
||||
Schema::dropIfExists('account_account_type');
|
||||
Schema::dropIfExists('account_actions');
|
||||
|
||||
Schema::enableForeignKeyConstraints();
|
||||
}
|
||||
}
|
||||
15
flexiapi/database/seeds/AccountTypeSeeder.php
Normal file
15
flexiapi/database/seeds/AccountTypeSeeder.php
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\AccountType;
|
||||
|
||||
class AccountTypeSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
AccountType::create(['key' => 'phone']);
|
||||
AccountType::create(['key' => 'door']);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
<?php
|
||||
|
||||
use Database\Seeders\AccountTypeSeeder;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// $this->call(UsersTableSeeder::class);
|
||||
$this->call(AccountTypeSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ An API to deal with the Flexisip server
|
|||
|
||||
The API is available under `/api`
|
||||
|
||||
A `from` (consisting of the user SIP address, prefixed with `sip:`), `content-type` and `accept` HTTP headers are required to use the API properly
|
||||
A `from` (consisting of the user SIP address, prefixed with `sip:`), `content-type` and `accept` HTTP headers are REQUIRED to use the API properly
|
||||
|
||||
```
|
||||
> GET /api/{endpoint}
|
||||
|
|
@ -167,6 +167,7 @@ JSON parameters:
|
|||
* `algorithm` required, values can be `SHA-256` or `MD5`
|
||||
* `domain` **not configurable except during test deployments** the value is enforced to the default registration domain set in the global configuration
|
||||
* `activated` optional, a boolean, set to `false` by default
|
||||
* `display_name` optional, string
|
||||
* `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
|
||||
* `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`.
|
||||
|
|
@ -186,6 +187,77 @@ Activate an account.
|
|||
#### `GET /accounts/{id}/deactivate`
|
||||
Deactivate an account.
|
||||
|
||||
### Contacts
|
||||
|
||||
#### `GET /accounts/{id}/contacts/`
|
||||
Get all the account contacts.
|
||||
|
||||
#### `POST /accounts/{id}/contacts/{contact_id}`
|
||||
Add a contact to the list.
|
||||
|
||||
#### `DELETE /accounts/{id}/contacts/{contact_id}`
|
||||
Remove a contact from the list.
|
||||
|
||||
### Account Actions
|
||||
|
||||
#### `GET /accounts/{id}/actions/`
|
||||
Show an account related actions.
|
||||
|
||||
#### `GET /accounts/{id}/actions/{action_id}`
|
||||
Show an account related action.
|
||||
|
||||
#### `POST /accounts/{id}/actions/`
|
||||
Create an account action.
|
||||
|
||||
JSON parameters:
|
||||
|
||||
* `key` required, alpha numeric with dashes, lowercase
|
||||
* `code` required, alpha numeric, lowercase
|
||||
* `protocol` required, values must be `sipinfo` or `rfc2833`
|
||||
|
||||
#### `PUT /accounts/{id}/actions/{action_id}`
|
||||
Create an account action.
|
||||
|
||||
JSON parameters:
|
||||
|
||||
* `key` required, alpha numeric with dashes, lowercase
|
||||
* `code` required, alpha numeric, lowercase
|
||||
* `protocol` required, values must be `sipinfo` or `rfc2833`
|
||||
|
||||
#### `DELETE /accounts/{id}/actions/{action_id}`
|
||||
Delete an account related action.
|
||||
|
||||
### Account Types
|
||||
|
||||
#### `GET /account_types/`
|
||||
Show all the account types.
|
||||
|
||||
#### `GET /account_types/{id}`
|
||||
Show an account type.
|
||||
|
||||
#### `POST /account_types/`
|
||||
Create an account type.
|
||||
|
||||
JSON parameters:
|
||||
|
||||
* `key` required, alpha numeric with dashes, lowercase
|
||||
|
||||
#### `PUT /account_types/{id}`
|
||||
Update an account type.
|
||||
|
||||
JSON parameters:
|
||||
|
||||
* `key` required, alpha numeric with dashes, lowercase
|
||||
|
||||
#### `DELETE /account_types/{id}`
|
||||
Delete an account type.
|
||||
|
||||
#### `POST /accounts/{id}/types/{type_id}`
|
||||
Add a type to the account.
|
||||
|
||||
#### `DELETE /accounts/{id}/contacts/{type_id}`
|
||||
Remove a a type from the account.
|
||||
|
||||
### Statistics
|
||||
|
||||
#### `GET /statistics/day`
|
||||
|
|
@ -197,12 +269,14 @@ Retrieve registrations statistics for a week.
|
|||
#### `GET /statistics/month`
|
||||
Retrieve registrations statistics for a month.
|
||||
|
||||
# Provisioning
|
||||
# Non-API Endpoints
|
||||
|
||||
The following URLs are **not API endpoints**, they are not located under `/api` but directly under the root path.
|
||||
|
||||
## Provisioning
|
||||
|
||||
When an account is having an available `confirmation_key` it can be provisioned using the two following URL.
|
||||
|
||||
Those two URL are **not API endpoints**, they are not located under `/api`.
|
||||
|
||||
### `VISIT /provisioning/`
|
||||
Return the provisioning information available in the liblinphone configuration file (if correctly configured).
|
||||
|
||||
|
|
@ -216,4 +290,12 @@ Return a QRCode that points to the provisioning URL.
|
|||
## Authenticated provisioning
|
||||
|
||||
### `VISIT /provisioning/me`
|
||||
Return the same base content as the previous URL and the account related information, similar to the `confirmation_key` endpoint. However this endpoint will always return those information.
|
||||
Return the same base content as the previous URL and the account related information, similar to the `confirmation_key` endpoint. However this endpoint will always return those information.
|
||||
|
||||
## Authenticated contact list
|
||||
|
||||
### `VISIT /contacts/vcard`
|
||||
Return the authenticated user contacts list, in [vCard 4.0 format](https://datatracker.ietf.org/doc/html/rfc6350).
|
||||
|
||||
### `VISIT /contacts/vcard/{sip}`
|
||||
Return a specific user authenticated contact, in [vCard 4.0 format](https://datatracker.ietf.org/doc/html/rfc6350).
|
||||
|
|
@ -49,12 +49,39 @@ Route::group(['middleware' => ['auth.digest_or_key']], function () {
|
|||
Route::post('accounts/me/email/request', 'Api\EmailController@requestUpdate');
|
||||
Route::post('accounts/me/password', 'Api\PasswordController@update');
|
||||
|
||||
Route::get('accounts/me/contacts', 'Api\AccountContactController@index');
|
||||
Route::get('accounts/me/contacts/{sip}', 'Api\AccountContactController@show');
|
||||
|
||||
Route::group(['middleware' => ['auth.admin']], function () {
|
||||
// Accounts
|
||||
Route::get('accounts/{id}/activate', 'Api\Admin\AccountController@activate');
|
||||
Route::get('accounts/{id}/deactivate', 'Api\Admin\AccountController@deactivate');
|
||||
Route::post('accounts', 'Api\Admin\AccountController@store');
|
||||
Route::get('accounts', 'Api\Admin\AccountController@index');
|
||||
Route::get('accounts/{id}', 'Api\Admin\AccountController@show');
|
||||
Route::delete('accounts/{id}', 'Api\Admin\AccountController@destroy');
|
||||
|
||||
// Account actions
|
||||
Route::get('accounts/{id}/actions', 'Api\Admin\AccountActionController@index');
|
||||
Route::get('accounts/{id}/actions/{action_id}', 'Api\Admin\AccountActionController@show');
|
||||
Route::post('accounts/{id}/actions', 'Api\Admin\AccountActionController@store');
|
||||
Route::delete('accounts/{id}/actions/{action_id}', 'Api\Admin\AccountActionController@destroy');
|
||||
Route::put('accounts/{id}/actions/{action_id}', 'Api\Admin\AccountActionController@update');
|
||||
|
||||
// Account contacts
|
||||
Route::get('accounts/{id}/contacts', 'Api\Admin\AccountContactController@index');
|
||||
Route::get('accounts/{id}/contacts/{contact_id}', 'Api\Admin\AccountContactController@show');
|
||||
Route::post('accounts/{id}/contacts/{contact_id}', 'Api\Admin\AccountContactController@add');
|
||||
Route::delete('accounts/{id}/contacts/{contact_id}', 'Api\Admin\AccountContactController@remove');
|
||||
|
||||
// Account types
|
||||
Route::get('account_types', 'Api\Admin\AccountTypeController@index');
|
||||
Route::get('account_types/{id}', 'Api\Admin\AccountTypeController@show');
|
||||
Route::post('account_types', 'Api\Admin\AccountTypeController@store');
|
||||
Route::delete('account_types/{id}', 'Api\Admin\AccountTypeController@destroy');
|
||||
Route::put('account_types/{id}', 'Api\Admin\AccountTypeController@update');
|
||||
|
||||
Route::post('accounts/{id}/types/{type_id}', 'Api\Admin\AccountController@typeAdd');
|
||||
Route::delete('accounts/{id}/types/{type_id}', 'Api\Admin\AccountController@typeRemove');
|
||||
});
|
||||
});
|
||||
|
|
@ -34,6 +34,10 @@ Route::post('authenticate/phone/confirm', 'Account\AuthenticateController@valida
|
|||
|
||||
Route::group(['middleware' => 'auth.digest_or_key'], function () {
|
||||
Route::get('provisioning/me', 'Account\ProvisioningController@me')->name('provisioning.me');
|
||||
|
||||
// Vcard 4.0
|
||||
Route::get('contacts/vcard/{sip}', 'Account\ContactVcardController@show');
|
||||
Route::get('contacts/vcard', 'Account\ContactVcardController@index');
|
||||
});
|
||||
|
||||
Route::get('provisioning/qrcode/{confirmation}', 'Account\ProvisioningController@qrcode')->name('provisioning.qrcode');
|
||||
|
|
|
|||
149
flexiapi/tests/Feature/AccountActionTest.php
Normal file
149
flexiapi/tests/Feature/AccountActionTest.php
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<?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\Password;
|
||||
use App\AccountAction;
|
||||
use App\Admin;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccountActionTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected $route = '/api/accounts';
|
||||
protected $method = 'POST';
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
$password = Password::factory()->create();
|
||||
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password->account->id.'/actions', [
|
||||
'key' => '123',
|
||||
'code' => '123',
|
||||
'protocol' => 'sipinfo'
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->assertEquals(1, AccountAction::count());
|
||||
|
||||
// Missing key
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password->account->id.'/actions', [
|
||||
'code' => '123',
|
||||
'protocol' => 'sipinfo'
|
||||
])
|
||||
->assertStatus(422);
|
||||
|
||||
// Invalid protocol
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password->account->id.'/actions', [
|
||||
'key' => 'abc1234',
|
||||
'code' => '123',
|
||||
'protocol' => 'wrong'
|
||||
])
|
||||
->assertStatus(422);
|
||||
|
||||
// Invalid key
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password->account->id.'/actions', [
|
||||
'key' => 'Abc1234',
|
||||
'code' => '123',
|
||||
'protocol' => 'wrong'
|
||||
])
|
||||
->assertStatus(422);
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->get($this->route.'/'.$password->account->id.'/actions')
|
||||
->assertJson([
|
||||
[
|
||||
'key' => '123',
|
||||
'code' => '123',
|
||||
'protocol' => 'sipinfo'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
$password = Password::factory()->create();
|
||||
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password->account->id.'/actions', [
|
||||
'key' => '123',
|
||||
'code' => '123',
|
||||
'protocol' => 'sipinfo'
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->assertEquals(1, AccountAction::count());
|
||||
$accountAction = AccountAction::first();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->delete($this->route.'/'.$password->account->id.'/actions/'.$accountAction->id)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->assertEquals(0, AccountAction::count());
|
||||
}
|
||||
|
||||
public function testUpdate()
|
||||
{
|
||||
$password = Password::factory()->create();
|
||||
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password->account->id.'/actions', [
|
||||
'key' => '123',
|
||||
'code' => '123',
|
||||
'protocol' => 'sipinfo'
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->assertEquals(1, AccountAction::count());
|
||||
$accountAction = AccountAction::first();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json('PUT', $this->route.'/'.$password->account->id.'/actions/'.$accountAction->id, [
|
||||
'key' => '123',
|
||||
'code' => 'abc',
|
||||
'protocol' => 'sipinfo'
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->get($this->route.'/'.$password->account->id.'/actions')
|
||||
->assertJson([
|
||||
[
|
||||
'code' => 'abc',
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
138
flexiapi/tests/Feature/AccountContactsTest.php
Normal file
138
flexiapi/tests/Feature/AccountContactsTest.php
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
<?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\Password;
|
||||
use App\AccountAction;
|
||||
use App\AccountType;
|
||||
use App\Admin;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccountContactTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected $route = '/api/accounts';
|
||||
protected $method = 'POST';
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
$password1 = Password::factory()->create();
|
||||
$password2 = Password::factory()->create();
|
||||
|
||||
$typeKey = 'phone';
|
||||
$actionKey = '123';
|
||||
$actionCode = '123';
|
||||
$actionProtocol = 'sipinfo';
|
||||
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password1->account->id.'/contacts/'.$password2->account->id)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->assertEquals(1, DB::table('contacts')->count());
|
||||
|
||||
// Type
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, '/api/account_types', [
|
||||
'key' => $typeKey,
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$accountType = AccountType::first();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, '/api/accounts/'.$password2->account->id.'/types/'.$accountType->id)
|
||||
->assertStatus(200);
|
||||
|
||||
// Action
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password2->account->id.'/actions', [
|
||||
'key' => $actionKey,
|
||||
'code' => $actionCode,
|
||||
'protocol' => $actionProtocol
|
||||
]);
|
||||
|
||||
// Retry
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route.'/'.$password1->account->id.'/contacts/'.$password2->account->id)
|
||||
->assertStatus(403);
|
||||
$this->assertEquals(1, DB::table('contacts')->count());
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->get($this->route.'/'.$password1->account->id.'/contacts')
|
||||
->assertJson([
|
||||
[
|
||||
'id' => $password2->account->id
|
||||
]
|
||||
]);
|
||||
|
||||
// /me
|
||||
$password1->account->generateApiKey();
|
||||
$password1->account->save();
|
||||
|
||||
$this->keyAuthenticated($password1->account)
|
||||
->get($this->route.'/me/contacts')
|
||||
->assertStatus(200)
|
||||
->assertJson([[
|
||||
'username' => $password2->account->username,
|
||||
'activated' => true
|
||||
]]);
|
||||
|
||||
// Vcard 4.0
|
||||
$this->keyAuthenticated($password1->account)
|
||||
->get('/contacts/vcard')
|
||||
->assertStatus(200)
|
||||
->assertSeeText($typeKey)
|
||||
->assertSeeText($actionKey.';'.$actionCode.';'.$actionProtocol);
|
||||
|
||||
$this->keyAuthenticated($password1->account)
|
||||
->get('/contacts/vcard/'.$password2->account->identifier)
|
||||
->assertStatus(200)
|
||||
->assertSeeText($typeKey)
|
||||
->assertSeeText($actionKey.';'.$actionCode.';'.$actionProtocol);
|
||||
|
||||
$this->keyAuthenticated($password1->account)
|
||||
->get($this->route.'/me/contacts/'.$password2->account->identifier)
|
||||
->assertStatus(200)
|
||||
->assertJson([
|
||||
'username' => $password2->account->username,
|
||||
'activated' => true
|
||||
]);
|
||||
|
||||
// Remove
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->delete($this->route.'/'.$password1->account->id.'/contacts/'.$password2->account->id)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->assertEquals(0, DB::table('contacts')->count());
|
||||
|
||||
// Retry
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->delete($this->route.'/'.$password1->account->id.'/contacts/'.$password2->account->id)
|
||||
->assertStatus(403);
|
||||
$this->assertEquals(0, DB::table('contacts')->count());
|
||||
}
|
||||
}
|
||||
171
flexiapi/tests/Feature/AccountTypeTest.php
Normal file
171
flexiapi/tests/Feature/AccountTypeTest.php
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<?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\Password;
|
||||
use App\AccountType;
|
||||
use App\Admin;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccountTypeTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected $route = '/api/account_types';
|
||||
protected $method = 'POST';
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route, [
|
||||
'key' => 'phone',
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->assertEquals(1, AccountType::count());
|
||||
|
||||
// Missing key
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route, [])
|
||||
->assertStatus(422);
|
||||
|
||||
// Invalid key
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route, [
|
||||
'key' => 'Abc1234',
|
||||
])
|
||||
->assertStatus(422);
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->get($this->route)
|
||||
->assertJson([
|
||||
[
|
||||
'key' => 'phone'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route, [
|
||||
'key' => 'phone',
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->assertEquals(1, AccountType::count());
|
||||
$accountType = AccountType::first();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->delete($this->route.'/'.$accountType->id)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->assertEquals(0, AccountType::count());
|
||||
}
|
||||
|
||||
public function testUpdate()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route, [
|
||||
'key' => 'phone',
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->assertEquals(1, AccountType::count());
|
||||
$accountType = AccountType::first();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json('PUT', $this->route.'/'.$accountType->id, [
|
||||
'key' => 'door',
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->get($this->route)
|
||||
->assertJson([
|
||||
[
|
||||
'key' => 'door',
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function testAccountAddType()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$admin->account->generateApiKey();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, $this->route, [
|
||||
'key' => 'phone',
|
||||
])
|
||||
->assertStatus(201)
|
||||
->assertJson([
|
||||
'id' => 1,
|
||||
'key' => 'phone',
|
||||
]);
|
||||
|
||||
$accountType = AccountType::first();
|
||||
$password = Password::factory()->create();
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, '/api/accounts/'.$password->account->id.'/types/'.$accountType->id)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->json($this->method, '/api/accounts/'.$password->account->id.'/types/'.$accountType->id)
|
||||
->assertStatus(403);
|
||||
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->get('/api/accounts/'.$password->account->id)
|
||||
->assertJson([
|
||||
'types' => [
|
||||
[
|
||||
'id' => $accountType->id,
|
||||
'key' => $accountType->key
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
// Remove
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->delete('/api/accounts/'.$password->account->id.'/types/'.$accountType->id)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->assertEquals(0, DB::table('account_account_type')->count());
|
||||
|
||||
// Retry
|
||||
$this->keyAuthenticated($admin->account)
|
||||
->delete('/api/accounts/'.$password->account->id.'/types/'.$accountType->id)
|
||||
->assertStatus(403);
|
||||
$this->assertEquals(0, DB::table('account_account_type')->count());
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
#%define _datadir %{_datarootdir}
|
||||
#%define _docdir %{_datadir}/doc
|
||||
|
||||
%define build_number 107
|
||||
%define build_number 108
|
||||
%define var_dir /var/opt/belledonne-communications
|
||||
%define opt_dir /opt/belledonne-communications/share/flexisip-account-manager
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue