I'm install 2amigos/yii2-usuario:~1.5.1 on a yii2-basic-template, using https://yii2-usuario.readthedocs.io/en/latest/. However, it returns this error (Getting unknown property: Da\User\Module::isGuest yii2-usuario) in any view.
My config/console.php:
'components' => [
...
'authManager' => [
'class'=> 'yii\rbac\DbManager',
],
...
],
'controllerMap' => [
'migrate' => [
'class' => \yii\console\controllers\MigrateController::class,
'migrationPath' => [
'#app/migrations',
'#yii/rbac/migrations', // Just in case you forgot to run it on console (see next note)
],
'migrationNamespaces' => [
'Da\User\Migration',
],
],
],
My config/web.php:
'components' => [
...
'user' => [
'class' => Da\User\Module::class,
'classMap' => [
'User' => app\models\User::class,
],
],
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
'view' => [
'theme' => [
'pathMap' => [
'#Da/User/resources/views' => '#app/views/user'
]
]
]
],
I managed to solve it with help.
Follow the line:
Remove : config/web.php
'user' => [
'identityClass' => 'app\models\Users',
'enableAutoLogin' => true,
'enableSession' => true,
],
'user-management' => [
'class' => 'webvimark\modules\UserManagement\UserManagementModule',
'on beforeAction'=>function(yii\base\ActionEvent $event) {
if ( $event->action->uniqueId == 'user-management/auth/login' ){
$event->action->controller->layout = 'loginLayout.php';
};
},
],
add into config/web.php:
'components' =>[ ...
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
'view' => ['theme' => [ 'pathMap' => ['#Da/User/resources/views' => '#app/views/user']]] //If your view is modified.
]
'modules' => ['user' => [
'class' => \Da\User\Module::class,
'allowAccountDelete' => true,
'enableRegistration' => false,
'administratorPermissionName' => 'user-management']
...]
``
Here's urlManager configs:
return [
'class' => \yii\web\UrlManager::class,
'enablePrettyUrl' => true,
'showScriptName' => false,
'baseUrl' => '',
'rules' => [
'page/<id:[\\w-_]+>' => 'page/index',
],
];
Here's urlManager using:
$menuItems = [
[
'label' => 'Home',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page']),
],
[
'label' => 'About',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page', 'id' => 'about']),
],
[
'label' => 'Contact',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page', 'id' => 'contact']),
],
];
And here's results from browser:
http://localhost/page?id=about
http://localhost/page?id=contact
What's wrong in my code?
You need to use exact route when creating URLs:
$menuItems = [
[
'label' => 'Home',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page']),
],
[
'label' => 'About',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page/index', 'id' => 'about']),
],
[
'label' => 'Contact',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page/index', 'id' => 'contact']),
],
];
Background: I am using REST methods only.
I've called a create() method, which returns the id of the record I have created, and I want to call a different controller's get() method with that id.
module.config.php :
namespace PrivateStatement;
use Zend\Router\Http\Literal;
use Zend\Router\Http\Method;
return [
'router' => [
'routes' => [
'privateStatement' => [
'type' => Literal::class,
'options' => [
'route' => '/private-statements/private-statements',
'defaults' => [
'controller' => Controller\PrivateStatementController::class,
],
],
'child_routes' => [
'get' => [
'type' => Method::class,
'options' => [
'verb' => 'get',
'defaults' => [
'modules' => [
],
],
],
'may_terminate' => true,
],
'post' => [
'type' => Method::class,
'options' => [
'verb' => 'post',
'defaults' => [
'modules' => [
],
'params' => [
],
'requestVo' => '',
'controller' => Controller\PrivateStatementCreateController::class,
],
],
'may_terminate' => true,
],
],
],
],
],
'view_manager' => [
'strategies' => [
'ViewJsonStrategy',
],
],
];
In the PrivateStatementCreateController, I have the create() function:
public function create($data)
{
$requiredParams = [
PrivateStatementConstants::COLUMN_PROPERTY_ID,
PrivateStatementConstants::COLUMN_STOCK_UNIT_ID,
PrivateStatementConstants::API_FROM,
PrivateStatementConstants::API_TO,
];
$validRequest = ControllerUtil::verifyRequiredParams($requiredParams, $data);
if ($validRequest) {
$personId = $this->authResult->getIdentity();
$id = $this->model->createPrivateStatementService(
$data[PrivateStatementConstants::COLUMN_PROPERTY_ID],
$data[PrivateStatementConstants::COLUMN_STOCK_UNIT_ID],
$data[PrivateStatementConstants::API_FROM],
$data[PrivateStatementConstants::API_TO],
$personId
);
if ($id) {
return $this->redirect()->toRoute('privateStatement', array('action' => 'get', 'params' => array('private_statement_id' => $id)));
} else {
$this->getResponse()->setStatusCode(Response::STATUS_CODE_400);
}
} else {
$this->getResponse()->setStatusCode(Response::STATUS_CODE_400);
}
return new JsonModel([]);
}
The part I'm currently struggling with is return $this->redirect()->toRoute('privateStatement', array('action' => 'get', 'params' => array('private_statement_id' => $id)));
When I call this an exception gets thrown with the message Part route may not terminate - I honestly don't know how to continue from here - I only need to call the get() function in the PrivateStatementController and return the results.
I've got a basic Yii2 project, in which i created a separate module "rest". I have set up urlManager in config/web.php file. It works fine for common url, but it seems to me it is not working with url starting with my module name: rest/.. I have actionAuth() in AuthController in my rest module, and it is accessible with this url: test.ru/auth/auth. But i want it to be accessible with this url:test.ru/auth. I tried to write like this in web.php :
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\auth',
'extraPatterns' => [
'POST /' => 'auth',
],
'pluralize' => false,
],
],
],
But it does not work(not found error in browser).
I also tried like this:
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\auth',
'extraPatterns' => [
'POST rest/auth' => 'auth',
],
'pluralize' => false,
],
],
],
It seems to me that urlManager does not want to work for module. Next i tried to write the same code in my Module.php in rest/ directory. But it produced many errors. I think because of the same error things like that dont work too:`
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\city',
'extraPatterns' => [
'DELETE {id}' => 'delete',
],
`
So my question is: how to set up urlManager for module in Yii2? I need to configure HTTP DELETE method, post methods work without any settings in urlManager.
The whole web.php file:
<?php
$params = require(__DIR__ . '/params.php');
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'language' => 'ru',
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'xxxxxxx',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
// 'loginUrl' => ['site/login'],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => require(__DIR__ . '/db.php'),
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\user',
'except' => ['delete', 'create', 'update', 'index'],
'extraPatterns' => [
'GET all' => 'all',
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\auth',
'extraPatterns' => [
'POST reg' => 'reg',
'POST auth' => 'auth',
'POST rest/auth' => 'auth',
],
'pluralize' => false,
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest\city',
'extraPatterns' => [
'DELETE {id}' => 'delete',
],
],
],
],
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
// 'basePath' => '#app/messages', // if advanced application, set #frontend/messages
'sourceLanguage' => 'en',
'fileMap' => [
//'main' => 'main.php',
],
],
],
],
],
'modules' => [
'admin' => [
'class' => 'app\modules\admin\Module',
],
'manager' => [
'class' => 'app\modules\manager\Module',
],
'rest' => [
'class' => 'app\modules\rest\Module',
],
'rbac' => [
'class' => 'mdm\admin\Module',
'controllerMap' => [
'assignment' => [
'class' => 'mdm\admin\controllers\AssignmentController',
/* 'userClassName' => 'app\models\User', */
'idField' => 'id',
'usernameField' => 'username',
],
],
'layout' => 'left-menu',
'mainLayout' => '#app/views/layouts/admin.php',
]
],
'aliases' => [
//'#mdm/admin' => 'app/mdm/admin',
],
'params' => $params,
];
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
}
return $config;
My Module.php code(commented code shows my attempt to write urlManager):
<?php
namespace app\modules\rest;
/**
* rest module definition class
*/
class Module extends \yii\base\Module
{
/**
* #inheritdoc
*/
public $controllerNamespace = 'app\modules\rest\controllers';
/**
* #inheritdoc
*/
public function init()
{
parent::init();
// custom initialization code goes here
\Yii::$app->user->enableSession = false;
$config = [
'components' => [
'basePath' => dirname(__DIR__),
// 'user' => [
// 'identityClass' => 'app\models\User',
// 'class' => 'app\models\User',
// 'enableSession' => false
// ],
// 'urlManager' => [
// 'enablePrettyUrl' => true,
// 'enableStrictParsing' => true,
// 'showScriptName' => false,
// 'rules' => [
// [
// 'class' => 'yii\rest\UrlRule',
// 'controller' => 'rest\city',
// 'extraPatterns' => [
// 'DELETE {id}' => 'delete',
// ],
// ],
// ],
// ],
'response' => [
'format' => \yii\web\Response::FORMAT_JSON,
'charset' => 'UTF-8',
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if(( $response->statusCode >= 200) && ( $response->statusCode < 300)) {
if(isset($response->data['_appErr'])) {
unset($response->data['_appErr']);
$response->data = [
'success' => false,
'error' => $response->data,
'data' => null,
];
} else {
$response->data = [
'success' => $response->isSuccessful,
'error' => null,
'data' => $response->data,
];
}
} else {
if($response->statusCode == 401) {
$response->data = [
'success' => false,
'error' => [
'code' => 9,
'message' => 'Unauthorized',
'user_msg' => 'You need to be authorized',
],
'data' => null,
];
}
// else {
// $response->data = [
// 'success' => false,
// 'error' => [
// 'code' => 1,
// 'message' => 'server has returned '.$response->statusCode.' error',
// ],
// 'data' => null,
// ];
// }
}
},
],
],
];
\Yii::configure(\Yii::$app, $config);
}
}
Try this:
namespace yii\rest;
class UrlRule extends Object implements UrlRuleInterface {
public function parseRequest($manager, $request) {
list($e1, $e2) = sscanf($request->getPathInfo(), '%[a-zA-Z]/%[a-zA-Z]');
if ($e1 === 'auth' && $e2 === '') {
return ['/auth/auth', $request->queryParams];
}
return false;
}
}
Use forward slash(/) while defining the controller value in the rules array.
This will work:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest/user',
'except' => ['delete', 'create', 'update', 'index'],
'extraPatterns' => [
'GET all' => 'all',
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest/auth',
'extraPatterns' => [
'POST reg' => 'reg',
'POST auth' => 'auth',
],
'pluralize' => false,
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'rest/city',
'extraPatterns' => [
'DELETE {id}' => 'delete',
],
],
]
Check out the documentation here: http://www.yiiframework.com/doc-2.0/guide-rest-versioning.html
I always got "You are requesting with an invalid credential." but I need to have a public endpoint specifically "view" action that everybody can access whitout send access token and keep the other actions with token validation
This is part of my Api controller:
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'contentNegotiator' => [
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
//'application/xml' => Response::FORMAT_XML,
],
],
'verbFilter' => [
'class' => VerbFilter::className(),
'actions' => $this->verbs(),
],
'access' => [
'class' => AccessControl::className(),
'only' => ['view'],
'rules' => [
[
'actions' => ['view'],
'allow' => true,
'roles' => ['?'],
],
],
],
'authenticator' => [
'class' => CompositeAuth::className(),
'authMethods' => [
HttpBasicAuth::className(),
HttpBearerAuth::className(),
QueryParamAuth::className(),
],
],
'rateLimiter' => [
'class' => RateLimiter::className(),
],
];
}
I try using:
'access' => [
'class' => AccessControl::className(),
'only' => ['view'],
'rules' => [
[
'actions' => ['view'],
'allow' => true,
'roles' => ['?'],
],
],
],
But the authenticator behavior does not allow that my view action are a public action
I found the solutions is just using 'only' or 'except' key on the authenticator behavior
'authenticator' => [
'class' => CompositeAuth::className(),
'except' => ['view'],
'authMethods' => [
HttpBasicAuth::className(),
HttpBearerAuth::className(),
QueryParamAuth::className(),
],
],
Source:
https://github.com/yiisoft/yii2/issues/4575
https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-filters.md#using-filters-
Thanks, Enjoy Yii2 and REST ;)
There is two property to bypass authenticator on actions
1. only => bypass the rest of action in array configured
2. except => bypass only configured in array
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'except' => ['login', 'register','regenerate'],
//'only'=>['index'],
'authMethods' => [
[
'class' => HttpBasicAuth::className(),
'auth' => function ($username, $password) {
$user = User::findByLogin($username);
return $user->validatePassword($password)
? $user
: null;
}
],
HttpBearerAuth::className(),
QueryParamAuth::className()
],
];
return $behaviors;
}