Yii2: How to add separate api module in root directory? - rest

I have yii2 basic project with working web application functionality and now i want to add api functionality for this application.Currently i have directory stucture as
root
+ api
+ config
+ modules
+ v1
+ controllers
+.htaccess
+index.php
+index.php
+.htaccess
+ web
+ config
+ controllers
...
Now i am requesting /api/v1/controller/action but is getting 404 not found as response. Anything i have to configure?

If you have set up everything correctly and added the new api alias in the common/bootstrap.php file like Yii::setAlias('api', dirname(dirname(__DIR__)) . '/api');, you need to define the rules under urlManager in order to access the specific controller action inside your api/config/main.php.
For example I have a controller inside the api/modules/v1/controller/ with the name Lead and have two actions with the name actionTest() and actionLists() and i want to be able to send POST request to the actionLists() and GET request to the actionTest() then i will define them in the UrlManager like below
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'pluralize' => false,
'controller' => 'v1/lead',
'tokens' => [
'{id}' => '<id:\\w+>'
],
'extraPatterns' => [
'POST create' => 'create',
'GET test' => 'test'
]
],
]
]
Now I can send POST request to http://example.com/api/v1/lead/list and GET request to http://example.com/api/v1/lead/test?id=1234
Note: Notice the 'pluralize'=>false for the rule if no set you will notice the controller ID lead appears in plural form as leads in the endpoint URLs. This is because yii\rest\UrlRule automatically pluralizes controller IDs when creating child URL rules. You may disable this behavior by setting yii\rest\UrlRule::$pluralize to be false.

Related

Backend module: Link to another backend module in TYPO3 9

Let's say I have to different extensions with two different backend modules. Registered like:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
'Vendor.ext',
'ext',
'controller1',
'',
[
'Controller1' => 'any1',
],
[
'access' => 'user,group',
'icon' => '...',
'labels' => '...',
]
);
And in the second extension also like:
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule(
'Vendor.ext2',
'ext2',
'controller2',
'',
[
'Controller2' => 'any2',
],
[
'access' => 'user,group',
'icon' => '...',
'labels' => '...',
]
);
How can I build a link from ext1 in the module to ext2?
What did I tried before in FLUID was:
<f:link.action action="any2" controller="Controller2" extensionName="ext">click me</f:link.action>
or
<f:be.link route="/ext/Ext2Controller2/">click me</f:be.link> (by copying the route that's available via GET parameter)
No luck yet - any ideas? Or how to get the correct route if be.link would be the correct function?
Finally I found the reason.
It's simply possible to use the existing viewhelper like <f:be.link route="lux_LuxLeads">click me</f:be.link>
But the route must be the key and not the path. The key can be picked in the backend module configuration and backendroutes

urlManager can't find site/index in Yii2

I just create a Basic App schema in Yii 2.
I try to test RESTFull api.
The site is working, by default, but when I change the urlManager
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'cliente'],
],
],
I only get 404 error.
I lost site/index!!!
Any idea?
It is this setting:
'enableStrictParsing' => true,
Look here:
https://github.com/yiisoft/yii2/blob/master/framework/web/UrlManager.php#L323
There are no explicit url rules for the siteController defined.
Read more here:
https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#url-rules
site/index action no longer works because of this setting: 'enableStrictParsing' => true. From $enableStrictParsing documentation:
If strict parsing is enabled, the incoming requested URL must match at least one of the $rules in order to be treated as a valid request. Otherwise, the path info part of the request will be treated as the requested route.
So if you enable this setting, you need to have matching URL rule to support given URL. In your case, you have only one rule for REST endpoint, so any other URL will not work. You should either disable this setting or add rule for your main page:
'rules' => [
'' => 'site/index',
['class' => 'yii\rest\UrlRule', 'controller' => 'cliente'],
],

How to check if authenticated user is handler of REST resourece

