Kohana rest api implementaion: how to start with SupersonicAds/kohana-restful-api? - rest

I am new to kohana framework. I need to implement rest api for my application.
I have downloded rest api from https://github.com/SupersonicAds/kohana-restful-api and placed in my localhost. Under modules. now the file structre is
I have enabled module in bootstrap.php as
Kohana::modules(array(
'auth' => MODPATH.'auth', // Basic authentication
'rest' => MODPATH.'rest', // Basic Rest example
// 'cache' => MODPATH.'cache', // Caching with multiple backends
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
'database' => MODPATH.'database', // Database access
// 'image' => MODPATH.'image', // Image manipulation
// 'minion' => MODPATH.'minion', // CLI Tasks
'orm' => MODPATH.'orm', // Object Relationship Mapping
// 'unittest' => MODPATH.'unittest', // Unit testing
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
));
i have created a controller by extending "Controller_Rest" Now according to wiki i should be able to access "$this->_user, $this->_auth_type and $this->_auth_source" variables but in my case its not happening what i am doing wrong?
And i checked in console network it always showing status as "401 Unauthorised"

For using Authorization,you need to extend Kohana_RestUser Class
The module you are using comes with an abstract Kohana_RestUser class, which you must extend in your app. The only function that requires implementation is the protected function _find(). The function's implementation is expected to load any user related data, based on an API key.
I will explain you with an example
<?php
// Model/RestUser.php
class RestUser extends Kohana_RestUser {
protected $user='';
protected function _find()
{
//generally these are stored in databases
$api_keys=array('abc','123','testkey');
$users['abc']['name']='Harold Finch';
$users['abc']['roles']=array('admin','login');
$users['123']['name']='John Reese';
$users['123']['roles']=array('login');
$users['testkey']['name']='Fusco';
$users['testkey']['roles']=array('login');
foreach ($api_keys as $key => $value) {
if($value==$this->_api_key){
//the key is validated which is authorized key
$this->_id = $key;//if this not null then controller thinks it is validated
//$this->_id must be set if key is valid.
//setting name
$this->user = $users[$value];
$this->_roles = $users[$value]['roles'];
break;
}
}
}//end of _find
public function get_user()
{
return $this->name;
}
}//end of RestUser
Now Test Controller
<?php defined('SYSPATH') or die('No direct script access.');
//Controller/Test.php
class Controller_Test extends Controller_Rest
{
protected $_rest;
// saying the user must pass an API key.It is set according to the your requirement
protected $_auth_type = RestUser::AUTH_TYPE_APIKEY;
// saying the authorization data is expected to be found in the request's query parameters.
protected $_auth_source = RestUser::AUTH_SOURCE_GET;//depends on requirement/coding style
//note $this->_user is current Instance of RestUser Class
public function before()
{
parent::before();
//An extension of the base model class with user and ACL integration.
$this->_rest = Model_RestAPI::factory('RestUserData', $this->_user);
}
//Get API Request
public function action_index()
{
try
{
$user = $this->_user->get_name();
if ($user)
{
$this->rest_output( array(
'user'=>$user,
) );
}
else
{
return array(
'error'
);
}
}
catch (Kohana_HTTP_Exception $khe)
{
$this->_error($khe);
return;
}
catch (Kohana_Exception $e)
{
$this->_error('An internal error has occurred', 500);
throw $e;
}
}
//POST API Request
public function action_create()
{
//logic to create
try
{
//create is a method in RestUserData Model
$this->rest_output( $this->_rest->create( $this->_params ) );
}
catch (Kohana_HTTP_Exception $khe)
{
$this->_error($khe);
return;
}
catch (Kohana_Exception $e)
{
$this->_error('An internal error has occurred', 500);
throw $e;
}
}
//PUT API Request
public function action_update()
{
//logic to create
}
//DELETE API Request
public function action_delete()
{
//logic to create
}
}
Now RestUserData Model
<?php
//Model/RestUserData.php
class Model_RestUserData extends Model_RestAPI {
public function create($params)
{
//logic to store data in db
//You can access $this->_user here
}
}
So index.php/test?apiKey=abc returns
{
"user": {
"name": "Harold Finch",
"roles": [
"admin",
"login"
]
}
}
Note: K in apiKey is Capital/UpperCase
I Hope this Helps
Happy Coding :)

Related

Omnipay Paypal set store name and logo (Laravel)

