Hello everybody i need help on codeigniter roles or permision. i have one user role (the admin) :
Table users ine the database :
id int(11)
email varchar(100)
password varchar(128)
name varchar(100)
in my admin panel i have (page.php controller)=page management, page order, (agent.php controller) = add,edit,delete... , (gyms) = add,edit,delete... ,(article.php controller)
and i have 21 sections, for each section i have more than one treatment, what i want is to assign to each section an admin than can edit and view only his section. so i will have 21 section_admin and one (or more) global_admin than can manage everything
i add an other field in users table named type :
type varchar(50)
it will have two values section_admin or global_admin. I searched but i found no tutorial that shows me how do that.
i don't know how to integrate roles management in my system. Can someone help me?
The controler : user.php
class User extends Admin_Controller
{
public function __construct ()
{
parent::__construct();
}
public function index ()
{
// Fetch all users
$this->data['users'] = $this->user_m->get();
// Load view
$this->data['subview'] = 'admin/user/index';
$this->load->view('admin/_layout_main', $this->data);
}
public function edit ($id = NULL)
{
// Fetch a user or set a new one
if ($id) {
$this->data['user'] = $this->user_m->get($id);
count($this->data['user']) || $this->data['errors'][] = 'User could not be found';
}
else {
$this->data['user'] = $this->user_m->get_new();
}
// Set up the form
$rules = $this->user_m->rules_admin;
$id || $rules['password']['rules'] .= '|required';
$this->form_validation->set_rules($rules);
// Process the form
if ($this->form_validation->run() == TRUE) {
$data = $this->user_m->array_from_post(array('name', 'email', 'password'));
$data['password'] = $this->user_m->hash($data['password']);
$this->user_m->save($data, $id);
redirect('admin/user');
}
// Load the view
$this->data['subview'] = 'admin/user/edit';
$this->load->view('admin/_layout_main', $this->data);
}
public function delete ($id)
{
$this->user_m->delete($id);
redirect('admin/user');
}
public function login ()
{
// Redirect a user if he's already logged in
$dashboard = 'admin/dashboard';
$this->user_m->loggedin() == FALSE || redirect($dashboard);
// Set form
$rules = $this->user_m->rules;
$this->form_validation->set_rules($rules);
// Process form
if ($this->form_validation->run() == TRUE) {
// We can login and redirect
if ($this->user_m->login() == TRUE) {
redirect($dashboard);
}
else {
$this->session->set_flashdata('error', 'That email/password combination does not exist');
redirect('admin/user/login', 'refresh');
}
}
// Load view
$this->data['subview'] = 'admin/user/login';
$this->load->view('admin/_layout_modal', $this->data);
}
public function logout ()
{
$this->user_m->logout();
redirect('admin/user/login');
}
public function _unique_email ($str)
{
// Do NOT validate if email already exists
// UNLESS it's the email for the current user
$id = $this->uri->segment(4);
$this->db->where('email', $this->input->post('email'));
!$id || $this->db->where('id !=', $id);
$user = $this->user_m->get();
if (count($user)) {
$this->form_validation->set_message('_unique_email', '%s should be unique');
return FALSE;
}
return TRUE;
}
}
The model user_m.php :
protected $_table_name = 'users';
protected $_order_by = 'name';
public $rules = array(
'email' => array(
'field' => 'email',
'label' => 'Email',
'rules' => 'trim|required|valid_email|xss_clean'
),
'password' => array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required'
)
);
public $rules_admin = array(
'name' => array(
'field' => 'name',
'label' => 'Name',
'rules' => 'trim|required|xss_clean'
),
'email' => array(
'field' => 'email',
'label' => 'Email',
'rules' => 'trim|required|valid_email|callback__unique_email|xss_clean'
),
'password' => array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|matches[password_confirm]'
),
'password_confirm' => array(
'field' => 'password_confirm',
'label' => 'Confirm password',
'rules' => 'trim|matches[password]'
),
);
function __construct ()
{
parent::__construct();
}
public function login ()
{
$user = $this->get_by(array(
'email' => $this->input->post('email'),
'password' => $this->hash($this->input->post('password')),
), TRUE);
if (count($user)) {
// Log in user
$data = array(
'name' => $user->name,
'email' => $user->email,
'id' => $user->id,
'loggedin' => TRUE,
);
$this->session->set_userdata($data);
}
}
public function logout ()
{
$this->session->sess_destroy();
}
public function loggedin ()
{
return (bool) $this->session->userdata('loggedin');
}
public function get_new(){
$user = new stdClass();
$user->name = '';
$user->email = '';
$user->password = '';
return $user;
}
public function hash ($string)
{
return hash('sha512', $string . config_item('encryption_key'));
}
}
There's too many ways how you can incorporate permission system in your project and it all depends what you need. I will give you a basic idea for your case how I would do it IF I understood your question right:
Yes, you can add another field to user table and call it role
To your section table add a user_id field. This is how you connect user with section.
Once user logs in, veryfy if that user is section_user and if yes you need to pull the right section based on that user_id from db.
If not, it means its a global_admin and then display all sections.
I'm not sure if I understood your question right tho.
Let me know.
Save yourself the trouble and use this: Flexi-Auth. You'll have roles and permissions for all the admin types you want for example.
I'm not sure exactly what you're trying to achieve, but I'll explain roughly what I would do:
1) Define a URL scheme
For example if you had a website for car enthusiasts, each brand might be its own section:
somesite.com/section/honda
somesite.com/section/ford
somesite.com/section/toyota
Those URL slugs (honda, ford, toyota etc) effectively become the identifiers for the section you're trying to access. Each one is unique.
You would then want to make sure that each slug after /section/ is a parameter rather than a function call. You can do this by going into /application/config/routes.php and defining a route like this:
$route['section/(:any)'] = section_controller/$1;
// $1 is the placeholder variable for the (:any) regex. So anything that comes after /section will be used as a parameter in the index() function of the section_controller class.
2. Create a new database called 'section', and a corresponding model
For now just give it two fields: *section_id*, and *section_name*. This will store each unique section. The code for the model would be something like this:
class Section extends CI_Model
{
public $section_name;
public $section_id;
public function loadByName($section_name)
{
$query = $this->db->select('section_id', 'section_name')
->from('section')
->where('section_name', $section_name);
$row = $query->row();
$this->section_name = $row->section_name;
$this->section_id = $row->section_id;
return $row;
}
public function loadById($section_id)
{
$query = $this->db->select('section_id', 'section_name')
->from('section')
->where('section_id', $section_id);
$row = $query->row();
$this->section_name = $row->section_name;
$this->section_id = $row->section_id;
return $row;
}
}
3. In the user table, create an additional field called *section_id*
This will be the reference to the ID of the section which they are an admin of. For example if the Toyota section_id is 381, then use 381 as the number in the section_id field in the user table.
4. When the page is requested, look up the section_id based on the slug name.
In your controller file, you should then load the section model somewhere in the index() method like so:
class Section_controller extends CI_Controller
{
public function index($section_name)
{
// I will assume you've already loaded your logged in User somewhere
$this->load->model('Section');
$this->Section->loadByName($section_name);
if ($this->User->section_id == $this->Section->section_id)
{
// Render the page with appropriate permissions
}
else
{
// Throw an error
}
}
}
I won't get into any more specifics of doing all of that; you'll have to read the Codeigniter documentation for a grasp on how to handle routes, controllers, DB queries etc.
if you have only 2 roles then it can achieve easily. you know the user is admin or not if user >is admin then it activate all the section where admin has acess. if user is then he won,t able >to gain access.
if you are comfortalbe to use tankauth authentication library if you have enough time to do task then go to tankauth.
you can also use bonfire(HMVC) for user authentication.
Related
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 try to find a good and clean way to deal with an admin panel "edit user" in cakePHP v.2.7.
To be clear : I want to be able to edit my user with or without overwriting their password, but the cakePHP validator tool don't let me do what I want...
I've already take a look at CakePHP: Edit Users without changing password and Updating user email and password with CakePHP but it seem really dirty :
the first one don't apply the rules onUpdate
the second display the hash (just no... u_u")
There is no other way to do it ? (with as few line as possible)
TL;DR :
View
// add in your view `app/View/Users/edit.ctp`
// a 'fake' field you'll only use on the controller
echo $this->Form->input('new_password');
Controller
// add in your controller `app/Model/User.php#edit()`
// if we have a new password, create key `password` in data
if(!empty($new_password = $this->request->data['User']['new_password']))
$this->request->data['User']['password'] = $new_password;
else // else, we remove the rules on password
$this->User->validator()->remove('password');
Ok, I finally get what I want, here is my code :
On your app/View/Users/edit.ctp you add a field to your form (a custom one, don't add it to your DB)
<?php
// app/View/Users/edit.ctp
echo $this->Form->create('User');
// your other fields
// a 'fake' field you'll only use on the controller
echo $this->Form->input('new_password');
Don't change your app/Model/User.php ; here is mine :
<?php
// app/Model/User.php
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
public $validate = array(
// [...] other rules
'password' => array(
'passwordLength'=>array(
'rule' => array('minLength', 8),
'message' => 'Too short...',
),
'passwordNotBlank'=>array(
'rule' => 'notBlank',
'required' => true,
'allowEmpty' => false,
'message' => 'A password is required',
),
),
);
public function beforeSave($options = array()) {
if (!empty($pwd = $this->data[$this->alias]['password']))
$this->data[$this->alias]['password'] = AuthComponent::password($pwd);
return true;
}
}
And on your app/Controller/UsersController.php you use this :
<?php
public function edit($id = null) {
$this->User->id = $id;
if (!$this->User->exists())
throw new NotFoundException(__('Invalid user'));
if ($this->request->is('post') || $this->request->is('put')) {
// IMPORTANT >>>>>>>>>>>
// if we have a new password, create key `password` in data
if(!empty($new_password = $this->request->data['User']['new_password']))
$this->request->data['User']['password'] = $new_password;
else // else, we remove the rules on password
$this->User->validator()->remove('password');
// <<<<<<<<<<<<<<<<<<<<<
// then we try to save
if ($this->User->save($this->request->data)) {
$this->Flash->success(__('The user has been updated'));
$this->redirect(array('action' => 'index'));
}
else
$this->Flash->warning(__('The user could not be updated.'));
}
else {
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
}
}
With the 4 important lines, you are now able to set a new password if needed or disable the validation on the password.
I used this for reference
http://book.cakephp.org/2.0/en/models/data-validation.html#removing-rules-from-the-set
I have a form where one can upload his/her own CV files(docx/pdf).I have a drop down menu "employee name" in the from which shows only the login user name in the list.But now i want to show the login user name in the from input field.how can i do that.Can any one give me code example.As i am very poor at coding.
Here is my from code:
if($UserType == "employee")
{
$criteria=new CDbCriteria();
$criteria->condition = "status= 'active' and id = $ID";
echo $form->dropDownListGroup(
$model,
'user_id',
array(
'wrapperHtmlOptions' => array(
'class' => 'col-sm-5',
),
'widgetOptions' => array(
'data' => CHtml::listData(User::model()->findAll($criteria), 'id', 'user_id'),
'htmlOptions' => array('prompt'=>'Select'),
)
)
);
}
user name input field
logged-in user name
This is the way I do:
First, in /protected/components, I set a session variable to store the logged-in user name:
public function authenticate()
{
$user = Users::model()->find('user = ? ', array($this->username)); //user entered when trying to log in
...
}
If authentication is correct:
public function authenticate()
{
...
$session = new CHttpSession;
$session->open(); //session_start
$session['user'] = $user; //$user is the logged-in username
...
}
In controller action create:
public function actionCreate(){
$session = new CHttpSession;
$session->open();
$user = $session['user'];
...
$this->render('create',array(
'user'=>$user,
'model'=>$model,
...
));
}
In view (in /_form, for example):
...
$model->user = $user;
$form=$this->beginWidget('bootstrap.widgets.TbActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
...
echo $form->dropDownList($model,'user',...); //Here, the attribute 'user' of the model $model will have the logged-in user-name
...
This is assuming you have an attribute called 'user' in your model. If not, then, in /model, create an auxiliary attribute 'user' in order to use this attribute in your /_form:
class YourModel extends CActiveRecord
{
public $user; //$variable used to set the logged-in username
...
}
how to make the registered user can edit only their data but not others. When it was set up ACL(aro and aco).
My settings:
class User extends AppModel {
public function bindNode($user) {
return array('model' => 'Group', 'foreign_key' => $user['User']['group_id']);
}
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
You should add the isAuthorized method to your controller. In this method you check that the users are authorized for the actions they are trying to do with the parameters they are passing. You could use code like this:
switch ($this->action) {
case 'delete':
case 'edit':
// id of what they are trying to edit
$this->Topic->id = $this->params['pass'][0];
// id of the owner of what they are trying to edit
$ownerId = $this->Topic->field('user_id');
$userId = $this->Auth->user('id');
if ($ownerId == $userId) {
// allow users to edit or delete their own topics
return TRUE;
} else {
// allow admin group to edit any topic
return $this->Auth->user('group') == 'admin';
}
}
If you want to use Cake's ACL system for checking permissions rather than hard-coding checks like "user is a member of admin group", see the tutorial here: http://jonisalonen.com/2010/role-based-acl-in-cakephp/
It was written for Cake 1.3 though, I haven't checked if there are major differences.
I have installed ion auth and everything is up and functional. The only problem I have is I want to change the login to use the visitors username instead of e-mail. I change the CONFIG option in the ion_auth.php config file and it still doesnt work. Is there an extra step Im missing??
ion_auth config
/**
* A database column which is used to
* login with.
**/
$config['identity'] = 'username';
login() in the controller
//log the user in
function login()
{
$this->data['title'] = "Login";
//validate form input
$this->form_validation->set_rules('email', 'E-mail Address', 'required|valid_email');
$this->form_validation->set_rules('password', 'Password', 'required');
if ($this->form_validation->run() == true)
{ //check to see if the user is logging in
//check for "remember me"
$remember = (bool) $this->input->post('remember');
if ($this->ion_auth->login($this->input->post('email'), $this->input->post('password'), $remember))
{ //if the login is successful
//redirect them back to the home page
$this->session->set_flashdata('message', $this->ion_auth->messages());
redirect($this->config->item('base_url'), 'refresh');
}
else
{ //if the login was un-successful
//redirect them back to the login page
$this->session->set_flashdata('message', $this->ion_auth->errors());
redirect('auth/login', 'refresh'); //use redirects instead of loading views for compatibility with MY_Controller libraries
}
}
else
{ //the user is not logging in so display the login page
//set the flash data error message if there is one
$this->data['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
$this->data['email'] = array('name' => 'email',
'id' => 'email',
'type' => 'text',
'value' => $this->form_validation->set_value('email'),
);
$this->data['password'] = array('name' => 'password',
'id' => 'password',
'type' => 'password',
);
$this->load->view('auth/login', $this->data);
}
}
login() model
public function login($identity, $password, $remember=FALSE)
{
if (empty($identity) || empty($password) || !$this->identity_check($identity))
{
return FALSE;
}
$query = $this->db->select($this->identity_column.', id, password, group_id')
->where($this->identity_column, $identity)
->where('active', 1)
->where($this->ion_auth->_extra_where)
->limit(1)
->get($this->tables['users']);
$result = $query->row();
if ($query->num_rows() == 1)
{
$password = $this->hash_password_db($identity, $password);
if ($result->password === $password)
{
$this->update_last_login($result->id);
$group_row = $this->db->select('name')->where('id', $result->group_id)->get($this->tables['groups'])->row();
$session_data = array(
$this->identity_column => $result->{$this->identity_column},
'id' => $result->id, //kept for backwards compatibility
'user_id' => $result->id, //everyone likes to overwrite id so we'll use user_id
'group_id' => $result->group_id,
'group' => $group_row->name
);
$this->session->set_userdata($session_data);
if ($remember && $this->config->item('remember_users', 'ion_auth'))
{
$this->remember_user($result->id);
}
return TRUE;
}
}
return FALSE;
}
Why are you still processing email in the controller (instead of username)?
You need to change your controller since it is still grabbing email from POST and using it to try to login.
You should add an index in the users table of username column