You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2015/12/22 15:33:58 UTC

syncope git commit: [SYNCOPE-156] fix for entitlement management + clone operation on user, group and anyobject

Repository: syncope
Updated Branches:
  refs/heads/master 5279aca98 -> e5bb44d90


[SYNCOPE-156] fix for entitlement management + clone operation on user, group and anyobject


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/e5bb44d9
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/e5bb44d9
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/e5bb44d9

Branch: refs/heads/master
Commit: e5bb44d903785433f8966964cd2f6807eb7face4
Parents: 5279aca
Author: fmartelli <fa...@gmail.com>
Authored: Tue Dec 22 15:33:39 2015 +0100
Committer: fmartelli <fa...@gmail.com>
Committed: Tue Dec 22 15:33:39 2015 +0100

----------------------------------------------------------------------
 .../syncope/client/console/pages/BasePage.java  |  9 ++++
 .../syncope/client/console/pages/Realms.java    | 16 ++----
 .../panels/AnyObjectSearchResultPanel.java      | 53 ++++++++++++--------
 .../console/panels/GroupSearchResultPanel.java  | 27 +++++++---
 .../syncope/client/console/panels/Realm.java    |  8 +++
 .../console/panels/RealmSidebarPanel.java       |  6 +++
 .../console/panels/UserSearchResultPanel.java   | 32 ++++++++----
 .../search/GroupSelectionSearchResultPanel.java |  4 +-
 .../search/UserSelectionSearchResultPanel.java  |  4 +-
 .../common/lib/types/AnyEntitlement.java        | 29 +++++++++++
 .../syncope/core/logic/AnyObjectLogic.java      | 23 +++++----
 .../syncope/core/misc/EntitlementsHolder.java   | 12 +----
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    |  3 +-
 13 files changed, 150 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index 65a2c35..b034eda 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -82,19 +82,25 @@ public class BasePage extends AbstractBasePage implements IAjaxIndicatorAware {
         liContainer = new WebMarkupContainer(getLIContainerId("realms"));
         add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("realms", Realms.class));
+        MetaDataRoleAuthorizationStrategy.authorize(liContainer, WebPage.RENDER, StandardEntitlement.REALM_LIST);
 
         liContainer = new WebMarkupContainer(getLIContainerId("topology"));
         add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("topology", Topology.class));
+        MetaDataRoleAuthorizationStrategy.authorize(liContainer, WebPage.RENDER,
+                String.format("%s,%s", StandardEntitlement.CONNECTOR_LIST, StandardEntitlement.RESOURCE_LIST));
 
         liContainer = new WebMarkupContainer(getLIContainerId("reports"));
         add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("reports", Reports.class));
+        MetaDataRoleAuthorizationStrategy.authorize(liContainer, WebPage.RENDER, StandardEntitlement.REPORT_LIST);
 
         WebMarkupContainer confLIContainer = new WebMarkupContainer(getLIContainerId("configuration"));
         add(confLIContainer);
         WebMarkupContainer confULContainer = new WebMarkupContainer(getULContainerId("configuration"));
         confLIContainer.add(confULContainer);
+        MetaDataRoleAuthorizationStrategy.authorize(
+                liContainer, WebPage.RENDER, StandardEntitlement.CONFIGURATION_LIST);
 
         liContainer = new WebMarkupContainer(getLIContainerId("securityQuestions"));
         confULContainer.add(liContainer);
