Version 0.1.0 0.1.0
authorThierry Florac <thierry.florac@onf.fr>
Wed, 17 Jun 2015 09:59:18 +0200
changeset 42 07229ac2497b
parent 41 905e30f5467b
child 43 d2ee97ff6d3e
Version 0.1.0
.installed.cfg
docs/README.txt
setup.py
src/pyams_security.egg-info/PKG-INFO
src/pyams_security.egg-info/SOURCES.txt
src/pyams_security.egg-info/requires.txt
src/pyams_security/__init__.py
src/pyams_security/index.py
src/pyams_security/interfaces/__init__.py
src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.mo
src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.po
src/pyams_security/locales/pyams_security.pot
src/pyams_security/plugin/admin.py
src/pyams_security/plugin/group.py
src/pyams_security/plugin/social.py
src/pyams_security/plugin/userfolder.py
src/pyams_security/principal.py
src/pyams_security/property.py
src/pyams_security/role.py
src/pyams_security/security.py
src/pyams_security/site.py
src/pyams_security/utility.py
src/pyams_security/views/login.py
src/pyams_security/widget/__init__.py
src/pyams_security/zmi/plugin/group.py
src/pyams_security/zmi/plugin/social.py
src/pyams_security/zmi/plugin/userfolder.py
src/pyams_security/zmi/security.py
src/pyams_security/zmi/utility.py
--- a/.installed.cfg	Wed May 20 12:31:27 2015 +0200
+++ b/.installed.cfg	Wed Jun 17 09:59:18 2015 +0200
@@ -1,26 +1,29 @@
 [buildout]
-installed_develop_eggs = /home/tflorac/Dropbox/src/PyAMS/pyams_security/develop-eggs/pyams-security.egg-link
+installed_develop_eggs = 
 parts = package i18n pyflakes test
 
 [package]
-__buildout_installed__ = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pshell
-	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pviews
+__buildout_installed__ = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/ptweens
+	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/proutes
+	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pshell
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pcreate
-	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/proutes
+	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pdistreport
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/prequest
-	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pdistreport
-	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/ptweens
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pserve
-__buildout_signature__ = zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.1-py3.4.egg zc.buildout-2.3.1-py3.4.egg
+	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pviews
+	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/zpasswd
+__buildout_signature__ = zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.3-py3.4.egg zc.buildout-2.3.1-py3.4.egg
 _b = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin
 _d = /home/tflorac/Dropbox/src/PyAMS/pyams_security/develop-eggs
 _e = /var/local/env/pyams/eggs
 bin-directory = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin
 develop-eggs-directory = /home/tflorac/Dropbox/src/PyAMS/pyams_security/develop-eggs
-eggs = pyams_security
+eggs = authomatic
+	pyams_security
 	pyramid
 	zope.component
 	zope.interface
+	zope.password
 eggs-directory = /var/local/env/pyams/eggs
 recipe = zc.recipe.egg
 
@@ -28,7 +31,7 @@
 __buildout_installed__ = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pybabel
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pot-create
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/polint
-__buildout_signature__ = zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.1-py3.4.egg zc.buildout-2.3.1-py3.4.egg
+__buildout_signature__ = zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.3-py3.4.egg zc.buildout-2.3.1-py3.4.egg
 _b = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin
 _d = /home/tflorac/Dropbox/src/PyAMS/pyams_security/develop-eggs
 _e = /var/local/env/pyams/eggs
@@ -42,7 +45,7 @@
 [pyflakes]
 __buildout_installed__ = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pyflakes
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/pyflakes
-__buildout_signature__ = zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.1-py3.4.egg zc.buildout-2.3.1-py3.4.egg
+__buildout_signature__ = zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.3-py3.4.egg zc.buildout-2.3.1-py3.4.egg
 _b = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin
 _d = /home/tflorac/Dropbox/src/PyAMS/pyams_security/develop-eggs
 _e = /var/local/env/pyams/eggs
@@ -58,7 +61,7 @@
 [test]
 __buildout_installed__ = /home/tflorac/Dropbox/src/PyAMS/pyams_security/parts/test
 	/home/tflorac/Dropbox/src/PyAMS/pyams_security/bin/test
-__buildout_signature__ = zc.recipe.testrunner-2.0.0-py3.4.egg zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.1-py3.4.egg zope.testrunner-4.4.6-py3.4.egg zc.buildout-2.3.1-py3.4.egg zope.interface-4.1.2-py3.4-linux-x86_64.egg zope.exceptions-4.0.7-py3.4.egg six-1482e89f68d85eea27f4ed7749df2819
+__buildout_signature__ = zc.recipe.testrunner-2.0.0-py3.4.egg zc.recipe.egg-2.0.1-py3.4.egg setuptools-12.3-py3.4.egg zope.testrunner-4.4.6-py3.4.egg zc.buildout-2.3.1-py3.4.egg zope.interface-4.1.2-py3.4-linux-x86_64.egg zope.exceptions-4.0.7-py3.4.egg six-e6b62e54b4df360c40dfcbb76c1ecf1a
 _b = /home/tflorac/Dropbox/src/PyAMS/pyams_security/bin
 _d = /home/tflorac/Dropbox/src/PyAMS/pyams_security/develop-eggs
 _e = /var/local/env/pyams/eggs
--- a/docs/README.txt	Wed May 20 12:31:27 2015 +0200
+++ b/docs/README.txt	Wed Jun 17 09:59:18 2015 +0200
@@ -2,6 +2,16 @@
 PyAMS security package
 ======================
 
+OAuth
+-----
+ - twitter : F41qIog95eVs07RupYccokWbk
+             yrEYMT3VnkT4yvCsXvaKDWok5gehU6fjz38e2FTphE8BXaapUA
+ - facebook : 417712258385794
+              0a2bfc72bdc05caff800b8e46fe8ca64
+ - google : 203791088227-a2nuqdo2t74ebv1n0s8houb4jfmjtp1t.apps.googleusercontent.com
+            gsATqmPQASMtC60OACMcOH0i
+
+
 Roles et permissions
 --------------------
  - déclaration des permissions
--- a/setup.py	Wed May 20 12:31:27 2015 +0200
+++ b/setup.py	Wed Jun 17 09:59:18 2015 +0200
@@ -61,7 +61,8 @@
           'pyramid',
           'zope.component',
           'zope.interface',
-          'zope.password'
+          'zope.password',
+          'zope.principalannotation'
       ],
       entry_points={
           'fanstatic.libraries': [
--- a/src/pyams_security.egg-info/PKG-INFO	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security.egg-info/PKG-INFO	Wed Jun 17 09:59:18 2015 +0200
@@ -10,6 +10,16 @@
         PyAMS security package
         ======================
         
+        OAuth
+        -----
+         - twitter : F41qIog95eVs07RupYccokWbk
+                     yrEYMT3VnkT4yvCsXvaKDWok5gehU6fjz38e2FTphE8BXaapUA
+         - facebook : 417712258385794
+                      0a2bfc72bdc05caff800b8e46fe8ca64
+         - google : 203791088227-a2nuqdo2t74ebv1n0s8houb4jfmjtp1t.apps.googleusercontent.com
+                    gsATqmPQASMtC60OACMcOH0i
+        
+        
         Roles et permissions
         --------------------
          - déclaration des permissions
--- a/src/pyams_security.egg-info/SOURCES.txt	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security.egg-info/SOURCES.txt	Wed Jun 17 09:59:18 2015 +0200
@@ -6,11 +6,17 @@
 src/pyams_security/configure.zcml
 src/pyams_security/credential.py
 src/pyams_security/include.py
+src/pyams_security/index.py
+src/pyams_security/notification.py
 src/pyams_security/permission.py
 src/pyams_security/principal.py
+src/pyams_security/property.py
 src/pyams_security/role.py
+src/pyams_security/schema.py
+src/pyams_security/security.py
 src/pyams_security/site.py
 src/pyams_security/utility.py
+src/pyams_security/vocabulary.py
 src/pyams_security.egg-info/PKG-INFO
 src/pyams_security.egg-info/SOURCES.txt
 src/pyams_security.egg-info/dependency_links.txt
@@ -21,9 +27,45 @@
 src/pyams_security.egg-info/top_level.txt
 src/pyams_security/doctests/README.txt
 src/pyams_security/interfaces/__init__.py
+src/pyams_security/interfaces/notification.py
+src/pyams_security/locales/pyams_security.pot
+src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.mo
+src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.po
 src/pyams_security/plugin/__init__.py
 src/pyams_security/plugin/admin.py
+src/pyams_security/plugin/group.py
 src/pyams_security/plugin/http.py
+src/pyams_security/plugin/social.py
+src/pyams_security/plugin/userfolder.py
+src/pyams_security/plugin/templates/register-info.pt
+src/pyams_security/plugin/templates/register-message.pt
+src/pyams_security/resources/img/behance.ico
+src/pyams_security/resources/img/bitbucket.ico
+src/pyams_security/resources/img/bitly.ico
+src/pyams_security/resources/img/cosm.ico
+src/pyams_security/resources/img/deviantart.ico
+src/pyams_security/resources/img/facebook.ico
+src/pyams_security/resources/img/flickr.ico
+src/pyams_security/resources/img/foursquare.ico
+src/pyams_security/resources/img/github.ico
+src/pyams_security/resources/img/google.ico
+src/pyams_security/resources/img/linkedin.ico
+src/pyams_security/resources/img/meetup.ico
+src/pyams_security/resources/img/paypal.ico
+src/pyams_security/resources/img/plurk.ico
+src/pyams_security/resources/img/reddit.ico
+src/pyams_security/resources/img/tumblr.ico
+src/pyams_security/resources/img/twitter.ico
+src/pyams_security/resources/img/ubuntuone.ico
+src/pyams_security/resources/img/viadeo.ico
+src/pyams_security/resources/img/vimeo.ico
+src/pyams_security/resources/img/vk.ico
+src/pyams_security/resources/img/windows_live.ico
+src/pyams_security/resources/img/xero.ico
+src/pyams_security/resources/img/xing.ico
+src/pyams_security/resources/img/yahoo.ico
+src/pyams_security/resources/img/yammer.ico
+src/pyams_security/resources/img/yandex.ico
 src/pyams_security/resources/js/authomatic.js
 src/pyams_security/resources/js/authomatic.min.js
 src/pyams_security/resources/js/security.js
@@ -34,10 +76,31 @@
 src/pyams_security/views/__init__.py
 src/pyams_security/views/login.py
 src/pyams_security/views/oauth.py
+src/pyams_security/views/userfolder.py
+src/pyams_security/views/utility.py
 src/pyams_security/views/templates/social-login.pt
+src/pyams_security/views/templates/user-registration-end.pt
+src/pyams_security/views/templates/user-registration.pt
+src/pyams_security/widget/__init__.py
+src/pyams_security/widget/interfaces.py
+src/pyams_security/widget/templates/permission-display.pt
+src/pyams_security/widget/templates/permission-input.pt
+src/pyams_security/widget/templates/permissions-set-display.pt
+src/pyams_security/widget/templates/permissions-set-input.pt
+src/pyams_security/widget/templates/principal-display.pt
+src/pyams_security/widget/templates/principal-input.pt
+src/pyams_security/widget/templates/principals-set-display.pt
+src/pyams_security/widget/templates/principals-set-input.pt
 src/pyams_security/zmi/__init__.py
-src/pyams_security/zmi/configure.zcml
 src/pyams_security/zmi/interfaces.py
+src/pyams_security/zmi/notification.py
+src/pyams_security/zmi/security.py
 src/pyams_security/zmi/utility.py
 src/pyams_security/zmi/plugin/__init__.py
-src/pyams_security/zmi/plugin/admin.py
\ No newline at end of file
+src/pyams_security/zmi/plugin/admin.py
+src/pyams_security/zmi/plugin/group.py
+src/pyams_security/zmi/plugin/social.py
+src/pyams_security/zmi/plugin/userfolder.py
+src/pyams_security/zmi/widget/__init__.py
+src/pyams_security/zmi/widget/templates/ordered-list-display.pt
+src/pyams_security/zmi/widget/templates/ordered-list-input.pt
\ No newline at end of file
--- a/src/pyams_security.egg-info/requires.txt	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security.egg-info/requires.txt	Wed Jun 17 09:59:18 2015 +0200
@@ -1,8 +1,10 @@
 setuptools
+authomatic
 fanstatic
 pyramid
 zope.component
 zope.interface
 zope.password
+zope.principalannotation
 
 [test]
--- a/src/pyams_security/__init__.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/__init__.py	Wed Jun 17 09:59:18 2015 +0200
@@ -40,6 +40,14 @@
     config.register_permission({'id': 'system.manage',
                                 'title': _("Manage system properties")})
 
+    config.register_permission({'id': 'security.manage',
+                                'title': _("Manage security")})
+    config.register_permission({'id': 'security.manage_roles',
+                                'title': _("Manage roles")})
+
+    # register custom roles
     config.register_role({'id': 'system.Manager',
                           'title': "System manager (role)",
-                          'permissions': {'public', 'view', 'manage', 'system.manage', 'system.view'}})
+                          'permissions': {'public', 'view', 'manage', 'system.manage', 'system.view',
+                                          'security.manage', 'security.manage_roles'},
+                          'managers': {'system:admin', 'role:system.Manager'}})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_security/index.py	Wed Jun 17 09:59:18 2015 +0200
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_security.interfaces import IProtectedObject
+
+# import packages
+from hypatia.keyword import KeywordIndex
+
+
+class PrincipalsRoleIndex(KeywordIndex):
+    """Principals role index"""
+
+    def __init__(self, role_id, family=None):
+        KeywordIndex.__init__(self, role_id, family)
+        self.role_id = role_id
+
+    def discriminate(self, obj, default):
+        protected_object = IProtectedObject(obj, None)
+        if protected_object is None:
+            return default
+        return protected_object.get_principals(self.role_id)
--- a/src/pyams_security/interfaces/__init__.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/interfaces/__init__.py	Wed Jun 17 09:59:18 2015 +0200
@@ -33,6 +33,9 @@
 from pyams_security import _
 
 
