Fix #59 Move to Redis for the devices management

This commit is contained in:
Timothée Jaussoin 2022-12-06 15:58:49 +01:00
parent 0d513197b4
commit 6e56559050
14 changed files with 158 additions and 70 deletions

View file

@ -23,10 +23,10 @@ cleanup-package-semvers:
rm flexisip-account-manager.spec.run rm flexisip-account-manager.spec.run
prepare: prepare:
cd flexiapi && php composer.phar install --no-dev cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis --no-dev
prepare-dev: prepare-dev:
cd flexiapi && php composer.phar install cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis
package-common: package-common:
rm -rf $(OUTPUT_DIR)/flexisip-account-manager rm -rf $(OUTPUT_DIR)/flexisip-account-manager
@ -82,7 +82,7 @@ deb-only:
fakeroot alien -g -k --scripts $(OUTPUT_DIR)/rpmbuild/tmp.rpm fakeroot alien -g -k --scripts $(OUTPUT_DIR)/rpmbuild/tmp.rpm
rm -r $(OUTPUT_DIR)/rpmbuild rm -r $(OUTPUT_DIR)/rpmbuild
rm -rf $(OUTPUT_DIR)/*.orig rm -rf $(OUTPUT_DIR)/*.orig
sed -i 's/Depends:.*/Depends: $${shlibs:Depends}, php, php-xml, php-pdo, php-gd, php-mysql, php-mbstring, php-sqlite3/g' $(OUTPUT_DIR)/bc-flexisip-account-manager*/debian/control sed -i 's/Depends:.*/Depends: $${shlibs:Depends}, php, php-xml, php-pdo, php-gd, php-redis, php-mysql, php-mbstring, php-sqlite3/g' $(OUTPUT_DIR)/bc-flexisip-account-manager*/debian/control
cd `ls -rt $(OUTPUT_DIR) | tail -1` && dpkg-buildpackage --no-sign cd `ls -rt $(OUTPUT_DIR) | tail -1` && dpkg-buildpackage --no-sign
@echo "📦✅ DEB Package Created" @echo "📦✅ DEB Package Created"

View file

@ -5,7 +5,6 @@ APP_DEBUG=false
APP_URL=http://localhost APP_URL=http://localhost
APP_SIP_DOMAIN=sip.example.com APP_SIP_DOMAIN=sip.example.com
APP_FLEXISIP_PROXY_PID=/var/run/flexisip-proxy.pid
APP_LINPHONE_DAEMON_UNIX_PATH= APP_LINPHONE_DAEMON_UNIX_PATH=
APP_FLEXISIP_PUSHER_PATH= APP_FLEXISIP_PUSHER_PATH=
@ -55,6 +54,18 @@ DB_DATABASE=flexisip
DB_USERNAME=flexisip DB_USERNAME=flexisip
DB_PASSWORD=flexisip DB_PASSWORD=flexisip
# Redis
REDIS_CLIENT=phpredis # Use phpredis-sentinel and uncomment the REDIS_SENTINEL variable bellow
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=
# REDIS_SENTINEL_HOST=
# REDIS_SENTINEL_PORT=
# REDIS_SENTINEL_SERVICE=
# REDIS_SENTINEL_PASSWORD=
# Logs # Logs
# Ensure that you have the proper SELinux configuration to write in the storage directory, see the README # Ensure that you have the proper SELinux configuration to write in the storage directory, see the README
BROADCAST_DRIVER=log BROADCAST_DRIVER=log

View file

@ -31,4 +31,29 @@ class Device extends Model
$this->update_time = Carbon::createFromTimestamp($contact->{'update-time'}); $this->update_time = Carbon::createFromTimestamp($contact->{'update-time'});
$this->user_agent = $contact->{'user-agent'}; $this->user_agent = $contact->{'user-agent'};
} }
public function fromRedisContact(string $contact)
{
// Ugly :'(
$result = [];
$exploded = explode(';', urldecode($contact));
foreach ($exploded as $line) {
$line = explode('=', $line);
if (count($line) == 2) {
$result[trim($line[0])] = $line[1];
}
// User agent
if (count($line) == 4) {
$result['userAgent'] = substr($line[3], 0, -1);
}
}
$this->uuid = \substr($result['sip.instance'], 2, -2);
$this->expires_at = Carbon::createFromTimestamp($result['message-expires']);
$this->update_time = Carbon::createFromTimestamp($result['updatedAt']);
$this->user_agent = $result['userAgent'];
}
} }