@@ -114,6 +120,7 @@ public class BasePage extends AbstractBasePage implements IAjaxIndicatorAware {
         final BookmarkablePageLink<Page> logsLink = new BookmarkablePageLink<>("logs", Logs.class);
         MetaDataRoleAuthorizationStrategy.authorize(logsLink, WebPage.ENABLE, StandardEntitlement.LOG_LIST);
         liContainer.add(logsLink);
+        MetaDataRoleAuthorizationStrategy.authorize(liContainer, WebPage.RENDER, StandardEntitlement.LOG_LIST);
 
         liContainer = new WebMarkupContainer(getLIContainerId("types"));
         confULContainer.add(liContainer);
@@ -124,6 +131,7 @@ public class BasePage extends AbstractBasePage implements IAjaxIndicatorAware {
         liContainer = new WebMarkupContainer(getLIContainerId("policies"));
         confULContainer.add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("policies", Policies.class));
+        MetaDataRoleAuthorizationStrategy.authorize(liContainer, WebPage.RENDER, StandardEntitlement.POLICY_LIST);
 
         liContainer = new WebMarkupContainer(getLIContainerId("layouts"));
         confULContainer.add(liContainer);
@@ -132,6 +140,7 @@ public class BasePage extends AbstractBasePage implements IAjaxIndicatorAware {
         liContainer = new WebMarkupContainer(getLIContainerId("notifications"));
         confULContainer.add(liContainer);
         liContainer.add(new BookmarkablePageLink<>("notifications", Notifications.class));
+        MetaDataRoleAuthorizationStrategy.authorize(liContainer, WebPage.RENDER, StandardEntitlement.NOTIFICATION_LIST);
 
         liContainer = new WebMarkupContainer(getLIContainerId("camelRoutes"));
         add(liContainer);

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
index b8a48d9..922dacc 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Realms.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.pages;
 
-import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.Realm;
 import org.apache.syncope.client.console.panels.RealmModalPanel;
@@ -146,10 +145,7 @@ public class Realms extends BasePage {
         };
 
         deleteLink.add(new ConfirmationModalBehavior());
-
-        if (SyncopeConsoleSession.get().owns(StandardEntitlement.REALM_DELETE)) {
-            MetaDataRoleAuthorizationStrategy.authorize(deleteLink, ENABLE, StandardEntitlement.REALM_DELETE);
-        }
+        MetaDataRoleAuthorizationStrategy.authorize(deleteLink, ENABLE, StandardEntitlement.REALM_DELETE);
 
         content.addOrReplace(deleteLink);
     }
@@ -181,10 +177,7 @@ public class Realms extends BasePage {
             }
         };
 
-        if (SyncopeConsoleSession.get().owns(StandardEntitlement.REALM_CREATE)) {
-            MetaDataRoleAuthorizationStrategy.authorize(createLink, ENABLE, StandardEntitlement.REALM_CREATE);
-        }
-
+        MetaDataRoleAuthorizationStrategy.authorize(createLink, ENABLE, StandardEntitlement.REALM_CREATE);
         content.addOrReplace(createLink);
     }
 
@@ -214,10 +207,7 @@ public class Realms extends BasePage {
             }
         };
 
-        if (SyncopeConsoleSession.get().owns(StandardEntitlement.REALM_UPDATE)) {
-            MetaDataRoleAuthorizationStrategy.authorize(editLink, ENABLE, StandardEntitlement.REALM_UPDATE);
-        }
-
+        MetaDataRoleAuthorizationStrategy.authorize(editLink, ENABLE, StandardEntitlement.REALM_UPDATE);
         content.addOrReplace(editLink);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectSearchResultPanel.java
index 9469427..4dcfee5 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectSearchResultPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectSearchResultPanel.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.AnyDisplayAttributesModalPage;
 import org.apache.syncope.client.console.pages.BasePage;
@@ -42,7 +43,9 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.types.AnyEntitlement;
 import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.event.Broadcast;
@@ -65,16 +68,11 @@ public class AnyObjectSearchResultPanel<T extends AnyTO> extends AbstractSearchR
 
     protected final String pageID = "Any";
 
