Drupal 7:User information not saving when edited by allowed users - drupal-7

I'm currently developping a new website for an artists organization. The administrator role is allowed to create accounts and some other node content, the created accounts have the same default role called "artisan". Administrators are Artisans as well. Artisans can create and edit their own content. Both administrators and artisans should be able to edit user profile (all for admin, only their own for artisan). The fact is admin can create a user but nobody (except user1) can save user profile after edit (but it works great for other nodes). Permissions have been scanned multiple times. I have been searching everywhere with no success, what am I missing ? I made very few changes, the only related code I wrote is the following :
<?php
function canardesign_system_form_alter(&$form, &$form_state, $form_id){
global $user;
switch ($form_id){
case 'oeuvre_node_form':
$form['actions']['submit']['#submit'][] = 'canardesign_system_oeuvre_redirect';
if (in_array('artisan', array_values($user->roles))){
$form['field_auteur']['#type']= 'hidden';
$form['field_auteur']['und']['#default_value']= $user->uid;
}
break;
case 'user_profile_form':
if (in_array('artisan', array_values($user->roles))){
$form['actions']['submit']['#submit'][] = 'canardesign_system_user_profile_form_submit';
}
break;
}
}
function canardesign_system_oeuvre_redirect($form, &$form_state) {
$type=$form['#node']->type;
if(isset($type))
{
$node = node_load($form_state['nid']);
$uid=field_get_items('node', $node, 'field_auteur')[0]['target_id'];
$form_state['redirect'] = 'oeuvres/'.$uid;
}
}
function canardesign_system_user_profile_form_submit($form, &$form_state) {
drupal_goto('artisans');
}
/*default role when administrator (who is artisan as well) creates an account*/
function canardesign_system_user_insert(&$edit, $account, $category) {
global $user;
if (in_array('artisan', array_values($user->roles))){
$account->role = 'artisan';
}
}
?>
Thank you for your help.

I'm not sure if this is the cause of your issue, but calling drupal_goto() inside a submit hook is definitely problematic. It essentially shorts out the handling of the form.
This may be causing the issue by preventing other necessary code from executing.
You should instead set the redirect key of $form_state to the destination you would like the user to end up on.
Once the form handling is complete, Drupal will send the user there.
function canardesign_system_user_profile_form_submit($form, &$form_state) {
$form_state['redirect'] = 'artisans';
}

Related

CakePHP 3: How to automatically log a user in after registration

I am trying to log a user in using CakePHP 3 right after registration, but I have not been successful. This is what I am doing:
function register(){
// ....
if($result = $this->Users->save($user)){
// Retrieves corresponding user that was just saved
$authUser = $this->Users->get($result->id);
// Log user in using Auth
$this->Auth->setUser($authUser);
// Redirect user
$this->redirect('/users/account');
}
}
I guess posting this question opened my eyes to a fix. This is what I did to get it to work... if there is better way, I would be glad to change it...
function register(){
// .... Default CakePHP generated code
if($result = $this->Users->save($user)){
// Retrieve user from DB
$authUser = $this->Users->get($result->id)->toArray();
// Log user in using Auth
$this->Auth->setUser($authUser);
// Redirect user
$this->redirect(['action' => 'account']);
}
}
CakePHP 3.8 × cakephp/authentication update.
Any place you were calling AuthComponent::setUser(), you should now use setIdentity():
// Assume you need to read a user by access token
$user = $this->Users->find('byToken', ['token' => $token])->first();
// Persist the user into configured authenticators.
$this->Authentication->setIdentity($user);
Source: /authentication/1/en/migration-from-the-authcomponent.html#checking-identities

Cakephp 2.x Authentication Prefix admin and agent

Iam writing an application with cakephp where i will have admin and agents where they can login to the system. Admin will have different layout from the agents. I have already create the the users table where i added a role field (admin,agent) ,i added the prefixes in core.php
Configure::write('Routing.prefixes', array('admin','agent'));
I managed to create the login and the logout for admin, but still iam confused how i should proceed with the rest. For Example i dont understand how beforeFilter() and isAuthorized() functions works. How i can check if user has access to that function or not. Also the redirections if a someone try to access this page domain.com/admin to be redirected to admin/login page .
Thanks.
Use the beforeFilter() to control access to each action, the below example will only allow access to the view and index action - any other action will be blocked :
$this->Auth->allow('view', 'index');
if you want to allow access to all the actions in your controller , try this in your before filter:
$this->Auth->allow();
To control who has access to what you could use a simple function in your app controller like so:
protected function _isAuthorized($role_required) {
if ($this->Auth->user('role') != $role_required) {
$this->Session->setFlash("your message here...");
$this->redirect("wherever you want the user to go to...");
}
}
In your controller action, eg. admin_delete on the first line you would do the following:
$this->_isAuthorized('admin');
Finally the redirect works like so:
$this->redirect(array('controller' => 'home', 'action' => 'dashboard'));
if you are redirecting within the same controller simply do the following:
$this->redirect('dashboard');
Hope this helps.
What i usually do is extend my App controller into an AdminAppController and SiteController , in the AdminAppController I have the following code in my beforeFilter:
$controller = strtolower($this->params["controller"]);
$action = strtolower($this->params["action"]);
$crole = $this->Auth->user("role");
$allowed = false;
$roles = array(
"all"=>array("user#login","user#register","user#forgot"),
"admin"=>array("pages#index","pages#view")
);
if(in_array($controller."#".$action,$roles["all"])){
$allowed = true;
}else{
if(in_array($controller."#".$action,$roles[$crole])){
$allowed = true;
}
}
if($allowed==false){
$this->setFlash("Access denied message...");
$this->redirect("...");
}
Don't know if this is the best practice but it works just fine. I normally hate CakePHP's built in Authorization system.
To check for allowance per role, I think it's best to use the Auth->allow([...]) in a per controller basis.
I find it best to check in Controller::beforeFilter() with a:
switch ($role) {
case 'admin':
$this->Auth->allow(...); //Allow delete
//notice no break; statement, so next case will execute too if admin
case 'manager':
$this->Auth->allow(...); //Allow edit
case default:
$this->Auth->allow(...); //Allow index
}
While you can check in AppController, I don't want to remember to change two files when I edit just one.

