Permalink
Browse files

Merge pull request #23 from Wollari/master

The access check module
  • Loading branch information...
2 parents c2a63c2 + 38998ff commit aa1262cb67436d174e4e96b4ef5992a3dce49100 @ppetermann ppetermann committed Oct 4, 2011
Showing with 434 additions and 13 deletions.
  1. +83 −12 Pheal.php
  2. +33 −0 PhealAccessException.php
  3. +41 −0 PhealAccessInterface.php
  4. +167 −0 PhealCheckAccess.php
  5. +8 −0 PhealConfig.php
  6. +44 −0 PhealNullAccess.php
  7. +58 −1 README.md
View
@@ -53,11 +53,21 @@ class Pheal
private $key;
/**
+ * var @string|null
+ */
+ private $keyType;
+
+ /**
+ * @var int
+ */
+ private $accessMask;
+
+ /**
* EVE Api scope to be used (for example: "account", "char","corp"...)
- * @var String
+ * @var string
*/
public $scope;
-
+
/**
* Result of the last XML request, so application can use the raw xml data
* @var String
@@ -108,9 +118,62 @@ public function __get($name)
}
/**
+ * Set keyType/accessMask
+ * @param string $keyType must be Account/Character/Corporation or null
+ * @param int $accessMask must be integer or 0
+ * @return void
+ */
+ public function setAccess($keyType=null, $accessMask=0)
+ {
+ $this->keyType = in_array(ucfirst(strtolower($keyType)),array('Account','Character','Corporation')) ? $keyType : null;
+ $this->accessMask = (int)$accessMask;
+ }
+
+ /**
+ * clear+reset keyType/accessMask
+ * @return void
+ */
+ public function clearAccess()
+ {
+ $this->setAccess();
+ }
+
+ /**
+ * if userid+key is given it automatically detects (api call) the keyinfo and
+ * set the correct access level for futher checks.
+ *
+ * Keep in mind this method will make an api request to account/APIKeyInfo based
+ * on the given PhealConfig settings with the given key credentials.
+ *
+ * More important! This method will throw Exceptions on invalid keys or networks errors
+ * So place this call into your try statement
+ *
+ * @throws PhealException|PhealAPIException|PhealHTTPException
+ * @return bool|PhealResult
+ */
+ public function detectAccess()
+ {
+ // don't request keyinfo if api keys are not set or if new CAK aren't enabled
+ if(!$this->userid || !$this->key || !PhealConfig::getInstance()->api_customkeys)
+ return false;
+
+ // request api key info, save old scope and restore it afterwords
+ $old = $this->scope;
+ $this->scope = "account";
+ $keyinfo = $this->APIKeyInfo();
+ $this->scope = $old;
+
+ // set detected keytype and accessMask
+ $this->setAccess($keyinfo->key->type, $keyinfo->key->accessMask);
+
+ // return the APIKeyInfo Result object in the case you need it.
+ return $keyinfo;
+ }
+
+ /**
* method will ask caching class for valid xml, if non valid available
* will make API call, and return the appropriate result
- * @throws PhealException|PhealAPIException|PhealHTTPException
+ * @throws PhealException|PhealAPIException|PhealHTTPException|PhealAccessException
* @param string $scope api scope (examples: eve, map, server, ...)
* @param string $name api method (examples: ServerStatus, Kills, Sovereignty, ...)
* @param array $opts additional arguments (example: characterID => 12345, ...), should not contain apikey/userid/keyid/vcode
@@ -126,19 +189,27 @@ private function request_xml($scope, $name, array $opts = array())
unset($opts[$k]);
}
+ // prepare http arguments + url (to not modify original argument list for cache saving)
+ $url = PhealConfig::getInstance()->api_base . $scope . '/' . $name . ".xml.aspx";
+ $use_customkey = (bool)PhealConfig::getInstance()->api_customkeys;
+ $http_opts = $opts;
+ if($this->userid) $http_opts[($use_customkey?'keyID':'userid')] = $this->userid;
+ if($this->key) $http_opts[($use_customkey?'vCode':'apikey')] = $this->key;
+
+ // check access level if given (throws PhealAccessExpception if API call is not allowed)
+ if($use_customkey && $this->userid && $this->key && $this->keyType) {
+ try {
+ PhealConfig::getInstance()->access->check($scope,$name,$this->keyType,$this->accessMask);
+ } catch (Exception $e) {
+ PhealConfig::getInstance()->log->errorLog($scope,$name,$http_opts,$e->getMessage());
+ throw $e;
+ }
+ }
+
// check cache first
if(!$this->xml = PhealConfig::getInstance()->cache->load($this->userid,$this->key,$scope,$name,$opts))
{
- // build url
- $url = PhealConfig::getInstance()->api_base . $scope . '/' . $name . ".xml.aspx";
- $use_customkey = (bool)PhealConfig::getInstance()->api_customkeys;
-
try {
- // prepare http arguments (to not modify original argument list for cache saving)
- $http_opts = $opts;
- if($this->userid) $http_opts[($use_customkey?'keyID':'userid')] = $this->userid;
- if($this->key) $http_opts[($use_customkey?'vCode':'apikey')] = $this->key;
-
// start measure the response time
PhealConfig::getInstance()->log->start();
@@ -0,0 +1,33 @@
+<?php
+/*
+ MIT License
+ Copyright (c) 2010 Peter Petermann
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+*/
+/**
+ * Pheal Access Exception. Should be thrown when Pheal dedects a not allowed API Call based on accessMask
+ */
+class PhealAccessException extends PhealException
+{
+
+}
@@ -0,0 +1,41 @@
+<?php
+/*
+ MIT License
+ Copyright (c) 2010 Peter Petermann
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+*/
+/**
+ * Interface that should be implemented by the access handlers
+ */
+interface PhealAccessInterface
+{
+ /**
+ * Check if the api key is allowed to make this api call
+ * @param string $scope
+ * @param string $name
+ * @param string $keyType
+ * @param int $accessMask
+ */
+ public function check($scope, $name, $keyType, $accessMask);
+
+}
View
@@ -0,0 +1,167 @@
+<?php
+/*
+ MIT License
+ Copyright (c) 2010 Peter Petermann, Daniel Hoffend
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following
+ conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+ * check access modules. Check if the given keyinfo allows a specific api call
+ * access bits are static for performance reason. Feel free to write your own version
+ * if you like to check api->calllist live.
+ *
+ * new/unknown api calls are allowed by default.
+ */
+class PhealCheckAccess implements PhealAccessInterface
+{
+ /**
+ * Key Type of the given API key
+ * @var string (Account, Character, Corporation)
+ */
+ protected $keyType = null;
+
+ /**
+ * accessMask for this API Key
+ * @var int
+ */
+ protected $accessMask = 0;
+
+ /**
+ * Database of calls to check against the given keyinfo
+ * list based on pheal()->apiScope->calllist()
+ * with manually added information
+ * @var array
+ */
+ protected $bits = array(
+ 'char' => array(
+ 'contracts' => array('Character', 67108864),
+ 'wallettransactions' => array('Character', 4194304),
+ 'walletjournal' => array('Character', 2097152),
+ 'upcomingcalendarevents' => array('Character', 1048576),
+ 'standings' => array('Character', 524288),
+ 'skillqueue' => array('Character', 262144),
+ 'skillintraining' => array('Character', 131072),
+ 'research' => array('Character', 65536),
+ 'notificationtexts' => array('Character', 32768),
+ 'notifications' => array('Character', 16384),
+ 'medals' => array('Character', 8192),
+ 'marketorders' => array('Character', 4096),
+ 'mailmessages' => array('Character', 2048),
+ 'mailinglists' => array('Character', 1024),
+ 'mailbodies' => array('Character', 512),
+ 'killlog' => array('Character', 256),
+ 'industryjobs' => array('Character', 128),
+ 'facwarstats' => array('Character', 64),
+ 'contactnotifications' => array('Character', 32),
+ 'contactlist' => array('Character', 16),
+ 'charactersheet' => array('Character', 8),
+ 'calendareventattendees' => array('Character', 4),
+ 'assetlist' => array('Character', 2),
+ 'accountbalance' => array('Character', 1)
+ ),
+ 'account' => array(
+ 'accountstatus' => array('Character', 33554432)
+ ),
+ 'corp' => array(
+ 'contracts' => array('Corporation', 8388608),
+ 'titles' => array('Corporation', 4194304),
+ 'wallettransactions' => array('Corporation', 2097152),
+ 'walletjournal' => array('Corporation', 1048576),
+ 'starbaselist' => array('Corporation', 524288),
+ 'standings' => array('Corporation', 262144),
+ 'starbasedetail' => array('Corporation', 131072),
+ 'shareholders' => array('Corporation', 65536),
+ 'outpostservicedetail' => array('Corporation', 32768),
+ 'outpostlist' => array('Corporation', 16384),
+ 'medals' => array('Corporation', 8192),
+ 'marketorders' => array('Corporation', 4096),
+ 'membertracking' => array('Corporation', 2048),
+ 'membersecuritylog' => array('Corporation', 1024),
+ 'membersecurity' => array('Corporation', 512),
+ 'killlog' => array('Corporation', 256),
+ 'industryjobs' => array('Corporation', 128),
+ 'facwarstats' => array('Corporation', 64),
+ 'containerlog' => array('Corporation', 32),
+ 'contactlist' => array('Corporation', 16),
+ 'corporationsheet' => array('Corporation', 8),
+ 'membermedals' => array('Corporation', 4),
+ 'assetlist' => array('Corporation', 2),
+ 'accountbalance' => array('Corporation', 1)
+ )
+
+ // characterinfo is a public call with more details if you've better api keys
+ // no detailed configuration needed atm
+ /*
+ 'eve' => array(
+ 'characterinfo' => array('Character', array(16777216, 8388608))
+ )
+ */
+ );
+
+ /**
+ * Check if the api key is allowed to make this api call
+ * @param string $scope
+ * @param string $name
+ * @param string $keyType
+ * @param int $accessMask
+ */
+ public function check($scope, $name, $keyType, $accessMask)
+ {
+ // there's no "Account" type on the access bits level
+ $type = ($keyType == "Account") ? "Character" : $keyType;
+
+ // no keyinfo configuration found
+ // assume it's a public call or it's not yet defined
+ // allow and let the CCP decide
+ if( !$keyType
+ || !in_array($type, array('Character','Corporation'))
+ || !isset($this->bits[strtolower($scope)][strtolower($name)]))
+ return true;
+
+ // check accessLevel
+ $check = $this->bits[strtolower($scope)][strtolower($name)];
+
+ // check if keytype is correct for this call
+ if($check[0] == $type) {
+
+ // check single accessbit
+ if(is_int($check[1]) && (int)$accessMask & (int)$check[1])
+ return true;
+
+ // fix if multiple accessbits are valid (eve/CharacterInfo)
+ //elseif(is_array($check[1]))
+ // foreach($check[1] AS $checkbit)
+ // if($checkbit && $checkbit & $accessMask)
+ // return true;
+ }
+
+ // no match == no access right found.
+ throw new PhealAccessException(sprintf(
+ "Pheal blocked an API call (%s/%s) which is not allowed by the given keyType/accessMask (%s/%d)",
+ $scope,
+ $name,
+ $keyType,
+ $accessMask
+ ));
+ }
+}
View
@@ -45,6 +45,13 @@ class PhealConfig
public $archive;
/**
+ * Access Object to validate and check an API with a given keyType+accessMask
+ * defaults to PhealNullAccess Object
+ * @var PhealAccessInterface
+ */
+ public $access;
+
+ /**
* usually this points to the EVE API directly, however if you use a API
* proxy you might want to modify this.
* use https://api.eveonline.com/ if you like to have ssl support
@@ -125,6 +132,7 @@ private function __construct()
$this->cache = new PhealNullCache();
$this->archive = new PhealNullArchive();
$this->log = new PhealNullLog();
+ $this->access = new PhealNullAccess();
}
/**
Oops, something went wrong.

0 comments on commit aa1262c

Please sign in to comment.