-    protected final String entitlement;
-
-    protected AnyObjectSearchResultPanel(
-            final String id, final AbstractSearchResultPanel.Builder<T> builder, final String entitlement) {
+    protected AnyObjectSearchResultPanel(final String id, final AbstractSearchResultPanel.Builder<T> builder) {
         super(id, builder);
 
         modal.size(Modal.Size.Large);
 
-        this.entitlement = entitlement;
-
         add(new Label("name", builder.type));
 
         this.schemaNames = new ArrayList<>();
@@ -146,23 +144,35 @@ public class AnyObjectSearchResultPanel<T extends AnyTO> extends AbstractSearchR
                                                 new AnyObjectRestClient().<T>read(model.getObject().getKey())),
                                         target));
                     }
-                }, ActionLink.ActionType.EDIT, entitlement).add(new ActionLink<T>() {
+                }, ActionLink.ActionType.EDIT, String.format("%s_%s", type, AnyEntitlement.READ)).add(
+                        new ActionLink<T>() {
 
-                    private static final long serialVersionUID = -7978723352517770644L;
+                    private static final long serialVersionUID = -7978723352517770645L;
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final T ignore) {
-                        try {
-                            restClient.delete(model.getObject().getETagValue(), model.getObject().getKey());
-                            info(getString(Constants.OPERATION_SUCCEEDED));
-                            target.add(container);
-                        } catch (SyncopeClientException e) {
-                            error(getString(Constants.ERROR) + ": " + e.getMessage());
-                            LOG.error("While deleting object {}", model.getObject().getKey(), e);
-                        }
-                        ((BasePage) getPage()).getFeedbackPanel().refresh(target);
+                        final T clone = SerializationUtils.clone(model.getObject());
+                        clone.setKey(0L);
+                        send(AnyObjectSearchResultPanel.this, Broadcast.EXACT,
+                                new AjaxWizard.NewItemActionEvent<AnyHandler<T>>(new AnyHandler<T>(clone), target));
                     }
-                }, ActionLink.ActionType.DELETE, entitlement);
+                }, ActionLink.ActionType.CLONE, StandardEntitlement.USER_CREATE).add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -7978723352517770646L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                try {
+                                    restClient.delete(model.getObject().getETagValue(), model.getObject().getKey());
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                    target.add(container);
+                                } catch (SyncopeClientException e) {
+                                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                                    LOG.error("While deleting object {}", model.getObject().getKey(), e);
+                                }
+                                ((BasePage) getPage()).getFeedbackPanel().refresh(target);
+                            }
+                        }, ActionLink.ActionType.DELETE, String.format("%s_%s", type, AnyEntitlement.DELETE));
 
                 return panel.build(componentId, model.getObject());
             }
@@ -184,7 +194,8 @@ public class AnyObjectSearchResultPanel<T extends AnyTO> extends AbstractSearchR
                         modal.header(new ResourceModel("any.attr.display", ""));
                         modal.show(true);
                     }
-                }, ActionLink.ActionType.CHANGE_VIEW, entitlement).add(new ActionLink<Serializable>() {
+                }, ActionLink.ActionType.CHANGE_VIEW, String.format("%s_%s", type, AnyEntitlement.READ)).add(
+                        new ActionLink<Serializable>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -194,7 +205,7 @@ public class AnyObjectSearchResultPanel<T extends AnyTO> extends AbstractSearchR
                             target.add(container);
                         }
                     }
-                }, ActionLink.ActionType.RELOAD, entitlement);
+                }, ActionLink.ActionType.RELOAD, String.format("%s_%s", type, AnyEntitlement.SEARCH));
 
                 return panel.build(componentId);
             }