How can I set the store name and logo using the Omnipay Paypal package for Laravel?
Please see my code below, until now I tried to use the method setBrandName on the gateway variable, but this method was not found. It seems like the class ExpressCheckout has such methods but is like deprecated and one should use this code and checkout procedure. Also tried to add entry to the purchase method array parameter but it didn't work.
<?php
namespace App\Http\Controllers;
..
use Omnipay\Omnipay;
class PurchaseController extends Controller
{
public $gateway;
public function __construct()
{
$this->gateway = Omnipay::create('PayPal_Rest');
$this->gateway->setClientId(...);
$this->gateway->setSecret(...);
$this->gateway->setTestMode(true);
}
protected function makePurchase(Request $request) {
try {
$items = ...;
$response = $this->gateway->purchase(array(
'amount' => $cart->getSum(),
'items' => $items,
'currency' => config('paypal.currency'),
'returnUrl' => route('payment.success'),
'cancelUrl' => route('cart'),
))->send();
if ($response->isRedirect()) {
$response->redirect(); // this will automatically forward the customer
} else {
// not successful
return $response->getMessage() . ", " . $response->getCode();
}
} catch(Exception $e) {
return $e->getMessage();
}
}
protected function purchaseCompleted(Request $request) {
...
}
}

How to get the image url from a gallery in SonataMediaBundle, for use with FOSRestBundle?

I'm working on a mobile app that has to show some images of houses from a server. I have installed Symfony2, FOSRestBundle and Sonata Media Bundle for the backend.
In order to get the houses images URLs, I have configured FOSRestBundle for an entity named Property which has a gallery field. This is the REST controller
class PropertiesController extends FOSRestController
{
public function getPropertiesAction()
{
$response = $this->getDoctrine()->getRepository('ComissionBundle:Property')->findAll();
if ($response == null){
return "No properties";
}
else{
return $response;
}
}
}
But i get this:
[
{
"id":2,
"name":"test",
"city":"test",
"address":"test",
"sector":"test",
"area":0,
"rooms":112343,
"price":0,
"gallery":{
"context":"default",
"name":"test",
"enabled":false,
"updated_at":"2016-08-26T17:18:51+0200",
"created_at":"2016-08-26T17:18:51+0200",
"default_format":"default_small",
"id":1
}
}
]
As you can see, there are no media objects.
Then, I tried with a customized repository method:
class PropertyRepository extends EntityRepository
{
public function findMainInfoElements($elements)
{
$em = $this->getEntityManager();
$queryText = "SELECT u, g, h FROM ComissionBundle:Property u JOIN u.gallery g JOIN g.galleryHasMedias h";
$query = $em->createQuery($queryText);
return $query->setMaxResults($elements)->getResult();
}
}
but the result is the same.
How can i get the URLs from the gallery in order to show them in the mobile app? (Especially the thumb images that Sonata Media Bundle generates, which are better for the app performance)
I guess you should join the galleryHasMedia entity with the Media entity too in the PropertyRepository query, but it will not be enough.
You should create a custom serialization handler for the Media entity too.
Declare the serialization handler
myapp.serialization.media_handler:
class: Path\ToYourApp\Serializer\MediaSerializationHandler
tags:
- { name: jms_serializer.handler, type: Path\ToYourMedia\Entity\Media, direction: serialization, format: json, method: serializeMedia }
arguments: [ #sonata.media.provider.image, #sonata.media.provider.file ]
Create the serialization handler
<?php
namespace Camelot\Social\ApiBundle\Serializer;
use Path\ToYourMedia\Entity\Media;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Context;
use Sonata\MediaBundle\Provider\ImageProvider;
use Sonata\MediaBundle\Provider\FileProvider;
class MediaSerializationHandler
{
/**
* #var ImageProvider
*/
private $imageProvider;
/**
* #var FileProvider
*/
private $fileProvider;
public function __construct(ImageProvider $imageProvider, FileProvider $fileProvider)
{
$this->imageProvider = $imageProvider;
$this->fileProvider = $fileProvider;
}
public function serializeMedia(JsonSerializationVisitor $visitor, Media $media, array $type, Context $context)
{
switch ($media->getProviderName()) {
case 'sonata.media.provider.file':
$serialization = $this->serializeFile($media);
break;
case 'sonata.media.provider.image':
$serialization = $this->serializeImage($media);
break;
default:
throw new \RuntimeException("Serialization media provider not recognized");
}
if ($visitor->getRoot() === null) {
$visitor->setRoot($serialization);
}
return $serialization;
}
private function serializeImage(Media $media)
{
// here you can provide one ore more URLs based on your SonataMedia configuration
// you can also add some more properties coming from the media entity based on your needs (e.g. authorName, description, copyright etc)
return [
"url" => [
"orig" => $this->imageProvider->generatePublicUrl($media, "reference"),
"small" => $this->imageProvider->generatePublicUrl($media, "default_small"),
"big" => $this->imageProvider->generatePublicUrl($media, "default_big"),
]
];
}
private function serializeFile(Media $media)
{
return [
"name" => $media->getName(),
"size" => $media->getSize(),
"url" => $this->fileProvider->generatePublicUrl($media, 'reference')
];
}
}

Zend Framework 1.12 plugin for checking "Authorization" header

I'm writing REST api using Zend Framework 1.12. I want to check "Authorization" header in controller plugin.
I put code in the preDispatch action of the plugin
$authorizationHeader = $request->getHeader('Authorization');
if(empty($authorizationHeader)) {
$this->getResponse()->setHttpResponseCode(400);
$this->getResponse()->setBody('Hello');
die(); //It doesn't work
}
The problem is that after it controller's action is still being called. I tried 'die()', 'exit'. My question is how to return response from plugin and do not call controller's action.
Did a similar REST API with Zend several weeks ago with this approach:
Class Vars/Consts:
protected $_hasError = false;
const HEADER_APIKEY = 'Authorization';
My preDispatch:
public function preDispatch()
{
$this->_apiKey = ($this->getRequest()->getHeader(self::HEADER_APIKEY) ? $this->getRequest()->getHeader(self::HEADER_APIKEY) : null);
if (empty($this->_apiKey)) {
return $this->setError(sprintf('Authentication required!'), 401);
}
[...]
}
My custom setError Function:
private function setError($msg, $code) {
$this->getResponse()->setHttpResponseCode($code);
$this->view->error = array('code' => $code, 'message' => $msg);
$this->_hasError = true;
return false;
}
Then simply check if a error has been set inside your functions:
public function yourAction()
{
if(!$this->_hasError) {
//do stuff
}
}
If you're using contextSwitch and JSON, then your array with errors will be automatically returned & displayed, if an error occours:
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$this->_helper->contextSwitch()->initContext('json');
[...]
}
Hope this helps
Since checking headers is typically a low level request operation, you could do the header verification and then throw an exception if not valid in dispatchLoopStartup of the plugin. Then in your error controller, return the appropriate response. This would prevent the action from being dispatched/run and could be applied to any controller/action without modifying any controller code.
Controller plugin:
class AuthHeader extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(\Zend_Controller_Request_Abstract $request)
{
// Validate the header.
$authorizationHeader = $request->getHeader('Authorization');
if ($invalid) {
throw new Zend_Exception($error_message, $error_code);
}
}
}
Error handler:
class ErrorController extends Zend_Controller_Action
{
public function init()
{
// Enable JSON output for API originating errors.
if ($this->isApiRequest($this->getRequest())) {
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('error', 'json')
->setAutoJsonSerialization(true)
->initContext('json');
}
}
public function errorAction()
{
// Handle authorization header errors
// ...
// Handle errors
// ...
}
public function isApiRequest($request)
{
// Determine if request is an API request.
// ...
}
}

