- improved /setup page for WebSocket config check, #420

- improved /setup page for Redis server config check,
This commit is contained in:
Exodus4D
2017-01-09 21:01:24 +01:00
parent 9be139f281
commit 2701ea4b6c
11 changed files with 326 additions and 93 deletions

View File

@@ -424,55 +424,48 @@ class Setup extends Controller {
'version' => strstr(PCRE_VERSION, ' ', true),
'check' => version_compare( strstr(PCRE_VERSION, ' ', true), $f3->get('REQUIREMENTS.PHP.PCRE_VERSION'), '>=')
],
'pdo' => [
'ext_pdo' => [
'label' => 'PDO',
'required' => 'installed',
'version' => extension_loaded('pdo') ? 'installed' : 'missing',
'check' => extension_loaded('pdo')
],
'pdoMysql' => [
'ext_pdoMysql' => [
'label' => 'PDO_MYSQL',
'required' => 'installed',
'version' => extension_loaded('pdo_mysql') ? 'installed' : 'missing',
'check' => extension_loaded('pdo_mysql')
],
'openssl' => [
'ext_openssl' => [
'label' => 'OpenSSL',
'required' => 'installed',
'version' => extension_loaded('openssl') ? 'installed' : 'missing',
'check' => extension_loaded('openssl')
],
'mcrypt' => [
'ext_mcrypt' => [
'label' => 'Mcrypt',
'required' => 'installed',
'version' => (extension_loaded('mcrypt')) ? 'installed' : 'missing',
'check' => extension_loaded('mcrypt')
],
'xml' => [
'ext_xml' => [
'label' => 'XML',
'required' => 'installed',
'version' => extension_loaded('xml') ? 'installed' : 'missing',
'check' => extension_loaded('xml')
],
'gd' => [
'ext_gd' => [
'label' => 'GD Library (for Image plugin)',
'required' => 'installed',
'version' => (extension_loaded('gd') && function_exists('gd_info')) ? 'installed' : 'missing',
'check' => (extension_loaded('gd') && function_exists('gd_info'))
],
'curl' => [
'ext_curl' => [
'label' => 'cURL (for Web plugin)',
'required' => 'installed',
'version' => (extension_loaded('curl') && function_exists('curl_version')) ? 'installed' : 'missing',
'check' => (extension_loaded('curl') && function_exists('curl_version'))
],
'redis' => [
'label' => 'Redis [optional]',
'required' => $f3->get('REQUIREMENTS.PHP.REDIS'),
'version' => extension_loaded('redis') ? phpversion('redis') : 'missing',
'check' => version_compare( phpversion('redis'), $f3->get('REQUIREMENTS.PHP.REDIS'), '>='),
'tooltip' => 'Redis can replace the default file-caching mechanic. It is much faster (preferred)!'
],
'maxInputVars' => [
'label' => 'max_input_vars',
'required' => $f3->get('REQUIREMENTS.PHP.MAX_INPUT_VARS'),
@@ -486,6 +479,33 @@ class Setup extends Controller {
'version' => ini_get('max_execution_time'),
'check' => ini_get('max_execution_time') >= $f3->get('REQUIREMENTS.PHP.MAX_EXECUTION_TIME'),
'tooltip' => 'PHP default = 30. Max execution time for PHP scripts.'
],
[
'label' => 'Redis Server [optional]'
],
'ext_redis' => [
'label' => 'Redis',
'required' => $f3->get('REQUIREMENTS.PHP.REDIS'),
'version' => extension_loaded('redis') ? phpversion('redis') : 'missing',
'check' => version_compare( phpversion('redis'), $f3->get('REQUIREMENTS.PHP.REDIS'), '>='),
'tooltip' => 'Redis can replace the default file-caching mechanic. It is much faster!'
],
[
'label' => 'ØMQ TCP sockets [optional]'
],
'ext_zmq' => [
'label' => 'ZeroMQ extension',
'required' => $f3->get('REQUIREMENTS.PHP.ZMQ'),
'version' => extension_loaded('zmq') ? phpversion('zmq') : 'missing',
'check' => version_compare( phpversion('zmq'), $f3->get('REQUIREMENTS.PHP.ZMQ'), '>='),
'tooltip' => 'ØMQ PHP extension. Required for WebSocket configuration.'
],
'lib_zmq' => [
'label' => 'ZeroMQ installation',
'required' => $f3->get('REQUIREMENTS.LIBS.ZMQ'),
'version' => (class_exists('ZMQ') && defined('ZMQ::LIBZMQ_VER')) ? \ZMQ::LIBZMQ_VER : 'unknown',
'check' => version_compare( (class_exists('ZMQ') && defined('ZMQ::LIBZMQ_VER')) ? \ZMQ::LIBZMQ_VER : 0, $f3->get('REQUIREMENTS.LIBS.ZMQ'), '>='),
'tooltip' => 'ØMQ version. Required for WebSocket configuration.'
]
];
@@ -949,24 +969,12 @@ class Setup extends Controller {
],
'webSocket' => [
'label' => 'WebSocket (clients) [HTTP]',
'online' => true,
'online' => false,
'data' => [
[
'label' => 'HOST',
'value' => 'pathfinder.local',
'check' => true
],[
'label' => 'PORT',
'value' => 80,
'check' => true
],[
'label' => 'URI',
'value' => 'ws://pathfinder.local/ws/map/update',
'check' => true
],[
'label' => 'timeout (ms)',
'value' => $ttl,
'check' => !empty( $ttl )
'value' => '',
'check' => false
]
]
]

View File

@@ -47,9 +47,12 @@ class Socket {
protected $maxRetries = self::DEFAULT_RETRY_MAX;
public function __construct($uri, $ttl = self::DEFAULT_TTL_MAX, $maxRetries = self::DEFAULT_RETRY_MAX){
$this->setSocketUri($uri);
$this->setTtl($ttl, $maxRetries);
$this->initSocket();
if( self::checkRequirements() ){
$this->setSocketUri($uri);
$this->initSocket();
}
}
/**
@@ -155,5 +158,24 @@ class Socket {
return $response;
}
/**
* check whether this installation fulfills all requirements
* -> check for ZMQ PHP extension and installed ZQM version
* -> this does NOT check versions! -> those can be verified on /setup page
* @return bool
*/
static function checkRequirements(){
$check = false;
if(
extension_loaded('zmq') &&
class_exists('ZMQ')
){
$check = true;
}
return $check;
}
}

View File

@@ -20,6 +20,9 @@ PCRE_VERSION = 8.02
; Redis extension (optional), required if you want to use Redis as caching Engine (recommended)
REDIS = 3.0.0
; ZeroMQ (ØMQ) extension (optional) required for WebSocket Server extension (recommended)
ZMQ = 1.1.3
; max execution time for requests
MAX_EXECUTION_TIME = 10
@@ -29,6 +32,10 @@ MAX_EXECUTION_TIME = 10
; PHP default = 1000
MAX_INPUT_VARS = 3000
[REQUIREMENTS.LIBS]
ZMQ = 4.1.3
[REQUIREMENTS.MYSQL]
; min MySQL Version
; newer "deviation" of MySQL like "MariaDB" > 10.1 are recommended

View File

@@ -120,6 +120,7 @@ define([
};
return {
getWebSocketURL: getWebSocketURL,
init: init,
send: send
};

View File

@@ -5,19 +5,20 @@
define([
'jquery',
'app/init',
'app/util'
], function($, Init, Util) {
'app/util',
'app/map/worker'
], function($, Init, Util, MapWorker) {
'use strict';
var config = {
let config = {
splashOverlayClass: 'pf-splash' // class for "splash" overlay
};
/**
* set page observer
*/
var setPageObserver = function(){
var body = $('body');
let setPageObserver = () => {
let body = $('body');
// collapse ---------------------------------------
body.find('[data-toggle="collapse"]').css({cursor: 'pointer'}).on('click', function(){
@@ -39,10 +40,97 @@ define([
}
};
/**
* perform a basic check if Clients (browser) can connect to the webSocket server
*/
let testWebSocket = () => {
let webSocketPanel = $('#pf-setup-webSocket');
let WebSocketURI = MapWorker.getWebSocketURL();
webSocketPanel.showLoadingAnimation();
let removeColorClasses = (el) => {
el.removeClass (function (index, css) {
return (css.match (/\btxt-color-\S+/g) || []).join(' ');
});
};
/**
* updates the WebSocket panel with new data
* @param data
*/
let updateWebSocketPanel = (data) => {
if(data.uri){
let uriRow = webSocketPanel.find('.panel-body table tr');
uriRow.find('td:nth-child(2) kbd').text(data.uri.value);
if(data.uri.status){
let statusIcon = uriRow.find('td:nth-child(3) i');
removeColorClasses(statusIcon);
statusIcon.toggleClass('fa-warning', false).toggleClass('fa-check', true).addClass('txt-color-success');
}
}
if(data.status){
let footer = webSocketPanel.find('.panel-footer h3');
removeColorClasses(footer);
footer.text(data.status.label).addClass(data.status.class);
}
};
// update initial
updateWebSocketPanel({
uri: {
value: WebSocketURI,
status: true
},
status: {
label: 'CONNECTING...',
class: 'txt-color-warning'
}
});
// try to connect to WebSocket server
let socket = new WebSocket(WebSocketURI);
socket.onopen = (e) => {
updateWebSocketPanel({
status: {
label: 'CONNECTED',
class: 'txt-color-success'
}
});
webSocketPanel.hideLoadingAnimation();
};
socket.onerror = (e) => {
updateWebSocketPanel({
status: {
label: 'CONNECTION FAILED',
class: 'txt-color-danger'
}
});
webSocketPanel.hideLoadingAnimation();
};
socket.onclose = (closeEvent) => {
updateWebSocketPanel({
status: {
label: 'CONNECTION FAILED',
class: 'txt-color-danger'
}
});
webSocketPanel.hideLoadingAnimation();
};
};
/**
* main init "setup" page
*/
$(function(){
$(() => {
// show app information in browser console --------
Util.showVersionInfo();
@@ -51,5 +139,7 @@ define([
$('.' + config.splashOverlayClass).hideSplashOverlay();
setPageObserver();
testWebSocket();
});
});

View File

@@ -120,6 +120,7 @@ define([
};
return {
getWebSocketURL: getWebSocketURL,
init: init,
send: send
};

View File

@@ -5,19 +5,20 @@
define([
'jquery',
'app/init',
'app/util'
], function($, Init, Util) {
'app/util',
'app/map/worker'
], function($, Init, Util, MapWorker) {
'use strict';
var config = {
let config = {
splashOverlayClass: 'pf-splash' // class for "splash" overlay
};
/**
* set page observer
*/
var setPageObserver = function(){
var body = $('body');
let setPageObserver = () => {
let body = $('body');
// collapse ---------------------------------------
body.find('[data-toggle="collapse"]').css({cursor: 'pointer'}).on('click', function(){
@@ -39,10 +40,97 @@ define([
}
};
/**
* perform a basic check if Clients (browser) can connect to the webSocket server
*/
let testWebSocket = () => {
let webSocketPanel = $('#pf-setup-webSocket');
let WebSocketURI = MapWorker.getWebSocketURL();
webSocketPanel.showLoadingAnimation();
let removeColorClasses = (el) => {
el.removeClass (function (index, css) {
return (css.match (/\btxt-color-\S+/g) || []).join(' ');
});
};
/**
* updates the WebSocket panel with new data
* @param data
*/
let updateWebSocketPanel = (data) => {
if(data.uri){
let uriRow = webSocketPanel.find('.panel-body table tr');
uriRow.find('td:nth-child(2) kbd').text(data.uri.value);
if(data.uri.status){
let statusIcon = uriRow.find('td:nth-child(3) i');
removeColorClasses(statusIcon);
statusIcon.toggleClass('fa-warning', false).toggleClass('fa-check', true).addClass('txt-color-success');
}
}
if(data.status){
let footer = webSocketPanel.find('.panel-footer h3');
removeColorClasses(footer);
footer.text(data.status.label).addClass(data.status.class);
}
};
// update initial
updateWebSocketPanel({
uri: {
value: WebSocketURI,
status: true
},
status: {
label: 'CONNECTING...',
class: 'txt-color-warning'
}
});
// try to connect to WebSocket server
let socket = new WebSocket(WebSocketURI);
socket.onopen = (e) => {
updateWebSocketPanel({
status: {
label: 'CONNECTED',
class: 'txt-color-success'
}
});
webSocketPanel.hideLoadingAnimation();
};
socket.onerror = (e) => {
updateWebSocketPanel({
status: {
label: 'CONNECTION FAILED',
class: 'txt-color-danger'
}
});
webSocketPanel.hideLoadingAnimation();
};
socket.onclose = (closeEvent) => {
updateWebSocketPanel({
status: {
label: 'CONNECTION FAILED',
class: 'txt-color-danger'
}
});
webSocketPanel.hideLoadingAnimation();
};
};
/**
* main init "setup" page
*/
$(function(){
$(() => {
// show app information in browser console --------
Util.showVersionInfo();
@@ -51,5 +139,7 @@ define([
$('.' + config.splashOverlayClass).hideSplashOverlay();
setPageObserver();
testWebSocket();
});
});

View File

@@ -87,7 +87,7 @@
<p>
The <em>"Update counter"</em> starts counting backwards during map interaction. While the counter is active, no data is pushed to server.
Once the counter hits 0, all map date will be stored and active pilots will receive the map updates.<br>
There is no need for any save/edit buttons.
There is no need for any safe/edit buttons.
</p>
<div class="clearfix"></div>

View File

@@ -7,11 +7,8 @@
<div class="panel-body no-padding text-align-center">
<div class="price-features" style="min-height: inherit;">
<ul class="list-unstyled text-left">
<li><i class="fa fa-fw fa-angle-right"></i>NEW option for auto-delete expired (WH) connections</li>
<li><i class="fa fa-fw fa-angle-right"></i>NEW option for hide "current location</li>
<li><i class="fa fa-fw fa-angle-right"></i>improved "Route finder" module</li>
<li><i class="fa fa-fw fa-angle-right"></i>improved "Statistics" module</li>
<li><i class="fa fa-fw fa-angle-right"></i>improved "System notes" UI (new scrollbars)</li>
<li><i class="fa fa-fw fa-angle-right"></i>NEW WebSocket server. Map updates are pushed to clients immediately</li>
<li><i class="fa fa-fw fa-angle-right"></i>NEW "Route finder" option for "safer search" (HighSec)</li>
<li><i class="fa fa-fw fa-angle-double-right"></i>Complete <a href="javascript:void(0)" class="pf-navbar-version-info">changelog</a></li>
</ul>
</div>

View File

@@ -846,7 +846,7 @@
Cookies are valid for {{ @PATHFINDER.LOGIN.COOKIE_EXPIRE }} days and will be destroyed on 'logout'.
Read <a target="_blank" href="https://github.com/exodus4d/pathfinder/issues/138#issuecomment-216036606">more</a>.
</p>
<h3>Are my data save?</h3>
<h3>Are my data safe?</h3>
<p>
Whoever said, his program is "bullet proof", is lying! But I promise to give my very best to protect any personal or map data that is stored on my server.
The login process is handled by <em>CCP</em>´s SSO. There is no account data (or even your <em>EVE Online</em> login data) stored or available to <em>Pathfinder</em>.<br>

View File

@@ -92,42 +92,59 @@
</tr>
</thead>
<tbody>
<repeat group="{{ @checkRequirements }}" value="{{ @requirement }}">
<tr>
<td>
{{@requirement.label}}
<check if="{{ @requirement.tooltip }}">
<i class="fa fa-fw fa-question-circle pf-help-light" title="{{ @requirement.tooltip }}"></i>
</check>
</td>
<td class="text-right">
<check if="{{ @requirement.required }}">
<kbd>{{@requirement.required}}</kbd>
</check>
</td>
<td class="text-right">
<check if="{{ @requirement.check }}">
<true>
<kbd class="txt-color txt-color-success">{{@requirement.version}}</kbd>
</true>
<false>
<kbd class="txt-color txt-color-warning">{{@requirement.version}}</kbd>
{* Check failed *}
<set requirementsFulfilled="Warnings" />
</false>
</check>
</td>
<td class="text-right">
<check if="{{ @requirement.check }}">
<true>
<i class="fa fa-lg fa-fw fa-check txt-color txt-color-success"></i>
</true>
<false>
<i class="fa fa-lg fa-fw fa-warning txt-color txt-color-warning"></i>
</false>
</check>
</td>
</tr>
<repeat group="{{ @checkRequirements }}" key="{{ @dbKey }}" value="{{ @requirement }}">
{* if for optional divider *}
<check if="{{ is_numeric( @dbKey ) }}">
<true>
</tbody>
</table>
<div class="panel-footer text-left">
<h3 class="panel-title">{{@requirement.label}}</h3>
</div>
<table class="table">
<tbody>
</true>
<false>
<tr>
<td>
{{@requirement.label}}
<check if="{{ @requirement.tooltip }}">
<i class="fa fa-fw fa-question-circle pf-help-light" title="{{ @requirement.tooltip }}"></i>
</check>
</td>
<td class="text-right col-md-3 text-right">
<check if="{{ @requirement.required }}">
<kbd>{{@requirement.required}}</kbd>
</check>
</td>
<td class="text-right col-md-3 text-right">
<check if="{{ @requirement.check }}">
<true>
<kbd class="txt-color txt-color-success">{{@requirement.version}}</kbd>
</true>
<false>
<kbd class="txt-color txt-color-warning">{{@requirement.version}}</kbd>
{* Check failed *}
<set requirementsFulfilled="Warnings" />
</false>
</check>
</td>
<td class="text-right col-md-1 text-right">
<check if="{{ @requirement.check }}">
<true>
<i class="fa fa-lg fa-fw fa-check txt-color txt-color-success"></i>
</true>
<false>
<i class="fa fa-lg fa-fw fa-warning txt-color txt-color-warning"></i>
</false>
</check>
</td>
</tr>
</false>
</check>
</repeat>
</tbody>
</table>
@@ -136,7 +153,7 @@
<div class="panel-footer text-align-center">
<check if="{{ @requirementsFulfilled == 'OK' }}">
<true>
<h3 class="panel-title txt-color txt-color-green">{{ @requirementsFulfilled }}</h3>
<h3 class="panel-title txt-color txt-color-success">{{ @requirementsFulfilled }}</h3>
</true>
<false>
<h3 class="panel-title txt-color txt-color-warning">{{ @requirementsFulfilled }}</h3>
@@ -531,7 +548,7 @@
<true>
<check if="{{ @dbStatusCheck == 'OK' }}">
<true>
<h3 class="panel-title txt-color txt-color-green">{{ @dbConnectionStatus }}</h3>
<h3 class="panel-title txt-color txt-color-success">{{ @dbConnectionStatus }}</h3>
</true>
<false>
<h3 class="panel-title txt-color txt-color-warning">{{ @dbStatusCheck }}</h3>
@@ -749,7 +766,7 @@
<set dbWarnings="{{ @dbWarnings }} + {{ @dbInformation.info.statusCheckCount }}" />
</true>
<false>
<h3 class="panel-title txt-color txt-color-green">{{ @dbConnectionStatus }}</h3>
<h3 class="panel-title txt-color txt-color-success">{{ @dbConnectionStatus }}</h3>
</false>
</check>
</div>
@@ -800,9 +817,9 @@
<div class="row text-center">
<repeat group="{{ @socketInformation }}" value="{{ @socketData }}">
<repeat group="{{ @socketInformation }}" key="{{ @socketType }}" value="{{ @socketData }}">
<div class="col-xs-12 col-md-6 pf-landing-pricing-panel">
<div class="panel panel-default pricing-big">
<div id="pf-setup-{{ @socketType }}" class="panel panel-default pricing-big" style="position: relative">
<div class="panel-heading text-left">
<h3 class="panel-title">{{ @socketData.label }}</h3>
</div>
@@ -835,10 +852,10 @@
<div class="panel-footer text-align-center">
<check if="{{ @socketData.online }}">
<true>
<h3 class="panel-title txt-color txt-color-green">ONLINE</h3>
<h3 class="panel-title txt-color txt-color-success">CONNECTED</h3>
</true>
<false>
<h3 class="panel-title txt-color txt-color-danger">OFFLINE</h3>
<h3 class="panel-title txt-color txt-color-danger">CONNECTION FAILED</h3>
</false>
</check>
</div>