@@ -243,7 +254,7 @@ public class AnyObjectSearchResultPanel<T extends AnyTO> extends AbstractSearchR
 
         @Override
         protected WizardMgtPanel<AnyHandler<AnyObjectTO>> newInstance(final String id) {
-            return new AnyObjectSearchResultPanel<>(id, this, type + "_LIST");
+            return new AnyObjectSearchResultPanel<>(id, this);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java
index 9ffef22..4712328 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupSearchResultPanel.java
@@ -25,6 +25,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.pages.GroupDisplayAttributesModalPage;
@@ -58,8 +59,8 @@ public class GroupSearchResultPanel extends AnyObjectSearchResultPanel<GroupTO>
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    protected GroupSearchResultPanel(final String id, final Builder builder, final String entitlement) {
-        super(id, builder, entitlement);
+    protected GroupSearchResultPanel(final String id, final Builder builder) {
+        super(id, builder);
     }
 
     @Override
@@ -119,7 +120,18 @@ public class GroupSearchResultPanel extends AnyObjectSearchResultPanel<GroupTO>
                                         new GroupHandler(new GroupRestClient().read(model.getObject().getKey())),
                                         target));
                     }
-                }, ActionLink.ActionType.EDIT, entitlement).add(new ActionLink<GroupTO>() {
+                }, ActionLink.ActionType.EDIT, StandardEntitlement.GROUP_READ).add(new ActionLink<GroupTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final GroupTO anyTO) {
+                        final GroupTO clone = SerializationUtils.clone(model.getObject());
+                        clone.setKey(0L);
+                        send(GroupSearchResultPanel.this, Broadcast.EXACT,
+                                new AjaxWizard.NewItemActionEvent<GroupHandler>(new GroupHandler(clone), target));
+                    }
+                }, ActionLink.ActionType.CLONE, StandardEntitlement.GROUP_CREATE).add(new ActionLink<GroupTO>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -135,7 +147,7 @@ public class GroupSearchResultPanel extends AnyObjectSearchResultPanel<GroupTO>
                         }
                         ((BasePage) getPage()).getFeedbackPanel().refresh(target);
                     }
-                }, ActionLink.ActionType.DELETE, entitlement);
+                }, ActionLink.ActionType.DELETE, StandardEntitlement.GROUP_DELETE);
 
                 return panel.build(componentId);
             }
@@ -156,7 +168,8 @@ public class GroupSearchResultPanel extends AnyObjectSearchResultPanel<GroupTO>
                         modal.header(new ResourceModel("any.attr.display", ""));
                         modal.show(true);
                     }
-                }, ActionLink.ActionType.CHANGE_VIEW, entitlement).add(new ActionLink<Serializable>() {
+                }, ActionLink.ActionType.CHANGE_VIEW, StandardEntitlement.GROUP_READ).add(
+                        new ActionLink<Serializable>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -166,7 +179,7 @@ public class GroupSearchResultPanel extends AnyObjectSearchResultPanel<GroupTO>
                             target.add(container);
                         }
                     }
-                }, ActionLink.ActionType.RELOAD, entitlement).build(componentId);
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.GROUP_SEARCH).build(componentId);
             }
         });
 
@@ -208,7 +221,7 @@ public class GroupSearchResultPanel extends AnyObjectSearchResultPanel<GroupTO>
 
         @Override
         protected WizardMgtPanel<AnyHandler<GroupTO>> newInstance(final String id) {
-            return new GroupSearchResultPanel(id, this, StandardEntitlement.GROUP_SEARCH);
+            return new GroupSearchResultPanel(id, this);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
index 32ae031..73d39e0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
@@ -36,9 +36,13 @@ import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyEntitlement;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.Model;
 import org.slf4j.Logger;
@@ -125,6 +129,7 @@ public class Realm extends Panel {
                                 BaseModal.CONTENT_ID, userTO, anyTypeTO.getClasses(), pageRef)).
                         addNotificationPanel(BasePage.class.cast(this.pageRef.getPage()).getFeedbackPanel()).
                         build(id);
+                MetaDataRoleAuthorizationStrategy.authorize(panel, WebPage.RENDER, StandardEntitlement.USER_LIST);
                 break;
             case GROUP:
                 final GroupTO groupTO = new GroupTO();
@@ -138,6 +143,7 @@ public class Realm extends Panel {
                                 BaseModal.CONTENT_ID, groupTO, anyTypeTO.getClasses(), pageRef)).
                         addNotificationPanel(BasePage.class.cast(this.pageRef.getPage()).getFeedbackPanel()).
                         build(id);