How to get the Request object from the ServiceManger in Zend Framework 2?

I'm developing a RESTful application and I want to build a factory that creates the proper ViewModel (Zend\View\Model\ViewModel, Zend\View\Model\JsonModel, my XmlModel) object dependent on the Accept (e.g. -H 'Accept: application/json') parameter in the HTTP request header. I want to implement this as a callback:
class Module implements ServiceProviderInterface
{
...
public function getServiceConfig() {
try {
return array (
'factories' => array(
'RestViewModel' => function($serviceManager) {
// Here I need the the Request object.
$requestHeadAccept = $requestObject->getHeaders()->get('Accept')->toString();
$return = null;
if (strpos($requestHeadAccept, 'application/json') != -1) {
$return = new JsonModel(array('data' => $data));
} elseif (strpos($requestHeadAccept, 'application/xml') != -1) {
...
} else {
...
}
return $return;
}
)
);
} catch (\Exception $e) {
...
}
}
...
}
How can I get the Request object at this place?
The short answer: the request is registered as Request:
$request = $serviceManager->get('Request');
However, what you aims to achieve is not a piece that belongs to the service manager's factories. It is a context dependant factory required in the controller domain. Therefore, I would create is as a controller plugin.
And to be honest, this feature is already available in ZF2 via an existing controller plugin called acceptableViewModelSelector. An example is available at the manual but this would be the scenario in your case:
use Zend\Mvc\Controller\AbstractActionController;
class SomeController extends AbstractActionController
{
protected $acceptCriteria = array(
'Zend\View\Model\JsonModel' => array(
'application/json',
),
'My\View\XmlModel' => array(
'application/xml',
),
);
public function apiAction()
{
$model = $this->acceptableViewModelSelector($this->acceptCriteria);
}
}
Then you will get either a JsonModel, XmlModel or by default the ViewModel.
Creating and Registering Alternate Rendering and Response Strategies
http://framework.zend.com/manual/2.0/en/modules/zend.view.quick-start.html#creating-and-registering-alternate-rendering-and-response-strategies

