yii php unit test Yii::app->user->id error - yii

I m testing a class that saves a model. This model has a behavior where it saves the user of the record which I m going to insert, with this method
public function beforeSave($event) {
if (($this->getOwner()->getTableSchema()->getColumn($this->campoUsuarioCreacion)!==null))
$this->getOwner()->{$this->campoUsuarioCreacion} = Yii::app()->user->id;
if ($this->getOwner()->getTableSchema()->getColumn($this->campoUsuarioModificacion)!==null)
$this->getOwner()->{$this->campoUsuarioModificacion} = Yii::app()->user->id;
return parent::beforeSave();
}
But when I m testing, there is a problem with Yii::app()->user->id. I think that the problem is that no user is logged in. So, How can I solve the problem, without copying again the class with a harcoded user id? Is there a way to set the app user id?

Without broaching the issue of whether or not the user is logged in or Yii::app()->user->id is defined, you need to add this to the bottom of your function:
return parent::beforeSave();
eg:
public function beforeSave($event) {
if (($this->getOwner()->getTableSchema()->getColumn($this->campoUsuarioCreacion)!==null))
$this->getOwner()->{$this->campoUsuarioCreacion} = Yii::app()->user->id;
if ($this->getOwner()->getTableSchema()->getColumn($this->campoUsuarioModificacion)!==null)
$this->getOwner()->{$this->campoUsuarioModificacion} = Yii::app()->user->id;
return parent::beforeSave();
}

Related

Laravel Authentication with condition

I am using Laravel 5.1 and Laravel's default authentication system.
In database (MySQL) I add a new column named 'role'. The value will be 1 for admin and 2 for members.
Now I want to give login permission only for admin, means where the value is 1. How can I do that?
Actually I solved it. I just add these code in postLogin() method of AthenticatesUsers.php method.
// If role is equal to 1, user allowed to login
// You can change $admin value anytime according to database Design
// Example: In role column the value for admin is 2 or A. You just need to change the value of $admin.
$userData = User::select('role')->where('email',$request['email'])->first();
$admin = 1;
$role = $userData->role;
if($role == $admin){
$request['role'] = $role;
}
I feel that there are better ways to achieve what you're after, such as middleware, however given what you're after this would be one way to do it.
Upon logging in a user us sent to 'home', unless you specify otherwise in the AuthController.
Inside your routes.php, if you just set up a GET route to point to a HomeController (or whatever you name it) then you could use a function to run the tests you're after.
routes.php
Route::get('home', 'HomeController#index');
HomeController
public function index()
{
//If they are yet to log in then return your normal homepage
if (Auth::guest())
{
return View::make('home');
}
else
{
//Run your tests here to check their role and direct appropriately
//Given you have added the role column to the users table, you can access it like so:
//Auth::user()->role
}
}

LARAVEL 5: Need to keep query string after auth redirects

I have a link I am sending via email. For example, www.swings.com/worker?id=3382&tok=jfli3uf
In this case I want the person to click the link, get sent to the login page(which it does) and then be directed to a controller method WITH the $id and $tok variables. I can't get that part to work. Any ideas? I am only using the RedirectIfAuthenticated class and this is what it looks like:
public function handle($request, Closure $next)
{
$user = $request->user();
if ($this->auth->check()) {
if($user && $user->hasRole('worker'))
{
return redirect('worker');
}
return redirect('home');
}
return $next($request);
}
hasRole is a method I created in the User model that checks the role of the logged in user
You can flash data to the session when redirecting by chaining the with() method:
// in your handle() method:
return redirect('home')->with($request->only('id', 'tok'));
// then in home controller method:
$id = session('id');
$tok = session('tok');
AFTER SOME HOURS I WAS ABLE TO HAVE A SOLUTION:
ReturnIfAuthenticated wasn't changed. I just added the following within my controller that this link should go to:
for instance, the route would be:
Route::get('worker', 'WorkerController#methodINeed');
Within this method:
public function methodINeed() {
$id = Input::get('id');
$tok = Input::get('tok');
// Do what I need this variables to do
}
What I didn't understand and what could not be properly understood is that the auth controller in Laravel 5 is triggered when a user is a guest it will still redirect to the actual method with all its original data once auth is successful. Hope this is helpful.

Yii2 per content visibility depending on role

We have used RBAC to implement simple role based permissions for CRUD, but now we need to also add a 'visibility' functionality which makes it possible to limit content visibility (R) to only registered users or only the content owners.
So, how can we limit content visibility on different levels, for example
PUBLIC: anybody can see the content, including anonymous
INTERNAL: only registered users can see the content
PRIVATE: only the creator can see the content
What would be the best way to implement this, it looks like RBAC does not have a straightforward way of dealing with this.
I think that the problem can be solved by using defaultScope in models. Thus, before giving the content, we can check the current role of the user data and give the necessary conditions.
public static function find()
{
$userRoleArray = \Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());
$userRole = current($userRoleArray)->name;
if ($userRole == 'admin') {
return parent::find()->where("Your condition");
} elseif ($userRole == 'moderator') {
return parent::find()->where("Your condition");
}
}
you can make a permission function and run in each function that will take user role as argument and returns true or redirect to not allowed page.
Here is something I tried but you can modify according to your need.
public function allowUser($min_level) {
//-1 no login required 0..3: admin level
$userRole = //get user role;
$current_level = -1;
if (Yii::$app->user->isGuest)
$current_level = 0;
else
$current_level = userRole;
if ($min_level > $current_level) {
$this->redirect(array("/pages/not-allowed"),true);
}
}