+                // list of group is available to all authenticated users
                 break;
             case ANY_OBJECT:
                 final AnyObjectTO anyObjectTO = new AnyObjectTO();
@@ -152,6 +158,8 @@ public class Realm extends Panel {
                                 BaseModal.CONTENT_ID, anyObjectTO, anyTypeTO.getClasses(), pageRef)).
                         addNotificationPanel(BasePage.class.cast(this.pageRef.getPage()).getFeedbackPanel()).
                         build(id);
+                MetaDataRoleAuthorizationStrategy.authorize(panel, WebPage.RENDER,
+                        String.format("%s_%s", anyObjectTO.getType(), AnyEntitlement.LIST));
                 break;
             default:
                 panel = new LabelPanel(id, null);

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmSidebarPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmSidebarPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmSidebarPanel.java
index eb899c9..f1a6fee 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmSidebarPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmSidebarPanel.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.client.console.panels;
 
+import static org.apache.wicket.Component.ENABLE;
+
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -29,10 +31,12 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.panels.RealmSidebarPanel.ControlSidebarClick;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.head.IHeaderResponse;
@@ -151,6 +155,8 @@ public class RealmSidebarPanel extends Panel {
             fragment.addOrReplace(link);
             fragment.setOutputMarkupId(true);
             listItems.addOrReplace(fragment);
+
+            MetaDataRoleAuthorizationStrategy.authorize(link, ENABLE, StandardEntitlement.REALM_LIST);
         }
 
         return container;

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
index 69055f0..327d9fc 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserSearchResultPanel.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.pages.StatusModal;
@@ -61,8 +62,8 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    protected UserSearchResultPanel(final String id, final Builder builder, final String entitlement) {
-        super(id, builder, entitlement);
+    protected UserSearchResultPanel(final String id, final Builder builder) {
+        super(id, builder);
     }
 
     @Override
@@ -130,7 +131,7 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
                                 getString("any.edit"), model.getObject().getKey())));
                         modal.show(true);
                     }
-                }, ActionLink.ActionType.MANAGE_RESOURCES, StandardEntitlement.USER_LIST).add(new ActionLink<UserTO>() {
+                }, ActionLink.ActionType.MANAGE_RESOURCES, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -147,7 +148,7 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
                                 getString("any.edit"), model.getObject().getKey())));
                         modal.show(true);
                     }
-                }, ActionLink.ActionType.ENABLE, entitlement).add(new ActionLink<UserTO>() {
+                }, ActionLink.ActionType.ENABLE, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -158,7 +159,19 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
                                         new AnyHandler<UserTO>(new UserRestClient().read(model.getObject().getKey())),
                                         target));
                     }
-                }, ActionLink.ActionType.EDIT, entitlement).add(new ActionLink<UserTO>() {
+                }, ActionLink.ActionType.EDIT, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
+                        final UserTO clone = SerializationUtils.clone(model.getObject());
+                        clone.setKey(0L);
+                        send(UserSearchResultPanel.this, Broadcast.EXACT,
+                                new AjaxWizard.NewItemActionEvent<AnyHandler<UserTO>>(
+                                        new AnyHandler<UserTO>(clone), target));
+                    }
+                }, ActionLink.ActionType.CLONE, StandardEntitlement.USER_CREATE).add(new ActionLink<UserTO>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -174,7 +187,7 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
                         }
                         ((BasePage) getPage()).getFeedbackPanel().refresh(target);
                     }
-                }, ActionLink.ActionType.DELETE, entitlement);
+                }, ActionLink.ActionType.DELETE, StandardEntitlement.USER_DELETE);
 
                 return panel.build(componentId, model.getObject());
             }
@@ -195,7 +208,8 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
                         modal.header(new ResourceModel("any.attr.display", ""));
                         modal.show(true);
                     }
