How to edit only their own data in CakePHP 2? - php

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.

Related

CakePHP 3: Different login redirection depending on user roles

I'm using CakePHP 3 and trying to change the default route after user is logged in. I want to set default route different depends on user's role_id.
I found a solution but it's only for CakePHP 2.
I can't use it in CakePHP 3, I can't use Session component in bootstrap.
So I tried this in my AppController
public $redirects = [
'admin' => ['controller' => 'Clients', 'action' => 'statistics'],
'user' => ['controller' => 'Clients', 'action' => 'index'],
];
public function initialize()
{
parent::initialize();
...
if ($this->Auth->user())
Configure::write('Route.default', $this->redirects[$this->Auth->user('role_id')]);
else
Configure::write('Route.default', ['controller' => 'Users', 'action' => 'login']);
Router::scope('/', function($routes) {
$routes->connect('/', Configure::read('Route.default'));
$routes->fallbacks('InflectedRoute');
});
}
My default route is
$routes->connect('/', \Cake\Core\Configure::read('Route.default'));
And I defined Route.default in bootstrap.php as
Configure::write('Route.default', ['controller' => 'Users', 'action' => 'login']);
But when I open the / page I still see the users/login page even if I have already logged in
So I added the redirection before Router::scope
if (
$this->Auth->user()
&& $this->request->params['controller'] == 'Users'
&& $this->request->params['action'] == 'login'
) {
$this->redirect(Configure::read('Route.default'));
}
Could anyone help me with that?
We can check user role from session data and make redirect according the role.
We can edit in the users controllers login function as follows
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
$loggedUser = $this->request->session()->read('Auth.User');
if($loggedUser['role'] == 'customer'){
return $this->redirect('/');
}else if($loggedUser['role'] == 'admin'){
return $this->redirect('/admin');
}else{
return $this->redirect($this->Auth->redirectUrl());
}
}
}
}
My cakephp version is 3.3.8
hey i found a solution!
create an file in App\Routing\Filter like that:
<?php
namespace App\Routing\Filter;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
class HFilter extends DispatcherFilter {
public function beforeDispatch(Event $event) {
$request = $event->data['request'];
if (isset($request->url) && $request->url == '') {
if ($request->session()->read('Auth.User')){
$request->params['controller'] = 'Users';
$request->params['action'] = 'index';
} else {
$request->params['controller'] = 'Pages';
$request->params['action'] = 'home';
}
}
}
}
?>
after add it into the bootstrap.php file without the Filter in the name like that
DispatcherFactory::add('H');
DispatcherFactory::add('Asset');
DispatcherFactory::add('Routing');
DispatcherFactory::add('ControllerFactory');

Retreving specific row from database in yii

