Skip to content

Commit

Permalink
Merge pull request #513 from exodus4d/develop
Browse files Browse the repository at this point in the history
v1.2.4
  • Loading branch information
exodus4d authored Jul 28, 2017
2 parents 7c9068b + 10fa280 commit 489e7d8
Show file tree
Hide file tree
Showing 113 changed files with 1,227 additions and 70,423 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,6 @@ Temporary Items
*.gz
*.lock
/conf/
/node_modules/
/public/js/vX.X.X/
/vendor/
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/
CI/CD config files:
--------------------------
|-- .jshintrc --> "JSHint" config (not used for production)
|-- build.js --> "RequireJs Optimizer" config (not used for production)
|-- config.rb --> "Compass" config (not used for production)
|-- gulpfile.js --> "Gulp" task config (not used for production )
|-- package.json --> "Node.js" dependency config (not used for production)
Expand Down
17 changes: 10 additions & 7 deletions app/config.ini
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; Global Framework Config

[SERVER]
SERVER_NAME = PATHFINDER
SERVER_NAME = PATHFINDER

[globals]
; Default Verbosity level of the stack trace.
Expand All @@ -23,7 +23,6 @@ CACHE = folder=tmp/cache/

; Callback functions ==============================================================================
ONERROR = Controller\Controller->showError

UNLOAD = Controller\Controller->unload

; Path configurations =============================================================================
Expand All @@ -50,11 +49,15 @@ EXPORT = export/
; Default language (overwrites HTTP Accept-Language request header) used for "setlocale()" affects number formatting. (default: en-US)
LANGUAGE = en-US

; custom *.ini file folder, can be used to overwrite default *.ini files
CONF.CUSTOM = conf/
CONF.DEFAULT = app/