my zend session name spacing does not work

I am new to Zend and very keen to learn, so I would really appreciate some help and guidance.
I am trying to create a 'method in a class' that will save the session variables of product pages visited by members to a site i.e
i,e examplesite com/product/?producttype= 6
I want to save the number 6 in a session variable. I also do not want to have a global session for the entire site; I just want it for selected pages. So, I guess I have to have Zend_Session::start() on the selected page; but I am not clear how this should be done.
Should I instantiate it in the page view page. i.e products page or do this in the indexAction() method for the products page. I have attempted to instantiate it below but it did not work.
public function rememberLastProductSearched()
{ //my attempt to start a session start for this particular page.
Zend_Session::start();
}
$session->productSearchCategory = $this->_request->getParam('product-search-category');
return" $session->productSearchCategory ";
}
else
{
//echo " nothing there
return " $session->productSearchCategory";
//";
}
}
With the rememberLastProductSearched() method I was trying to get the method to first check whether the user had searched for a new product or just arrived at the page by default. i.e whether he had used the get() action to search for a new product. If the answer is no, then I wanted the system to check whether their had been a previous saved session variable. so in procedural syntax it would have gone like this:
if(isset($_Get['producttype']))
{
//$dbc database connection
$producttype = mysqli_real_escape_string($dbc,trim($_GET['producttype']));
}
else
if(isset($_SESSION['producttype'])){
$producttype = mysqli_real_escape_string($dbc,trim($_SESSION['producttype']));
}
Can you please help me with the Zend/oop syntax. I am totally confused how it should be?
you're asking about simple work flow in an action, it should begin something like:
//in any controller
public function anyAction()
{
//open seesion, start will be called if needed
$session = new Zend_Session_Namespace('products');
//get value
$productCategory = $this->getRequest()->getParam('producttype');
//save value to namespace
$session->productType = $productCategory;
//...
}
now to move this off to a separate method you have to pass the data to the method...
protected function rememberLastProductSearched($productType)
{
//open seesion, start will be called if needed
$session = new Zend_Session_Namespace('products');
$session->productType = $productType;
}
So now if you want to test for presence of a value...
//in any controller
public function anyAction()
{
//open seesion, call the namespace whenever you need to access it
$session = new Zend_Session_Namespace('products');
if (!isset($session->productType)) {
$productCategory = $this->getRequest()->getParam('producttype');
//save value to session
$this->rememberLastProductSearched($productCategory)
} else {
$productCategory = $session->productType;
}
}
That's the idea.
Be mindful of your work flow as it can sometimes be very simple to inadvertently overwrite your session values.
$session = new Zend_Session_Namespace("productSearch");
if ($this->getRequest()->getParam('producttype')) { //isset GET param ?
$session->productType = $this->getRequest()->getParam('producttype');
$searchedProductType = $session->productType;
} else { //take the session saved value
if ($session->productType) {
$searchedProductType = $session->productType;
}
}
//now use $searchedProductType for your query

Yii Behaviors and scenario

i have a behavior for my models, the behavior has beforeFind, beforeSave, in methods i override user_id, something like:
...
public functio beforeSave() {
$this->owner->user_id = Yii::app()->user->id
}
I have model User, how can i disable behavior for registration new user?
Saving code:
$user = new User();
$user->id = 1332;
$user->field1 = 'data';
$user->save();
but on save i have null in $user->id (because work behavior).
i tried
$user->disableBehaviors();
$user->detachBehavior();
Without result.
Maybe its not right way? I create behaviors for identify users in system (find only user something, save only with user id...), but that if i have new user with full previegies, i should again detach behaviors?
If condition can be changed in future I just pass it as callback parameter into behavior from model.
This give you a bit more control over the condition. Hence, behavior becomes more reusable - if it is used by several models this condition can be unique for each.
Example below is a bit simplified, but you should get the idea.
Behavior:
class SomeBehavior extends CActiveRecordBehavior
{
public $trigger;
public function beforeSave($event)
{
if(!call_user_func($this->trigger))
return;
// do what you need
$this->owner->user_id = Yii::app()->user->id;
}
}
Model:
class SomeModel extends CActiveRecord
{
public function behaviors()
{
$me=$this;
return array(
'some'=>array(
'class'=>'SomeBehavior',
'trigger'=>function() use($me){
return $me->scenario=='some-scenario';
}
)
);
}
}
Also I use PHP 5.3. So, I use closure for trigger callback.
If your PHP version is less than 5.3 - anything callable can be used instead. Check here http://www.php.net/manual/en/function.is-callable.php
Because of behavior is a method, you can declare your own logic inside.
The model knows about its scenario, so there is no problem to return different arrays for different conditions:)
Hope it be helpful for somebody.
You can check Yii::app()-user->isGuest to determine if the user is logged in or not. or you can just try looking for the null. Like this:
if (!Yii::app()->user->isGuest)
$this->owner->user_id = Yii::app()->user->id;
or
if (null !== Yii::app()->user->id)
$this->owner->user_id = Yii::app()->user->id;