Skip to content

Commit

Permalink
Added RESTOpen, updated docs and tests accordingly
Browse files Browse the repository at this point in the history
- Also made a bug fix to there return of the parent auth status on the
RESTUser controller
  • Loading branch information
danrwalker committed May 12, 2017
1 parent 79db867 commit 582db41
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 183 deletions.
178 changes: 78 additions & 100 deletions dist/twist/Core/Controllers/BaseREST.controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,131 +26,109 @@
use Twist\Classes\Error;

/*
* An REST API base controller (basic API Key auth) that can be used instead of Base when adding REST API support to your site. This controller should be used as an extension to a route controller class.
* An REST API base controller (no authentication) that can be used instead of Base when adding REST API support to your site. This controller should be used as an extension to a route controller class.
* See twistphp.com/examples for a full guide on RESTful routing
*
* @package Twist\Core\Controllers
*/
class BaseREST extends Base{

protected static $blRequestHeaderAuth = true;
protected static $srtFormat = 'json';
protected static $srtApiKey = '';
protected static $arrKeyInfo = array();
protected static $srtFormat = 'json';

/**
* Default functionality for every request that is made though the REST API. Every call must be authenticated.
*/
/**
* Default functionality for every request that is made though the REST API.
*/
public function _baseCalls(){

header("Access-Control-Allow-Orgin: *");
header("Access-Control-Allow-Methods: *");
header("Access-Control-Allow-Orgin: *");
header("Access-Control-Allow-Methods: *");

$this->_timeout(60);
$this->_ignoreUserAbort(true);

//Determine the format in which to return the data, default is JSON
self::$srtFormat = (array_key_exists('format',$_REQUEST)) ? $_REQUEST['format'] : strtolower(self::$srtFormat);
//Determine the format in which to return the data, default is JSON
self::$srtFormat = (array_key_exists('format',$_REQUEST)) ? $_REQUEST['format'] : strtolower(self::$srtFormat);

return $this->_auth();
return $this->_auth();
}

/**
* Standard function to validate the Auth Key and connection IP address to ensure that access has been granted
*/
/**
* Open REST dosnt require any auth but this function is needed for RESTKey and RESTUser
* @return bool
*/
public function _auth(){

//Basic Auth is an API key, BaseRESTUser has a more advance auth
self::$blRequestHeaderAuth = \Twist::framework()->setting('API_REQUEST_HEADER_AUTH');

self::$srtApiKey = (self::$blRequestHeaderAuth) ? $_SERVER['HTTP_AUTH_KEY'] : $_REQUEST[(array_key_exists('Auth-Key',$_REQUEST)) ? 'Auth-Key' : 'auth-key'];
self::$arrKeyInfo = \Twist::Database()->records(TWIST_DATABASE_TABLE_PREFIX.'apikeys')->get(self::$srtApiKey,'key',true);

if(count(self::$arrKeyInfo) == 0){
//Invalid API Key
return $this->_respondError('Unauthorized Access: Invalid API key passed',401);

}elseif(self::$arrKeyInfo['enabled'] == '0'){
//Disabled API key
return $this->_respondError('Disabled: API key has been disabled',401);

}elseif(self::$arrKeyInfo['allowed_ips'] != '' && !in_array($_SERVER['REMOTE_ADDR'],explode(',',self::$arrKeyInfo['allowed_ips']))){
//Invalid IP address
return $this->_respondError('Forbidden: you IP address is not on the allowed list',403);
}

return true;
return true;
}

/**
* The main response of the controller, treat this function as though it where an index.php file.
*/
/**
* The main response of the controller, treat this function as though it where an index.php file.
*/
public function _index(){
return $this->_respond('Welcome: API connection successful',1);
return $this->_respond('Welcome: API connection successful',1);
}

/**
* This is the function that will be called in the even that Routes was unable to find a exact controller response.
*/
public function _fallback(){
return $this->_respondError('Invalid function called',404);
}

/**
* This is the function that will be called in the even that Routes was unable to find a exact controller response.
*/
public function _fallback(){
return $this->_respondError('Invalid function called',404);
}

/**
* Successful response to an API call should be used to return a standardised RESTful success response
* @param mixed $mxdResults Results of the function call to be returned to the user
* @param int $intCount Number of results returned by the function call
* @param int $intResponseCode HTTP response code for the call
*/
/**
* Successful response to an API call should be used to return a standardised RESTful success response
* @param mixed $mxdResults Results of the function call to be returned to the user
* @param int $intCount Number of results returned by the function call
* @param int $intResponseCode HTTP response code for the call
*/
public function _respond($mxdResults,$intCount = 1,$intResponseCode = 200){

header(sprintf("HTTP/1.1 %s %s",$intResponseCode,Error::responseInfo($intResponseCode)));

$strOutput = '';
$arrOut = array(
'status' => 'success',
'format' => self::$srtFormat,
'count' => $intCount,
'results' => $mxdResults
);

if(self::$srtFormat == 'json'){
header("Content-type: application/json");
$strOutput = json_encode($arrOut);
}elseif(self::$srtFormat == 'xml'){
header("Content-type: text/xml");
$strOutput = \Twist::XML()->arrayToXML($arrOut);
}

return $strOutput;
header(sprintf("HTTP/1.1 %s %s",$intResponseCode,Error::responseInfo($intResponseCode)));

$strOutput = '';
$arrOut = array(
'status' => 'success',
'format' => self::$srtFormat,
'count' => $intCount,
'results' => $mxdResults
);

if(self::$srtFormat == 'json'){
header("Content-type: application/json");
$strOutput = json_encode($arrOut);
}elseif(self::$srtFormat == 'xml'){
header("Content-type: text/xml");
$strOutput = \Twist::XML()->arrayToXML($arrOut);
}

return $strOutput;
}

/**
* Error response to an API call should be used to return a standardised RESTful error response
* @param string $strErrorMessage Error message to indicate what when wrong
* @param int $intResponseCode HTTP response code for the call
*/
public function _respondError($strErrorMessage,$intResponseCode = 404){

header(sprintf("HTTP/1.1 %s %s",$intResponseCode,Error::responseInfo($intResponseCode)));

$strOutput = '';
$arrOut = array(
'status' => 'error',
'error' => $strErrorMessage,
'count' => 0,
'format' => self::$srtFormat,
);

if(self::$srtFormat == 'json'){
header("Content-type: application/json");
$strOutput = json_encode($arrOut);
}elseif(self::$srtFormat == 'xml'){
header("Content-type: text/xml");
$strOutput = \Twist::XML()->arrayToXML($arrOut);
}

return $strOutput;
}
/**
* Error response to an API call should be used to return a standardised RESTful error response
* @param string $strErrorMessage Error message to indicate what when wrong
* @param int $intResponseCode HTTP response code for the call
*/
public function _respondError($strErrorMessage,$intResponseCode = 404){

header(sprintf("HTTP/1.1 %s %s",$intResponseCode,Error::responseInfo($intResponseCode)));

$strOutput = '';
$arrOut = array(
'status' => 'error',
'error' => $strErrorMessage,
'count' => 0,
'format' => self::$srtFormat,
);

if(self::$srtFormat == 'json'){
header("Content-type: application/json");
$strOutput = json_encode($arrOut);
}elseif(self::$srtFormat == 'xml'){
header("Content-type: text/xml");
$strOutput = \Twist::XML()->arrayToXML($arrOut);
}

return $strOutput;
}

}
83 changes: 83 additions & 0 deletions dist/twist/Core/Controllers/BaseRESTKey.controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/**
* TwistPHP - An open source PHP MVC framework built from the ground up.
* Copyright (C) 2016 Shadow Technologies Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Shadow Technologies Ltd. <contact@shadow-technologies.co.uk>
* @license https://www.gnu.org/licenses/gpl.html GPL License
* @link https://twistphp.com
*/