; load additional config files
; DO NOT load environment.ini, it is loaded automatically
[configs]
app/routes.ini = true
app/pathfinder.ini = true
conf/pathfinder.ini = true
app/requirements.ini = true
app/cron.ini = true
{{@CONF.DEFAULT}}routes.ini = true
{{@CONF.DEFAULT}}pathfinder.ini = true
{{@CONF.CUSTOM}}pathfinder.ini = true
{{@CONF.DEFAULT}}requirements.ini = true
{{@CONF.DEFAULT}}cron.ini = true
4 changes: 2 additions & 2 deletions app/environment.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SERVER = DEVELOP
; -> e.g. set /pathfinder if your URL looks like https://www.[YOUR_DOMAIN]/pathfinder (subfolder)
BASE =
; deployment URL (e.g. http://localhost)
URL = http://local.pathfinder
URL = {{@SCHEME}}://local.pathfinder
; level of debug/error stack trace
DEBUG = 3
; main db
Expand Down Expand Up @@ -57,7 +57,7 @@ SMTP_ERROR = [email protected]
; -> e.g. set /pathfinder if your URL looks like https://www.[YOUR_DOMAIN]/pathfinder (subfolder)
BASE =
; deployment URL (e.g. https://www.pathfinder-w.space)
URL = https://www.pathfinder-w.space
URL = {{@SCHEME}}://www.pathfinder-w.space
; level of debug/error stack trace
DEBUG = 0
; main db
Expand Down
21 changes: 14 additions & 7 deletions app/main/controller/admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
class Admin extends Controller{

const ERROR_SSO_CHARACTER_EXISTS = 'No character found. Please login first.';
const ERROR_SSO_CHARACTER_SCOPES = 'Additional ESI scopes are required for "%s". Use the SSO button below.';
const ERROR_SSO_CHARACTER_ROLES = 'Insufficient in-game roles. "%s" requires at least one of these corp roles: %s.';

const LOG_TEXT_KICK_BAN = '%s "%s" from corporation "%s", by "%s"';
Expand Down Expand Up @@ -86,13 +87,19 @@ protected function getAdminCharacter(\Base $f3){
if($character->role != 'MEMBER'){
// current character is admin
$adminCharacter = $character;
}elseif( !$character->hasAdminScopes() ){
$f3->set(Sso::SESSION_KEY_SSO_ERROR,
sprintf(
self::ERROR_SSO_CHARACTER_SCOPES,
$character->name
));
}else{
$f3->set(Sso::SESSION_KEY_SSO_ERROR,
sprintf(
self::ERROR_SSO_CHARACTER_ROLES,
$character->name,
implode(', ', CorporationModel::ADMIN_ROLES
)));
implode(', ', CorporationModel::ADMIN_ROLES)
));
}
}else{
$f3->set(Sso::SESSION_KEY_SSO_ERROR, self::ERROR_SSO_CHARACTER_EXISTS);
Expand All @@ -107,9 +114,9 @@ protected function getAdminCharacter(\Base $f3){
* @param CharacterModel $character
*/
protected function setCharacterRole(CharacterModel $character){
$character->virtual('role', function($character){
$character->virtual('role', function ($character){
// default role based on roleId (auto-detected)
if( ($role = array_search ($character->roleId, CharacterModel::ROLES)) === false ){
if(($role = array_search($character->roleId, CharacterModel::ROLES)) === false){
$role = 'MEMBER';
}

Expand All @@ -119,9 +126,9 @@ protected function setCharacterRole(CharacterModel $character){
*/
if($this->getF3()->exists('PATHFINDER.ADMIN.CHARACTER', $globalAdminData)){
foreach((array)$globalAdminData as $adminData){
if($adminData['ID'] === $character->_id){
if( CharacterModel::ROLES[$adminData['ROLE']] ){
$role = $adminData['ROLE'];
if($adminData[ 'ID' ] === $character->_id){
if(CharacterModel::ROLES[ $adminData[ 'ROLE' ] ]){
$role = $adminData[ 'ROLE' ];
}
break;
}
Expand Down
2 changes: 1 addition & 1 deletion app/main/controller/api/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected function loginByCharacter(Model\CharacterModel &$characterModel){
* -> return character data (if valid)
* @param \Base $f3
*/
public function getCookieCharacter($f3){
public function getCookieCharacter(\Base $f3){
$data = $f3->get('POST');

$return = (object) [];
Expand Down
19 changes: 11 additions & 8 deletions app/main/controller/ccp/sso.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Sso extends Api\User{
public function requestAdminAuthorization($f3){
$f3->set(self::SESSION_KEY_SSO_FROM, 'admin');

$scopes = $this->getScopesByAuthType('admin');
$scopes = self::getScopesByAuthType('admin');
$this->rerouteAuthorization($f3, $scopes, 'admin');
}

Expand Down Expand Up @@ -105,7 +105,7 @@ public function requestAuthorization($f3){

if($loginCheck){
// set "login" cookie
$this->setLoginCookie($character, $this->generateHashFromScopes($this->getScopesByAuthType()) );
$this->setLoginCookie($character);

// -> pass current character data to target page
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $character->_id);
Expand All @@ -122,7 +122,7 @@ public function requestAuthorization($f3){
}

// redirect to CCP SSO ----------------------------------------------------------------------
$scopes = $this->getScopesByAuthType();
$scopes = self::getScopesByAuthType();
$this->rerouteAuthorization($f3, $scopes);
}

Expand Down Expand Up @@ -207,9 +207,10 @@ public function callbackAuthorization($f3){

if( isset($characterData->character) ){
// add "ownerHash" and SSO tokens
$characterData->character['ownerHash'] = $verificationCharacterData->CharacterOwnerHash;
$characterData->character['crestAccessToken'] = $accessData->accessToken;
$characterData->character['crestRefreshToken'] = $accessData->refreshToken;
$characterData->character['ownerHash'] = $verificationCharacterData->CharacterOwnerHash;
$characterData->character['crestAccessToken'] = $accessData->accessToken;
$characterData->character['crestRefreshToken'] = $accessData->refreshToken;
$characterData->character['esiScopes'] = Lib\Util::convertScopesString($verificationCharacterData->Scopes);

// add/update static character data
$characterModel = $this->updateCharacter($characterData);
Expand Down Expand Up @@ -255,7 +256,7 @@ public function callbackAuthorization($f3){

if($loginCheck){
// set "login" cookie
$this->setLoginCookie($characterModel, $this->generateHashFromScopes( explode(' ', $verificationCharacterData->Scopes) ));
$this->setLoginCookie($characterModel);

// -> pass current character data to target page
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $characterModel->_id);
Expand Down Expand Up @@ -569,7 +570,9 @@ protected function updateCharacter($characterData){
*/
$characterModel = Model\BasicModel::getNew('CharacterModel');
$characterModel->getById((int)$characterData->character['id'], 0);
$characterModel->copyfrom($characterData->character, ['id', 'name', 'ownerHash', 'crestAccessToken', 'crestRefreshToken', 'securityStatus']);
$characterModel->copyfrom($characterData->character, [
'id', 'name', 'ownerHash', 'crestAccessToken', 'crestRefreshToken', 'esiScopes', 'securityStatus'
]);
$characterModel->corporationId = $characterData->corporation;
$characterModel->allianceId = $characterData->alliance;
$characterModel = $characterModel->save();
Expand Down
97 changes: 47 additions & 50 deletions app/main/controller/controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Controller\Api as Api;
use lib\Config;
use lib\Socket;
use Lib\Util;
use Model;
use DB;

Expand Down Expand Up @@ -187,9 +188,8 @@ protected function getCookieByName($cookieName, $prefix = false){
* set/update logged in cookie by character model
* -> store validation data in DB
* @param Model\CharacterModel $character
* @param string $scopeHash
*/
protected function setLoginCookie(Model\CharacterModel $character, $scopeHash = ''){
protected function setLoginCookie(Model\CharacterModel $character){

if( $this->getCookieState() ){
$expireSeconds = (int) $this->getF3()->get('PATHFINDER.LOGIN.COOKIE_EXPIRE');
Expand Down Expand Up @@ -221,8 +221,7 @@ protected function setLoginCookie(Model\CharacterModel $character, $scopeHash =
'characterId' => $character,
'selector' => $selector,
'token' => $token,
'expires' => $expireTime->format('Y-m-d H:i:s'),
'scopeHash' => $scopeHash
'expires' => $expireTime->format('Y-m-d H:i:s')
];

$authenticationModel = $character->rel('characterAuthentications');
Expand Down Expand Up @@ -276,10 +275,6 @@ protected function getCookieCharacters($cookieData = [], $checkAuthorization = t
// "expire data" and "validate token"
if( !$characterAuth->dry() ){
if(
(
$characterAuth->scopeHash === $this->generateHashFromScopes($this->getScopesByAuthType()) ||
$characterAuth->scopeHash === $this->generateHashFromScopes($this->getScopesByAuthType('admin'))
) &&
strtotime($characterAuth->expires) >= $currentTime->getTimestamp() &&
hash_equals($characterAuth->token, hash('sha256', $data[1]))
){
Expand All @@ -297,20 +292,32 @@ protected function getCookieCharacters($cookieData = [], $checkAuthorization = t
$character = $characterAuth->rel('characterId');
$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
// -> do NOT remove cookie on failure. This can be a temporary problem (e.g. ESI is down,..)
if( $character->hasUserCharacter() ){
$authStatus = $character->isAuthorized();

if(
$authStatus == 'OK' ||
!$checkAuthorization
){
$character->virtual( 'authStatus', $authStatus);
// check ESI scopes
$scopeHash = Util::getHashFromScopes($character->esiScopes);

if(
$scopeHash === Util::getHashFromScopes(self::getScopesByAuthType()) ||
$scopeHash === Util::getHashFromScopes(self::getScopesByAuthType('admin'))
){
// 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
// -> do NOT remove cookie on failure. This can be a temporary problem (e.g. ESI is down,..)
if( $character->hasUserCharacter() ){
$authStatus = $character->isAuthorized();

if(
$authStatus == 'OK' ||
!$checkAuthorization
){
$character->virtual( 'authStatus', $authStatus);
}

$characters[$name] = $character;
}

$characters[$name] = $character;
}else{
// outdated/invalid ESI scopes
$characterAuth->erase();
$invalidCookie = true;
}
}else{
$invalidCookie = true;
Expand Down Expand Up @@ -434,35 +441,6 @@ public function getUser($ttl = 0){
return $user;
}

/**
* get scope array by a "role"
* @param string $authType
* @return array
*/
protected function getScopesByAuthType($authType = ''){
$scopes = (array)self::getEnvironmentData('CCP_ESI_SCOPES');

switch($authType){
case 'admin':
$scopesAdmin = (array)self::getEnvironmentData('CCP_ESI_SCOPES_ADMIN');
$scopes = array_merge($scopes, $scopesAdmin);
break;
}
sort($scopes, SORT_NUMERIC);
return $scopes;
}

/**
* get hash from an array of ESI scopes
* @param array $scopes
* @return string
*/
protected function generateHashFromScopes($scopes){
$scopes = (array)$scopes;
sort($scopes);
return md5(serialize( $scopes ));
}

/**
* log out current character
* @param \Base $f3
Expand Down Expand Up @@ -715,6 +693,25 @@ static function getController($className){
return $controller;
}


/**
* get scope array by a "role"
* @param string $authType
* @return array
*/
static function getScopesByAuthType($authType = ''){
$scopes = (array)self::getEnvironmentData('CCP_ESI_SCOPES');

switch($authType){
case 'admin':
$scopesAdmin = (array)self::getEnvironmentData('CCP_ESI_SCOPES_ADMIN');
$scopes = array_merge($scopes, $scopesAdmin);
break;
}
sort($scopes);
return $scopes;
}

/**
* Helper function to return all headers because
* getallheaders() is not available under nginx
Expand Down
Loading

0 comments on commit 489e7d8

Please sign in to comment.