how can I secure routes so that user can access only those departments that he belongs to?
my current filter:
Route::filter('department', function ($route, $request) {
// Check to see if the current user belongs to the department:
if (!Request::isMethod('post'))
{
if($request->segment(2) != "create")
{
if (!Auth::user()->canAccessDepartment($request->segment(2))) {
// The user shouldn't be allowed to access the department! Redirect them
return Redirect::to('/')->with( 'notice', 'Error!' );;
}
}
}
});
And this is my method in user model
public function canAccessDepartment($department_id) {
$user = Confide::user();
if ($user->departments()->where('department_id', $department_id)->count() < 1)
{
return false;
}
else{ return true; }
}
In the code you have, the filter is applied to all the routes, and then checks to see if we have a matching method/action. My preference would be to only apply the filter when it's needed. So
[Warning - untested code follows]
Route::resource('department', 'DepartmentController',
array('except' => array('create','store', 'update', 'destroy')));
Route::resource('department','DepartmentController',array('only'=>array('create','store', 'update', 'destroy'),'before'=>'departmentFilter'));
Route::filter('department', function ($route, $request) {
// should this be Confide::user() ?
if (!Auth::user()->canAccessDepartment($request->segment(2))) {
// The user shouldn't be allowed to access the department! Redirect them
return Redirect::to('/')->with( 'notice', 'Error!' );
}
});
I think that this should be done in the database/model level. Since the data that you need to compare is in a database, its better if you do this transaction in a database level.
Related
I need to check if a user is existing in the mgrUser table. now the propblem is the controller is in the adminController while the model is in the mgrUserModel. how do i use Auth for this? Thats the reason why I made a generic login code.
public function login() {
// if ($this->Auth->login()) {
// return $this->redirect($this->Auth->redirectUrl());
// }
// $this->Flash->error(
// __('Username ou password incorrect')
// );
//since the model is in a different view, I needed to includ the mgrModel and create a generic login
//will revamp the code to fit the built in Aut code for php cake
if(isset($_POST['submit'])) {
$User_ID = htmlspecialchars($_POST['user_id']);
$Pass = htmlspecialchars($_POST['pass']);
try {
$mgrUserModel = new MgrUser();
$isValid = $mgrUserModel->find('first', array(
'conditions' => array("user_id" => $User_ID)
));
if($isValid != null){
if (($isValid['MgrUser']['pass']) == $Pass) {
//this doesnot work
$this->Auth->allow();
$this->redirect($this->Auth->redirectUrl());
}
else{
}
}
} catch (Exception $e) {
//echo "not logged in";
}
// this echo will show the id and pass that was taken based on the user_id and pass that the user will input
//for testing only
// echo $isValid2['MgrUser']['id'];
// echo $isValid2['MgrUser']['pass'];
}
}
You need double == to compare things,
function checkMe()
{
if($user == 'me'){
$this->Auth->allow('detail');
}
}
what you did was assign "me" string to variable $user which always returns true because assignment was possible
Anyway you should use it in beforeFilter which is running before every action from this controller, which makes much more sense
public function beforeFilter() {
parent::beforeFilter();
if($user == 'me'){
$this->Auth->allow('detail');
}
}
the Auth component could be configured to read the user information via another userModel (The model name of the users table). It defaults to Users.
please consult the book for appropriate cakephp version: https://book.cakephp.org/3.0/en/controllers/components/authentication.html#configuring-authentication-handlers
I am working on one role based login system. Actually, What should I do to the controller, model and the views in this role based login system to allocate different access criteria.
I am little confused about how to set and access for the user according to the role.
Mainly I am not sure about how to allocate different view as a role.
ex. I apply if condition to check role and then view according to the role the menu show the different links. like main admin can only watch account tab. the user can not see the account tab.
I also set the same if condition with the session in the controller for preventing direct access to that page.
Here is my code which I applied to menu and controller.
<?php
$login_role= $this->session->userdata('user_data');
if($login_role['user_role'] === 'super_admin'){
?><li><a href="<?php echo base_url('account/view_account'); ?>">
<div>Account</div></a></li><?php
}
?>
and the same condition in the controller
public function index()
{
$login_role= $this->session->userdata('user_data');
if($login_role['user_role'] === 'super_admin')
{
$this->load->model('location_model');
$city_list = $this->location_model->get_city_list();
$state_list = $this->location_model->get_state_list();
//log_message('info', 'City and State list will sucessfully loded.');
$this->load->view('admin/account_insert',['city_list'=>$city_list,'state_list'=>$state_list]);
} else {
redirect('admin/dashboard','refresh');
}
}
I am not sure about is this safe to use like this way. or I have to do something else as a good practice.
I am using a single Controller Login system for all user roles. I have a table of user roles and I have role id in users table. Then I have controller names matching those roles. When user login, I check for role and redirect the user to that controller after verification. Following is the index function of my Login Controller.
public function index()
{
if(!$this->isLoggedIn())
{
$data['title']='Title You want to set on Page';
if($_POST)
{
$config=array(
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'trim|required|valid_email',
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required',
),
);
$this->form_validation->set_rules($config);
if($this->form_validation->run()==false)
{
$data['errors']=validation_errors();
$this->load->view('static/head', $data);
$this->load->view('admin/login');
}
else
{
$user=$this->admin_model->checkUser($_POST);
if(!empty($user))
{
if($user['role']==1)
{
$user['type']='admin';
}
elseif($user['role']==2)
{
$user['type']='team';
}
elseif($user['role']==3)
{
$user['type']='client';
}
elseif($user['role']==4)
{
$user['type']='manager';
}
$this->session->set_userdata($user);
redirect(base_url().$user['type']);
}
else
{
$data['errors']='The credentials you have provided are incorrect or your account has not been approved yet.';
$this->load->view('static/head', $data);
$this->load->view('admin/login');
}
}
}
else
{
$this->load->view('static/head', $data);
$this->load->view('admin/login');
}
}
else
{
redirect(base_url().$this->session->userdata['type']);
}
}
Its working perfectly for me. Furthermore in each Controller I have functions to check if the user is logged in for this role like this
public function isLoggedIn()
{
if(!empty($this->session->userdata['id'])&& $this->session->userdata['type']=='team')
{
return true;
}
else
{
return false;
}
}
And I render my index function of that controller. E.g Following is the team controller index function
public function index()
{
if($this->isLoggedIn())
{
$data['menu']=$this->team_model->getMenuItems();
$data['task_logs']=$this->admin_model->getAllLogs();
$data['title']='Title';
$this->load->view('static/head',$data);
$this->load->view('static/header');
$this->load->view('static/sidebar');
$this->load->view('team/dashboard');
$this->load->view('static/footer');
}
else
{
redirect(base_url());
}
}
I want to use Laravel 5 AuthServiceProvider to prevent logged in user to view other users profile. I'm using route like this user/1. How can I compare if the logged in user ID is match with the ID in the URL. If not then can't proceed.
Here's the following code I'm trying in my AuthServiceProvider:
$gate->define('view-profile', function($user, $id) {
return Auth::user()->id === $id;
});
However, the above code doesn't work as I can't pass the correct ID from the URL. Can anyone please help?
Here's the code I've in my controller:
if (Gate::denies('view-post', [Auth::user()->id, (int) $id])) {
return abort(403);
} else {
return 'success';
}
Just to let all of you know that I've figured it out myself using Gate::forUser() method. Here's the relevant code which I hope anyone may find helpful:
In AuthServiceProvider:
$gate->define('view-post', function($user, $id) {
return $user->id === (int) $id;
});
In your particular Controller:
$user = Auth::user();
if(Gate::forUser($user)->allows('view-post', $id)) {
return 'true';
}
return abort(403, trans('Sorry, not sorry!'));
If you route user controller with user, then user/1 will route the user controller show function, and in show function you can check your authentication user with id:
Function show ($id)
{
if ( Auth::user()->id == $id) {
//your code here
}
}
I want to get the roles of the registered users and show the content to the registered users according to their roles.
I have two users right now.
admin
user(authenticated)
The thing i am trying to do is that when the admin logs in via "webapp/user/login" a sidebarwidget which i have already made should be shown upon login and when the user(authenticated) gets logged in, the user(authenticated) should only be able to see the index.php page.
I am using Yii users and rights. I have looked around and found this piece of code which is for getting the role of the logged in user but I dont know where to place this piece of code to get the output.
Below are two pieces of codes, please do tell me which one will be more useful.
if($user = Users::model()->findAll()) {
foreach($user as $id => $user) {
if(!$user->checkAccess('Authenticated')) {
unset($user[$id]);
}
}
$users = array_values($user); // to reset indices (optional)
}
and this is another piece of code which i have found.
$command = Yii::app()->db->createCommand("SELECT * FROM `authassignment` WHERE userid={$user->id}");
$results = $command->queryAll();
$roles = array();
foreach ($results as $result)
{
$roles[] = $result['itemname'];
}
$this->setState('roles', $roles);
From what I have done following tutorials, here is a proposal.
The authentication can take place in file protected/components/UserIdentity.php :
public function authenticate($native=false){
$record=User::model()->findByAttributes(array('username'=>$this->username));
//can provide function "same" if needed - found it here:
//http://codereview.stackexchange.com/questions/13512
if($record!==null&&$this->same($record->password,crypt($this->password,$record->password)){
$authRoleName=Role::model()->findByAttributes(array('id'=>$record->role_id))->name;
$this->setState('role_name', $authRoleName);
$this->errorCode = self::ERROR_NONE;
}else{
$this->errorCode=self::ERROR_UNKNOWN_IDENTITY;
}
return !$this->errorCode;
}
In this case the several roles (admin, mobile, user, etc) are stored in db (table roles) and each user model has a role_id.
I assume the SiteController does the login (file protected/controllers/SiteController.php):
public function actionLogin()
{
$model=new LoginForm;
// if it is ajax validation request
if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if($model->validate() && $model->login()){
$this->redirect(Yii::app()->user->returnUrl);
}
}
// display the login form
$this->render('login',array('model'=>$model));
}
File protected/models/LoginForm.php:
class LoginForm extends CFormModel
public $username;
public $password;
public $rememberMe;
private $_identity;
public function authenticate($attribute,$params)
{
if(!$this->hasErrors())
{
$this->_identity=new UserIdentity($this->username,$this->password);
if(!$this->_identity->authenticate())
$this->addError('password','False username or password.');
}
}
public function login()
{
if($this->_identity===null)
{
$this->_identity=new UserIdentity($this->username,$this->password);
$this->_identity->authenticate();
}
if($this->_identity->errorCode===UserIdentity::ERROR_NONE)
{
$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
Yii::app()->user->login($this->_identity, duration);
return true;
}
else
return false;
}
In view you could do a role based decision making, like the example below in file protected/views/site/index.php :
<?php
$userModel =User::model()->findByAttributes(array('id'=>Yii::app()->user->getId()));
if($userModel){
if(Yii::app()->user->getState('role_name') == 'admin'){
$this->renderPartial(
//...
);
}else{
//...
}
}
Moreover, if RBAC is on your mind, and you manage to have a proper protected/data/auth.php (there are ways for this, I use command "./protected/yiic rbac" after creating file protected/commands/RbacCommand.php - I can post this latter file if needed) then in any place in your code you simply:
if(Yii::app()->user->checkAccess('admin')){
//staff for admins
}
Also, in this case, you could set the rights of whole actions in controller's function accessRules() by issuing roles instead of usernames:
public function accessRules()
{
return array{
array('allow',
'actions'=>array('index', 'index2', 'view','create','update','getRecordDetails', 'getTotalCount'),
'roles'=>array('admin'),
),
);
}
I have this in my database
|username|password|type|
------------------------
|foo |12345 |1 |
|asd |adsdsd |0 |
Here 1 means that the user is an admin, 0 a normal user.
How can I redirect the admin to the admin page and the normal user to normal user page??
if($attempt)
{
$id = User::find($attempt);
$user = $id->type;
if($user === 0)
{
return Redirect::action('LoginUsersController#profile');
}
else
{
return Redirect::to('adminpage');
}
}
I created this in my UsersController page I don’t know if this is the proper way to do this, and my code is not working.
Are you using normal Laravel Authentication?
You will get Object Auth::user(), this will return current user Object.
It should look like this.
Controller (SessionsController#store)
public function store() {
$input = Input::all();
$attempt = Auth::attempt([
'username' => $input['username'],
'password' => $input['password']
]);
if($attempt) {
if(Auth::user()->type == 1) {
return Redirect::admin(); // If admin, redirect to admin
} else {
return Redirect::profile(); // Else, redirect to user profile
}
}
}
Route
Route::resource('sessions', 'SessionsController', ['only' => ['create','store','destroy']]);
Route::get('admin', 'AdminController#dashboard')->before('adminAuth');
Route::get('profile/{id}', 'UsersController#showProfile')->before('auth');
First of all you have to add a new field in your users table to check against, for example 'rank'. If rank for a user is '1' so he is an Admin,
else he is a normal user.
Then define all required routes in your routes file like this:
Route::get('login', 'adminController#login');
Route::post('login', 'adminController#checkuser');
Route::group(array('before' => 'auth'), function() {
Route::resource('admin', 'adminController');
Route::resource('normaluser', 'normaluserController');
} );
Then in your controller you have to define all actions:
public function login()
{
return View::make('loginview');
}
public function checkuser()
{
if (Auth::attempt(array('username'=>Input::get('username'), 'password'=>Input::get('password'))))
{
$user_data = Auth::getUser();
if ($user_data->rank == 1) //if true, so this user is an admin
{return Redirect::to('admin');} //go to adminController index action
else //if not, so he is a normal user
{return Redirect::to('normaluser');} // go to normaluserController index action
}
else
{
//return 'wrong user name or password';
Session::flash('mismatch', "Username and Password mismatch");
return Redirect::to('login'); // go again to login form to relogin
}
}
if any thing is not clear, don't hesitate to ask.
in the if statement use:
if($attempt)
{
$id = User::find($attempt);
$user = $id->type;
if($user === 0)
{
return Redirect::action('LoginUsersController#profile');
header('Location: http://www.example.com/userpahe.php');
}
else
{
return Redirect::to('adminpage');
header('Location: http://www.example.com/admin-page.php');
}
}