I've developing a REST service on Yii2 and Angular 2 client. Using Bearer JWT authentication.
For example there is a uri: http://127.0.0.1/v1/accounts/123456/meters, which should return all user's meters by account, which he own.
Applied router rule:
'<accountId:\w+>/<action:[\w-]+>' => '<action>',
Controllers has following behaviors:
'authenticator' => [
'class' => HttpBearerAuth::className(),
'except' => ['options']
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['meters'],
'roles' => ['#'],
]
]
]
Action AccountController::actionMeters looks:
public function actionMeters($accountId)
{
// Call MS SQL procedure
$meters = Yii::$app->db->createCommand("EXEC [getMetersByAccountId] :accountId")->bindValue(':accountId', $accountId)->queryAll()
return $meters;
}
But in this way authenticated user can get (if modify GET accountId parameter) meters, which belongs to another user.
I have a user_account table in database, which link users and accounts, but I don't know in which place of application should I perform a checking properly.
How to make a check if authenticated user has an access to this resource by specified accountId parameter?
Thank you.
I've found solution to determine matchCallback in access rule. Now it's look:
[
'allow' => true,
'actions' => ['meters'],
'roles' => ['#'],
'matchCallback' => function() {
return Yii::$app->user->identity->user->hasAccount(Yii::$app->request->get('accountId'));
}
],
And define hasAccount method in User model:
public function hasAccount($accountId) {
return $this->hasOne(UserAccount::className(), ['user_id' => 'id'])->where(['account_id' => $accountId])->exists();
}
It's work correct. Is it a proper solution?

Yii 2 redirecting to Login if Guest visit the website

I need some advice how to make redirecting to login if someone does not login into the website and he is only Guest
use Yii;
use \yii\helpers\Url;
if ( Yii::$app->user->isGuest )
return Yii::$app->getResponse()->redirect(array(Url::to(['site/login'],302)));
Use can use it in actions or views , but if you need to use it in lots of actions you probably need look at AccessControl and restrict access even before action is fired
There are two options:
You can use the AccessControl as mentioned by #Maksym Semenykhin
You can use the option below especially when you would like the logged user to be returned to this page after login.
public function beforeAction($action){
if (parent::beforeAction($action)){
if (Yii::$app->user->isGuest){
Yii::$app->user->loginUrl = ['/auth/default/index', 'return' => \Yii::$app->request->url];
return $this->redirect(Yii::$app->user->loginUrl)->send();
}
}}
You can also create a custom 'Controller' class which inherits \yii\web\Controller then have all controllers that need authorization inherit your custom controller.
On the login function, replace the redirect part with the following code:
$return_url = empty(Yii::$app->request->get('return'))? \yii\helpers\Url::to(['/admin/default/index']) :Yii::$app->request->get('return');
return $this->redirect($return_url);
Use the access section to set access to various actions in the controller.
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
'access' => [
'class' => \yii\filters\AccessControl::className(),
'only' => ['create', 'update','index'],
'rules' => [
// deny all POST requests
[
'allow' => false,
'verbs' => ['POST']
],
// allow authenticated users
[
'allow' => true,
'roles' => ['#'],
],
// everything else is denied
],
],
];
}
works for me.
use Yii;
use \yii\helpers\Url;
if ( Yii::$app->user->isGuest )
return Yii::$app->getResponse()->redirect(array(Url::to(['site/login'])));
The Access Control Filter will do the work for you and redirects you to the configured user->loginUrl (config/main.php) if an action is not allowed.
Add the rule:
array('deny',
'users'=>array('?'),
),
To your base controller (f.e. ‘Controller’) where all your controllers are inherited from.
I used index.php in my web/admin directory
This is the sample my index.php
<?php
// comment out the following two lines when deployed to production
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require __DIR__ . '/../../vendor/autoload.php';
require __DIR__ . '/../../vendor/yiisoft/yii2/Yii.php';
$config = require __DIR__ . '/../../config/web.php';
$config["controllerNamespace"]='app\controllers\backend';
(new yii\web\Application($config))->run();
if(Yii::$app->user->isGuest){
$request_headers = apache_request_headers();
$srv=$request_headers['Host'];
header("Location: https://".$srv);
die();
}

Yii2 REST ful Api how to send status code

Yii2 Restful API
In the above link they mention for GET Search method , Please anyone tell me for like POST create and PUT Update ...
In main.config under rules i created like,
['class' => 'yii\rest\UrlRule', 'controller' => 'v1/lkup-access-profile','extraPatterns' => ['POST create' => 'create']],
But its comes error as Method Not Allowed. This url can only handle the following request methods: POST.
yii\rest\UrlRule will create default REST URLs and actions. There's no need to add 'extraPatterns' => ['POST create' => 'create']. It's already built in. Check out the docs http://www.yiiframework.com/doc-2.0/yii-rest-urlrule.html
Use extraPatterns to extend default routes for controller. For example
['class' => 'yii\rest\UrlRule', 'controller' => 'v1/invite',
'extraPatterns' => [
'PUT {id}/accept' => 'accept',
'PUT {id}/reject' => 'reject',
],
],