diff --git a/app/environment.ini b/app/environment.ini index 7c19b936..409cdf58 100644 --- a/app/environment.ini +++ b/app/environment.ini @@ -35,7 +35,7 @@ CCP_SSO_DOWNTIME = 11:00 ; CCP ESI API CCP_ESI_URL = https://esi.evetech.net CCP_ESI_DATASOURCE = singularity -CCP_ESI_SCOPES = esi-location.read_online.v1,esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1,esi-universe.read_structures.v1,esi-corporations.read_corporation_membership.v1 +CCP_ESI_SCOPES = esi-location.read_online.v1,esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1,esi-universe.read_structures.v1,esi-corporations.read_corporation_membership.v1,esi-clones.read_clones.v1 CCP_ESI_SCOPES_ADMIN = ; SMTP settings (optional) @@ -88,7 +88,7 @@ CCP_SSO_DOWNTIME = 11:00 ; CCP ESI API CCP_ESI_URL = https://esi.evetech.net CCP_ESI_DATASOURCE = tranquility -CCP_ESI_SCOPES = esi-location.read_online.v1,esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1,esi-universe.read_structures.v1,esi-corporations.read_corporation_membership.v1 +CCP_ESI_SCOPES = esi-location.read_online.v1,esi-location.read_location.v1,esi-location.read_ship_type.v1,esi-ui.write_waypoint.v1,esi-ui.open_window.v1,esi-universe.read_structures.v1,esi-corporations.read_corporation_membership.v1,esi-clones.read_clones.v1 CCP_ESI_SCOPES_ADMIN = ; SMTP settings (optional) diff --git a/app/main/controller/api/map.php b/app/main/controller/api/map.php index af52586d..3fddbcce 100644 --- a/app/main/controller/api/map.php +++ b/app/main/controller/api/map.php @@ -317,7 +317,7 @@ class Map extends Controller\AccessController { $mapDataSystems = (array)$mapDataData['systems']; $mapDataConnections = (array)$mapDataData['connections']; $systemCount = count($mapDataSystems); - if( $systemCount <= $defaultConfig['max_systems']){ + if($systemCount <= $defaultConfig['max_systems']){ $map->copyfrom($mapDataConfig, ['name', 'icon', 'position', 'locked', 'rallyUpdated', 'rallyPoke']); $map->typeId = $mapType; @@ -583,7 +583,7 @@ class Map extends Controller\AccessController { } // reload the same map model (refresh) // this makes sure all data is up2date - $map->getById( $map->_id, 0 ); + $map->getById($map->_id, 0); // broadcast map Access -> and send map Data $this->broadcastMapAccess($map); @@ -717,7 +717,7 @@ class Map extends Controller\AccessController { $return->status = $status; - echo json_encode( $return ); + echo json_encode($return); } /** @@ -817,7 +817,7 @@ class Map extends Controller\AccessController { $return->userData = $activeCharacter->getUser()->getData(); } - echo json_encode( $return ); + echo json_encode($return); } /** @@ -901,7 +901,7 @@ class Map extends Controller\AccessController { // add error (if exists) $return->error = []; - echo json_encode( $return ); + echo json_encode($return); } @@ -987,6 +987,7 @@ class Map extends Controller\AccessController { $addSourceSystem = false; $addTargetSystem = false; $addConnection = false; + $route = []; switch($mapScope->name){ case 'all': @@ -1031,10 +1032,9 @@ class Map extends Controller\AccessController { ){ // check distance between systems (in jumps) // -> if > 1 it is !very likely! a wormhole - $routeController = new Route(); - $route = $routeController->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1); + $route = (new Route())->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1); - if( !$route['routePossible'] ){ + if(!$route['routePossible']){ $addSourceSystem = true; $addTargetSystem = true; $addConnection = true; @@ -1043,7 +1043,7 @@ class Map extends Controller\AccessController { break; } - // save source system --------------------------------------------------------------------------------- + // save source system ============================================================================= if( $addSourceSystem && $sourceSystem && @@ -1061,7 +1061,7 @@ class Map extends Controller\AccessController { } } - // save target system --------------------------------------------------------------------------------- + // save target system ============================================================================= if( $addTargetSystem && $targetSystem && @@ -1082,23 +1082,52 @@ class Map extends Controller\AccessController { $sourceSystem && $targetSystem ){ - $connection = $map->searchConnection( $sourceSystem, $targetSystem); + $connection = $map->searchConnection($sourceSystem, $targetSystem); - // save connection -------------------------------------------------------------------------------- + // save connection ============================================================================ if( $addConnection && !$connection ){ - $connection = $map->getNewConnection($sourceSystem, $targetSystem); - $connection = $map->saveConnection($connection, $character); - // get updated maps object - if($connection){ - $map = $connection->mapId; - $mapDataChanged = true; + // .. do not add connection if character got "podded" ------------------------------------- + if( + $log->shipTypeId == 670 && + $character->cloneLocationId + ){ + // .. current character location must be clone location + if( + ( + 'station' == $character->cloneLocationType && + $character->cloneLocationId == $log->stationId + ) || ( + 'structure' == $character->cloneLocationType && + $character->cloneLocationId == $log->structureId + ) + ){ + // .. now we need to check jump distance between systems + // -> if > 1 it is !very likely! podded jump + if(empty($route)){ + $route = (new Route())->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1); + } + + if(!$route['routePossible']){ + $addConnection = false; + } + } + } + + if($addConnection){ + $connection = $map->getNewConnection($sourceSystem, $targetSystem); + $connection = $map->saveConnection($connection, $character); + // get updated maps object + if($connection){ + $map = $connection->mapId; + $mapDataChanged = true; + } } } - // log jump mass ---------------------------------------------------------------------------------- + // log jump mass ============================================================================== if( $connection && $connection->isWormhole() @@ -1122,7 +1151,7 @@ class Map extends Controller\AccessController { * @param \Base $f3 * @throws Exception */ - public function getConnectionData (\Base $f3){ + public function getConnectionData(\Base $f3){ $postData = (array)$f3->get('POST'); $addData = (array)$postData['addData']; @@ -1217,16 +1246,3 @@ class Map extends Controller\AccessController { } } - - - - - - - - - - - - - diff --git a/app/main/controller/api/user.php b/app/main/controller/api/user.php index c6d41901..d036b876 100644 --- a/app/main/controller/api/user.php +++ b/app/main/controller/api/user.php @@ -37,7 +37,7 @@ class User extends Controller\Controller{ /** * valid reasons for captcha images - * @var string array + * @var array */ private static $captchaReason = [self::SESSION_CAPTCHA_ACCOUNT_UPDATE, self::SESSION_CAPTCHA_ACCOUNT_DELETE]; @@ -68,25 +68,27 @@ class User extends Controller\Controller{ is_null($currentUser) || $currentUser->_id !== $user->_id ){ - // user has changed OR new user --------------------------------------------------- + // user has changed OR new user ----------------------------------------------------------------------- //-> set user/character data to session $this->getF3()->set(self::SESSION_KEY_USER, [ 'ID' => $user->_id, 'NAME' => $user->name ]); }else{ - // user has NOT changed ----------------------------------------------------------- + // user has NOT changed ------------------------------------------------------------------------------- $sessionCharacters = $character::mergeSessionCharacterData($sessionCharacters); } $this->getF3()->set(self::SESSION_KEY_CHARACTERS, $sessionCharacters); - // save user login information -------------------------------------------------------- - $character->roleId = $character->requestRole(); + $character->updateCloneData(); + $character->updateRoleData(); + + // save user login information ---------------------------------------------------------------------------- $character->touch('lastLogin'); $character->save(); - // write login log -------------------------------------------------------------------- + // write login log ---------------------------------------------------------------------------------------- self::getLogger('CHARACTER_LOGIN')->write( sprintf(self::LOG_LOGGED_IN, $user->_id, @@ -96,7 +98,7 @@ class User extends Controller\Controller{ ) ); - // set temp character data ------------------------------------------------------------ + // set temp character data -------------------------------------------------------------------------------- // -> pass character data over for next http request (reroute()) $this->setTempCharacterData($character->_id); @@ -263,7 +265,7 @@ class User extends Controller\Controller{ if($activeCharacter = $this->getCharacter()){ $user = $activeCharacter->getUser(); - // captcha is send -> check captcha ------------------------------------------- + // captcha is send -> check captcha --------------------------------------------------------------- if( isset($formData['captcha']) && !empty($formData['captcha']) @@ -303,7 +305,7 @@ class User extends Controller\Controller{ } } - // sharing config ------------------------------------------------------------- + // sharing config --------------------------------------------------------------------------------- if(isset($formData['share'])){ $privateSharing = (int)$formData['privateSharing']; $corporationSharing = (int)$formData['corporationSharing']; @@ -327,7 +329,7 @@ class User extends Controller\Controller{ $activeCharacter->save(); } - // character config ----------------------------------------------------------- + // character config ------------------------------------------------------------------------------- if(isset($formData['character'])){ $activeCharacter->copyfrom($formData, ['logLocation', 'selectLocation']); diff --git a/app/main/controller/ccp/sso.php b/app/main/controller/ccp/sso.php index 21d2690c..75201286 100644 --- a/app/main/controller/ccp/sso.php +++ b/app/main/controller/ccp/sso.php @@ -69,7 +69,7 @@ class Sso extends Api\User{ isset($params['characterId']) && ( $activeCharacter = $this->getCharacter() ) ){ - // authentication restricted to a characterId ----------------------------------------------- + // authentication restricted to a characterId ------------------------------------------------------------- // restrict login to this characterId e.g. for character switch on map page $characterId = (int)trim((string)$params['characterId']); @@ -114,7 +114,7 @@ class Sso extends Api\User{ $f3->set(self::SESSION_KEY_SSO_FROM, 'map'); } - // redirect to CCP SSO ---------------------------------------------------------------------- + // redirect to CCP SSO ---------------------------------------------------------------------------------------- $scopes = self::getScopesByAuthType(); $this->rerouteAuthorization($f3, $scopes); } diff --git a/app/main/controller/controller.php b/app/main/controller/controller.php index 75804e51..51794b65 100644 --- a/app/main/controller/controller.php +++ b/app/main/controller/controller.php @@ -384,13 +384,11 @@ class Controller { * @return array * @throws \Exception */ - public function getSessionCharacterData(){ + public function getSessionCharacterData() : array { $data = []; - if($user = $this->getUser()){ $header = self::getRequestHeaders(); $requestedCharacterId = (int)$header['Pf-Character']; - if( !$this->getF3()->get('AJAX') ){ $requestedCharacterId = (int)$_COOKIE['old_char_id']; if(!$requestedCharacterId){ @@ -398,7 +396,6 @@ class Controller { if((int)$tempCharacterData['ID'] > 0){ $requestedCharacterId = (int)$tempCharacterData['ID']; } - } } diff --git a/app/main/controller/setup.php b/app/main/controller/setup.php index fdd543c2..f3db6302 100644 --- a/app/main/controller/setup.php +++ b/app/main/controller/setup.php @@ -1376,7 +1376,6 @@ class Setup extends Controller { ksort($requiredTables); $this->databases[$dbAlias]['info'] = [ - // 'db' => $db, 'label' => $dbLabel, 'host' => $dbConfigValues['SOCKET'] ? : $dbConfigValues['HOST'], 'port' => $dbConfigValues['PORT'] && !$dbConfigValues['SOCKET'] ? $dbConfigValues['PORT'] : '', diff --git a/app/main/model/pathfinder/charactermodel.php b/app/main/model/pathfinder/charactermodel.php index aed8effe..8fd7d099 100644 --- a/app/main/model/pathfinder/charactermodel.php +++ b/app/main/model/pathfinder/charactermodel.php @@ -16,6 +16,9 @@ use Model\Universe; class CharacterModel extends AbstractPathfinderModel { + /** + * @var string + */ protected $table = 'character'; /** @@ -23,6 +26,9 @@ class CharacterModel extends AbstractPathfinderModel { */ const DATA_CACHE_KEY_LOG = 'LOG'; + /** + * log message for character access + */ const LOG_ACCESS = 'charId: [%20s], status: %s, charName: %s'; /** @@ -52,8 +58,10 @@ class CharacterModel extends AbstractPathfinderModel { * @var bool */ private $allowBanChange = false; - + /** + * @var array + */ protected $fieldConf = [ 'lastLogin' => [ 'type' => Schema::DT_TIMESTAMP, @@ -124,6 +132,16 @@ class CharacterModel extends AbstractPathfinderModel { ] ], ], + 'cloneLocationId' => [ + 'type' => Schema::DT_BIGINT, + 'index' => true, + 'activity-log' => true + ], + 'cloneLocationType' => [ + 'type' => Schema::DT_VARCHAR128, + 'nullable' => false, + 'default' => '' + ], 'kicked' => [ 'type' => Schema::DT_TIMESTAMP, 'index' => true @@ -490,39 +508,42 @@ class CharacterModel extends AbstractPathfinderModel { /** * get ESI API "access_token" from OAuth * @return bool|mixed - * @throws \Exception */ public function getAccessToken(){ $accessToken = false; $refreshToken = true; - $timezone = self::getF3()->get('getTimeZone')(); - $now = new \DateTime('now', $timezone); + try{ + $timezone = self::getF3()->get('getTimeZone')(); + $now = new \DateTime('now', $timezone); - if( - !empty($this->esiAccessToken) && - !empty($this->esiAccessTokenExpires) - ){ - $expireTime = \DateTime::createFromFormat( - 'Y-m-d H:i:s', - $this->esiAccessTokenExpires, - $timezone - ); - - // check if token is not expired - if($expireTime->getTimestamp() > $now->getTimestamp()){ - // token still valid - $accessToken = $this->esiAccessToken; - - // check if token should be renewed (close to expire) - $timeBuffer = 2 * 60; - $expireTime->sub(new \DateInterval('PT' . $timeBuffer . 'S')); + if( + !empty($this->esiAccessToken) && + !empty($this->esiAccessTokenExpires) + ){ + $expireTime = \DateTime::createFromFormat( + 'Y-m-d H:i:s', + $this->esiAccessTokenExpires, + $timezone + ); + // check if token is not expired if($expireTime->getTimestamp() > $now->getTimestamp()){ - // token NOT close to expire - $refreshToken = false; + // token still valid + $accessToken = $this->esiAccessToken; + + // check if token should be renewed (close to expire) + $timeBuffer = 2 * 60; + $expireTime->sub(new \DateInterval('PT' . $timeBuffer . 'S')); + + if($expireTime->getTimestamp() > $now->getTimestamp()){ + // token NOT close to expire + $refreshToken = false; + } } } + }catch(\Exception $e){ + self::getF3()->error(500, $e->getMessage(), $e->getTrace()); } // no valid "accessToken" found OR @@ -673,7 +694,7 @@ class CharacterModel extends AbstractPathfinderModel { * @return RoleModel * @throws \Exception */ - public function requestRole() : RoleModel{ + protected function requestRole() : RoleModel { $role = null; // check config files for hardcoded character roles @@ -718,7 +739,7 @@ class CharacterModel extends AbstractPathfinderModel { * @return array * @throws \Exception */ - protected function requestRoles(){ + protected function requestRoles() : array { $rolesData = []; // check if character has accepted all admin scopes (one of them is required for "role" request) @@ -741,16 +762,39 @@ class CharacterModel extends AbstractPathfinderModel { * check whether this char has accepted all "basic" api scopes * @return bool */ - public function hasBasicScopes(){ - return empty( array_diff(Sso::getScopesByAuthType(), $this->esiScopes) ); + public function hasBasicScopes() : bool { + return empty(array_diff(Sso::getScopesByAuthType(), $this->esiScopes)); } /** * check whether this char has accepted all admin api scopes * @return bool */ - public function hasAdminScopes(){ - return empty( array_diff(Sso::getScopesByAuthType('admin'), $this->esiScopes) ); + public function hasAdminScopes() : bool { + return empty(array_diff(Sso::getScopesByAuthType('admin'), $this->esiScopes)); + } + + /** + * update clone data + */ + public function updateCloneData(){ + if($accessToken = $this->getAccessToken()){ + $clonesData = self::getF3()->ccpClient()->getCharacterClonesData($this->_id, $accessToken); + if(!isset($clonesData['error'])){ + if(!empty($homeLocationData = $clonesData['home']['location'])){ + // clone home location data + $this->cloneLocationId = (int)$homeLocationData['id']; + $this->cloneLocationType = (string)$homeLocationData['type']; + } + } + } + } + + /** + * @throws \Exception + */ + public function updateRoleData(){ + $this->roleId = $this->requestRole(); } /** @@ -760,7 +804,7 @@ class CharacterModel extends AbstractPathfinderModel { * @return CharacterModel * @throws \Exception */ - public function updateLog($additionalOptions = []){ + public function updateLog($additionalOptions = []) : self { $deleteLog = false; $invalidResponse = false; @@ -966,7 +1010,7 @@ class CharacterModel extends AbstractPathfinderModel { * @return array (some status messages) * @throws \Exception */ - public function updateFromESI(){ + public function updateFromESI() : array { $status = []; if( $accessToken = $this->getAccessToken() ){ @@ -1005,7 +1049,7 @@ class CharacterModel extends AbstractPathfinderModel { * -> but is should be unique * @return string */ - public function getCookieName(){ + public function getCookieName() : string { return md5($this->name); } diff --git a/app/main/model/pathfinder/usermodel.php b/app/main/model/pathfinder/usermodel.php index e7b70664..0ced12f0 100644 --- a/app/main/model/pathfinder/usermodel.php +++ b/app/main/model/pathfinder/usermodel.php @@ -209,7 +209,7 @@ class UserModel extends AbstractPathfinderModel { * @return array * @throws Exception */ - public function getSessionCharacterData($characterId = 0, $objectCheck = true){ + public function getSessionCharacterData($characterId = 0, $objectCheck = true) : array { $data = []; $characterId = (int)$characterId; $currentSessionUser = (array)$this->getF3()->get(User::SESSION_KEY_USER); @@ -254,7 +254,7 @@ class UserModel extends AbstractPathfinderModel { * @param int $characterId * @return array */ - public function findSessionCharacterData(int $characterId): array{ + public function findSessionCharacterData(int $characterId): array { $data = []; if($characterId){ $sessionCharacters = (array)$this->getF3()->get(User::SESSION_KEY_CHARACTERS);