namespace Twist\Core\Controllers;
use Twist\Classes\Error;

/*
* An REST API base controller (basic API Key auth) that can be used instead of Base when adding REST API support to your site. This controller should be used as an extension to a route controller class.
* See twistphp.com/examples for a full guide on RESTful routing
*
* @package Twist\Core\Controllers
*/
class BaseRESTKey extends BaseREST{

protected static $blRequestHeaderAuth = true;
protected static $srtApiKey = '';
protected static $arrKeyInfo = array();

/**
* Default functionality for every request that is made though the REST API. Every call must be authenticated.
*/
public function _baseCalls(){

$mxdResponse = parent::_baseCalls();

return ($mxdResponse === true || is_null($mxdResponse)) ? $this->_auth() : $mxdResponse;
}

/**
* Standard function to validate the Auth Key and connection IP address to ensure that access has been granted
*/
public function _auth(){

$mxdResponse = parent::_auth();

if($mxdResponse === true || is_null($mxdResponse)){

//Basic Auth is an API key, BaseRESTUser has a more advance auth
self::$blRequestHeaderAuth = \Twist::framework()->setting('API_REQUEST_HEADER_AUTH');

self::$srtApiKey = (self::$blRequestHeaderAuth) ? $_SERVER['HTTP_AUTH_KEY'] : $_REQUEST[(array_key_exists('Auth-Key',$_REQUEST)) ? 'Auth-Key' : 'auth-key'];
self::$arrKeyInfo = \Twist::Database()->records(TWIST_DATABASE_TABLE_PREFIX.'apikeys')->get(self::$srtApiKey,'key',true);

if(count(self::$arrKeyInfo) == 0){
//Invalid API Key
return $this->_respondError('Unauthorized Access: Invalid API key passed',401);

}elseif(self::$arrKeyInfo['enabled'] == '0'){
//Disabled API key
return $this->_respondError('Disabled: API key has been disabled',401);

}elseif(self::$arrKeyInfo['allowed_ips'] != '' && !in_array($_SERVER['REMOTE_ADDR'],explode(',',self::$arrKeyInfo['allowed_ips']))){
//Invalid IP address
return $this->_respondError('Forbidden: you IP address is not on the allowed list',403);
}

return true;
}

return $mxdResponse;
}
}
41 changes: 23 additions & 18 deletions dist/twist/Core/Controllers/BaseRESTUser.controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*
* @package Twist\Core\Controllers
*/
class BaseRESTUser extends BaseREST{
class BaseRESTUser extends BaseRESTKey{

protected static $srtSessionToken = '';
protected static $arrSessionData = array();
Expand All @@ -44,30 +44,35 @@ class BaseRESTUser extends BaseREST{
public function _auth(){

//Call the default API key and IP restrictions before validating the users session
parent::_auth();
$mxdResponse = parent::_auth();

//Basic Auth is an API key, BaseRESTUser has a more advance auth
self::$srtSessionToken = (self::$blRequestHeaderAuth) ? $_SERVER['HTTP_AUTH_TOKEN'] : $_REQUEST[(array_key_exists('Auth-Token',$_REQUEST)) ? 'Auth-Token' : 'auth-token'];
if($mxdResponse === true || is_null($mxdResponse)){

//If a session key is set try to validate the session
if(self::$srtSessionToken != ''){
//Basic Auth is an API key, BaseRESTUser has a more advance auth
self::$srtSessionToken = (self::$blRequestHeaderAuth) ? $_SERVER['HTTP_AUTH_TOKEN'] : $_REQUEST[(array_key_exists('Auth-Token',$_REQUEST)) ? 'Auth-Token' : 'auth-token'];

\Twist::Session()->data('user-session_key',self::$srtSessionToken);
//If a session key is set try to validate the session
if(self::$srtSessionToken != ''){

self::$arrSessionData = Auth::current(false);
if(count(self::$arrSessionData) && self::$arrSessionData['status'] == true){
\Twist::Session()->data('user-session_key',self::$srtSessionToken);

//Valid user has been detected, allow the controller to continue
return true;
}
self::$arrSessionData = Auth::current(false);
if(count(self::$arrSessionData) && self::$arrSessionData['status'] == true){

//Error user is not logged in
return $this->_respondError('Unauthorized Access: Invalid auth token provided',401);
}
//Valid user has been detected, allow the controller to continue
return true;
}

//Error user is not logged in
return $this->_respondError('Unauthorized Access: Invalid auth token provided',401);
}

//If no session key has been passed in then try to authenticate the user
//Every possible outcome of this function call will end the script here
return $this->_authenticate();
}

//If no session key has been passed in then try to authenticate the user
//Every possible outcome of this function call will end the script here
return $this->_authenticate();
return $mxdResponse;
}

/**
Expand Down
Loading

0 comments on commit 582db41

Please sign in to comment.