CakeDC admin is accessible by all kinds of users/roles by default, make it secure

I've installed CakeDC Users plugin and I found out that role, is_admin don't function by default. If I login with regular username role=registered and is_admin=0, I can still go to /admin/users/add/. Why are there two types of checks, role and is_admin, what if role=administrator and is_admin=0, or vice-versa?
I am looking for a preferred solution to this problem so I could secure admin section and make use of user roles on different pages. Still, can't understand why is_admin is present, when role=administrator could take care of it all.
I solved the very same issue by adding the following piece of code in "app/Controller/AppController.php" in method "beforeFilter()" :
if (isset($this->params['prefix']) && $this->params['prefix'] == 'admin') {
if ($this->Session->check('Auth.User.role') and 'admin' !== $this->Session->read('Auth.User.role')) {
$this->Auth->deny('*');
return $this->flash('Non admin access unauthorized', '/');
}
}
While I admit this solution is not optimal, it sure does the trick!
This is not an issue of the plugin: You have to implement your auth application wide on your own. The plugin just gives you the basics but does not your job of customizing the app based on the requirements of your client. I recommend you to read this chapter http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html
The is_admin check AND role field are there for multiple reasons: Your user can have any role but only if they have is_admin checked they can access an admin area for example. is_admin alone does not allow you to have roles. Both fields are there to cover different scenarios. Again, the plugin is thought to be a kick start and base you can build on. That's what you have to do when you want to customize it.
There is an example that shows pretty much how to use whatever you need:
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#using-controllerauthorize
class AppController extends Controller {
public $components = array(
'Auth' => array('authorize' => 'Controller'),
);
public function isAuthorized($user = null) {
// Any registered user can access public functions
if (empty($this->request->params['admin'])) {
return true;
}
// Only admins can access admin functions
if (isset($this->request->params['admin'])) {
return (bool)($user['role'] === 'admin');
}
// Default deny
return false;
}
}

How to add acl per row?

I have problem with ACL. I read tutorial from here and here, and now I know how to add permission to some user/group to edit his profile, but then all users can edit each other profile. How I can set permission so user can edit just his own profile, not others, or can I somehow put this code in edit function:
function edit($id = null) {
if ($logedUserId != $id) {
// deny access
return;
}
// edit user
}
Assuming that you are using action-based access control (which it appears as though you are), then unless you have an action named after each profile (which would be completely wrong) you will have to do an additional check within the edit() method to ensure that the profile being edited belongs to the currently logged in user.
So you sort of answered your own question--correctly.

How can I save an automatically generated password in CakePHP?

I am trying to automatically register users. You enter an email address and it sends the user a password. Sounds simple enough, right? Here are a bunch of things that I've tried in my add action, but none of them work (as indicated).
if (!empty($this->data)) {
$this->User->create();
$random_pass = $this->Auth->password($this->generatePassword());
// Doesn't work:
$user_data['User'] = $this->data['User'];
$user_data['User']['password'] = $random_pass;
if ($this->User->save($user_data)) { /* ... */ }
// Doesn't work:
$this->User->set('password', $random_pass);
if ($this->User->save($this->data)) { /* ... */ }
// Doesn't work:
$this->data['User']['password'] = $random_pass;
if ($this->User->save($this->data)) { /* ... */ }
// Doesn't work:
$this->data['User'][0]['password'] = $random_pass;
if ($this->User->saveAll($this->data)) { /* ... */ }
}
According to Why is the CakePHP password field is empty when trying to access it using $this->data? it's because the Auth component is removing the password. Seems common enough, no? So how do I get around it?
More information
I'm using this function to generate the password. The add view only has three fields, first_name, last_name, and email (which is assigned to the username field in the Auth component).
first of all.. you can do
$random_pass = $this->Auth->password($this->generatePassword());
pr($random_pass);
to make sure there is actually data in that variable...
then you can save that data with...
$this->data['User']['password'] = $random_pass;
$this->User->save($this->data);
Also keep in mind that... during your testing you have if (!empty($this->data))
so make sure you are actually testing by entering some form of default data somewhere in your form.
Maybe you've got some validation rules defined in your User model that are not satisfied? You can try to check this by printing $this->validationErrors (or just check your User model to see if there are any rules).
JohnP answered this question in the comments. I had some junk in the beforeSave action. Removed and now it's working perfectly. Thanks again JohnP!
I am using Cake PHP 2.3.3 and following code works for me
public function recover()
{
if ($this->request->is('post') )
{
$this->loadModel('AclManagement.User');
$passwords = AuthComponent::password($this->data['User']['password']);
$this->User->query("UPDATE users SET password = '".$passwords."' WHERE password_change = '".$this->request->data['User']['id']."' ");
$this->Session->setFlash(__('Password Saved Sucessfully'), 'success');
$this->redirect(array('action' => 'login'));
} else {
$this->set('resettoken', $_REQUEST['id']);
}
}

Resources