-                }, ActionLink.ActionType.CHANGE_VIEW, entitlement).add(new ActionLink<Serializable>() {
+                }, ActionLink.ActionType.CHANGE_VIEW, StandardEntitlement.USER_READ).add(
+                        new ActionLink<Serializable>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -205,7 +219,7 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
                             target.add(container);
                         }
                     }
-                }, ActionLink.ActionType.RELOAD, entitlement).build(componentId);
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.USER_SEARCH).build(componentId);
             }
         });
 
@@ -247,7 +261,7 @@ public class UserSearchResultPanel extends AnyObjectSearchResultPanel<UserTO> {
 
         @Override
         protected WizardMgtPanel<AnyHandler<UserTO>> newInstance(final String id) {
-            return new UserSearchResultPanel(id, this, StandardEntitlement.USER_LIST);
+            return new UserSearchResultPanel(id, this);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionSearchResultPanel.java
index b47647f..4ed3e68 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionSearchResultPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionSearchResultPanel.java
@@ -55,7 +55,7 @@ public final class GroupSelectionSearchResultPanel extends GroupSearchResultPane
     private static final long serialVersionUID = -1100228004207271271L;
 
     private GroupSelectionSearchResultPanel(final String id, final Builder builder) {
-        super(id, builder, StandardEntitlement.GROUP_SEARCH);
+        super(id, builder);
     }
 
     @Override
@@ -132,7 +132,7 @@ public final class GroupSelectionSearchResultPanel extends GroupSearchResultPane
                             target.add(container);
                         }
                     }
-                }, ActionLink.ActionType.RELOAD, entitlement).build(componentId);
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.GROUP_SEARCH).build(componentId);
             }
         });
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionSearchResultPanel.java
index 929c280..1af9901 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionSearchResultPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionSearchResultPanel.java
@@ -55,7 +55,7 @@ public final class UserSelectionSearchResultPanel extends UserSearchResultPanel
     private static final long serialVersionUID = -1100228004207271272L;
 
     private UserSelectionSearchResultPanel(final String id, final UserSelectionSearchResultPanel.Builder builder) {
-        super(id, builder, StandardEntitlement.USER_LIST);
+        super(id, builder);
     }
 
     @Override
@@ -134,7 +134,7 @@ public final class UserSelectionSearchResultPanel extends UserSearchResultPanel
                             target.add(container);
                         }
                     }
-                }, ActionLink.ActionType.RELOAD, entitlement).build(componentId);
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.USER_SEARCH).build(componentId);
             }
         });
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyEntitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyEntitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyEntitlement.java
new file mode 100644
index 0000000..55bf8f6
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyEntitlement.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.types;
+
+public enum AnyEntitlement {
+    SEARCH,
+    LIST,
+    CREATE,
+    READ,
+    UPDATE,
+    DELETE;
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
index cca89c3..37392a2 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
@@ -34,6 +34,7 @@ import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
+import org.apache.syncope.common.lib.types.AnyEntitlement;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
@@ -101,7 +102,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
 
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(searchCond.hasAnyTypeCond(), EntitlementsHolder.AnyEntitlement.SEARCH)),
+                        getFor(searchCond.hasAnyTypeCond(), AnyEntitlement.SEARCH)),
                 realm);
 
         return searchDAO.count(effectiveRealms, searchCond, AnyTypeKind.ANY_OBJECT);
@@ -118,7 +119,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
 
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(searchCond.hasAnyTypeCond(), EntitlementsHolder.AnyEntitlement.SEARCH)),
+                        getFor(searchCond.hasAnyTypeCond(), AnyEntitlement.SEARCH)),
                 realm);
 
         List<AnyObject> matchingAnyObjects = searchDAO.search(
@@ -145,7 +146,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
 
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(before.getLeft().getType(), EntitlementsHolder.AnyEntitlement.CREATE)),
+                        getFor(before.getLeft().getType(), AnyEntitlement.CREATE)),
                 before.getLeft().getRealm());
         securityChecks(effectiveRealms, before.getLeft().getRealm(), null);
 