+FORBIDDEN_PERMISSION = 'system.forbidden'
+
+
 class IPermission(Interface):
     """Permission utility class"""
 
@@ -63,6 +66,12 @@
                       value_type=TextLine(),
                       required=False)
 
+    managers = Set(title="Managers",
+                   description="List of principal IDs allowed to manage this role. "
+                               "If it's a role, use 'role:role_id' syntax...",
+                   value_type=TextLine(),
+                   required=False)
+
 
 class IPrincipalInfo(Interface):
     """Principal info class
@@ -178,8 +187,12 @@
 class IDirectoryInfo(Interface):
     """Principal directory plug-in interface"""
 
-    def get_principal(self, principal_id):
-        """Returns real principal matching given ID, or None"""
+    def get_principal(self, principal_id, info=True):
+        """Returns real principal matching given ID, or None
+
+        If info is True, returns a PrincipalINfo record instead
+        of original principal object
+        """
 
     def get_all_principals(self, principal_id):
         """Returns all principals matching given principal ID"""
Binary file src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.mo has changed
--- a/src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.po	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/locales/fr/LC_MESSAGES/pyams_security.po	Wed Jun 17 09:59:18 2015 +0200
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2015-04-17 13:45+0200\n"
+"POT-Creation-Date: 2015-06-01 14:47+0200\n"
 "PO-Revision-Date: 2015-02-18 22:19+0100\n"
 "Last-Translator: Thierry Florac <tflorac@ulthar.net>\n"
 "Language-Team: French\n"
@@ -16,35 +16,49 @@
 "Generated-By: Lingua 3.8\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: src/pyams_security/__init__.py:41
+#: src/pyams_security/__init__.py:33
 msgid "View public contents"
 msgstr "Voir les contenus publics"
 
-#: src/pyams_security/__init__.py:43
+#: src/pyams_security/__init__.py:35
 msgid "View protected contents"
 msgstr "Voir les contenus protégés"
 
-#: src/pyams_security/__init__.py:45
+#: src/pyams_security/__init__.py:37
 msgid "Manage contents properties"
 msgstr "Gérer les propriétés des contenus"
 
-#: src/pyams_security/__init__.py:47
+#: src/pyams_security/__init__.py:39
 msgid "View management screens"
 msgstr "Voir les propriétés du système"
 
-#: src/pyams_security/__init__.py:49
+#: src/pyams_security/__init__.py:41
 msgid "Manage system properties"
 msgstr "Gérer les propriétés du système"
 
+#: src/pyams_security/__init__.py:44
+msgid "Manage security"
+msgstr "Gérer les paramètres de sécurité"
+
+#: src/pyams_security/__init__.py:46
+msgid "Manage roles"
+msgstr "Gérer l'attribution des rôles"
+
 #: src/pyams_security/principal.py:53
 msgid "Not logged in"
 msgstr "Non connecté"
 
 #: src/pyams_security/widget/templates/principals-set-input.pt:4
 #: src/pyams_security/widget/templates/principal-input.pt:4
+#: src/pyams_security/widget/templates/permission-input.pt:4
+#: src/pyams_security/widget/templates/permissions-set-input.pt:4
 msgid "Clear selected values"
 msgstr "Effacer les valeurs sélectionnées"
 
+#: src/pyams_security/widget/templates/permissions-set-input.pt:11
+msgid "Select permissions..."
+msgstr "Sélectionner des permissions..."
+
 #: src/pyams_security/zmi/utility.py:75
 msgid "Security"
 msgstr "Sécurité"
@@ -53,39 +67,39 @@
 msgid "Authentication and users directory plug-ins"
 msgstr "Modules d'authentification et dossiers utilisateurs"
 
-#: src/pyams_security/zmi/utility.py:105
+#: src/pyams_security/zmi/utility.py:104
 msgid "See plug-in contents"
 msgstr "Voir le contenu du module"
 
-#: src/pyams_security/zmi/utility.py:120
+#: src/pyams_security/zmi/utility.py:119
 #: src/pyams_security/zmi/plugin/social.py:195
 #: src/pyams_security/zmi/plugin/social.py:328
 #: src/pyams_security/zmi/plugin/userfolder.py:192
 #: src/pyams_security/zmi/plugin/group.py:159
-#: src/pyams_security/interfaces/__init__.py:236
+#: src/pyams_security/interfaces/__init__.py:246
 msgid "Name"
 msgstr "Nom"
 
-#: src/pyams_security/zmi/utility.py:129
+#: src/pyams_security/zmi/utility.py:128
 msgid "Delete plug-in"
 msgstr "Supprimer ce module"
 
-#: src/pyams_security/zmi/utility.py:163
+#: src/pyams_security/zmi/utility.py:162
 #: src/pyams_security/zmi/plugin/social.py:370
 #: src/pyams_security/zmi/plugin/social.py:388
 #: src/pyams_security/zmi/plugin/social.py:443
 msgid "Security manager"
 msgstr "Gestionnaire de sécurité"
 
-#: src/pyams_security/zmi/utility.py:164
+#: src/pyams_security/zmi/utility.py:163
 msgid "Security manager plug-ins"
 msgstr "Modules du gestionnaire de sécurité"
 
-#: src/pyams_security/zmi/utility.py:172
+#: src/pyams_security/zmi/utility.py:171
 msgid "Properties..."
 msgstr "Propriétés..."
 
-#: src/pyams_security/zmi/utility.py:185
+#: src/pyams_security/zmi/utility.py:184
 #: src/pyams_security/zmi/notification.py:58
 #: src/pyams_security/zmi/plugin/social.py:79
 #: src/pyams_security/zmi/plugin/userfolder.py:76
@@ -94,29 +108,29 @@
 msgid "System security manager"
 msgstr "Gestionnaire de sécurité"
 
-#: src/pyams_security/zmi/utility.py:186
+#: src/pyams_security/zmi/utility.py:185
 msgid "Security manager properties"
 msgstr "Propriétés du gestionnaire de sécurité"
 
-#: src/pyams_security/zmi/utility.py:223
+#: src/pyams_security/zmi/utility.py:222
 msgid "Plug-ins"
 msgstr "Modules"
 
-#: src/pyams_security/zmi/utility.py:208
-#: src/pyams_security/interfaces/__init__.py:542
+#: src/pyams_security/zmi/utility.py:207
+#: src/pyams_security/interfaces/__init__.py:552
 msgid "Enable social login?"
 msgstr "Activer les réseaux sociaux ?"
 
-#: src/pyams_security/zmi/utility.py:215
-#: src/pyams_security/interfaces/__init__.py:566
+#: src/pyams_security/zmi/utility.py:214
+#: src/pyams_security/interfaces/__init__.py:576
 msgid "Enable free registration?"
 msgstr "Activer l'inscription libre ?"
 
-#: src/pyams_security/zmi/utility.py:245
+#: src/pyams_security/zmi/utility.py:244
 msgid "No provided object_name argument!"
 msgstr "Argument 'object_name' non fourni !"
 
-#: src/pyams_security/zmi/utility.py:249
+#: src/pyams_security/zmi/utility.py:248
 msgid "Given plug-in name doesn't exist!"
 msgstr "Le module indiqué n'existe pas !"
 
@@ -128,15 +142,19 @@
 msgid "Notifications properties"
 msgstr "Paramétrage des notifications"
 
-#: src/pyams_security/zmi/security.py:41
+#: src/pyams_security/zmi/security.py:46
 msgid "Access rules..."
 msgstr "Règles d'accès..."
 
-#: src/pyams_security/zmi/security.py:56
-msgid "Edit local roles"
-msgstr "Gestion des règles d'accès"
+#: src/pyams_security/zmi/security.py:71
+msgid "Security management"
+msgstr "Paramètres de sécurité"
 
-#: src/pyams_security/zmi/security.py:73 src/pyams_security/zmi/security.py:74
+#: src/pyams_security/zmi/security.py:93
+msgid "Granted roles"
+msgstr "Affectation des rôles"
+
+#: src/pyams_security/zmi/security.py:83 src/pyams_security/zmi/security.py:84
 msgid "(inherit from parent)"
 msgstr "(héritée du parent)"
 
@@ -168,19 +186,19 @@
 
 #: src/pyams_security/zmi/plugin/social.py:205
 #: src/pyams_security/zmi/plugin/userfolder.py:202
-#: src/pyams_security/interfaces/__init__.py:247
-#: src/pyams_security/interfaces/__init__.py:323
+#: src/pyams_security/interfaces/__init__.py:257
+#: src/pyams_security/interfaces/__init__.py:333
 msgid "E-mail address"
 msgstr "Adresse de messagerie"
 
 #: src/pyams_security/zmi/plugin/social.py:215
-#: src/pyams_security/interfaces/__init__.py:231
+#: src/pyams_security/interfaces/__init__.py:241
 msgid "OAuth provider name"
 msgstr "Nom du fournisseur"
 
 #: src/pyams_security/zmi/plugin/social.py:225
 #: src/pyams_security/zmi/plugin/userfolder.py:212
-#: src/pyams_security/interfaces/__init__.py:271
+#: src/pyams_security/interfaces/__init__.py:281
 msgid "Registration date"
 msgstr "Date d'enregistrement"
 
@@ -266,8 +284,8 @@
 msgstr "Code utilisateur"
 
 #: src/pyams_security/zmi/plugin/userfolder.py:228
-#: src/pyams_security/interfaces/__init__.py:445
-#: src/pyams_security/interfaces/__init__.py:448
+#: src/pyams_security/interfaces/__init__.py:455
+#: src/pyams_security/interfaces/__init__.py:458
 msgid "Activation date"
 msgstr "Date d'activation"
 
@@ -305,7 +323,7 @@
 msgstr "Groupes locaux"
 
 #: src/pyams_security/zmi/plugin/group.py:169
-#: src/pyams_security/interfaces/__init__.py:489
+#: src/pyams_security/interfaces/__init__.py:499
 msgid "Description"
 msgstr "Description"
 
@@ -424,9 +442,9 @@
 msgstr "Veuillez indiquer vos paramètres de connexion"
 
 #: src/pyams_security/views/login.py:57
-#: src/pyams_security/interfaces/__init__.py:342
-#: src/pyams_security/interfaces/__init__.py:368
-#: src/pyams_security/interfaces/__init__.py:420
+#: src/pyams_security/interfaces/__init__.py:352
+#: src/pyams_security/interfaces/__init__.py:378
+#: src/pyams_security/interfaces/__init__.py:430
 msgid "Password"
 msgstr "Mot de passe"
 
@@ -465,92 +483,92 @@
 msgid "Return to home page"
 msgstr "Retourner à la page d'accueil"
 
-#: src/pyams_security/interfaces/__init__.py:131
+#: src/pyams_security/interfaces/__init__.py:137
 msgid "Plug-in prefix"
 msgstr "Préfixe du module"
 
-#: src/pyams_security/interfaces/__init__.py:132
+#: src/pyams_security/interfaces/__init__.py:138
 msgid ""
 "This prefix is mainly used by authentication plug-ins to mark principals"
 msgstr ""
 "Ce préfixe est utilisé par les modules d'authentification pour identifier "
 "les utilisateurs"
 
-#: src/pyams_security/interfaces/__init__.py:134
+#: src/pyams_security/interfaces/__init__.py:140
 msgid "Plug-in title"
 msgstr "Libellé du module"
 
-#: src/pyams_security/interfaces/__init__.py:137
+#: src/pyams_security/interfaces/__init__.py:143
 msgid "Enabled plug-in?"
 msgstr "Module actif ?"
 
-#: src/pyams_security/interfaces/__init__.py:138
+#: src/pyams_security/interfaces/__init__.py:144
 msgid "You can choose to disable any plug-in..."
 msgstr ""
 "Un module inactif ne peut plus être utilisé pour authentifier ou rechercher "
 "les utilisateurs..."
 
-#: src/pyams_security/interfaces/__init__.py:173
+#: src/pyams_security/interfaces/__init__.py:179
 msgid "Admin. login"
 msgstr "Code utilisateur"
 
-#: src/pyams_security/interfaces/__init__.py:175
+#: src/pyams_security/interfaces/__init__.py:181
 msgid "Admin. password"
 msgstr "Mot de passe"
 
-#: src/pyams_security/interfaces/__init__.py:229
+#: src/pyams_security/interfaces/__init__.py:239
 msgid "Internal provider ID"
 msgstr "ID du connecteur"
 
-#: src/pyams_security/interfaces/__init__.py:233
+#: src/pyams_security/interfaces/__init__.py:243
 msgid "User name"
 msgstr "Nom d'utilisateur"
 
-#: src/pyams_security/interfaces/__init__.py:238
-#: src/pyams_security/interfaces/__init__.py:333
-#: src/pyams_security/interfaces/__init__.py:404
+#: src/pyams_security/interfaces/__init__.py:248
+#: src/pyams_security/interfaces/__init__.py:343
+#: src/pyams_security/interfaces/__init__.py:414
 msgid "First name"
 msgstr "Prénom"
 
-#: src/pyams_security/interfaces/__init__.py:241
-#: src/pyams_security/interfaces/__init__.py:336
-#: src/pyams_security/interfaces/__init__.py:407
+#: src/pyams_security/interfaces/__init__.py:251
+#: src/pyams_security/interfaces/__init__.py:346
+#: src/pyams_security/interfaces/__init__.py:417
 msgid "Last name"
 msgstr "Nom"
 
-#: src/pyams_security/interfaces/__init__.py:244
+#: src/pyams_security/interfaces/__init__.py:254
 msgid "Nickname"
 msgstr "Surnom"
 
-#: src/pyams_security/interfaces/__init__.py:250
+#: src/pyams_security/interfaces/__init__.py:260
 msgid "Timezone"
 msgstr "Fuseau horaire"
 
-#: src/pyams_security/interfaces/__init__.py:253
+#: src/pyams_security/interfaces/__init__.py:263
 msgid "Country"
 msgstr "Pays"
 
-#: src/pyams_security/interfaces/__init__.py:256
+#: src/pyams_security/interfaces/__init__.py:266
 msgid "City"
 msgstr "Ville"
 
-#: src/pyams_security/interfaces/__init__.py:259
+#: src/pyams_security/interfaces/__init__.py:269
 msgid "Postal code"
 msgstr "Code postal"
 
-#: src/pyams_security/interfaces/__init__.py:262
+#: src/pyams_security/interfaces/__init__.py:272
 msgid "Locale code"
 msgstr "Langue"
 
-#: src/pyams_security/interfaces/__init__.py:265
+#: src/pyams_security/interfaces/__init__.py:275
 msgid "Picture URL"
 msgstr "Photo (URL)"
 
-#: src/pyams_security/interfaces/__init__.py:268
+#: src/pyams_security/interfaces/__init__.py:278
 msgid "Birth date"
 msgstr "Date de naissance"
 
-#: src/pyams_security/interfaces/__init__.py:304
+#: src/pyams_security/interfaces/__init__.py:314
 msgid ""
 "Your password must contain at least three of these kinds of characters: "
 "lowercase letters, uppercase letters, numbers and special characters"
@@ -558,20 +576,20 @@
 "Votre mot de passe doit contenir au moins trois de ces types de caractères : "
 "minuscules, majuscules, chiffres et autres caractères"
 
-#: src/pyams_security/interfaces/__init__.py:314
-#: src/pyams_security/interfaces/__init__.py:365
-#: src/pyams_security/interfaces/__init__.py:387
+#: src/pyams_security/interfaces/__init__.py:324
+#: src/pyams_security/interfaces/__init__.py:375
+#: src/pyams_security/interfaces/__init__.py:397
 msgid "User login"
 msgstr "Code utilisateur"
 
-#: src/pyams_security/interfaces/__init__.py:315
+#: src/pyams_security/interfaces/__init__.py:325
 msgid ""
 "If you don't provide a custom login, your login will be your email address..."
 msgstr ""
 "Si vous n'indiquez pas de code utilisateur, vous pourrez utiliser votre "
 "adresse de messagerie pour vous connecter..."
 
-#: src/pyams_security/interfaces/__init__.py:324
+#: src/pyams_security/interfaces/__init__.py:334
 msgid ""
 "An email will be sent to this address to validate account activation; it "
 "will be used as your future user login"
@@ -580,12 +598,12 @@
 "permettre d'activer votre compte ; il pourra être utilisé compte identifiant "
 "de connexion si vous n'avez pas indiqué de code utilisateur"
 
-#: src/pyams_security/interfaces/__init__.py:339
-#: src/pyams_security/interfaces/__init__.py:412
+#: src/pyams_security/interfaces/__init__.py:349
+#: src/pyams_security/interfaces/__init__.py:422
 msgid "Company name"
 msgstr "Société"
 
-#: src/pyams_security/interfaces/__init__.py:343
+#: src/pyams_security/interfaces/__init__.py:353
 msgid ""
 "Password must be at least 8 characters long, and contain at least three kins "
 "of characters between lowercase letters, uppercase letters, numbers and "
@@ -595,29 +613,29 @@
 "moins trois types de caractères parmi les lettres minuscules, les "
 "majuscules, les chiffres et les caractères spéciaux"
 
-#: src/pyams_security/interfaces/__init__.py:349
-#: src/pyams_security/interfaces/__init__.py:372
+#: src/pyams_security/interfaces/__init__.py:359
+#: src/pyams_security/interfaces/__init__.py:382
 msgid "Confirmed password"
 msgstr "Confirmation du mot de passe"
 
-#: src/pyams_security/interfaces/__init__.py:362
-#: src/pyams_security/interfaces/__init__.py:439
+#: src/pyams_security/interfaces/__init__.py:372
+#: src/pyams_security/interfaces/__init__.py:449
 msgid "Activation hash"
 msgstr "Clé d'activation"
 
-#: src/pyams_security/interfaces/__init__.py:396
+#: src/pyams_security/interfaces/__init__.py:406
 msgid "User email address"
 msgstr "Adresse de messagerie"
 
-#: src/pyams_security/interfaces/__init__.py:415
+#: src/pyams_security/interfaces/__init__.py:425
 msgid "Password manager name"
 msgstr "Gestionnaire de mot de passe"
 
-#: src/pyams_security/interfaces/__init__.py:424
+#: src/pyams_security/interfaces/__init__.py:434
 msgid "Wait confirmation?"
 msgstr "Attendre la confirmation ?"
 
-#: src/pyams_security/interfaces/__init__.py:425
+#: src/pyams_security/interfaces/__init__.py:435
 msgid ""
 "If 'no', user will be activated immediately without waiting email "
 "confirmation"
@@ -625,20 +643,20 @@
 "Si 'non', ce compte utilisateur sera activé immédiatement sans attendre le "
 "message de confirmation"
 
-#: src/pyams_security/interfaces/__init__.py:430
+#: src/pyams_security/interfaces/__init__.py:440
 msgid "Self-registered profile?"
 msgstr "Profil auto-enregistré ?"
 
-#: src/pyams_security/interfaces/__init__.py:435
+#: src/pyams_security/interfaces/__init__.py:445
 msgid "Activation secret key"
 msgstr "Clé secrète"
 
-#: src/pyams_security/interfaces/__init__.py:436
+#: src/pyams_security/interfaces/__init__.py:446
 msgid "This private secret is used to create and check activation hash"
 msgstr ""
 "Cette clé secrète est utilisé pour créer et vérifier la clé d'activation"
 
-#: src/pyams_security/interfaces/__init__.py:440
+#: src/pyams_security/interfaces/__init__.py:450
 msgid ""
 "This hash is provided into activation message URL. Activation hash is "
 "missing for local users which were registered without waiting their "
@@ -648,84 +666,84 @@
 "Cette clé d'activation n'est pas définie pour les utilisateurs pour lesquels "
 "l'attente de confirmation n'a pas été demandée."
 
-#: src/pyams_security/interfaces/__init__.py:480
+#: src/pyams_security/interfaces/__init__.py:490
 msgid "Group ID"
 msgstr "ID du groupe"
 
-#: src/pyams_security/interfaces/__init__.py:481
+#: src/pyams_security/interfaces/__init__.py:491
 msgid "This ID should be unique between all groups"
 msgstr "Cet ID doit être unique pour tous les groupes"
 
-#: src/pyams_security/interfaces/__init__.py:485
+#: src/pyams_security/interfaces/__init__.py:495
 msgid "Title"
 msgstr "Nom"
 
-#: src/pyams_security/interfaces/__init__.py:486
+#: src/pyams_security/interfaces/__init__.py:496
 msgid "Public label of this group"
 msgstr "Libellé public de ce groupe"
 
-#: src/pyams_security/interfaces/__init__.py:492
+#: src/pyams_security/interfaces/__init__.py:502
 msgid "Group principals"
 msgstr "Mandants du groupe"
 
-#: src/pyams_security/interfaces/__init__.py:493
+#: src/pyams_security/interfaces/__init__.py:503
 msgid "IDs of principals contained in this group"
 msgstr "ID des mandants contenus dans ce groupe"
 
-#: src/pyams_security/interfaces/__init__.py:543
+#: src/pyams_security/interfaces/__init__.py:553
 msgid "Enable login via social OAuth plug-ins"
 msgstr ""
 "Autoriser la connexion à partir des réseaux sociaux via les modules OAuth"
 
-#: src/pyams_security/interfaces/__init__.py:547
+#: src/pyams_security/interfaces/__init__.py:557
 msgid "Social users folder"
 msgstr "Dossier des utilisateurs \"sociaux\""
 
-#: src/pyams_security/interfaces/__init__.py:548
+#: src/pyams_security/interfaces/__init__.py:558
 msgid "Name of folder used to store social users properties"
 msgstr ""
 "Nom du dossier dans lequel seront stockés les profils des utilisateurs "
 "connectés via des réseaux sociaux"
 
-#: src/pyams_security/interfaces/__init__.py:557
+#: src/pyams_security/interfaces/__init__.py:567
 msgid "Authomatic secret"
 msgstr "Clé OAuth"
 
-#: src/pyams_security/interfaces/__init__.py:558
+#: src/pyams_security/interfaces/__init__.py:568
 msgid "This secret phrase is used to encrypt Authomatic cookie"
 msgstr ""
 "Cette phrase secrète est utilisée pour crypter le cookie d'authentification"
 
-#: src/pyams_security/interfaces/__init__.py:562
+#: src/pyams_security/interfaces/__init__.py:572
 msgid "Use social popup?"
 msgstr "Connection via une popup ?"
 
-#: src/pyams_security/interfaces/__init__.py:567
+#: src/pyams_security/interfaces/__init__.py:577
 msgid "If 'Yes', any use will be able to create a new user account"
 msgstr "Si 'oui', toute personne sera à même de se créer un compte utilisateur"
 
-#: src/pyams_security/interfaces/__init__.py:571
+#: src/pyams_security/interfaces/__init__.py:581
 msgid "Users folder"
 msgstr "Dossier des utilisateurs locaux"
 
-#: src/pyams_security/interfaces/__init__.py:572
+#: src/pyams_security/interfaces/__init__.py:582
 msgid "Name of users folder used to store registered principals"
 msgstr "Nom du dossier dans lequel seront créés les utilisateurs enregistrés"
 
-#: src/pyams_security/interfaces/__init__.py:581
+#: src/pyams_security/interfaces/__init__.py:591
 msgid "Credentials plug-ins"
 msgstr "Modules d'identification"
 
-#: src/pyams_security/interfaces/__init__.py:582
+#: src/pyams_security/interfaces/__init__.py:592
 msgid "These plug-ins can be used to extract request credentials"
 msgstr ""
 "Ces modules peuvent être utilisés pour extraire l'identitité des utilisateurs"
 
-#: src/pyams_security/interfaces/__init__.py:587
+#: src/pyams_security/interfaces/__init__.py:597
 msgid "Authentication plug-ins"
 msgstr "Modules d'authentification"
 
-#: src/pyams_security/interfaces/__init__.py:588
+#: src/pyams_security/interfaces/__init__.py:598
 msgid ""
 "The plug-ins can be used to check extracted credentials against a local or "
 "remote users database"
@@ -733,88 +751,88 @@
 "Ces modules sont utilisés pour vérifier l'identité des utilisateurs vis à "
 "vis d'une base d'utilisateurs locale ou distante"
 
-#: src/pyams_security/interfaces/__init__.py:593
+#: src/pyams_security/interfaces/__init__.py:603
 msgid "Directory plug-ins"
 msgstr "Modules d'annuaires"
 
-#: src/pyams_security/interfaces/__init__.py:594
+#: src/pyams_security/interfaces/__init__.py:604
 msgid "The plug-in can be used to extract principals information"
 msgstr ""
 "Ces modules peuvent être utilisés pour extraire les propriétés des "
 "utilisateurs"
 
-#: src/pyams_security/interfaces/__init__.py:668
+#: src/pyams_security/interfaces/__init__.py:678
 msgid "Provider name"
 msgstr "Nom du fournisseur"
 
-#: src/pyams_security/interfaces/__init__.py:672
+#: src/pyams_security/interfaces/__init__.py:682
 msgid "Provider ID"
 msgstr "ID du fournisseur"
 
-#: src/pyams_security/interfaces/__init__.py:673
+#: src/pyams_security/interfaces/__init__.py:683
 msgid "This value should be unique between all providers"
 msgstr "Cette valeur numérique doit être unique pour tous les fournisseurs"
 
-#: src/pyams_security/interfaces/__init__.py:677
+#: src/pyams_security/interfaces/__init__.py:687
 msgid "Provider consumer key"
 msgstr "Clé cliente"
 
-#: src/pyams_security/interfaces/__init__.py:680
+#: src/pyams_security/interfaces/__init__.py:690
 msgid "Provider secret"
 msgstr "Clé secrète"
 
-#: src/pyams_security/interfaces/__init__.py:698
+#: src/pyams_security/interfaces/__init__.py:708
 msgid "Inherit parent security?"
 msgstr "Héritage de la sécurité ?"
 
-#: src/pyams_security/interfaces/__init__.py:699
+#: src/pyams_security/interfaces/__init__.py:709
 msgid "Get access control entries (ACE) inherited from parent levels"
 msgstr "Utiliser les règles d'accès (ACE) héritées du parent"
 
-#: src/pyams_security/interfaces/__init__.py:704
-msgid "Public permission"
-msgstr "Permission publique"
+#: src/pyams_security/interfaces/__init__.py:714
+msgid "Public permissions"
+msgstr "Permissions publiques"
 
-#: src/pyams_security/interfaces/__init__.py:705
-msgid "This permission will be granted to all users"
-msgstr "Cette permission sera attribuée à tous les utilisateurs"
+#: src/pyams_security/interfaces/__init__.py:715
+msgid "These permissions will be granted to all users"
+msgstr "Ces permissions seront attribuées à tous les utilisateurs"
 
-#: src/pyams_security/interfaces/__init__.py:709
-msgid "Authenticated permission"
-msgstr "Permission authentifiée"
+#: src/pyams_security/interfaces/__init__.py:718
+msgid "Authenticated permissions"
+msgstr "Permissions authentifiées"
 
-#: src/pyams_security/interfaces/__init__.py:710
-msgid "This permission will be granted to authenticated users"
-msgstr "Cette permission sera attribuée à tous les utilisateurs authentifiés"
+#: src/pyams_security/interfaces/__init__.py:719
+msgid "These permissions will be granted to authenticated users"
+msgstr "Ces permissions seront attribuées à tous les utilisateurs authentifiés"
 
-#: src/pyams_security/interfaces/__init__.py:714
+#: src/pyams_security/interfaces/__init__.py:723
 msgid "Inherit parent roles?"
 msgstr "Héritage des rôles ?"
 
-#: src/pyams_security/interfaces/__init__.py:715
+#: src/pyams_security/interfaces/__init__.py:724
 msgid "Get roles granted on parent levels"
 msgstr "Disposer des rôles affectés aux niveaux parents"
 
-#: src/pyams_security/interfaces/__init__.py:331
+#: src/pyams_security/interfaces/__init__.py:341
 msgid "Your email address is not valid!"
 msgstr "Votre adresse de messagerie est incorrecte !"
 
-#: src/pyams_security/interfaces/__init__.py:355
-#: src/pyams_security/interfaces/__init__.py:378
+#: src/pyams_security/interfaces/__init__.py:365
+#: src/pyams_security/interfaces/__init__.py:388
 msgid "You didn't confirmed your password correctly!"
 msgstr "Vous n'avez pas confirmé votre mot de passe correctement !"
 
-#: src/pyams_security/interfaces/__init__.py:402
+#: src/pyams_security/interfaces/__init__.py:412
 msgid "Given email address is not valid!"
 msgstr "L'adrese de messagerie indiquée est invalide !"
 
-#: src/pyams_security/interfaces/__init__.py:555
+#: src/pyams_security/interfaces/__init__.py:565
 msgid "You can't activate social login without selecting a social users folder"
 msgstr ""
 "Vous ne pouvez pas activer la connexion via les réseaux sociaux sans "
 "sélectionner de dossier de stockage des utilisateurs"
 
-#: src/pyams_security/interfaces/__init__.py:579
+#: src/pyams_security/interfaces/__init__.py:589
 msgid "You can't activate open registration without selecting a users folder"
 msgstr ""
 "Vous ne pouvez pas activer les fonctions d'inscription libre sans "
@@ -905,7 +923,7 @@
 msgstr ""
 "Impossible de confirmer votre inscription avec les paramètres fournis !"
 
-#: src/pyams_security/plugin/userfolder.py:252
+#: src/pyams_security/plugin/userfolder.py:255
 #, python-format
 msgid "{prefix}Please confirm registration"
 msgstr "{prefix}Veuillez confirmer votre inscription"
@@ -972,3 +990,6 @@
 msgstr ""
 "Vous avez créé un nouveau compte que vous devez confirmer avant de pouvoir "
 "utiliser ce service."
+
+#~ msgid "Edit local roles"
+#~ msgstr "Gestion des règles d'accès"
--- a/src/pyams_security/locales/pyams_security.pot	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/locales/pyams_security.pot	Wed Jun 17 09:59:18 2015 +0200
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2015-04-17 13:45+0200\n"
+"POT-Creation-Date: 2015-06-01 14:47+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,35 +16,49 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Lingua 3.10.dev0\n"
 
-#: ./src/pyams_security/__init__.py:41
+#: ./src/pyams_security/__init__.py:33
 msgid "View public contents"
 msgstr ""
 
-#: ./src/pyams_security/__init__.py:43
+#: ./src/pyams_security/__init__.py:35
 msgid "View protected contents"
 msgstr ""
 
-#: ./src/pyams_security/__init__.py:45
+#: ./src/pyams_security/__init__.py:37
 msgid "Manage contents properties"
 msgstr ""
 
-#: ./src/pyams_security/__init__.py:47
+#: ./src/pyams_security/__init__.py:39
 msgid "View management screens"
 msgstr ""
 
-#: ./src/pyams_security/__init__.py:49
+#: ./src/pyams_security/__init__.py:41
 msgid "Manage system properties"
 msgstr ""
 
+#: ./src/pyams_security/__init__.py:44
+msgid "Manage security"
+msgstr ""
+
+#: ./src/pyams_security/__init__.py:46
+msgid "Manage roles"
+msgstr ""
+
 #: ./src/pyams_security/principal.py:53
 msgid "Not logged in"
 msgstr ""
 
 #: ./src/pyams_security/widget/templates/principals-set-input.pt:4
 #: ./src/pyams_security/widget/templates/principal-input.pt:4
+#: ./src/pyams_security/widget/templates/permission-input.pt:4
+#: ./src/pyams_security/widget/templates/permissions-set-input.pt:4
 msgid "Clear selected values"
 msgstr ""
 
+#: ./src/pyams_security/widget/templates/permissions-set-input.pt:11
+msgid "Select permissions..."
+msgstr ""
+
 #: ./src/pyams_security/zmi/utility.py:75
 msgid "Security"
 msgstr ""
@@ -53,39 +67,39 @@
 msgid "Authentication and users directory plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:105
+#: ./src/pyams_security/zmi/utility.py:104
 msgid "See plug-in contents"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:120
+#: ./src/pyams_security/zmi/utility.py:119
 #: ./src/pyams_security/zmi/plugin/social.py:195
 #: ./src/pyams_security/zmi/plugin/social.py:328
 #: ./src/pyams_security/zmi/plugin/userfolder.py:192
 #: ./src/pyams_security/zmi/plugin/group.py:159
-#: ./src/pyams_security/interfaces/__init__.py:236
+#: ./src/pyams_security/interfaces/__init__.py:246
 msgid "Name"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:129
+#: ./src/pyams_security/zmi/utility.py:128
 msgid "Delete plug-in"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:163
+#: ./src/pyams_security/zmi/utility.py:162
 #: ./src/pyams_security/zmi/plugin/social.py:370
 #: ./src/pyams_security/zmi/plugin/social.py:388
 #: ./src/pyams_security/zmi/plugin/social.py:443
 msgid "Security manager"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:164
+#: ./src/pyams_security/zmi/utility.py:163
 msgid "Security manager plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:172
+#: ./src/pyams_security/zmi/utility.py:171
 msgid "Properties..."
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:185
+#: ./src/pyams_security/zmi/utility.py:184
 #: ./src/pyams_security/zmi/notification.py:58
 #: ./src/pyams_security/zmi/plugin/social.py:79
 #: ./src/pyams_security/zmi/plugin/userfolder.py:76
@@ -94,29 +108,29 @@
 msgid "System security manager"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:186
+#: ./src/pyams_security/zmi/utility.py:185
 msgid "Security manager properties"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:223
+#: ./src/pyams_security/zmi/utility.py:222
 msgid "Plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:208
-#: ./src/pyams_security/interfaces/__init__.py:542
+#: ./src/pyams_security/zmi/utility.py:207
+#: ./src/pyams_security/interfaces/__init__.py:552
 msgid "Enable social login?"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:215
-#: ./src/pyams_security/interfaces/__init__.py:566
+#: ./src/pyams_security/zmi/utility.py:214
+#: ./src/pyams_security/interfaces/__init__.py:576
 msgid "Enable free registration?"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:245
+#: ./src/pyams_security/zmi/utility.py:244
 msgid "No provided object_name argument!"
 msgstr ""
 
-#: ./src/pyams_security/zmi/utility.py:249
+#: ./src/pyams_security/zmi/utility.py:248
 msgid "Given plug-in name doesn't exist!"
 msgstr ""
 
@@ -128,16 +142,20 @@
 msgid "Notifications properties"
 msgstr ""
 
-#: ./src/pyams_security/zmi/security.py:41
+#: ./src/pyams_security/zmi/security.py:46
 msgid "Access rules..."
 msgstr ""
 
-#: ./src/pyams_security/zmi/security.py:56
-msgid "Edit local roles"
+#: ./src/pyams_security/zmi/security.py:71
+msgid "Security management"
 msgstr ""
 
-#: ./src/pyams_security/zmi/security.py:73
-#: ./src/pyams_security/zmi/security.py:74
+#: ./src/pyams_security/zmi/security.py:93
+msgid "Granted roles"
+msgstr ""
+
+#: ./src/pyams_security/zmi/security.py:83
+#: ./src/pyams_security/zmi/security.py:84
 msgid "(inherit from parent)"
 msgstr ""
 
@@ -169,19 +187,19 @@
 
 #: ./src/pyams_security/zmi/plugin/social.py:205
 #: ./src/pyams_security/zmi/plugin/userfolder.py:202
-#: ./src/pyams_security/interfaces/__init__.py:247
-#: ./src/pyams_security/interfaces/__init__.py:323
+#: ./src/pyams_security/interfaces/__init__.py:257
+#: ./src/pyams_security/interfaces/__init__.py:333
 msgid "E-mail address"
 msgstr ""
 
 #: ./src/pyams_security/zmi/plugin/social.py:215
-#: ./src/pyams_security/interfaces/__init__.py:231
+#: ./src/pyams_security/interfaces/__init__.py:241
 msgid "OAuth provider name"
 msgstr ""
 
 #: ./src/pyams_security/zmi/plugin/social.py:225
 #: ./src/pyams_security/zmi/plugin/userfolder.py:212
-#: ./src/pyams_security/interfaces/__init__.py:271
+#: ./src/pyams_security/interfaces/__init__.py:281
 msgid "Registration date"
 msgstr ""
 
@@ -267,8 +285,8 @@
 msgstr ""
 
 #: ./src/pyams_security/zmi/plugin/userfolder.py:228
-#: ./src/pyams_security/interfaces/__init__.py:445
-#: ./src/pyams_security/interfaces/__init__.py:448
+#: ./src/pyams_security/interfaces/__init__.py:455
+#: ./src/pyams_security/interfaces/__init__.py:458
 msgid "Activation date"
 msgstr ""
 
@@ -306,7 +324,7 @@
 msgstr ""
 
 #: ./src/pyams_security/zmi/plugin/group.py:169
-#: ./src/pyams_security/interfaces/__init__.py:489
+#: ./src/pyams_security/interfaces/__init__.py:499
 msgid "Description"
 msgstr ""
 
@@ -417,9 +435,9 @@
 msgstr ""
 
 #: ./src/pyams_security/views/login.py:57
-#: ./src/pyams_security/interfaces/__init__.py:342
-#: ./src/pyams_security/interfaces/__init__.py:368
-#: ./src/pyams_security/interfaces/__init__.py:420
+#: ./src/pyams_security/interfaces/__init__.py:352
+#: ./src/pyams_security/interfaces/__init__.py:378
+#: ./src/pyams_security/interfaces/__init__.py:430
 msgid "Password"
 msgstr ""
 
@@ -456,324 +474,324 @@
 msgid "Return to home page"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:131
+#: ./src/pyams_security/interfaces/__init__.py:137
 msgid "Plug-in prefix"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:132
+#: ./src/pyams_security/interfaces/__init__.py:138
 msgid ""
 "This prefix is mainly used by authentication plug-ins to mark principals"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:134
+#: ./src/pyams_security/interfaces/__init__.py:140
 msgid "Plug-in title"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:137
+#: ./src/pyams_security/interfaces/__init__.py:143
 msgid "Enabled plug-in?"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:138
+#: ./src/pyams_security/interfaces/__init__.py:144
 msgid "You can choose to disable any plug-in..."
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:173
+#: ./src/pyams_security/interfaces/__init__.py:179
 msgid "Admin. login"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:175
+#: ./src/pyams_security/interfaces/__init__.py:181
 msgid "Admin. password"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:229
+#: ./src/pyams_security/interfaces/__init__.py:239
 msgid "Internal provider ID"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:233
+#: ./src/pyams_security/interfaces/__init__.py:243
 msgid "User name"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:238
-#: ./src/pyams_security/interfaces/__init__.py:333
-#: ./src/pyams_security/interfaces/__init__.py:404
+#: ./src/pyams_security/interfaces/__init__.py:248
+#: ./src/pyams_security/interfaces/__init__.py:343
+#: ./src/pyams_security/interfaces/__init__.py:414
 msgid "First name"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:241
-#: ./src/pyams_security/interfaces/__init__.py:336
-#: ./src/pyams_security/interfaces/__init__.py:407
+#: ./src/pyams_security/interfaces/__init__.py:251
+#: ./src/pyams_security/interfaces/__init__.py:346
+#: ./src/pyams_security/interfaces/__init__.py:417
 msgid "Last name"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:244
+#: ./src/pyams_security/interfaces/__init__.py:254
 msgid "Nickname"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:250
+#: ./src/pyams_security/interfaces/__init__.py:260
 msgid "Timezone"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:253
+#: ./src/pyams_security/interfaces/__init__.py:263
 msgid "Country"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:256
+#: ./src/pyams_security/interfaces/__init__.py:266
 msgid "City"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:259
+#: ./src/pyams_security/interfaces/__init__.py:269
 msgid "Postal code"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:262
+#: ./src/pyams_security/interfaces/__init__.py:272
 msgid "Locale code"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:265
+#: ./src/pyams_security/interfaces/__init__.py:275
 msgid "Picture URL"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:268
+#: ./src/pyams_security/interfaces/__init__.py:278
 msgid "Birth date"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:304
+#: ./src/pyams_security/interfaces/__init__.py:314
 msgid ""
 "Your password must contain at least three of these kinds of characters: "
 "lowercase letters, uppercase letters, numbers and special characters"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:314
-#: ./src/pyams_security/interfaces/__init__.py:365
-#: ./src/pyams_security/interfaces/__init__.py:387
+#: ./src/pyams_security/interfaces/__init__.py:324
+#: ./src/pyams_security/interfaces/__init__.py:375
+#: ./src/pyams_security/interfaces/__init__.py:397
 msgid "User login"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:315
+#: ./src/pyams_security/interfaces/__init__.py:325
 msgid ""
 "If you don't provide a custom login, your login will be your email address..."
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:324
+#: ./src/pyams_security/interfaces/__init__.py:334
 msgid ""
 "An email will be sent to this address to validate account activation; it will"
 " be used as your future user login"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:339
-#: ./src/pyams_security/interfaces/__init__.py:412
+#: ./src/pyams_security/interfaces/__init__.py:349
+#: ./src/pyams_security/interfaces/__init__.py:422
 msgid "Company name"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:343
+#: ./src/pyams_security/interfaces/__init__.py:353
 msgid ""
 "Password must be at least 8 characters long, and contain at least three kins "
 "of characters between lowercase letters, uppercase letters, numbers and "
 "special characters"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:349
-#: ./src/pyams_security/interfaces/__init__.py:372
+#: ./src/pyams_security/interfaces/__init__.py:359
+#: ./src/pyams_security/interfaces/__init__.py:382
 msgid "Confirmed password"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:362
-#: ./src/pyams_security/interfaces/__init__.py:439
+#: ./src/pyams_security/interfaces/__init__.py:372
+#: ./src/pyams_security/interfaces/__init__.py:449
 msgid "Activation hash"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:396
+#: ./src/pyams_security/interfaces/__init__.py:406
 msgid "User email address"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:415
+#: ./src/pyams_security/interfaces/__init__.py:425
 msgid "Password manager name"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:424
+#: ./src/pyams_security/interfaces/__init__.py:434
 msgid "Wait confirmation?"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:425
+#: ./src/pyams_security/interfaces/__init__.py:435
 msgid ""
 "If 'no', user will be activated immediately without waiting email "
 "confirmation"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:430
+#: ./src/pyams_security/interfaces/__init__.py:440
 msgid "Self-registered profile?"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:435
+#: ./src/pyams_security/interfaces/__init__.py:445
 msgid "Activation secret key"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:436
+#: ./src/pyams_security/interfaces/__init__.py:446
 msgid "This private secret is used to create and check activation hash"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:440
+#: ./src/pyams_security/interfaces/__init__.py:450
 msgid ""
 "This hash is provided into activation message URL. Activation hash is missing"
 " for local users which were registered without waiting their confirmation."
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:480
+#: ./src/pyams_security/interfaces/__init__.py:490
 msgid "Group ID"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:481
+#: ./src/pyams_security/interfaces/__init__.py:491
 msgid "This ID should be unique between all groups"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:485
+#: ./src/pyams_security/interfaces/__init__.py:495
 msgid "Title"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:486
+#: ./src/pyams_security/interfaces/__init__.py:496
 msgid "Public label of this group"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:492
+#: ./src/pyams_security/interfaces/__init__.py:502
 msgid "Group principals"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:493
+#: ./src/pyams_security/interfaces/__init__.py:503
 msgid "IDs of principals contained in this group"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:543
+#: ./src/pyams_security/interfaces/__init__.py:553
 msgid "Enable login via social OAuth plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:547
-msgid "Social users folder"
-msgstr ""
-
-#: ./src/pyams_security/interfaces/__init__.py:548
-msgid "Name of folder used to store social users properties"
-msgstr ""
-
 #: ./src/pyams_security/interfaces/__init__.py:557
-msgid "Authomatic secret"
+msgid "Social users folder"
 msgstr ""
 
 #: ./src/pyams_security/interfaces/__init__.py:558
+msgid "Name of folder used to store social users properties"
+msgstr ""
+
+#: ./src/pyams_security/interfaces/__init__.py:567
+msgid "Authomatic secret"
+msgstr ""
+
+#: ./src/pyams_security/interfaces/__init__.py:568
 msgid "This secret phrase is used to encrypt Authomatic cookie"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:562
+#: ./src/pyams_security/interfaces/__init__.py:572
 msgid "Use social popup?"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:567
+#: ./src/pyams_security/interfaces/__init__.py:577
 msgid "If 'Yes', any use will be able to create a new user account"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:571
+#: ./src/pyams_security/interfaces/__init__.py:581
 msgid "Users folder"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:572
+#: ./src/pyams_security/interfaces/__init__.py:582
 msgid "Name of users folder used to store registered principals"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:581
+#: ./src/pyams_security/interfaces/__init__.py:591
 msgid "Credentials plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:582
+#: ./src/pyams_security/interfaces/__init__.py:592
 msgid "These plug-ins can be used to extract request credentials"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:587
+#: ./src/pyams_security/interfaces/__init__.py:597
 msgid "Authentication plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:588
+#: ./src/pyams_security/interfaces/__init__.py:598
 msgid ""
 "The plug-ins can be used to check extracted credentials against a local or "
 "remote users database"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:593
+#: ./src/pyams_security/interfaces/__init__.py:603
 msgid "Directory plug-ins"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:594
+#: ./src/pyams_security/interfaces/__init__.py:604
 msgid "The plug-in can be used to extract principals information"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:668
+#: ./src/pyams_security/interfaces/__init__.py:678
 msgid "Provider name"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:672
+#: ./src/pyams_security/interfaces/__init__.py:682
 msgid "Provider ID"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:673
+#: ./src/pyams_security/interfaces/__init__.py:683
 msgid "This value should be unique between all providers"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:677
+#: ./src/pyams_security/interfaces/__init__.py:687
 msgid "Provider consumer key"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:680
+#: ./src/pyams_security/interfaces/__init__.py:690
 msgid "Provider secret"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:698
+#: ./src/pyams_security/interfaces/__init__.py:708
 msgid "Inherit parent security?"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:699
+#: ./src/pyams_security/interfaces/__init__.py:709
 msgid "Get access control entries (ACE) inherited from parent levels"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:704
-msgid "Public permission"
-msgstr ""
-
-#: ./src/pyams_security/interfaces/__init__.py:705
-msgid "This permission will be granted to all users"
-msgstr ""
-
-#: ./src/pyams_security/interfaces/__init__.py:709
-msgid "Authenticated permission"
-msgstr ""
-
-#: ./src/pyams_security/interfaces/__init__.py:710
-msgid "This permission will be granted to authenticated users"
-msgstr ""
-
 #: ./src/pyams_security/interfaces/__init__.py:714
-msgid "Inherit parent roles?"
+msgid "Public permissions"
 msgstr ""
 
 #: ./src/pyams_security/interfaces/__init__.py:715
+msgid "These permissions will be granted to all users"
+msgstr ""
+
+#: ./src/pyams_security/interfaces/__init__.py:718
+msgid "Authenticated permissions"
+msgstr ""
+
+#: ./src/pyams_security/interfaces/__init__.py:719
+msgid "These permissions will be granted to authenticated users"
+msgstr ""
+
+#: ./src/pyams_security/interfaces/__init__.py:723
+msgid "Inherit parent roles?"
+msgstr ""
+
+#: ./src/pyams_security/interfaces/__init__.py:724
 msgid "Get roles granted on parent levels"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:331
+#: ./src/pyams_security/interfaces/__init__.py:341
 msgid "Your email address is not valid!"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:355
-#: ./src/pyams_security/interfaces/__init__.py:378
+#: ./src/pyams_security/interfaces/__init__.py:365
+#: ./src/pyams_security/interfaces/__init__.py:388
 msgid "You didn't confirmed your password correctly!"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:402
+#: ./src/pyams_security/interfaces/__init__.py:412
 msgid "Given email address is not valid!"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:555
+#: ./src/pyams_security/interfaces/__init__.py:565
 msgid "You can't activate social login without selecting a social users folder"
 msgstr ""
 
-#: ./src/pyams_security/interfaces/__init__.py:579
+#: ./src/pyams_security/interfaces/__init__.py:589
 msgid "You can't activate open registration without selecting a users folder"
 msgstr ""
 
@@ -857,7 +875,7 @@
 msgid "Can't activate profile with given params!"
 msgstr ""
 
-#: ./src/pyams_security/plugin/userfolder.py:252
+#: ./src/pyams_security/plugin/userfolder.py:255
 #, python-format
 msgid "{prefix}Please confirm registration"
 msgstr ""
--- a/src/pyams_security/plugin/admin.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/plugin/admin.py	Wed Jun 17 09:59:18 2015 +0200
@@ -61,15 +61,18 @@
         if login == self.login and manager.checkPassword(self._password, password):
             return "{0}:{1}".format(self.prefix, login)
 
-    def get_principal(self, principal_id):
+    def get_principal(self, principal_id, info=True):
         if not self.enabled:
             return None
         if not principal_id.startswith(self.prefix + ':'):
             return None
         prefix, login = principal_id.split(':', 1)
         if (prefix == self.prefix) and (login == self.login):
-            return PrincipalInfo(id=principal_id,
-                                 title=self.title)
+            if info:
+                return PrincipalInfo(id=principal_id,
+                                     title=self.title)
+            else:
+                return self
 
     def get_all_principals(self, principal_id):
         if not self.enabled:
--- a/src/pyams_security/plugin/group.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/plugin/group.py	Wed Jun 17 09:59:18 2015 +0200
@@ -19,7 +19,7 @@
 
 # import interfaces
 from pyams_security.interfaces import IGroupsFolderPlugin, ILocalGroup, IPrincipalsAddedToGroupEvent, \
-    IPrincipalsRemovedFromGroupEvent, PrincipalsAddedToGroupEvent, PrincipalsRemovedFromGroupEvent
+    IPrincipalsRemovedFromGroupEvent, PrincipalsAddedToGroupEvent, PrincipalsRemovedFromGroupEvent, ISecurityManager
 from zope.lifecycleevent.interfaces import IObjectAddedEvent
 
 # import packages
@@ -83,7 +83,7 @@
             return False
         return group_id not in self
 
-    def get_principal(self, principal_id):
+    def get_principal(self, principal_id, info=True):
         if not self.enabled:
             return None
         if not principal_id.startswith(self.prefix + ':'):
@@ -91,9 +91,12 @@
         prefix, group_id = principal_id.split(':', 1)
         group = self.get(group_id)
         if group is not None:
-            return PrincipalInfo(id='{prefix}:{group_id}'.format(prefix=self.prefix,
-                                                                 group_id=group.group_id),
-                                 title=group.title)
+            if info:
+                return PrincipalInfo(id='{prefix}:{group_id}'.format(prefix=self.prefix,
+                                                                     group_id=group.group_id),
+                                     title=group.title)
+            else:
+                return group
 
     def get_all_principals(self, principal_id, seen=None):
         if not self.enabled:
--- a/src/pyams_security/plugin/social.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/plugin/social.py	Wed Jun 17 09:59:18 2015 +0200
@@ -94,7 +94,7 @@
     title = FieldProperty(ISocialUsersFolderPlugin['title'])
     enabled = FieldProperty(ISocialUsersFolderPlugin['enabled'])
 
-    def get_principal(self, principal_id):
+    def get_principal(self, principal_id, info=True):
         if not self.enabled:
             return None
         if not principal_id.startswith(self.prefix + ':'):
@@ -102,9 +102,12 @@
         prefix, login = principal_id.split(':', 1)
         user = self.get(login)
         if user is not None:
-            return PrincipalInfo(id='{prefix}:{user_id}'.format(prefix=self.prefix,
-                                                                user_id=user.user_id),
-                                 title=user.title)
+            if info:
+                return PrincipalInfo(id='{prefix}:{user_id}'.format(prefix=self.prefix,
+                                                                    user_id=user.user_id),
+                                     title=user.title)
+            else:
+                return user
 
     def get_all_principals(self, principal_id):
         if not self.enabled:
--- a/src/pyams_security/plugin/userfolder.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/plugin/userfolder.py	Wed Jun 17 09:59:18 2015 +0200
@@ -9,8 +9,6 @@
 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
 # FOR A PARTICULAR PURPOSE.
 #
-from zope.component.interfaces import ISite
-from pyams_utils.traversing import get_parent
 
 __docformat__ = 'restructuredtext'
 
@@ -30,6 +28,7 @@
 from pyams_security.interfaces.notification import INotificationSettings
 from pyramid_chameleon.interfaces import IChameleonTranslate
 from pyramid_mailer.interfaces import IMailer
+from zope.component.interfaces import ISite
 from zope.lifecycleevent.interfaces import IObjectAddedEvent
 from zope.password.interfaces import IPasswordManager
 from zope.schema.interfaces import IVocabularyRegistry
@@ -42,6 +41,7 @@
 from pyams_utils.html import html_to_text
 from pyams_utils.registry import query_utility, get_utility
 from pyams_utils.request import check_request
+from pyams_utils.traversing import get_parent
 from pyramid.events import subscriber
 from pyramid_mailer.message import Message, Attachment
 from zope.container.contained import Contained
@@ -158,7 +158,7 @@
             return False
         return login not in self
 
-    def get_principal(self, principal_id):
+    def get_principal(self, principal_id, info=True):
         if not self.enabled:
             return None
         if not principal_id.startswith(self.prefix + ':'):
@@ -166,9 +166,12 @@
         prefix, login = principal_id.split(':', 1)
         user = self.get(login)
         if user is not None:
-            return PrincipalInfo(id='{prefix}:{login}'.format(prefix=self.prefix,
-                                                              login=user.login),
-                                 title=user.title)
+            if info:
+                return PrincipalInfo(id='{prefix}:{login}'.format(prefix=self.prefix,
+                                                                  login=user.login),
+                                     title=user.title)
+            else:
+                return user
 
     def get_all_principals(self, principal_id):
         if not self.enabled:
--- a/src/pyams_security/principal.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/principal.py	Wed Jun 17 09:59:18 2015 +0200
@@ -17,8 +17,12 @@
 
 # import interfaces
 from pyams_security.interfaces import IPrincipalInfo
+from zope.annotation.interfaces import IAnnotations
+from zope.principalannotation.interfaces import IPrincipalAnnotationUtility
 
 # import packages
+from pyams_utils.adapter import adapter_config
+from pyams_utils.registry import query_utility
 from zope.interface import implementer
 from zope.schema.fieldproperty import FieldProperty
 
@@ -74,3 +78,11 @@
 
     def __eq__(self, other):
         return isinstance(other, PrincipalInfo) and (self.id == other.id)
+
+
+@adapter_config(context=IPrincipalInfo, provides=IAnnotations)
+def get_principal_annotations(principal):
+    """Principal annotations adapter"""
+    annotations = query_utility(IPrincipalAnnotationUtility)
+    if annotations is not None:
+        return annotations.getAnnotations(principal)
--- a/src/pyams_security/property.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/property.py	Wed Jun 17 09:59:18 2015 +0200
@@ -18,7 +18,7 @@
 # import interfaces
 from pyams_security.interfaces import IRole, IProtectedObject, IPrincipalInfo, IRoleProtectedObject
 from pyams_security.schema import IRoleField
-from zope.schema.interfaces import IField
+from zope.schema.interfaces import IField, ISet
 
 # import packages
 
@@ -53,12 +53,15 @@
         return protection.get_principals(self.__role_id)
 
     def __set__(self, instance, value):
-        if value is None:
-            value = set()
-        elif isinstance(value, str):
-            value = set(value.split(','))
-        value = set(map(lambda x: x.id if IPrincipalInfo.providedBy(x) else x, value))
         field = self.__field.bind(instance)
+        if ISet.providedBy(field):
+            if value is None:
+                value = set()
+            elif isinstance(value, str):
+                value = set(value.split(','))
+            value = set(map(lambda x: x.id if IPrincipalInfo.providedBy(x) else x, value))
+        else:
+            value = value.id if IPrincipalInfo.providedBy(value) else value
         field.validate(value)
         if field.readonly:
             raise ValueError("Field {0} is readonly!".format(self.__name))
@@ -67,6 +70,8 @@
             raise ValueError("Can't use role properties on object not providing "
                              "IRoleProtectedObject interface!")
         old_principals = protection.get_principals(self.__role_id)
+        if not isinstance(value, set):
+            value = {value}
         added = value - old_principals
         removed = old_principals - value
         for principal_id in added:
--- a/src/pyams_security/role.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/role.py	Wed Jun 17 09:59:18 2015 +0200
@@ -34,6 +34,7 @@
     title = FieldProperty(IRole['title'])
     description = FieldProperty(IRole['description'])
     permissions = FieldProperty(IRole['permissions'])
+    managers = FieldProperty(IRole['managers'])
 
     def __init__(self, values=None, **args):
         if not isinstance(values, dict):
@@ -42,6 +43,7 @@
         self.title = values.get('title')
         self.description = values.get('description')
         self.permissions = values.get('permissions')
+        self.managers = values.get('managers')
 
 
 def register_role(config, role):
@@ -66,6 +68,8 @@
             # new registration of a given role to add permissions
             role_utility.permissions = (role_utility.permissions or set()) | \
                                        (role.get('permissions') or set())
+            role_utility.managers = (role_utility.managers or set()) | \
+                                    (role.get('managers') or set())
     else:
         registry.registerUtility(role, IRole, name=role.id)
 
--- a/src/pyams_security/security.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/security.py	Wed Jun 17 09:59:18 2015 +0200
@@ -27,7 +27,6 @@
 from pyams_utils.adapter import adapter_config
 from pyams_utils.property import request_property
 from pyams_utils.registry import query_utility
-from pyams_utils.request import check_request
 from pyramid.location import lineage
 from pyramid.security import DENY_ALL, Everyone, Allow, ALL_PERMISSIONS, Authenticated
 from pyramid.threadlocal import get_current_registry
@@ -88,7 +87,7 @@
         self._authenticated_permissions = value
 
     def grant_role(self, role_id, principal_ids):
-        registry = check_request().registry
+        registry = get_current_registry()
         if IRole.providedBy(role_id):
             role_id = role_id.id
         if isinstance(principal_ids, str):
@@ -106,13 +105,13 @@
                 registry.notify(GrantedRoleEvent(self, role_id, principal_id))
 
     def revoke_role(self, role_id, principal_ids):
-        registry = check_request().registry
+        registry = get_current_registry()
         if IRole.providedBy(role_id):
             role_id = role_id.id
         if isinstance(principal_ids, str):
             principal_ids = {principal_ids}
         role_principals = self._principals_by_role.get(role_id) or set()
-        for principal_id in principal_ids:
+        for principal_id in principal_ids.copy():
             if IPrincipalInfo.providedBy(principal_id):
                 principal_id = principal_id.id
             if principal_id in role_principals:
@@ -140,7 +139,7 @@
         return self._roles_by_principal.get(principal_id) or set()
 
     def get_permissions(self, principal_id):
-        registry = check_request().registry
+        registry = get_current_registry()
         result = set()
         for role_id in self.get_roles(principal_id):
             role = registry.queryUtility(IRole, role_id)
--- a/src/pyams_security/site.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/site.py	Wed Jun 17 09:59:18 2015 +0200
@@ -19,6 +19,7 @@
 from pyams_security.interfaces import ISecurityManager
 from pyams_utils.interfaces.site import ISiteGenerations
 from zope.lifecycleevent.interfaces import IObjectCreatedEvent
+from zope.principalannotation.interfaces import IPrincipalAnnotationUtility
 from zope.site.interfaces import INewLocalSite
 
 # import packages
@@ -29,14 +30,16 @@
 from pyramid.events import subscriber
 from pyramid.threadlocal import get_current_registry
 from zope.lifecycleevent import ObjectCreatedEvent
+from zope.principalannotation.utility import PrincipalAnnotationUtility
 
 
-REQUIRED_UTILITIES = ((ISecurityManager, '', SecurityManager, 'Security manager'),)
+REQUIRED_UTILITIES = ((ISecurityManager, '', SecurityManager, 'Security manager'),
+                      (IPrincipalAnnotationUtility, '', PrincipalAnnotationUtility, 'User profiles'))
 
 
 @subscriber(INewLocalSite)
 def handle_new_local_site(event):
-    """Create a new negotiator when a site is created"""
+    """Create a new security manager when a site is created"""
     site = event.manager.__parent__
     check_required_utilities(site, REQUIRED_UTILITIES)
 
--- a/src/pyams_security/utility.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/utility.py	Wed Jun 17 09:59:18 2015 +0200
@@ -17,6 +17,8 @@
 import logging
 logger = logging.getLogger('PyAMS (security)')
 
+from functools import lru_cache
+
 # import interfaces
 from pyams_security.interfaces import ISecurityManager, ICredentialsPlugin, IAuthenticationPlugin, \
     IDirectoryPlugin, AuthenticatedPrincipalEvent, IProtectedObject, IGroupsAwareDirectoryPlugin
@@ -162,12 +164,13 @@
         return principals
 
     # IDirectoryPlugin interface methods
-    def get_principal(self, principal_id):
+    @lru_cache(maxsize=100)
+    def get_principal(self, principal_id, info=True):
         if not principal_id:
             return UnknownPrincipal
         for plugin in self.get_directory_plugins():
             try:
-                principal = plugin.get_principal(principal_id)
+                principal = plugin.get_principal(principal_id, info)
             except:
                 logging.debug("Can't get principal {0}!".format(principal_id), exc_info=True)
                 continue
--- a/src/pyams_security/views/login.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/views/login.py	Wed Jun 17 09:59:18 2015 +0200
@@ -124,6 +124,8 @@
         if LOGIN_REFERER_KEY in session:
             status['location'] = session[LOGIN_REFERER_KEY] or '/'
             del session[LOGIN_REFERER_KEY]
+        else:
+            status['location'] = '/'
         return status
 
 
--- a/src/pyams_security/widget/__init__.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/widget/__init__.py	Wed Jun 17 09:59:18 2015 +0200
@@ -191,7 +191,11 @@
         if not value:
             return None
         manager = query_utility(ISecurityManager)
-        return manager.get_principal(value)
+        if isinstance(value, str):
+            return manager.get_principal(value)
+        else:
+            for principal_id in value:
+                return manager.get_principal(principal_id)
 
     def toFieldValue(self, value):
         # Principal widget only returns selected principal ID
--- a/src/pyams_security/zmi/plugin/group.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/zmi/plugin/group.py	Wed Jun 17 09:59:18 2015 +0200
@@ -18,7 +18,7 @@
 # import interfaces
 from pyams_security.interfaces import IGroupsFolderPlugin, ISecurityManager, ILocalGroup
 from pyams_skin.interfaces import IPageHeader, IInnerPage
-from pyams_skin.interfaces.viewlet import IToolbarViewletManager, IToolbarAddingMenu
+from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, IWidgetTitleViewletManager
 from pyams_skin.layer import IPyAMSLayer
 from pyams_zmi.layer import IAdminLayer
 from z3c.form.interfaces import DISPLAY_MODE, IDataExtractedEvent
@@ -31,6 +31,7 @@
 from pyams_security.plugin.group import GroupsFolder, Group
 from pyams_security.zmi.utility import SecurityManagerPluginsTable
 from pyams_skin.container import ContainerView
+from pyams_skin.page import DefaultPageHeaderAdapter
 from pyams_skin.table import BaseTable, I18nColumn
 from pyams_skin.viewlet.toolbar import ToolbarMenuItem, ToolbarAction
 from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
@@ -138,7 +139,7 @@
     """Groups folder contents table"""
 
     id = 'groups_folder_table'
-    title = _("Local groups")
+    title = _("Local groups list")
     cssClasses = {'table': 'table table-bordered table-striped table-hover table-tight datatable'}
 
 
@@ -186,18 +187,17 @@
 
 
 @adapter_config(context=(IGroupsFolderPlugin, IAdminLayer, GroupsFolderSearchView), provides=IPageHeader)
-class GroupsFolderSearchViewHeaderAdapter(ContextRequestViewAdapter):
+class GroupsFolderSearchViewHeaderAdapter(DefaultPageHeaderAdapter):
     """Groups folder search view header adapter"""
 
     back_url = '#security-manager.html'
     icon_class = 'fa fa-fw fa-users'
+    title = _("Security manager")
 
     @property
-    def title(self):
+    def subtitle(self):
         return self.context.title
 
-    subtitle = _("Groups list")
-
 
 #
 # Groups views
@@ -205,7 +205,7 @@
 
 @viewlet_config(name='groups-folder.toolbar.adding', context=IGroupsFolderPlugin,
                 view=GroupsFolderContentsTable, layer=IAdminLayer,
-                manager=IToolbarViewletManager, permission='system.manage')
+                manager=IWidgetTitleViewletManager, permission='system.manage')
 class LocalGroupAddAction(ToolbarAction):
     """Groups folder adding action"""
 
--- a/src/pyams_security/zmi/plugin/social.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/zmi/plugin/social.py	Wed Jun 17 09:59:18 2015 +0200
@@ -20,7 +20,7 @@
     ISocialLoginConfiguration, ISocialLoginProviderConnection
 from pyams_security.zmi.interfaces import ISecurityManagerMenu
 from pyams_skin.interfaces import IPageHeader, IInnerPage
-from pyams_skin.interfaces.viewlet import IToolbarViewletManager, IToolbarAddingMenu
+from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, IWidgetTitleViewletManager
 from pyams_skin.layer import IPyAMSLayer
 from pyams_zmi.layer import IAdminLayer
 from z3c.form.interfaces import DISPLAY_MODE, IDataExtractedEvent
@@ -35,6 +35,7 @@
 from pyams_security.plugin.social import SocialUsersFolder, SocialLoginProviderConnection, get_provider_info
 from pyams_security.zmi.utility import SecurityManagerPluginsTable
 from pyams_skin.container import ContainerView
+from pyams_skin.page import DefaultPageHeaderAdapter
 from pyams_skin.skin import apply_skin
 from pyams_skin.table import I18nColumn, BaseTable, ActionColumn, TrashColumn
 from pyams_skin.viewlet.menu import MenuItem
@@ -150,7 +151,7 @@
 
 
 @adapter_config(context=(ISocialUsersFolderPlugin, IAdminLayer, SocialUsersFolderSearchView), provides=IPageHeader)
-class SocialUsersFolderSearchViewHeaderAdapter(ContextRequestViewAdapter):
+class SocialUsersFolderSearchViewHeaderAdapter(DefaultPageHeaderAdapter):
     """Social users folder search view header adapter"""
 
     back_url = '#security-manager.html'
@@ -363,7 +364,7 @@
 
 
 @adapter_config(context=(ISite, IAdminLayer, SecurityManagerSocialProvidersView), provides=IPageHeader)
-class SecurityManagerSocialProvidersHeaderAdapter(ContextRequestViewAdapter):
+class SecurityManagerSocialProvidersHeaderAdapter(DefaultPageHeaderAdapter):
     """Security manager social providers header adapter"""
 
     icon_class = 'fa fa-fw fa-share-alt'
@@ -372,7 +373,7 @@
 
 
 @viewlet_config(name='security-manager.social.adding', context=ISite, view=SecurityManagerSocialProvidersTable,
-                layer=IAdminLayer, manager=IToolbarViewletManager, permission='system.manage')
+                layer=IAdminLayer, manager=IWidgetTitleViewletManager, permission='system.manage')
 class SocialToolbarAddingsAction(ToolbarAction):
     """Security manager social toolbar adding action"""
 
--- a/src/pyams_security/zmi/plugin/userfolder.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/zmi/plugin/userfolder.py	Wed Jun 17 09:59:18 2015 +0200
@@ -17,8 +17,9 @@
 from datetime import datetime
 
 # import interfaces
+from pyams_pagelet.interfaces import PageletCreatedEvent
 from pyams_security.interfaces import IUsersFolderPlugin, ISecurityManager, ILocalUser, IUserRegistrationInfo
-from pyams_skin.interfaces.viewlet import IToolbarViewletManager, IToolbarAddingMenu
+from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, IWidgetTitleViewletManager
 from pyams_skin.interfaces import IPageHeader
 from pyams_skin.layer import IPyAMSLayer
 from pyams_zmi.layer import IAdminLayer
@@ -33,10 +34,10 @@
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_security.plugin.userfolder import UsersFolder, User
 from pyams_security.zmi.utility import SecurityManagerPluginsTable
-from pyams_skin.skin import apply_skin
+from pyams_skin.page import DefaultPageHeaderAdapter
 from pyams_skin.table import I18nColumn
 from pyams_skin.viewlet.toolbar import ToolbarMenuItem, ToolbarAction
-from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
+from pyams_utils.adapter import adapter_config
 from pyams_utils.date import format_datetime
 from pyams_utils.registry import query_utility
 from pyams_utils.url import absolute_url
@@ -147,18 +148,17 @@
 
 
 @adapter_config(context=(IUsersFolderPlugin, IAdminLayer, UsersFolderSearchView), provides=IPageHeader)
-class UsersFolderSearchViewHeaderAdapter(ContextRequestViewAdapter):
+class UsersFolderSearchViewHeaderAdapter(DefaultPageHeaderAdapter):
     """Users folder search view header adapter"""
 
     back_url = '#security-manager.html'
     icon_class = 'fa fa-fw fa-user'
+    title = _("Security manager")
 
     @property
-    def title(self):
+    def subtitle(self):
         return self.context.title
 
-    subtitle = _("Search users")
-
 
 @view_config(name='search-results.html', context=IUsersFolderPlugin, request_type=IPyAMSLayer,
              permission='system.view')
@@ -171,7 +171,7 @@
 
     def __init__(self, context, request):
         super(UsersFolderSearchResultsView, self).__init__(context, request)
-        apply_skin(self.request, 'PyAMS admin skin')
+        request.registry.notify(PageletCreatedEvent(self))
 
 
 @adapter_config(name='login', context=(IUsersFolderPlugin, IAdminLayer, UsersFolderSearchResultsView),
@@ -241,7 +241,7 @@
 
 @viewlet_config(name='users-folder.toolbar.adding', context=IUsersFolderPlugin,
                 view=UsersFolderSearchView.search_form_factory, layer=IAdminLayer,
-                manager=IToolbarViewletManager, permission='system.manage')
+                manager=IWidgetTitleViewletManager, permission='system.manage')
 class LocalUserAddAction(ToolbarAction):
     """Users folder adding action"""
 
--- a/src/pyams_security/zmi/security.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/zmi/security.py	Wed Jun 17 09:59:18 2015 +0200
@@ -16,25 +16,36 @@
 # import standard library
 
 # import interfaces
-from pyams_security.interfaces import IDefaultProtectionPolicy, IProtectedObject
+from pyams_form.interfaces.form import IInnerSubForm
+from pyams_security.interfaces import IDefaultProtectionPolicy, IProtectedObject, IRole
 from pyams_skin.layer import IPyAMSLayer
 from pyams_zmi.interfaces.menu import IPropertiesMenu
 from pyams_zmi.layer import IAdminLayer
+from z3c.form.interfaces import DISPLAY_MODE, INPUT_MODE
 
 # import packages
-from pyams_form.form import AJAXEditForm
+from pyams_form.form import AJAXEditForm, InnerEditForm
 from pyams_pagelet.pagelet import pagelet_config
-from pyams_skin.viewlet.menu import MenuItem
+from pyams_skin.viewlet.menu import MenuItem, MenuDivider
+from pyams_utils.adapter import adapter_config
+from pyams_utils.registry import get_utility
 from pyams_viewlet.viewlet import viewlet_config
 from pyams_zmi.form import AdminDialogEditForm
 from pyramid.view import view_config
 from z3c.form import field
+from zope.interface import Interface
 
 from pyams_security import _
 
 
+@viewlet_config(name='protected-object-roles.divider', context=IDefaultProtectionPolicy, layer=IAdminLayer,
+                manager=IPropertiesMenu, permission='system.view', weight=899)
+class ProtectedObjectRolesMenuDivider(MenuDivider):
+    """Protected object roles menu divider"""
+
+
 @viewlet_config(name='protected-object-roles.menu', context=IDefaultProtectionPolicy, layer=IAdminLayer,
-                manager=IPropertiesMenu, permission='system.view', weight=10)
+                manager=IPropertiesMenu, permission='system.view', weight=900)
 class ProtectedObjectRolesMenuItem(MenuItem):
     """Protected object roles menu item"""
 
@@ -49,32 +60,67 @@
 class ProtectedObjectRolesEditForm(AdminDialogEditForm):
     """Protected object roles edit form"""
 
-    @property
-    def title(self):
-        return self.context.title
+    legend = None
+    fieldset_class = 'no-padding'
+
+    fields = field.Fields(Interface)
+    ajax_handler = 'protected-object-roles.json'
+    edit_permission = None
+
 
-    legend = _("Edit local roles")
+@adapter_config(name='security.subform',
+                context=(IDefaultProtectionPolicy, IPyAMSLayer, ProtectedObjectRolesEditForm),
+                provides=IInnerSubForm)
+class ProtectedObjectSecuritySubform(InnerEditForm):
+    """Protected object security sub-form"""
+
+    legend = _("Security management")
     icon_css_class = 'fa fa-fw fa-key'
     label_css_class = 'control-label col-md-4'
     input_css_class = 'col-md-8'
 
-    ajax_handler = 'protected-object-roles.json'
-    edit_permission = 'system.manage'
-
-    @property
-    def fields(self):
-        fields = field.Fields(IProtectedObject) + \
-                 field.Fields(self.context.roles_interface)
-        return fields
+    fields = field.Fields(IProtectedObject)
+    edit_permission = 'security.manage'
+    weight = 1
 
     def updateWidgets(self, prefix=None):
-        super(ProtectedObjectRolesEditForm, self).updateWidgets()
+        super(ProtectedObjectSecuritySubform, self).updateWidgets()
         translate = self.request.localizer.translate
         self.widgets['everyone_permissions'].noValueMessage = translate(_("(inherit from parent)"))
         self.widgets['authenticated_permissions'].noValueMessage = translate(_("(inherit from parent)"))
 
 
+@adapter_config(name='roles.subform',
+                context=(IDefaultProtectionPolicy, IPyAMSLayer, ProtectedObjectRolesEditForm),
+                provides=IInnerSubForm)
+class ProtectedObjectRolesSubform(InnerEditForm):
+    """Protected object roles edit form"""
+
+    legend = _("Granted roles")
+    icon_css_class = 'fa fa-fw fa-users'
+
+    @property
+    def fields(self):
+        return field.Fields(self.context.roles_interface)
+
+    edit_permission = 'security.manage_roles'
+    weight = 2
+
+    def updateWidgets(self, prefix=None):
+        super(ProtectedObjectRolesSubform, self).updateWidgets(prefix)
+        if self.mode == DISPLAY_MODE:
+            return
+        principals = self.request.effective_principals
+        for widget in self.widgets.values():
+            widget.mode = DISPLAY_MODE
+            role = get_utility(IRole, name=widget.field.role_id)
+            if role.managers:
+                for manager in role.managers:
+                    if manager in principals:
+                        widget.mode = INPUT_MODE
+
+
 @view_config(name='protected-object-roles.json', context=IDefaultProtectionPolicy, request_type=IPyAMSLayer,
-             permission='system.manage', renderer='json', xhr=True)
+             permission='security.manage', renderer='json', xhr=True)
 class ProtectedObjectRolesAJAXEditForm(AJAXEditForm, ProtectedObjectRolesEditForm):
     """Protected object roles edit form, AJAX view"""
--- a/src/pyams_security/zmi/utility.py	Wed May 20 12:31:27 2015 +0200
+++ b/src/pyams_security/zmi/utility.py	Wed Jun 17 09:59:18 2015 +0200
@@ -32,6 +32,7 @@
 from pyams_pagelet.pagelet import pagelet_config
 from pyams_security.zmi.widget import OrderedPluginsFieldWidget
 from pyams_skin.container import ContainerView
+from pyams_skin.page import DefaultPageHeaderAdapter
 from pyams_skin.table import BaseTable, DefaultElementEditorAdapter, ActionColumn, I18nColumn, TrashColumn
 from pyams_skin.viewlet.menu import MenuItem
 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
@@ -155,12 +156,12 @@
 
 
 @adapter_config(context=(ISite, IAdminLayer, SecurityManagerView), provides=IPageHeader)
-class SecurityManagerHeaderAdapter(ContextRequestViewAdapter):
+class SecurityManagerHeaderAdapter(DefaultPageHeaderAdapter):
     """Security manager header adapter"""
 
     icon_class = 'fa fa-fw fa-lock'
-    title = _("Security manager")
-    subtitle = _("Security manager plug-ins")
+    title = _("Control panel")
+    subtitle = _("Security manager")
 
 
 @viewlet_config(name='security-manager.properties.menu', context=ISite, layer=IAdminLayer,