diff --git a/include/class_msgPool.inc b/include/class_msgPool.inc
index 3b6f0fc0e21c26d9d037c95f078c86f59991e16a..f506ca7f0d8d6fdf88168c17c60bd1d374506d88 100644
--- a/include/class_msgPool.inc
+++ b/include/class_msgPool.inc
@@ -137,23 +137,28 @@ class msgPool {
   /*!
    * \brief Display that we have no permission to modify an object
    *
-   * \param string $name Name of the object which will be modified
+   * \param string $name Name of the object which cannot be modified (or array of objects names)
+   * \param string $fields Name of the field of the object which cannot be modified
    */
-  public static function permModify($name = "")
+  public static function permModify($name = '', $field = '')
   {
-    if ($name == "") {
-      return _("You have no permission to modify this object!");
+    if ($name == '') {
+      return _('You have no permission to modify this object!');
     }
 
     if (!is_array($name)) {
-      return _("You have no permission to modify the object:")."<br><br><i>$name</i>";
+      if ($field != '') {
+        return sprintf(_('You have no permission to modify the field "%s" of object "%s"'), $field, $name);
+      } else {
+        return sprintf(_('You have no permission to modify the object:<br/>%s'), '<br/><i>'.$name.'</i>');
+      }
     }
 
     if (count($name) == 1) {
-      return _("You have no permission to modify the object:")."<br>".msgPool::buildList($name);
+      return sprintf(_('You have no permission to modify the object:<br/>%s'), msgPool::buildList($name));
     }
 
-    return _("You have no permission to modify these objects:")."<br>".msgPool::buildList($name);
+    return sprintf(_('You have no permission to modify these objects:<br/>%s'), msgPool::buildList($name));
   }
 
   /*!
@@ -466,7 +471,7 @@ class msgPool {
       }
 
       return sprintf(_("The field '%s' contains invalid characters"), $name).". ".
-        (strlen($mismatch) == 1?sprintf(_("'%s' is not allowed:"), $mismatch):sprintf(_("'%s' are not allowed!"), $mismatch)).
+        ((strlen($mismatch) == 1) ? sprintf(_("'%s' is not allowed:"), $mismatch) : sprintf(_("'%s' are not allowed!"), $mismatch)).
         "<br><br> \"$result\"$example";
     } else {
       return sprintf(_("The field '%s' contains invalid characters"), $name)."!$example";
@@ -520,9 +525,9 @@ class msgPool {
    *
    * \param string $what Text for the button
    */
-  public static function addButton($what = "")
+  public static function addButton($what = '')
   {
-    return ($what == "" ? sprintf(_("Add")): sprintf(_("Add %s"), $what));
+    return (($what == '') ? sprintf(_('Add')) : sprintf(_('Add %s'), $what));
   }
 
   /*!
@@ -530,9 +535,9 @@ class msgPool {
    *
    * \param string $what Text for the button
    */
-  public static function delButton($what = "")
+  public static function delButton($what = '')
   {
-    return ($what == "" ? sprintf(_("Delete")): sprintf(_("Delete %s"), $what));
+    return (($what == '') ? sprintf(_('Delete')) : sprintf(_('Delete %s'), $what));
   }
 
   /*!
diff --git a/include/simpleplugin/class_simplePlugin.inc b/include/simpleplugin/class_simplePlugin.inc
index a67326c5175cac6df48d83e95e7708497a3e044b..4de2a901754ef411b35cf8bf9635a8c07bbe137a 100644
--- a/include/simpleplugin/class_simplePlugin.inc
+++ b/include/simpleplugin/class_simplePlugin.inc
@@ -625,8 +625,15 @@ class simplePlugin extends plugin
     return $display;
   }
 
-  function attr_is_writeable($attr)
+  /*! \brief Check if logged in user have enough right to write this attribute value
+   *
+   * \param mixed $attr Attribute object or name (in this case it will be fetched from attributesAccess)
+   */
+  function attrIsWriteable($attr)
   {
+    if (!is_object($attr)) {
+      $attr = $this->attributesAccess[$attr];
+    }
     if ($attr->getLdapName() == 'base') {
       if (!$this->acl_skip_write() && (!$this->initially_was_account || $this->acl_is_moveable() || $this->acl_is_removeable())) {
         return TRUE;
@@ -648,7 +655,7 @@ class simplePlugin extends plugin
 
     /* Handle rights to modify the base */
     if (isset($this->attributesAccess['base'])) {
-      if ($this->attr_is_writeable($this->attributesAccess['base'])) {
+      if ($this->attrIsWriteable('base')) {
         $smarty->assign('baseACL', 'rw');
       } else {
         $smarty->assign('baseACL', 'r');
@@ -841,7 +848,7 @@ class simplePlugin extends plugin
    */
   function save_object ()
   {
-    @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, "save_object");
+    @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'save_object');
     if ($this->displayHeader && isset($_POST[get_class($this).'_modify_state'])) {
       if ($this->is_account && $this->acl_is_removeable()) {
         $this->is_account = FALSE;
@@ -849,12 +856,12 @@ class simplePlugin extends plugin
         $this->is_account = TRUE;
       }
     }
-    if (isset($_POST[get_class($this)."_posted"])) {
+    if (isset($_POST[get_class($this).'_posted'])) {
       // If our form has been posted
       // A first pass that loads the post values
       foreach ($this->attributesInfo as $section => &$sectionInfo) {
         foreach ($sectionInfo['attrs'] as &$attr) {
-          if ($this->attr_is_writeable($attr)) {
+          if ($this->attrIsWriteable($attr)) {
             // Each attribute know how to read its value from POST
             $attr->loadPostValue();
           }
@@ -865,7 +872,7 @@ class simplePlugin extends plugin
       // A second one that applies them. That allow complex stuff such as attribute disabling
       foreach ($this->attributesInfo as $section => &$sectionInfo) {
         foreach ($sectionInfo['attrs'] as &$attr) {
-          if ($this->attr_is_writeable($attr)) {
+          if ($this->attrIsWriteable($attr)) {
             // Each attribute know how to read its value from POST
             $attr->applyPostValue();
           }
@@ -1582,10 +1589,10 @@ class simplePlugin extends plugin
   {
     foreach ($values as $name => $value) {
       if (isset($this->attributesAccess[$name])) {
-        if (!$checkAcl || $this->acl_is_writeable($this->attributesAccess[$name]->getAcl())) {
+        if (!$checkAcl || $this->attrIsWriteable($name)) {
           $this->attributesAccess[$name]->setValue($value);
         } else {
-          return sprintf(_('You don\'t have sufficient rights to edit field "%s"'), $name);
+          return msgPool::permModify($this->dn, $name);
         }
       } else {
         return sprintf(_('Unknown field "%s"'), $name);
diff --git a/plugins/personal/roles/class_userRoles.inc b/plugins/personal/roles/class_userRoles.inc
index 95da55faa36c59ff9c0e5df147963da3922166b4..53906b639e78dc400fa0e432517f5623b3705706 100644
--- a/plugins/personal/roles/class_userRoles.inc
+++ b/plugins/personal/roles/class_userRoles.inc
@@ -76,9 +76,9 @@ class userRoles extends simplePlugin
     /* Groups handling */
     $groups      = array();
     $groupsattrs = objects::ls('ogroup', array('cn' => 1,  'description' => 1));
-    foreach($groupsattrs as $dn => $groupattr) {
+    foreach ($groupsattrs as $dn => $groupattr) {
       $groupDisplay = $groupattr['cn'];
-      if(isset($groupattr['description'])) {
+      if (isset($groupattr['description'])) {
         if (strlen($groupattr['description']) > 50) {
           $groupattr['description'] = substr($groupattr['description'], 0, 50).'…';
         }
@@ -105,9 +105,9 @@ class userRoles extends simplePlugin
     /* Roles handling */
     $roles        = array();
     $rolesattrs  = objects::ls('role', array('cn' => 1,  'description' => 1));
-    foreach($rolesattrs as $dn => $roleattr) {
+    foreach ($rolesattrs as $dn => $roleattr) {
       $roleDisplay = $roleattr['cn'];
-      if(isset($roleattr['description'])) {
+      if (isset($roleattr['description'])) {
         if (strlen($roleattr['description']) > 50) {
           $roleattr['description'] = substr($roleattr['description'], 0, 50).'…';
         }
@@ -216,12 +216,16 @@ class userRoles extends simplePlugin
       foreach ($groupsMembership as $ogroupdn) {
         if (!in_array($ogroupdn, $this->savedGroupsMembership)) {
           $g = objects::open($ogroupdn, 'ogroup');
+          if (!$g->getBaseObject()->attrIsWriteable('member')) {
+            $errors[] = msgPool::permModify($ogroupdn, 'member');
+            continue;
+          }
           $g->getBaseObject()->attributesAccess['member']->addValue($this->dn, $fake_attrs);
           $msg = $g->save();
           if (empty($msg)) {
             $this->savedGroupsMembership[] = $ogroupdn;
           } else {
-            msg_dialog::displayChecks($msg);
+            $errors = array_merge($errors, $msg);
           }
         }
       }
@@ -230,12 +234,16 @@ class userRoles extends simplePlugin
       foreach ($this->savedGroupsMembership as $key => $ogroupdn) {
         if (!in_array($ogroupdn, $groupsMembership)) {
           $g = objects::open($ogroupdn, 'ogroup');
+          if (!$g->getBaseObject()->attrIsWriteable('member')) {
+            $errors[] = msgPool::permModify($ogroupdn, 'member');
+            continue;
+          }
           $g->getBaseObject()->attributesAccess['member']->searchAndRemove($this->dn);
           $msg = $g->save();
           if (empty($msg)) {
             unset($this->savedGroupsMembership[$key]);
           } else {
-            msg_dialog::displayChecks($msg);
+            $errors = array_merge($errors, $msg);
           }
         }
       }
@@ -245,12 +253,16 @@ class userRoles extends simplePlugin
       foreach ($rolesMembership as $roledn) {
         if (!in_array($roledn, $this->savedRolesMembership)) {
           $r = objects::open($roledn, 'role');
+          if (!$r->getBaseObject()->attrIsWriteable('roleOccupant')) {
+            $errors[] = msgPool::permModify($roledn, 'roleOccupant');
+            continue;
+          }
           $r->getBaseObject()->attributesAccess['roleOccupant']->addValue($this->dn, $fake_attrs);
           $msg = $r->save();
           if (empty($msg)) {
             $this->savedRolesMembership[] = $roledn;
           } else {
-            msg_dialog::displayChecks($msg);
+            $errors = array_merge($errors, $msg);
           }
         }
       }
@@ -259,15 +271,21 @@ class userRoles extends simplePlugin
       foreach ($this->savedRolesMembership as $key => $roledn) {
         if (!in_array($roledn, $rolesMembership)) {
           $r = objects::open($roledn, 'role');
+          if (!$r->getBaseObject()->attrIsWriteable('roleOccupant')) {
+            $errors[] = msgPool::permModify($roledn, 'roleOccupant');
+            continue;
+          }
           $r->getBaseObject()->attributesAccess['roleOccupant']->searchAndRemove($this->dn);
           $msg = $r->save();
           if (empty($msg)) {
             unset($this->savedRolesMembership[$key]);
           } else {
-            msg_dialog::displayChecks($msg);
+            $errors = array_merge($errors, $msg);
           }
         }
       }
+
+      return $errors;
     }
   }