View file

@ -31,8 +31,8 @@ class DeviceController extends Controller
return view( return view(
'account.devices.index', 'account.devices.index',
['devices' => $connector->getDevices($request->user()->identifier) [
->keyBy('uuid') 'devices' => $connector->getDevices($request->user()->identifier)
] ]
); );
} }
@ -43,17 +43,17 @@ class DeviceController extends Controller
return view( return view(
'account.devices.delete', 'account.devices.delete',
['device' => $connector->getDevices($request->user()->identifier) [
->keyBy('uuid') 'device' => $connector->getDevices($request->user()->identifier)
->where('uuid', $uuid) ->where('uuid', $uuid)->first()
] ]
); );
} }
public function destroy(Request $request, string $uuid) public function destroy(Request $request)
{ {
$connector = new FlexisipConnector; $connector = new FlexisipConnector;
$connector->deleteDevice($request->user()->identifier, $uuid); $connector->deleteDevice($request->user()->identifier, $request->get('uuid'));
return redirect()->route('account.device.index'); return redirect()->route('account.device.index');
} }

View file

@ -29,11 +29,10 @@ class DeviceController extends Controller
{ {
$connector = new FlexisipConnector; $connector = new FlexisipConnector;
return $connector->getDevices($request->user()->identifier) return $connector->getDevices($request->user()->identifier);
->keyBy('uuid');
} }
public function destroy(string $uuid) public function destroy(Request $request, string $uuid)
{ {
$connector = new FlexisipConnector; $connector = new FlexisipConnector;

View file

@ -20,52 +20,36 @@
namespace App\Libraries; namespace App\Libraries;
use App\Device; use App\Device;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
class FlexisipConnector class FlexisipConnector
{ {
private $socket;
public function __construct()
{
$pid = \file_get_contents(config('app.flexisip_proxy_pid'));
$this->socket = \stream_socket_client('unix:///tmp/flexisip-proxy-'.$pid, $errno, $errstr);
}
public function __destruct()
{
fclose($this->socket);
}
public function getDevices(string $from) public function getDevices(string $from)
{ {
$content = $this->request('REGISTRAR_GET', [
'sip:'.$from
]);
$devices = collect(); $devices = collect();
if ($content && isset($content->contacts)) { try {
foreach ($content->contacts as $contact) { $content = Redis::hgetall('fs:' . $from);
foreach ($content as $key => $contact) {
$device = new Device; $device = new Device;
$device->fromContact($contact); $device->fromRedisContact($contact);
$devices->push($device); $devices->push($device);
} }
} catch (\Throwable $th) {
Log::error('Redis server issue: ' . $th->getMessage());
} }
return $devices; return $devices->keyBy('uuid');
} }
public function deleteDevice(string $from, string $uuid) public function deleteDevice(string $from, string $uuid)
{ {
$this->request('REGISTRAR_DELETE', [ try {
'sip:'.$from, Redis::hdel('fs:' . $from, '"<' . $uuid . '>"');
'"<'.$uuid.'>"', } catch (\Throwable $th) {
]); Log::error('Redis server issue: ' . $th->getMessage());
} }
private function request(string $command, array $parameters): ?\stdClass
{
fwrite($this->socket, $command.' '.\implode(' ', $parameters));
return json_decode(fread($this->socket, 8192));
} }
} }

View file

@ -16,6 +16,7 @@
"laravel/framework": "^8.0", "laravel/framework": "^8.0",
"laravel/tinker": "^2.4", "laravel/tinker": "^2.4",
"laravelcollective/html": "^6.2", "laravelcollective/html": "^6.2",
"namoshek/laravel-redis-sentinel": "^0.1.2",
"ovh/ovh": "^2.0", "ovh/ovh": "^2.0",
"parsedown/laravel": "^1.2", "parsedown/laravel": "^1.2",
"react/socket": "^1.10", "react/socket": "^1.10",

94
flexiapi/composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "239806fda05a06e6027f9ac26670e52b", "content-hash": "1d639b63887c0a6cb7e1ead3a20cf069",
"packages": [ "packages": [
{ {
"name": "anhskohbo/no-captcha", "name": "anhskohbo/no-captcha",
@ -939,26 +939,29 @@
}, },
{ {
"name": "endroid/qr-code", "name": "endroid/qr-code",
"version": "4.6.1", "version": "4.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/endroid/qr-code.git", "url": "https://github.com/endroid/qr-code.git",
"reference": "a75c913b0e4d6ad275e49a2c1de1cacffc6c2184" "reference": "027522766a7bb40e15686fd380b77e0aaa76b7d4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/endroid/qr-code/zipball/a75c913b0e4d6ad275e49a2c1de1cacffc6c2184", "url": "https://api.github.com/repos/endroid/qr-code/zipball/027522766a7bb40e15686fd380b77e0aaa76b7d4",
"reference": "a75c913b0e4d6ad275e49a2c1de1cacffc6c2184", "reference": "027522766a7bb40e15686fd380b77e0aaa76b7d4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"bacon/bacon-qr-code": "^2.0.5", "bacon/bacon-qr-code": "^2.0.5",
"php": "^7.4||^8.0" "php": "^8.0"
},
"conflict": {
"khanamiryan/qrcode-detector-decoder": "^1.0.6"
}, },
"require-dev": { "require-dev": {
"endroid/quality": "dev-master", "endroid/quality": "dev-master",
"ext-gd": "*", "ext-gd": "*",
"khanamiryan/qrcode-detector-decoder": "^1.0.4", "khanamiryan/qrcode-detector-decoder": "^1.0.4||^2.0.2",
"setasign/fpdf": "^1.8.2" "setasign/fpdf": "^1.8.2"
}, },
"suggest": { "suggest": {
@ -999,7 +1002,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/endroid/qr-code/issues", "issues": "https://github.com/endroid/qr-code/issues",
"source": "https://github.com/endroid/qr-code/tree/4.6.1" "source": "https://github.com/endroid/qr-code/tree/4.7.0"
}, },
"funding": [ "funding": [
{ {
@ -1007,7 +1010,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-10-26T08:48:17+00:00" "time": "2022-12-12T16:10:52+00:00"
}, },
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
@ -2348,6 +2351,67 @@
], ],
"time": "2022-07-24T11:55:47+00:00" "time": "2022-07-24T11:55:47+00:00"
}, },
{
"name": "namoshek/laravel-redis-sentinel",
"version": "v0.1.2",
"source": {
"type": "git",
"url": "https://github.com/Namoshek/laravel-redis-sentinel.git",
"reference": "9ab2f0a69e5b0240cf929c459e0a4d3c82b7073b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Namoshek/laravel-redis-sentinel/zipball/9ab2f0a69e5b0240cf929c459e0a4d3c82b7073b",
"reference": "9ab2f0a69e5b0240cf929c459e0a4d3c82b7073b",
"shasum": ""
},
"require": {
"ext-redis": "*",
"illuminate/contracts": "^8.0|^9.0",
"illuminate/redis": "^8.0|^9.0",
"illuminate/support": "^8.0|^9.0",
"php": "^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"orchestra/testbench": "^6.0|^7.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Namoshek\\Redis\\Sentinel\\RedisSentinelServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Namoshek\\Redis\\Sentinel\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marvin Mall",
"email": "marvin-mall@msn.com",
"role": "Developer"
}
],
"description": "An extension of Laravels Redis driver which supports connecting to a Redis master through Redis Sentinel.",
"homepage": "https://github.com/Namoshek/laravel-redis-sentinel",
"keywords": [
"laravel",
"redis"
],
"support": {
"issues": "https://github.com/Namoshek/laravel-redis-sentinel/issues",
"source": "https://github.com/Namoshek/laravel-redis-sentinel/tree/v0.1.2"
},
"time": "2022-05-16T18:00:45+00:00"
},
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "2.64.0", "version": "2.64.0",
@ -7918,16 +7982,16 @@
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "9.2.19", "version": "9.2.21",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559" "reference": "3f893e19712bb0c8bc86665d1562e9fd509c4ef0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c77b56b63e3d2031bd8997fcec43c1925ae46559", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/3f893e19712bb0c8bc86665d1562e9fd509c4ef0",
"reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559", "reference": "3f893e19712bb0c8bc86665d1562e9fd509c4ef0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7983,7 +8047,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.19" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.21"
}, },
"funding": [ "funding": [
{ {
@ -7991,7 +8055,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-11-18T07:47:47+00:00" "time": "2022-12-14T13:26:54+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",

View file

@ -39,7 +39,6 @@ return [
/** /**
* External interfaces * External interfaces
*/ */
'flexisip_proxy_pid' => env('APP_FLEXISIP_PROXY_PID', '/var/run/flexisip-proxy.pid'),
'flexisip_pusher_path' => env('APP_FLEXISIP_PUSHER_PATH', null), 'flexisip_pusher_path' => env('APP_FLEXISIP_PUSHER_PATH', null),
'linphone_daemon_unix_pipe' => env('APP_LINPHONE_DAEMON_UNIX_PATH', null), 'linphone_daemon_unix_pipe' => env('APP_LINPHONE_DAEMON_UNIX_PATH', null),

View file

@ -132,7 +132,7 @@ return [
'options' => [ 'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'), 'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), 'prefix' => env('REDIS_PREFIX', ''),
], ],
'default' => [ 'default' => [
@ -141,6 +141,16 @@ return [
'password' => env('REDIS_PASSWORD', null), 'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379), 'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0), 'database' => env('REDIS_DB', 0),
// If a Redis Sentinel is used
'sentinel_host' => env('REDIS_SENTINEL_HOST', '127.0.0.1'),
'sentinel_port' => env('REDIS_SENTINEL_PORT', 26379),
'sentinel_service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
'sentinel_timeout' => env('REDIS_SENTINEL_TIMEOUT', 0),
'sentinel_persistent' => env('REDIS_SENTINEL_PERSISTENT'),
'sentinel_retry_interval' => env('REDIS_SENTINEL_RETRY_INTERVAL', 0),
'sentinel_read_timeout' => env('REDIS_SENTINEL_READ_TIMEOUT', 0),
'sentinel_password' => env('REDIS_SENTINEL_PASSWORD'),
], ],
'cache' => [ 'cache' => [

View file

@ -13,8 +13,7 @@
<p>Are you sure you want to delete the following device?</p> <p>Are you sure you want to delete the following device?</p>
<p> <p>
<b>User Agent:</b> {{ $device->user_agent }}<br /> <b>User Agent:</b> {{ $device->user_agent }}
<b>Expires At:</b> {{ $device->expires_at }}</p>
</p> </p>

View file

@ -10,7 +10,6 @@
<thead> <thead>
<tr> <tr>
<th scope="col">User Agent</th> <th scope="col">User Agent</th>
<th scope="col">Expires At</th>
<th scope="col"></th> <th scope="col"></th>
</tr> </tr>
</thead> </thead>
@ -18,7 +17,6 @@
@foreach ($devices as $device) @foreach ($devices as $device)
<tr> <tr>
<td>{{ $device->user_agent }}</td> <td>{{ $device->user_agent }}</td>
<td>{{ $device->expires_at }}</td>
<td> <td>
<a type="button" <a type="button"
class="btn btn-danger" class="btn btn-danger"

View file

@ -77,7 +77,7 @@ if (config('app.web_panel')) {
Route::get('devices', 'Account\DeviceController@index')->name('account.device.index'); Route::get('devices', 'Account\DeviceController@index')->name('account.device.index');
Route::get('devices/delete/{id}', 'Account\DeviceController@delete')->name('account.device.delete'); Route::get('devices/delete/{id}', 'Account\DeviceController@delete')->name('account.device.delete');
Route::delete('devices/{id}', 'Account\DeviceController@destroy')->name('account.device.destroy'); Route::delete('devices', 'Account\DeviceController@destroy')->name('account.device.destroy');
Route::post('auth_tokens', 'Account\AuthTokenController@create')->name('account.auth_tokens.create'); Route::post('auth_tokens', 'Account\AuthTokenController@create')->name('account.auth_tokens.create');

View file

@ -31,13 +31,11 @@ License: GPL
URL: http://www.linphone.org URL: http://www.linphone.org
Source0: flexisip-account-manager.tar.gz Source0: flexisip-account-manager.tar.gz
#These are not indented because rpm cannot recognize "Requires" with spaces/tabs (???) Requires: php php-gd php-xmlrpc php-pdo php-redis php-mysqlnd php-mbstring
%if "%{?dist}" == ".el7" %if "%{?dist}" == ".el7"
Requires: rh-php73-php rh-php73-php-gd rh-php73-php-xmlrpc rh-php73-php-pdo rh-php73-php-mysqlnd rh-php73-php-mbstring
%define apache_conf_path /opt/rh/httpd24/root/etc/httpd/conf.d %define apache_conf_path /opt/rh/httpd24/root/etc/httpd/conf.d
%else %else
Requires: php php-gd php-xmlrpc php-pdo php-mysqlnd php-mbstring
%define apache_conf_path /etc/httpd/conf.d %define apache_conf_path /etc/httpd/conf.d
%endif %endif