need to test functionality with oracle stored proc

i have code like this:
protected function _checkUserVisibility()
{
try {
if (!$params->getUsrParametr(self::ACTIVE_FIF)) { // calling oracle stored proc
throw new Unitex_Exception('ALARM');
}
}
catch (Exception $e) {
$this->logOut();
throw $e;
}
}
this func caled from another one (and so on).
a a question:
how to get worked unit test for that parts of code?
EDIT1:
firstly taked hehe http://framework.zend.com/manual/1.12/en/zend.test.phpunit.html
than improoved (hope)
test proc is:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase {
..........
public function testLoginAction()
{
$request = $this->getRequest();
$request->setMethod('POST')
->setHeader('X_REQUESTED_WITH', 'XMLHttpRequest')
->setPost(array(
'user' => 'test_user',
'password' => 'test_pwd',
));
$filialId = 1;
$stmt1 = Zend_Test_DbStatement::createUpdateStatement();
$this->getAdapter()->appendStatementToStack($stmt1);
$this->getAdapter()->appendStatementToStack($stmt1);
$this->getAdapter()->appendStatementToStack($stmt1);
$this->getAdapter()->appendStatementToStack($stmt1);
$stmt1Rows = array(array('IRL_ALIAS' => 'RO_COMMON', 'ISADM' => 'N'));
$stmt1 = Zend_Test_DbStatement::createSelectStatement($stmt1Rows);
$this->getAdapter()->appendStatementToStack($stmt1);
$this->dispatch('/user/login');// <-- crash here
$this->assertController('user');
$this->assertAction('login');
$this->assertNotRedirect();
$this->_getResponseJson();
}
In your unit test definitly you don't want any database interaction. The answer for your question is use stub for db functionality.
Let say that $params is property of SomeClass contains getUsrParametr which for example gets something from database. You're testing _checkUserVisibility method so you don't care about what are happening in SomeClass. That's way you test will look something like that:
class YourClass
{
protected $params;
public function __construct(SomeClass $params)
{
$this->params = $params;
}
public function doSomething()
{
$this->_checkUserVisibility();
}
protected function _checkUserVisibility()
{
try {
if (!$this->params->getUsrParametr(self::ACTIVE_FIF)) { // calling oracle stored proc
throw new Unitex_Exception('ALARM');
}
}
catch (Exception $e) {
$this->logOut();
throw $e;
}
}
}
And the unit test of course the only method you test is the public one, but you cover protected method through testing public one.
public function testDoSomethingAlarm()
{
// set expected exception:
$this->setExpectedException('Unitex_Exception', 'ALARM');
// create the stub
$params = $this->getMock('SomeClass', array('getUsrParametr'));
// and set desired result
$params->expects($this->any())
->method('getUsrParametr')
->will($this->returnValue(false));
$yourClass = new YourClass($params);
$yourClass->doSomething();
}
And the second test which test case if getUsrParametr will returns true:
public function testDoSomethingLogout()
{
// set expected exception:
$this->setExpectedException('SomeOtherException');
// create the stub
$params = $this->getMock('SomeClass', array('getUsrParametr'));
// set throw desired exception to test logout
$params->expects($this->any())
->method('getUsrParametr')
->will($this->throwException('SomeOtherException'));
// now you want create mock instead of real object beacuse you want check if your class will call logout method:
$yourClass = $this->getMockBuilder('YourClass')
->setMethods(array('logOut'))
->setConstructorArgs(array($params))
->getMock();
// now you want ensure that logOut will be called
$yourClass->expects($this->once())
->method('logOut');
// pay attention that you've mocked only logOut method, so doSomething is real one
$yourClass->doSomething();
}
If you're using PHP 5.3.2+ with PHPUnit, you can test your private and protected methods by using reflection to set them to be public prior to running your tests, otherwise you test protected/private methods by properly testing the public methods that use the protected/private methods. Generally speaking the later of the two options is generally how you should do it, but if you want to use reflection, here's a generic example:
protected static function getMethod($name) {
$class = new ReflectionClass('MyClass');
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
public function testFoo() {
$foo = self::getMethod('foo');
$obj = new MyClass();
$foo->invokeArgs($obj, array(...));
...
}

Categories