Version 4.3.0
This commit is contained in:
1 parent
96997ddd8e
commit
fe1acf984a
1349 files changed
+116159
-67711
No files matched your search
+140
-14
@@ -27,15 +27,89 @@ abstract class _Controller
|
||||
*/
|
||||
protected $apiKey;
|
||||
|
||||
/**
|
||||
* @brief OAuth Client
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @brief OAuth Authenticated Member
|
||||
*/
|
||||
protected $member;
|
||||
|
||||
/**
|
||||
* @brief OAuth Scopes
|
||||
*/
|
||||
protected $scopes;
|
||||
|
||||
/**
|
||||
* @brief Used OAuth Scope
|
||||
*/
|
||||
protected $usedScope;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \IPS\Api\Key $apiKey The API key being used to access
|
||||
* @param \IPS\Api\Key $apiKey The API key being used to access, if applicable
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( \IPS\Api\Key $apiKey )
|
||||
public function __construct( \IPS\Api\Key $apiKey = NULL, $accessToken = NULL )
|
||||
{
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
if ( $accessToken )
|
||||
{
|
||||
$this->client = \IPS\Api\OAuthClient::load( $accessToken['client_id'] );
|
||||
$this->scopes = $accessToken['scope'] ? json_decode( $accessToken['scope'] ) : NULL;
|
||||
if ( $accessToken['member_id'] )
|
||||
{
|
||||
$this->member = \IPS\Member::load( $accessToken['member_id'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access
|
||||
*
|
||||
* @param string $app Application key
|
||||
* @param string $controller Controller
|
||||
* @param string $method Method
|
||||
* @return bool
|
||||
*/
|
||||
protected function canAccess( $app, $controller, $method )
|
||||
{
|
||||
if ( $this->apiKey )
|
||||
{
|
||||
return $this->apiKey->canAccess( $app, $controller, $method );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( $this->usedScope = $this->client->scopesCanAccess( $this->scopes, $app, $controller, $method ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need to log this response?
|
||||
*
|
||||
* @param string $app Application key
|
||||
* @param string $controller Controller
|
||||
* @param string $method Method
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldLog( $app, $controller, $method )
|
||||
{
|
||||
if ( $this->apiKey )
|
||||
{
|
||||
return $this->apiKey->shouldLog( $app, $controller, $method );
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->client->scopeShouldLog( $this->usedScope, $app, $controller, $method );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,15 +133,33 @@ abstract class _Controller
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_ENDPOINT', '2S291/1', 404 );
|
||||
}
|
||||
|
||||
|
||||
if ( method_exists( $this, "{$method}{$endpointData['endpoint']}" ) )
|
||||
{
|
||||
preg_match( '/^IPS\\\(.+?)\\\api\\\(.+?)$/', get_called_class(), $matches );
|
||||
if ( !$this->apiKey->canAccess( $matches[1], $matches[2], "{$method}{$endpointData['endpoint']}" ) )
|
||||
|
||||
$shouldLog = $this->shouldLog( $matches[1], $matches[2], "{$method}{$endpointData['endpoint']}" );
|
||||
if ( !$this->canAccess( $matches[1], $matches[2], "{$method}{$endpointData['endpoint']}" ) )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2S291/3', 403 );
|
||||
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2S291/3', 403, 'insufficient_scope' );
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionMethod( $this, "{$method}{$endpointData['endpoint']}" );
|
||||
$docBlock = static::decodeDocblock( $reflection->getDocComment() );
|
||||
if ( !$this->member )
|
||||
{
|
||||
if ( isset( $docBlock['details']['apimemberonly'] ) )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2S291/3', 403, 'insufficient_scope' );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isset( $docBlock['details']['apiclientonly'] ) )
|
||||
{
|
||||
throw new \IPS\Api\Exception( 'NO_PERMISSION', '2S291/3', 403, 'insufficient_scope' );
|
||||
}
|
||||
}
|
||||
$shouldLog = $this->apiKey->shouldLog( $matches[1], $matches[2], "{$method}{$endpointData['endpoint']}" );
|
||||
|
||||
return call_user_func_array( array( $this, "{$method}{$endpointData['endpoint']}" ), $endpointData['params'] );
|
||||
}
|
||||
@@ -120,9 +212,10 @@ abstract class _Controller
|
||||
/**
|
||||
* Get all endpoints
|
||||
*
|
||||
* @param string|null $type If 'client' or 'member', will not include endpoints that are't applicable
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllEndpoints()
|
||||
public static function getAllEndpoints( $type = NULL )
|
||||
{
|
||||
$return = array();
|
||||
foreach ( \IPS\Application::applications() as $app )
|
||||
@@ -137,12 +230,20 @@ abstract class _Controller
|
||||
{
|
||||
$controllerName = mb_substr( $file, 0, -4 );
|
||||
$class = 'IPS\\' . $app->directory . '\\api\\' . $controllerName;
|
||||
$reflection = new \ReflectionClass( $class );
|
||||
foreach ( $reflection->getMethods() as $method )
|
||||
if( class_exists( $class ) )
|
||||
{
|
||||
if ( $method->getName() != 'execute' and !$method->isStatic() and $method->isPublic() and mb_substr( $method->getName(), 0, 1 ) != '_' )
|
||||
$reflection = new \ReflectionClass( $class );
|
||||
foreach ( $reflection->getMethods() as $method )
|
||||
{
|
||||
$return[ $app->directory . '/' . $controllerName . '/' . $method->getName() ] = static::decodeDocblock( $method->getDocComment() );
|
||||
if ( $method->getName() != 'execute' and !$method->isStatic() and $method->isPublic() and mb_substr( $method->getName(), 0, 1 ) != '_' )
|
||||
{
|
||||
$details = static::decodeDocblock( $method->getDocComment() );
|
||||
|
||||
if ( ( $type !== 'client' or !isset( $details['details']['apimemberonly'] ) ) and ( $type !== 'member' or !isset( $details['details']['apiclientonly'] ) ) )
|
||||
{
|
||||
$return[ $app->directory . '/' . $controllerName . '/' . $method->getName() ] = $details;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,10 +284,18 @@ abstract class _Controller
|
||||
{
|
||||
if ( isset( $matches[ $k ] ) )
|
||||
{
|
||||
$details[] = $matches[ $k ];
|
||||
$details[] = trim( $matches[ $k ] );
|
||||
}
|
||||
}
|
||||
$params[ $matches[1] ][] = $details;
|
||||
|
||||
$key = $matches[1];
|
||||
if ( $key === 'clientapiresponse' )
|
||||
{
|
||||
$key = 'apiresponse';
|
||||
$details[4] = 'client';
|
||||
}
|
||||
|
||||
$params[ $key ][] = $details;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +313,7 @@ abstract class _Controller
|
||||
* @param string $size Size of badge to show
|
||||
* @return array
|
||||
*/
|
||||
public static function parseEndpointForDisplay( $endpoint, $size='small' )
|
||||
public static function parseEndpointForDisplay( $endpoint, $size='small', $includeBaseUrl=FALSE )
|
||||
{
|
||||
$badgeStyles = array(
|
||||
'GET' => 'ipsBadge_positive',
|
||||
@@ -219,6 +328,23 @@ abstract class _Controller
|
||||
\IPS\Output::i()->error( \IPS\Member::loggedIn()->language()->addToStack( 'api_endpoint_phpdoc_error', FALSE, array( "sprintf" => array( $endpoint ) ) ), '3S291/4', 500 );
|
||||
}
|
||||
$pieces[0] = "<span class='ipsBadge ipsBadge_{$size} " . $badgeStyles[ $pieces[0] ] . "'>" . $pieces[0] . "</span>";
|
||||
|
||||
if ( $includeBaseUrl )
|
||||
{
|
||||
if ( \IPS\Settings::i()->use_friendly_urls and \IPS\Settings::i()->htaccess_mod_rewrite )
|
||||
{
|
||||
$url = \IPS\Http\Url::external( rtrim( \IPS\Settings::i()->base_url, '/' ) . '/api' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$url = \IPS\Http\Url::external( rtrim( \IPS\Settings::i()->base_url, '/' ) . '/api/index.php?' );
|
||||
}
|
||||
if ( \IPS\Request::i()->isSecure() )
|
||||
{
|
||||
$url = $url->setScheme('https');
|
||||
}
|
||||
$pieces[1] = $url . $pieces[1];
|
||||
}
|
||||
|
||||
return implode( ' ', $pieces );
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user