- improved "search for system name" performance (SQL optimization)

- improved file caching for "location data" CREST response
- improved error log formatting
- fixed broken zKillboard AJAX call
- fixed invisible warning for active "/setup" route
This commit is contained in:
Exodus4D
2016-09-17 20:38:16 +02:00
parent 23eb032759
commit af9b445510
17 changed files with 134 additions and 120 deletions

View File

@@ -49,9 +49,9 @@ class System extends \Controller\AccessController {
FROM
mapSolarSystems map_sys INNER JOIN
mapConstellations map_con ON
map_con.constellationID = map_sys.constellationID INNER JOIN
map_sys.constellationID = map_con.constellationID INNER JOIN
mapRegions map_reg ON
map_reg.regionID = map_sys.regionID";
map_con.regionID = map_reg.regionID";
private $whereQuery = "";

View File

@@ -34,7 +34,7 @@ class User extends Controller\Controller{
// log text
const LOG_LOGGED_IN = 'userId: [%10s], userName: [%30s], charId: [%20s], charName: %s';
const LOG_DELETE_ACCOUNT = 'userId: [%10s], userName: [%30s], ip: [%45s]';
const LOG_DELETE_ACCOUNT = 'userId: [%10s], userName: [%30s]';
/**
@@ -357,7 +357,7 @@ class User extends Controller\Controller{
if($status){
// save log
self::getLogger('DELETE_ACCOUNT')->write(
sprintf(self::LOG_DELETE_ACCOUNT, $user->id, $user->name, $f3->get('IP'))
sprintf(self::LOG_DELETE_ACCOUNT, $user->id, $user->name)
);
// remove user

View File

@@ -36,9 +36,6 @@ class Sso extends Api\User{
const SESSION_KEY_SSO_STATE = 'SESSION.SSO.STATE';
const SESSION_KEY_SSO_FROM_MAP = 'SESSION.SSO.FROM_MAP';
// cache keys
const CACHE_KEY_LOCATION_DATA = 'CACHED.LOCATION.%s';
// error messages
const ERROR_CCP_SSO_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].SSO_CCP_URL" url. %s';
const ERROR_CCP_CREST_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].CCP_CREST_URL" url. %s';
@@ -631,49 +628,36 @@ class Sso extends Api\User{
* get current character location data (result is cached!)
* -> solarSystem data where character is currently active
* @param $accessToken
* @param int $ttl
* @param array $additionalOptions
* @return array|mixed
* @return array
*/
public function getCharacterLocationData($accessToken, $ttl = 5, $additionalOptions = []){
public function getCharacterLocationData($accessToken, $additionalOptions = []){
// null == CREST call failed (e.g. timeout)
$locationData = [
'timeout' => false
];
// in addition to the cURL caching (based on cache-control headers,
// the final location data is cached additionally -> speed up
$cacheKey = sprintf(self::CACHE_KEY_LOCATION_DATA, 'TOKEN_' . hash('md5', $accessToken));
$endpoints = $this->getEndpoints($accessToken, $additionalOptions);
if( !$this->getF3()->exists($cacheKey) ){
$endpoints = $this->getEndpoints($accessToken, $additionalOptions);
$additionalOptions['accept'] = 'application/vnd.ccp.eve.CharacterLocation-v1+json';
$endpoint = $this->walkEndpoint($endpoints, $accessToken, [
'decode',
'character',
'location'
], $additionalOptions);
$additionalOptions['accept'] = 'application/vnd.ccp.eve.CharacterLocation-v1+json';
$endpoint = $this->walkEndpoint($endpoints, $accessToken, [
'decode',
'character',
'location'
], $additionalOptions);
if( !is_null($endpoint) ){
// request succeeded (e.g. no timeout)
if(isset($endpoint['solarSystem'])){
$locationData['system'] = (new Mapper\CrestSystem($endpoint['solarSystem']))->getData();
}
if(isset($endpoint['station'])){
$locationData['station'] = (new Mapper\CrestStation($endpoint['station']))->getData();
}
$this->getF3()->set($cacheKey, $locationData, $ttl);
}else{
// timeout
$locationData['timeout'] = true;
if( !is_null($endpoint) ){
// request succeeded (e.g. no timeout)
if(isset($endpoint['solarSystem'])){
$locationData['system'] = (new Mapper\CrestSystem($endpoint['solarSystem']))->getData();
}
if(isset($endpoint['station'])){
$locationData['station'] = (new Mapper\CrestStation($endpoint['station']))->getData();
}
}else{
$locationData = $this->getF3()->get($cacheKey);
// timeout
$locationData['timeout'] = true;
}
return $locationData;

View File

@@ -19,8 +19,10 @@ class Controller {
const COOKIE_NAME_STATE = 'cookie';
const COOKIE_PREFIX_CHARACTER = 'char';
const LOG_UNAUTHORIZED = 'ip: [%45s], User-Agent: [%s]';
const ERROR_SESSION_SUSPECT = 'Suspect id: [%45s], ip: [%45s], new ip: [%45s], User-Agent: %s ';
// log text
const LOG_UNAUTHORIZED = 'User-Agent: [%s]';
const ERROR_SESSION_SUSPECT = 'Suspect id: [%45s], ip: [%45s], new ip: [%45s], User-Agent: [%s]';
/**
* @var \Base
*/
@@ -282,7 +284,7 @@ class Controller {
// make sure character data is up2date!
// -> this is not the case if e.g. userCharacters was removed "ownerHash" changed...
$character = $characterAuth->rel('characterId');
$character->getById($characterAuth->characterId->_id);
$character->getById( $characterAuth->get('characterId', true) );
// check if character still has user (is not the case of "ownerHash" changed
// check if character is still authorized to log in (e.g. corp/ally or config has changed
@@ -620,7 +622,6 @@ class Controller {
case 403: // Unauthorized
self::getLogger('UNAUTHORIZED')->write(sprintf(
self::LOG_UNAUTHORIZED,
$f3->get('IP'),
$f3->get('AGENT')
));
$halt = true;

View File

@@ -8,7 +8,6 @@
namespace Model;
use Controller;
use Controller\Ccp\Sso as Sso;
use Controller\Api\User as User;
use DB\SQL\Schema;
@@ -316,7 +315,7 @@ class CharacterModel extends BasicModel {
if(
!empty($whitelistCorporations) &&
$this->hasCorporation() &&
in_array($this->getCorporation()->_id, $whitelistCorporations)
in_array($this->get('corporationId', true), $whitelistCorporations)
){
$isAuthorized = true;
}
@@ -326,7 +325,7 @@ class CharacterModel extends BasicModel {
!$isAuthorized &&
!empty($whitelistAlliance) &&
$this->hasAlliance() &&
in_array($this->getAlliance()->_id, $whitelistAlliance)
in_array($this->get('allianceId', true), $whitelistAlliance)
){
$isAuthorized = true;
}
@@ -344,7 +343,7 @@ class CharacterModel extends BasicModel {
public function updateLog($additionalOptions = []){
// Try to pull data from CREST
$ssoController = new Sso();
$logData = $ssoController->getCharacterLocationData($this->getAccessToken(), 5, $additionalOptions);
$logData = $ssoController->getCharacterLocationData($this->getAccessToken(), $additionalOptions);
if($logData['timeout'] === false){
if( empty($logData['system']) ){
@@ -496,7 +495,7 @@ class CharacterModel extends BasicModel {
$maps = array_merge($maps, $corporation->getMaps());
}
if($this->characterMaps){
if( is_object($this->characterMaps) ){
$mapCountPrivate = 0;
foreach($this->characterMaps as $characterMap){
if(
@@ -517,7 +516,7 @@ class CharacterModel extends BasicModel {
* -> clear authentication data
*/
public function logout(){
if($this->characterAuthentications){
if( is_object($this->characterAuthentications) ){
foreach($this->characterAuthentications as $characterAuthentication){
/**
* @var $characterAuthentication CharacterAuthenticationModel

View File

@@ -180,8 +180,8 @@ class ConnectionModel extends BasicModel{
if(
is_object($this->source) &&
is_object($this->target) &&
$this->source->_id === $this->target->_id ||
$this->source->mapId->_id !== $this->target->mapId->_id
$this->get('source', true) === $this->get('target', true) ||
$this->source->get('mapId', true) !== $this->target->get('mapId', true)
){
$isValid = false;
}

View File

@@ -288,7 +288,7 @@ class MapModel extends BasicModel {
/**
* get either all system models in this map
* @return array|mixed
* @return SystemModel[]
*/
public function getSystems(){
$systems = [];
@@ -310,10 +310,9 @@ class MapModel extends BasicModel {
* @return \stdClass[]
*/
public function getSystemData(){
$systemData = [];
$systems = $this->getSystems();
$systemData = [];
foreach($systems as $system){
/**
* @var $system SystemModel
@@ -326,15 +325,16 @@ class MapModel extends BasicModel {
/**
* get all connections in this map
* @return array
* @return ConnectionModel[]
*/
public function getConnections(){
$connections = [];
$this->filter('connections', [
'active = :active AND source > 0 AND target > 0',
':active' => 1
]);
$connections = [];
if($this->connections){
$connections = $this->connections;
}
@@ -347,9 +347,9 @@ class MapModel extends BasicModel {
* @return \stdClass[]
*/
public function getConnectionData(){
$connectionData = [];
$connections = $this->getConnections();
$connectionData = [];
foreach($connections as $connection){
/**
* @var $connection ConnectionModel
@@ -427,7 +427,6 @@ class MapModel extends BasicModel {
* @param array $clearKeys
*/
public function clearAccess($clearKeys = ['character', 'corporation', 'alliance']){
foreach($clearKeys as $key){
switch($key){
case 'character':
@@ -692,8 +691,8 @@ class MapModel extends BasicModel {
public function searchConnection(SystemModel $sourceSystem, SystemModel $targetSystem){
// check if both systems belong to this map
if(
$sourceSystem->mapId->id === $this->id &&
$targetSystem->mapId->id === $this->id
$sourceSystem->get('mapId', true) === $this->id &&
$targetSystem->get('mapId', true) === $this->id
){
$this->filter('connections', [
'active = :active AND

View File

@@ -221,7 +221,7 @@ class SystemModel extends BasicModel {
$systemData = (object) [];
$systemData->id = $this->id;
$systemData->mapId = is_object($this->mapId) ? $this->mapId->id : 0;
$systemData->mapId = is_object($this->mapId) ? $this->get('mapId', true) : 0;
$systemData->systemId = $this->systemId;
$systemData->name = $this->name;
$systemData->alias = $this->alias;
@@ -284,7 +284,6 @@ class SystemModel extends BasicModel {
* @return float
*/
public function set_trueSec($trueSec){
if(
$trueSec > 0 &&
$trueSec < 0.1
@@ -452,9 +451,9 @@ class SystemModel extends BasicModel {
* @return SystemSignatureModel[]
*/
public function getSignatures(){
$signatures = [];
$this->filter('signatures', ['active = ?', 1], ['order' => 'name']);
$signatures = [];
if($this->signatures){
$signatures = $this->signatures;
}
@@ -467,9 +466,9 @@ class SystemModel extends BasicModel {
* @return \stdClass[]
*/
public function getSignaturesData(){
$signaturesData = [];
$signatures = $this->getSignatures();
$signaturesData = [];
foreach($signatures as $signature){
$signaturesData[] = $signature->getData();
}

View File

@@ -91,9 +91,7 @@ class SystemSignatureModel extends BasicModel {
* @param $signatureData
*/
public function setData($signatureData){
foreach((array)$signatureData as $key => $value){
if(!is_array($value)){
if($this->exists($key)){
$this->$key = $value;

View File

@@ -139,7 +139,6 @@ class UserModel extends BasicModel {
*/
public function hasUserCharacters(){
$this->filter('userCharacters', ['active = ?', 1]);
return is_object($this->userCharacters);
}
@@ -254,8 +253,9 @@ class UserModel extends BasicModel {
* @return CharacterModel[]
*/
public function getCharacters(){
$userCharacters = $this->getUserCharacters();
$characters = [];
$userCharacters = $this->getUserCharacters();
foreach($userCharacters as $userCharacter){
/**
* @var $userCharacter UserCharacterModel
@@ -276,9 +276,9 @@ class UserModel extends BasicModel {
* @return CharacterModel[]
*/
public function getActiveCharacters(){
$activeCharacters = [];
$userCharacters = $this->getUserCharacters();
$activeCharacters = [];
foreach($userCharacters as $userCharacter){
/**
* @var $userCharacter UserCharacterModel

View File

@@ -70,7 +70,7 @@ define([
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + jqXHR.status + ': ' + error;
$(document).trigger('pf:shutdown', {reason: reason});
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason});
});
/**
@@ -282,7 +282,8 @@ define([
var reason = status + ' ' + jqXHR.status + ': ' + error;
var errorData = [];
if(jqXHR.responseText){
if(jqXHR.responseJSON){
// handle JSON
var errorObj = $.parseJSON(jqXHR.responseText);
if(
@@ -291,9 +292,15 @@ define([
){
errorData = errorObj.error;
}
}else{
// handle HTML
errorData.push({
type: 'error',
message: 'Please restart and reload this page'
});
}
$(document).trigger('pf:shutdown', {reason: reason, error: errorData});
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
};

View File

@@ -619,9 +619,15 @@ define([
logout: {
label: '<i class="fa fa-fw fa-refresh"></i> restart',
className: ['btn-primary'].join(' '),
callback: function() {
$(document).trigger('pf:menuLogout');
callback: function(){
// check if error was 5xx -> reload page
// -> else try to logout -> ajax request
if(data.status >= 500 && data.status < 600){
// redirect to login
window.location = '../';
}else{
$(document).trigger('pf:menuLogout');
}
}
}
},
@@ -642,7 +648,7 @@ define([
data.error &&
data.error.length
){
for(var i = 0; i < data.error.length; i++){
for(let i = 0; i < data.error.length; i++){
options.content.textSmaller.push(data.error[i].message);
}
}

View File

@@ -1036,19 +1036,23 @@ define([
*/
var ajaxSetup = function(){
$.ajaxSetup({
beforeSend: function(xhr) {
// add current character data to ANY XHR request (HTTP HEADER)
// -> This helps to identify multiple characters on multiple browser tabs
var userData = getCurrentUserData();
var currentCharacterId = 0;
if(
userData &&
userData.character
){
currentCharacterId = parseInt( userData.character.id );
}
beforeSend: function(xhr, settings) {
// Add custom application headers on "same origin" requests only!
// -> Otherwise a "preflight" request is made, which will "probably" fail
if(settings.crossDomain === false){
// add current character data to ANY XHR request (HTTP HEADER)
// -> This helps to identify multiple characters on multiple browser tabs
var userData = getCurrentUserData();
var currentCharacterId = 0;
if(
userData &&
userData.character
){
currentCharacterId = parseInt( userData.character.id );
}
xhr.setRequestHeader('Pf-Character', currentCharacterId);
xhr.setRequestHeader('Pf-Character', currentCharacterId);
}
}
});
};

View File

@@ -70,7 +70,7 @@ define([
}).fail(function( jqXHR, status, error) {
var reason = status + ' ' + jqXHR.status + ': ' + error;
$(document).trigger('pf:shutdown', {reason: reason});
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason});
});
/**
@@ -282,7 +282,8 @@ define([
var reason = status + ' ' + jqXHR.status + ': ' + error;
var errorData = [];
if(jqXHR.responseText){
if(jqXHR.responseJSON){
// handle JSON
var errorObj = $.parseJSON(jqXHR.responseText);
if(
@@ -291,9 +292,15 @@ define([
){
errorData = errorObj.error;
}
}else{
// handle HTML
errorData.push({
type: 'error',
message: 'Please restart and reload this page'
});
}
$(document).trigger('pf:shutdown', {reason: reason, error: errorData});
$(document).trigger('pf:shutdown', {status: jqXHR.status, reason: reason, error: errorData});
};

View File

@@ -619,9 +619,15 @@ define([
logout: {
label: '<i class="fa fa-fw fa-refresh"></i> restart',
className: ['btn-primary'].join(' '),
callback: function() {
$(document).trigger('pf:menuLogout');
callback: function(){
// check if error was 5xx -> reload page
// -> else try to logout -> ajax request
if(data.status >= 500 && data.status < 600){
// redirect to login
window.location = '../';
}else{
$(document).trigger('pf:menuLogout');
}
}
}
},
@@ -642,7 +648,7 @@ define([
data.error &&
data.error.length
){
for(var i = 0; i < data.error.length; i++){
for(let i = 0; i < data.error.length; i++){
options.content.textSmaller.push(data.error[i].message);
}
}

View File

@@ -1036,19 +1036,23 @@ define([
*/
var ajaxSetup = function(){
$.ajaxSetup({
beforeSend: function(xhr) {
// add current character data to ANY XHR request (HTTP HEADER)
// -> This helps to identify multiple characters on multiple browser tabs
var userData = getCurrentUserData();
var currentCharacterId = 0;
if(
userData &&
userData.character
){
currentCharacterId = parseInt( userData.character.id );
}
beforeSend: function(xhr, settings) {
// Add custom application headers on "same origin" requests only!
// -> Otherwise a "preflight" request is made, which will "probably" fail
if(settings.crossDomain === false){
// add current character data to ANY XHR request (HTTP HEADER)
// -> This helps to identify multiple characters on multiple browser tabs
var userData = getCurrentUserData();
var currentCharacterId = 0;
if(
userData &&
userData.character
){
currentCharacterId = parseInt( userData.character.id );
}
xhr.setRequestHeader('Pf-Character', currentCharacterId);
xhr.setRequestHeader('Pf-Character', currentCharacterId);
}
}
});
};

View File

@@ -62,6 +62,20 @@
<section id="pf-landing-login">
<div class="container">
{* check for setup mode *}
<check if="{{ array_key_exists('/setup', @ROUTES) && @PATHFINDER.SHOW_SETUP_WARNING }}">
<div class="container-fluid">
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div class="alert alert-warning" >
<span class="txt-color txt-color-warning">Setup mode active</span>
<small>Disable setup route in routes.ini on production environment! <a href="{{ 'setup' | alias }}">Setup</a></small>
</div>
</div>
</div>
</div>
</check>
{* cookie characters *}
<check if="{{ @cookieCharacters }}">
<true>
@@ -80,20 +94,6 @@
</div>
</div>
{* check for setup mode *}
<check if="{{ array_key_exists('/setup', @ROUTES) && @PATHFINDER.SHOW_SETUP_WARNING }}">
<div class="container-fluid">
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div class="alert alert-warning" >
<span class="txt-color txt-color-warning">Setup mode active</span>
<small>Disable setup route in routes.ini in production environment! <a href="{{ 'setup' | alias }}">Setup</a></small>
</div>
</div>
</div>
</div>
</check>
<div class="row text-center pf-character-selection">
<repeat group="{{ @cookieCharacters }}" key="{{ @cookieName }}" value="{{ @characterData }}">
<div class="col-sm-{{ @getCharacterGrid( @cookieCharacters ) }}">