@@ -167,7 +168,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
                 : anyObjectTO.getRealm();
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObjectTO.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObjectTO.getType(), AnyEntitlement.UPDATE)),
                 realm);
         securityChecks(effectiveRealms, realm, before.getLeft().getKey());
 
@@ -183,7 +184,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
 
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(before.getLeft().getType(), EntitlementsHolder.AnyEntitlement.DELETE)),
+                        getFor(before.getLeft().getType(), AnyEntitlement.DELETE)),
                 before.getLeft().getRealm());
         securityChecks(effectiveRealms, before.getLeft().getRealm(), before.getLeft().getKey());
 
@@ -201,7 +202,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
         AnyObjectTO anyObject = binder.getAnyObjectTO(key);
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObject.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObject.getType(), AnyEntitlement.UPDATE)),
                 anyObject.getRealm());
         securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
 
@@ -224,7 +225,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
         AnyObjectTO anyObject = binder.getAnyObjectTO(key);
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObject.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObject.getType(), AnyEntitlement.UPDATE)),
                 anyObject.getRealm());
         securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
 
@@ -249,7 +250,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
         AnyObjectTO anyObject = binder.getAnyObjectTO(key);
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObject.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObject.getType(), AnyEntitlement.UPDATE)),
                 anyObject.getRealm());
         securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
 
@@ -278,7 +279,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
         AnyObjectTO anyObject = binder.getAnyObjectTO(key);
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObject.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObject.getType(), AnyEntitlement.UPDATE)),
                 anyObject.getRealm());
         securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
 
@@ -303,7 +304,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
         AnyObjectTO anyObject = binder.getAnyObjectTO(key);
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObject.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObject.getType(), AnyEntitlement.UPDATE)),
                 anyObject.getRealm());
         securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
 
@@ -327,7 +328,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch
         AnyObjectTO anyObject = binder.getAnyObjectTO(key);
         Set<String> effectiveRealms = getEffectiveRealms(
                 AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                        getFor(anyObject.getType(), EntitlementsHolder.AnyEntitlement.UPDATE)),
+                        getFor(anyObject.getType(), AnyEntitlement.UPDATE)),
                 anyObject.getRealm());
         securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/core/misc/src/main/java/org/apache/syncope/core/misc/EntitlementsHolder.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/EntitlementsHolder.java b/core/misc/src/main/java/org/apache/syncope/core/misc/EntitlementsHolder.java
index 9c6c00c..5a5d09a 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/EntitlementsHolder.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/EntitlementsHolder.java
@@ -23,17 +23,9 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
-public final class EntitlementsHolder {
-
-    public enum AnyEntitlement {
-        SEARCH,
-        LIST,
-        CREATE,
-        READ,
-        UPDATE,
-        DELETE;
+import org.apache.syncope.common.lib.types.AnyEntitlement;
 
-    }
+public final class EntitlementsHolder {
 
     private static final Object MONITOR = new Object();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e5bb44d9/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 83cc0a5..659952b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -28,6 +28,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.common.lib.types.AnyEntitlement;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.misc.EntitlementsHolder;
 import org.apache.syncope.core.misc.security.AuthContextUtils;
@@ -64,7 +65,7 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
     @Override
     protected void securityChecks(final AnyObject anyObject) {
         Set<String> authRealms = AuthContextUtils.getAuthorizations().get(EntitlementsHolder.getInstance().
-                getFor(anyObject.getType().getKey(), EntitlementsHolder.AnyEntitlement.READ));
+                getFor(anyObject.getType().getKey(), AnyEntitlement.READ));
         boolean authorized = IterableUtils.matchesAny(authRealms, new Predicate<String>() {
 
             @Override