From 6e56559050f93b965fd883f3f3e26c50c02da9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Jaussoin?= Date: Tue, 6 Dec 2022 15:58:49 +0100 Subject: [PATCH] Fix #59 Move to Redis for the devices management --- Makefile | 6 +- flexiapi/.env.example | 13 ++- flexiapi/app/Device.php | 25 +++++ .../Controllers/Account/DeviceController.php | 14 +-- .../Http/Controllers/Api/DeviceController.php | 5 +- flexiapi/app/Libraries/FlexisipConnector.php | 46 +++------ flexiapi/composer.json | 1 + flexiapi/composer.lock | 94 ++++++++++++++++--- flexiapi/config/app.php | 1 - flexiapi/config/database.php | 12 ++- .../views/account/devices/delete.blade.php | 3 +- .../views/account/devices/index.blade.php | 2 - flexiapi/routes/web.php | 2 +- flexisip-account-manager.spec | 4 +- 14 files changed, 158 insertions(+), 70 deletions(-) diff --git a/Makefile b/Makefile index c0dc34b..8754e8c 100644 --- a/Makefile +++ b/Makefile @@ -23,10 +23,10 @@ cleanup-package-semvers: rm flexisip-account-manager.spec.run prepare: - cd flexiapi && php composer.phar install --no-dev + cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis --no-dev prepare-dev: - cd flexiapi && php composer.phar install + cd flexiapi && php composer.phar install --ignore-platform-req=ext-redis package-common: rm -rf $(OUTPUT_DIR)/flexisip-account-manager @@ -82,7 +82,7 @@ deb-only: fakeroot alien -g -k --scripts $(OUTPUT_DIR)/rpmbuild/tmp.rpm rm -r $(OUTPUT_DIR)/rpmbuild 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 @echo "📦✅ DEB Package Created" diff --git a/flexiapi/.env.example b/flexiapi/.env.example index 1c8afa5..e9bf089 100644 --- a/flexiapi/.env.example +++ b/flexiapi/.env.example @@ -5,7 +5,6 @@ APP_DEBUG=false APP_URL=http://localhost APP_SIP_DOMAIN=sip.example.com -APP_FLEXISIP_PROXY_PID=/var/run/flexisip-proxy.pid APP_LINPHONE_DAEMON_UNIX_PATH= APP_FLEXISIP_PUSHER_PATH= @@ -55,6 +54,18 @@ DB_DATABASE=flexisip DB_USERNAME=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 # Ensure that you have the proper SELinux configuration to write in the storage directory, see the README BROADCAST_DRIVER=log diff --git a/flexiapi/app/Device.php b/flexiapi/app/Device.php index 0afec12..39b20ad 100644 --- a/flexiapi/app/Device.php +++ b/flexiapi/app/Device.php @@ -31,4 +31,29 @@ class Device extends Model $this->update_time = Carbon::createFromTimestamp($contact->{'update-time'}); $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']; + } } diff --git a/flexiapi/app/Http/Controllers/Account/DeviceController.php b/flexiapi/app/Http/Controllers/Account/DeviceController.php index fd78f1e..1ba8273 100644 --- a/flexiapi/app/Http/Controllers/Account/DeviceController.php +++ b/flexiapi/app/Http/Controllers/Account/DeviceController.php @@ -31,8 +31,8 @@ class DeviceController extends Controller return view( '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( 'account.devices.delete', - ['device' => $connector->getDevices($request->user()->identifier) - ->keyBy('uuid') - ->where('uuid', $uuid) + [ + 'device' => $connector->getDevices($request->user()->identifier) + ->where('uuid', $uuid)->first() ] ); } - public function destroy(Request $request, string $uuid) + public function destroy(Request $request) { $connector = new FlexisipConnector; - $connector->deleteDevice($request->user()->identifier, $uuid); + $connector->deleteDevice($request->user()->identifier, $request->get('uuid')); return redirect()->route('account.device.index'); } diff --git a/flexiapi/app/Http/Controllers/Api/DeviceController.php b/flexiapi/app/Http/Controllers/Api/DeviceController.php index 93c2a11..644c987 100644 --- a/flexiapi/app/Http/Controllers/Api/DeviceController.php +++ b/flexiapi/app/Http/Controllers/Api/DeviceController.php @@ -29,11 +29,10 @@ class DeviceController extends Controller { $connector = new FlexisipConnector; - return $connector->getDevices($request->user()->identifier) - ->keyBy('uuid'); + return $connector->getDevices($request->user()->identifier); } - public function destroy(string $uuid) + public function destroy(Request $request, string $uuid) { $connector = new FlexisipConnector; diff --git a/flexiapi/app/Libraries/FlexisipConnector.php b/flexiapi/app/Libraries/FlexisipConnector.php index f3b1d0a..ec447be 100644 --- a/flexiapi/app/Libraries/FlexisipConnector.php +++ b/flexiapi/app/Libraries/FlexisipConnector.php @@ -20,52 +20,36 @@ namespace App\Libraries; use App\Device; +use Illuminate\Support\Facades\Redis; +use Illuminate\Support\Facades\Log; 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) { - $content = $this->request('REGISTRAR_GET', [ - 'sip:'.$from - ]); $devices = collect(); - if ($content && isset($content->contacts)) { - foreach ($content->contacts as $contact) { + try { + $content = Redis::hgetall('fs:' . $from); + + foreach ($content as $key => $contact) { $device = new Device; - $device->fromContact($contact); + $device->fromRedisContact($contact); $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) { - $this->request('REGISTRAR_DELETE', [ - 'sip:'.$from, - '"<'.$uuid.'>"', - ]); - } - - private function request(string $command, array $parameters): ?\stdClass - { - fwrite($this->socket, $command.' '.\implode(' ', $parameters)); - - return json_decode(fread($this->socket, 8192)); + try { + Redis::hdel('fs:' . $from, '"<' . $uuid . '>"'); + } catch (\Throwable $th) { + Log::error('Redis server issue: ' . $th->getMessage()); + } } } diff --git a/flexiapi/composer.json b/flexiapi/composer.json index 6e963ba..3ee6a7b 100644 --- a/flexiapi/composer.json +++ b/flexiapi/composer.json @@ -16,6 +16,7 @@ "laravel/framework": "^8.0", "laravel/tinker": "^2.4", "laravelcollective/html": "^6.2", + "namoshek/laravel-redis-sentinel": "^0.1.2", "ovh/ovh": "^2.0", "parsedown/laravel": "^1.2", "react/socket": "^1.10", diff --git a/flexiapi/composer.lock b/flexiapi/composer.lock index 6f3ad1f..65fdcab 100644 --- a/flexiapi/composer.lock +++ b/flexiapi/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "239806fda05a06e6027f9ac26670e52b", + "content-hash": "1d639b63887c0a6cb7e1ead3a20cf069", "packages": [ { "name": "anhskohbo/no-captcha", @@ -939,26 +939,29 @@ }, { "name": "endroid/qr-code", - "version": "4.6.1", + "version": "4.7.0", "source": { "type": "git", "url": "https://github.com/endroid/qr-code.git", - "reference": "a75c913b0e4d6ad275e49a2c1de1cacffc6c2184" + "reference": "027522766a7bb40e15686fd380b77e0aaa76b7d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/endroid/qr-code/zipball/a75c913b0e4d6ad275e49a2c1de1cacffc6c2184", - "reference": "a75c913b0e4d6ad275e49a2c1de1cacffc6c2184", + "url": "https://api.github.com/repos/endroid/qr-code/zipball/027522766a7bb40e15686fd380b77e0aaa76b7d4", + "reference": "027522766a7bb40e15686fd380b77e0aaa76b7d4", "shasum": "" }, "require": { "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": { "endroid/quality": "dev-master", "ext-gd": "*", - "khanamiryan/qrcode-detector-decoder": "^1.0.4", + "khanamiryan/qrcode-detector-decoder": "^1.0.4||^2.0.2", "setasign/fpdf": "^1.8.2" }, "suggest": { @@ -999,7 +1002,7 @@ ], "support": { "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": [ { @@ -1007,7 +1010,7 @@ "type": "github" } ], - "time": "2022-10-26T08:48:17+00:00" + "time": "2022-12-12T16:10:52+00:00" }, { "name": "erusev/parsedown", @@ -2348,6 +2351,67 @@ ], "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", "version": "2.64.0", @@ -7918,16 +7982,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.19", + "version": "9.2.21", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559" + "reference": "3f893e19712bb0c8bc86665d1562e9fd509c4ef0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c77b56b63e3d2031bd8997fcec43c1925ae46559", - "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/3f893e19712bb0c8bc86665d1562e9fd509c4ef0", + "reference": "3f893e19712bb0c8bc86665d1562e9fd509c4ef0", "shasum": "" }, "require": { @@ -7983,7 +8047,7 @@ ], "support": { "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": [ { @@ -7991,7 +8055,7 @@ "type": "github" } ], - "time": "2022-11-18T07:47:47+00:00" + "time": "2022-12-14T13:26:54+00:00" }, { "name": "phpunit/php-file-iterator", diff --git a/flexiapi/config/app.php b/flexiapi/config/app.php index 9e2ec60..e8894d0 100644 --- a/flexiapi/config/app.php +++ b/flexiapi/config/app.php @@ -39,7 +39,6 @@ return [ /** * External interfaces */ - 'flexisip_proxy_pid' => env('APP_FLEXISIP_PROXY_PID', '/var/run/flexisip-proxy.pid'), 'flexisip_pusher_path' => env('APP_FLEXISIP_PUSHER_PATH', null), 'linphone_daemon_unix_pipe' => env('APP_LINPHONE_DAEMON_UNIX_PATH', null), diff --git a/flexiapi/config/database.php b/flexiapi/config/database.php index c558606..eaac578 100644 --- a/flexiapi/config/database.php +++ b/flexiapi/config/database.php @@ -132,7 +132,7 @@ return [ 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'redis'), - 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + 'prefix' => env('REDIS_PREFIX', ''), ], 'default' => [ @@ -141,6 +141,16 @@ return [ 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', 6379), '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' => [ diff --git a/flexiapi/resources/views/account/devices/delete.blade.php b/flexiapi/resources/views/account/devices/delete.blade.php index 891a55a..54fd7d5 100644 --- a/flexiapi/resources/views/account/devices/delete.blade.php +++ b/flexiapi/resources/views/account/devices/delete.blade.php @@ -13,8 +13,7 @@

Are you sure you want to delete the following device?

- User Agent: {{ $device->user_agent }}
- Expires At: {{ $device->expires_at }}

+ User Agent: {{ $device->user_agent }}

diff --git a/flexiapi/resources/views/account/devices/index.blade.php b/flexiapi/resources/views/account/devices/index.blade.php index 954bbcd..edb0f10 100644 --- a/flexiapi/resources/views/account/devices/index.blade.php +++ b/flexiapi/resources/views/account/devices/index.blade.php @@ -10,7 +10,6 @@ User Agent - Expires At @@ -18,7 +17,6 @@ @foreach ($devices as $device) {{ $device->user_agent }} - {{ $device->expires_at }} name('account.device.index'); 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'); diff --git a/flexisip-account-manager.spec b/flexisip-account-manager.spec index dbf8152..65e52f9 100644 --- a/flexisip-account-manager.spec +++ b/flexisip-account-manager.spec @@ -31,13 +31,11 @@ License: GPL URL: http://www.linphone.org 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" -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 %else -Requires: php php-gd php-xmlrpc php-pdo php-mysqlnd php-mbstring %define apache_conf_path /etc/httpd/conf.d %endif