I am working on a job site,And want to show only the jobs posted by a particular user in cgridview.My actuall aim is to authenticate the user so that only jobs posted by him/her will be visible in cgridview.I have done the following stuff,but not working.
In controller:
public function actionViewJob() {
$user_id = Yii::app()->session['user_id'];
/* For User Authentication */
if (Yii::app()->user->getId() === null)
$this->redirect(array('site/login'));
/* For User Authentication */
/* Have tried the following codes to filter */
$model= ViewJob::model()->findAll(array(
'select'=>'*',"condition"=>"user_id='$user_id'",
));
// $model=ViewJob::model()->findByAttributes(array('user_id'=>Yii::app()->user->id));
// $model = ViewJob::model()->findAll("user_id=$user_id");
$model = new Viewjob('search');
$params = array('model' => $model,
);
$this->render('viewjob', $params);
}
In view
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' =>$model->search()
// 'filter' => $model, /* not using this option ,so commented it */
))
In model
// Do I really Need This Function //
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('user_id', $this->user_id, true);
return new CActiveDataProvider('viewjob', array(
'criteria'=>$criteria,
));
},,
What am I doing wrong here.It is still fetching all the available rows in table.
You define $model 3 times:
$model= ViewJob::model()->findAll(array(
'select'=>'*',"condition"=>"user_id='$user_id'",
));
Then
$model = new Viewjob('search');
And
'dataProvider' =>$model->search()
Choose one that you need, better last. And add to controller
$model->user_id = $user_id
It will works.
Create new CDbCriteria object and add condition using it and pass it to model.
In Controller:
public function actionViewJob() {
$criteria = new CDbCriteria ();
$criteria->condition = 'user_id=' . Yii::app()->user->id;
$model = ViewJob::model()->findAll($criteria);
$params = array('model' => $model);
$this->render('viewjob', $params);
}
And in View, simply:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' =>$model
Also for use Authentication, in your controller you don't need to check, if user has the user id, simply add access rules, which will automatically redirect user to the login page to view the job and once they are logged-in, will return them to the same page. So, add this at the top of our controller..
class YourController extends Controller {
public function filters() {
return array(
'accessControl', // perform access control
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* #return array access control rules
*/
public function accessRules() {
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions' => array('index', 'view'),
'users' => array('*'),
),
array('allow', // allow authenticate user actions
'actions' => array('viewjob'),
'users' => array('#'),
),
array('deny', // deny all users
'users' => array('*'),
),
);
}

Getting a particular row from database in yii

I am working on a job site.And using Yii.I have gridview which list all the jobs posted by user,but I just want to show the jobs which are posted by a particular user.like if the user is logged in as admin then it should show only jobs posted by admin.I have tried the following things but not working.
In Controller.
//codes
public function actionViewJob() {
$user_id = Yii::app()->session['user_id'];
/* For User Authentication */
if (Yii::app()->user->getId() === null)
$this->redirect(array('site/login'));
/* For User Authentication */
$model = ViewJob::model()->find(array(
'select' => array('*'), "condition" => "user_id= $user_id",
));
$params = array('model' => $model,
);
$this->render('viewjob', $params);
}
function as search() in model ViewJob.
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('key_skills','Admin',true);
return new CActiveDataProvider('viewjob', array(
// 'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'key_skills ASC',
),
));
}
What am I doing wrong here.?.Its still listing the whole data.
Try like
$model=ViewJob::model()->findByAttributes(array('user_id'=>Yii::app()->user->id));
Try this
$model = ViewJob::model()->findAll("user_id=$user_id");
/*
1. find() can fetch first matched row, where as findAll() fetches all matched rows in the db table
2. "user_id=$user_id" is equals to WHERE user_id=$user_id
*/
Code improvements(Yii way)
Register user sessions as bellow
Yii::app()->user->setState('user_id',$value_variable); //Set the session
Yii::app()->user->getState('user_id'); //Get the session
You can use accessRules() for bellow code
if (Yii::app()->user->getId() === null)
$this->redirect(array('site/login'));
Like
public function accessRules()
{
return array(
array('allow',
'actions' => array('viewJob'),
'users' => array('#'),
----
---

How to view data only made by the user?

I created a link and what it's supposed to do is take me to the page where it displays all the announcements that I posted but instead it shows me all of the announcements inside the database.
here is my link:
<a class="more" href="<?php echo Yii::app()->createUrl('announcement')?>" ><?php switch_lang('View Announcements', '查看更多', FALSE)?></a>
This is the controller for announcement for the actionView() :
public function actionView()
{
$post=$this->loadModel();
if(Persons::model()->compare_country(explode("|",$post->country)))
{
$post->view_count = $post->view_count + 1;
Yii::app()->db->createCommand("UPDATE content SET view_count = {$post->view_count} WHERE id = {$post->id}")->execute();
//$post->save();
$comment=$this->newComment($post, 'view');
if (!empty(Yii::app()->session['announcement_message']))
{
Yii::app()->user->setFlash('message',Yii::app()->session['announcement_message']);
Yii::app()->session['announcement_message'] = null;
}
$this->render('view',array(
'model'=>$post,
'comment'=>$comment,
'view'=>'view',
));
}
else
{
$this->redirect(Yii::app()->createAbsoluteUrl('news/index',array('page'=>'1')));
}
}
Yii supports the concept of the data owner in its access control implementation.
The first step to implementing this in your own application is to instruct the controller to enable this rule. This is done by overwriting the filters() function.
class ContentController extends Controller {
public function filters() {
return array(
'accessControl'
);
}
public function accessRules() {
}
}
The 'accessControl' flag specifies that access control is applied for data management. The actual business rules are defined in the accessRules() function, and specifying the access control expression that will be evaluated to provide the desired control. And example of the function implementation is.
public function accessRules() {
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions' => array('view'),
'users' => array('*'),
),
array('allow', // allow authenticated user to perform 'add' action
'actions' => array('add'),
'users' => array('#'),
),
array('allow', // allow only the owner to perform 'modify' 'delete' actions
'actions' => array('modify', 'delete'),
'expression' => array('ContentController','isMyRecord')
),
array('deny', // deny all users
'users' => array('*'),
),
);
}
The isMyRecord is a method that will be run that returns true or false to indicate if the action should be allowed.
public function isMyRecord(){
$content_id = $_GET["content_id"];
$person = Example::model()->findByPk($content_id);
if ($example->owner_id === Yii::app()->user->id)
return true;
else
return false;
}

Codeigniter roles for more than one admin

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.

Categories