You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2023/02/23 13:12:03 UTC

[syncope] branch 3_0_X updated: [SYNCOPE-1732] Support generic access policy configuration through BeanPanel (#413)

This is an automated email from the ASF dual-hosted git repository.

andreapatricelli pushed a commit to branch 3_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/3_0_X by this push:
     new dc5638b07e [SYNCOPE-1732] Support generic access policy configuration through BeanPanel (#413)
dc5638b07e is described below

commit dc5638b07ebf703659d7a41bf7f6af8728d65f81
Author: Andrea Patricelli <an...@apache.org>
AuthorDate: Thu Feb 23 14:11:57 2023 +0100

    [SYNCOPE-1732] Support generic access policy configuration through BeanPanel (#413)
    
    * [SYNCOPE-1732] support generic access policy configuration through bean panel
---
 .../policies/AccessPolicyDirectoryPanel.java       |  45 ---------
 .../console/policies/AccessPolicyModalPanel.java   | 102 +--------------------
 .../console/policies/AccessPolicyModalPanel.html   |   6 +-
 .../syncope/client/ui/commons/Constants.java       |   4 +-
 .../syncope/client/console/panels/BeanPanel.java   |   6 +-
 .../common/lib/policy/DefaultAccessPolicyConf.java |  24 +++--
 .../syncope/common/lib/SerializationTest.java      |   4 +-
 .../jpa/inner/AbstractClientAppTest.java           |   3 +-
 .../core/persistence/jpa/inner/PolicyTest.java     |   3 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |   2 +-
 .../org/apache/syncope/fit/core/PolicyITCase.java  |  11 +--
 .../org/apache/syncope/fit/core/RealmITCase.java   |   3 +-
 .../wa/starter/mapping/DefaultAccessMapper.java    |  10 +-
 .../syncope/wa/starter/WAServiceRegistryTest.java  |   3 +-
 14 files changed, 39 insertions(+), 187 deletions(-)

diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java
index 4261ad8236..a9e2232450 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyDirectoryPanel.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.client.console.policies;
 
 import java.util.List;
-import org.apache.syncope.client.console.panels.ModalDirectoryPanel;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
@@ -92,49 +91,5 @@ public class AccessPolicyDirectoryPanel extends PolicyDirectoryPanel<AccessPolic
                 policySpecModal.show(true);
             }
         }, ActionLink.ActionType.CHANGE_VIEW, IdRepoEntitlement.POLICY_UPDATE);
-
-        if (model.getObject().getConf() instanceof DefaultAccessPolicyConf) {
-            panel.add(new ActionLink<>() {
-
-                private static final long serialVersionUID = -3722207913631435501L;
-
-                @Override
-                public void onClick(final AjaxRequestTarget target, final AccessPolicyTO ignore) {
-                    model.setObject(PolicyRestClient.read(type, model.getObject().getKey()));
-                    target.add(ruleCompositionModal.setContent(new ModalDirectoryPanel<>(
-                            ruleCompositionModal,
-                            new AccessPolicyAttrsDirectoryPanel(
-                                    "panel",
-                                    ruleCompositionModal,
-                                    model,
-                                    DefaultAccessPolicyConf::getRequiredAttrs,
-                                    pageRef),
-                            pageRef)));
-                    ruleCompositionModal.header(new Model<>(getString("requiredAttrs.title", model)));
-                    ruleCompositionModal.show(true);
-                }
-            }, ActionLink.ActionType.TYPE_EXTENSIONS, IdRepoEntitlement.POLICY_UPDATE);
-
-            panel.add(new ActionLink<>() {
-
-                private static final long serialVersionUID = -3722207913631435501L;
-
-                @Override
-                public void onClick(final AjaxRequestTarget target, final AccessPolicyTO ignore) {
-                    model.setObject(PolicyRestClient.read(type, model.getObject().getKey()));
-                    target.add(ruleCompositionModal.setContent(new ModalDirectoryPanel<>(
-                            ruleCompositionModal,
-                            new AccessPolicyAttrsDirectoryPanel(
-                                    "panel",
-                                    ruleCompositionModal,
-                                    model,
-                                    DefaultAccessPolicyConf::getRejectedAttrs,
-                                    pageRef),
-                            pageRef)));
-                    ruleCompositionModal.header(new Model<>(getString("rejectedAttrs.title", model)));
-                    ruleCompositionModal.show(true);
-                }
-            }, ActionLink.ActionType.CLAIM, IdRepoEntitlement.POLICY_UPDATE);
-        }
     }
 }
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java
index e71d36e90c..f64256fe00 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java
@@ -18,36 +18,19 @@
  */
 package org.apache.syncope.client.console.policies;
 
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.lang3.time.DateFormatUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.AbstractModalPanel;
+import org.apache.syncope.client.console.panels.BeanPanel;
 import org.apache.syncope.client.console.rest.PolicyRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import org.apache.syncope.client.ui.commons.Constants;
-import org.apache.syncope.client.ui.commons.DateOps;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
 import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
 import org.apache.syncope.common.lib.policy.AccessPolicyTO;
-import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
-import org.apache.syncope.common.lib.policy.HttpRequestAccessPolicyConf;
-import org.apache.syncope.common.lib.policy.RemoteEndpointAccessPolicyConf;
-import org.apache.syncope.common.lib.policy.TimeBasedAccessPolicyConf;
 import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.wicket.Component;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.validation.validator.UrlValidator;
 
 public class AccessPolicyModalPanel extends AbstractModalPanel<AccessPolicyTO> {
 
@@ -64,88 +47,7 @@ public class AccessPolicyModalPanel extends AbstractModalPanel<AccessPolicyTO> {
         super(modal, pageRef);
         this.model = model;
 
-        List<Component> fields = new ArrayList<>();
-
-        if (model.getObject().getConf() instanceof DefaultAccessPolicyConf) {
-            fields.add(new AjaxSpinnerFieldPanel.Builder<Integer>().build(
-                    "field",
-                    "order",
-                    Integer.class,
-                    new PropertyModel<>(model.getObject().getConf(), "order")));
-            fields.add(new AjaxCheckBoxPanel(
-                    "field",
-                    "enabled",
-                    new PropertyModel<>(model.getObject().getConf(), "enabled"),
-                    false));
-            fields.add(new AjaxCheckBoxPanel(
-                    "field",
-                    "ssoEnabled",
-                    new PropertyModel<>(model.getObject().getConf(), "ssoEnabled"),
-                    false));
-            fields.add(new AjaxCheckBoxPanel(
-                    "field",
-                    "requireAllAttributes",
-                    new PropertyModel<>(model.getObject().getConf(), "requireAllAttributes"),
-                    false));
-            fields.add(new AjaxCheckBoxPanel(
-                    "field",
-                    "caseInsensitive",
-                    new PropertyModel<>(model.getObject().getConf(), "caseInsensitive"),
-                    false));
-            AjaxTextFieldPanel unauthorizedRedirectUrl = new AjaxTextFieldPanel(
-                    "field",
-                    "unauthorizedRedirectUrl",
-                    new PropertyModel<>(model.getObject().getConf(), "unauthorizedRedirectUrl"),
-                    false);
-            unauthorizedRedirectUrl.getField().add(new UrlValidator(new String[] { "http", "https" }));
-            fields.add(unauthorizedRedirectUrl);
-        } else if (model.getObject().getConf() instanceof HttpRequestAccessPolicyConf) {
-            fields.add(new AjaxTextFieldPanel("field", "ipAddress",
-                    new PropertyModel<>(model.getObject().getConf(), "ipAddress"), false));
-            fields.add(new AjaxTextFieldPanel("field", "userAgent",
-                    new PropertyModel<>(model.getObject().getConf(), "userAgent"), false));
-        } else if (model.getObject().getConf() instanceof RemoteEndpointAccessPolicyConf) {
-            AjaxTextFieldPanel endpointUrl = new AjaxTextFieldPanel(
-                    "field",
-                    "endpointUrl",
-                    new PropertyModel<>(model.getObject().getConf(), "endpointUrl"),
-                    false);
-            endpointUrl.getField().add(new UrlValidator(new String[] { "http", "https" }));
-            fields.add(endpointUrl.setRequired(true));
-
-            FieldPanel panel = new AjaxTextFieldPanel(
-                    "panel",
-                    "acceptableResponseCodes",
-                    new PropertyModel<>(model.getObject().getConf(), "acceptableResponseCodes"));
-            fields.add(new MultiFieldPanel.Builder<>(
-                    new PropertyModel<>(model.getObject().getConf(), "acceptableResponseCodes")).build(
-                    "field",
-                    "acceptableResponseCodes",
-                    panel));
-        } else if (model.getObject().getConf() instanceof TimeBasedAccessPolicyConf) {
-            fields.add(new AjaxDateTimeFieldPanel(
-                    "field",
-                    "start",
-                    new DateOps.WrappedDateModel(new PropertyModel<>(model.getObject().getConf(), "start")),
-                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT));
-            fields.add(new AjaxDateTimeFieldPanel(
-                    "field",
-                    "end",
-                    new DateOps.WrappedDateModel(new PropertyModel<>(model.getObject().getConf(), "end")),
-                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT));
-            fields.add(new AjaxTextFieldPanel("field", "zoneId",
-                    new PropertyModel<>(model.getObject().getConf(), "zoneId"), false));
-        }
-
-        add(new ListView<>("fields", fields) {
-
-            private static final long serialVersionUID = -9180479401817023838L;
-
-            @Override
-            protected void populateItem(final ListItem<Component> item) {
-                item.add(item.getModelObject());
-            }
-        });
+        add(new BeanPanel<>("bean", new PropertyModel<>(model, "conf"), pageRef).setRenderBodyOnly(true));
     }
 
     @Override
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.html
index b1fcbd9eac..793de99af0 100644
--- a/client/am/console/src/main/resources/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.html
+++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.html
@@ -18,10 +18,6 @@ under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:extend>
-    <div wicket:id="fields">
-      <div class="form-group">
-        <span wicket:id="field"/>
-      </div>
-    </div>
+    <span wicket:id="bean"/>
   </wicket:extend>
 </html>
diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java
index 789fa41872..644ce96cdb 100644
--- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java
+++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/Constants.java
@@ -108,7 +108,7 @@ public final class Constants {
     public static final String UNDEFINED_ICON = "fas fa-question-circle";
 
     public static final String NOT_FOUND_ICON = "fas fa-minus-circle";
-    
+
     public static final String WARNING_ICON = "fas fa-exclamation-circle";
 
     public static final int MAX_GROUP_LIST_SIZE = 30;
@@ -122,7 +122,7 @@ public final class Constants {
     public static final String NOTIFICATION_LEVEL_PARAM = "notificationLevel";
 
     public static final String ENDUSER_ANYLAYOUT = "enduser.anylayout";
-    
+
     public static final String CONTENT_ID = "content";
 
     public static Component getJEXLPopover(final Component caller, final TooltipConfig.Placement placement) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
index bc3e8079a3..40eee868fd 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
@@ -157,7 +157,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
                 item.replace(fragment);
             }
 
-            @SuppressWarnings({ "unchecked", "rawtypes" })
+            @SuppressWarnings({"unchecked", "rawtypes"})
             @Override
             protected void populateItem(final ListItem<String> item) {
                 item.add(new Fragment("required", "emptyFragment", this));
@@ -263,6 +263,8 @@ public class BeanPanel<T extends Serializable> extends Panel {
                 } else if (Map.class.equals(field.getType())) {
                     panel = new AjaxGridFieldPanel(
                             "value", fieldName, new PropertyModel<>(bean, fieldName)).hideLabel();
+                    Optional.ofNullable(field.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class))
+                            .ifPresent(annot -> setDescription(item, annot.description()));
                 } else {
                     Triple<FieldPanel, Boolean, Optional<String>> single =
                             buildSinglePanel(bean.getObject(), field.getType(), field.getName(),
@@ -279,7 +281,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
         }.setReuseItems(true).setOutputMarkupId(true));
     }
 
-    @SuppressWarnings({"unchecked", "rawtypes"})
+    @SuppressWarnings({ "unchecked", "rawtypes" })
     private Triple<FieldPanel, Boolean, Optional<String>> buildSinglePanel(
             final Serializable bean, final Class<?> type, final String fieldName,
             final io.swagger.v3.oas.annotations.media.Schema schema, final String id) {
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
index 6e04eb8495..c1ad289106 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccessPolicyConf.java
@@ -18,12 +18,10 @@
  */
 package org.apache.syncope.common.lib.policy;
 
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
 import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.syncope.common.lib.Attr;
+import java.util.HashMap;
+import java.util.Map;
 
 public class DefaultAccessPolicyConf implements AccessPolicyConf {
 
@@ -41,9 +39,13 @@ public class DefaultAccessPolicyConf implements AccessPolicyConf {
 
     private URI unauthorizedRedirectUrl;
 
-    private final List<Attr> requiredAttrs = new ArrayList<>();
+    @Schema(description =
+            "Insert comma-separated values in the right input field if you like to specify more than one value")
+    private final Map<String, String> requiredAttrs = new HashMap<>();
 
-    private final List<Attr> rejectedAttrs = new ArrayList<>();
+    @Schema(description =
+            "Insert comma-separated values in the right input field if you like to specify more than one value")
+    private final Map<String, String> rejectedAttrs = new HashMap<>();
 
     public int getOrder() {
         return order;
@@ -93,15 +95,11 @@ public class DefaultAccessPolicyConf implements AccessPolicyConf {
         this.unauthorizedRedirectUrl = unauthorizedRedirectUrl;
     }
 
-    @JacksonXmlElementWrapper(localName = "requiredAttrs")
-    @JacksonXmlProperty(localName = "requiredAttr")
-    public List<Attr> getRequiredAttrs() {
+    public Map<String, String> getRequiredAttrs() {
         return requiredAttrs;
     }
 
-    @JacksonXmlElementWrapper(localName = "rejectedAttrs")
-    @JacksonXmlProperty(localName = "rejectedAttr")
-    public List<Attr> getRejectedAttrs() {
+    public Map<String, String> getRejectedAttrs() {
         return rejectedAttrs;
     }
 }
diff --git a/common/am/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java b/common/am/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java
index ee0a2e81ce..60627a628a 100644
--- a/common/am/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java
+++ b/common/am/lib/src/test/java/org/apache/syncope/common/lib/SerializationTest.java
@@ -41,8 +41,8 @@ public abstract class SerializationTest {
         conf.setOrder(11);
         conf.setEnabled(true);
         conf.setUnauthorizedRedirectUrl(URI.create("https://syncope.apache.org"));
-        conf.getRequiredAttrs().add(new Attr.Builder("cn").values("admin", "Admin", "TheAdmin").build());
-        conf.getRejectedAttrs().add(new Attr.Builder("uid").values("plain").build());
+        conf.getRequiredAttrs().put("cn", "admin,Admin,TheAdmin");
+        conf.getRejectedAttrs().put("uid", "plain");
         policy.setConf(conf);
 
         StringWriter writer = new StringWriter();
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java
index d07ea3e676..dc601a64f6 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AbstractClientAppTest.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.inner;
 
 import java.util.List;
-import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
 import org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
@@ -57,7 +56,7 @@ public class AbstractClientAppTest extends AbstractTest {
         DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
         conf.setEnabled(true);
         conf.setSsoEnabled(false);
-        conf.getRequiredAttrs().add(new Attr.Builder("attribute1").values("value1", "value2").build());
+        conf.getRequiredAttrs().put("attribute1", "value1,value2");
         accessPolicy.setConf(conf);
 
         return policyDAO.save(accessPolicy);
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
index 190b55817a..39e3b0355e 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
@@ -26,7 +26,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.List;
 import java.util.UUID;
-import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
 import org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.DefaultAuthPolicyConf;
@@ -272,7 +271,7 @@ public class PolicyTest extends AbstractTest {
         accessPolicy.setName("AttrReleasePolicyAllowEverything");
 
         DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
-        conf.getRequiredAttrs().add(new Attr.Builder("cn").value("syncope").build());
+        conf.getRequiredAttrs().put("cn", "syncope");
         accessPolicy.setConf(conf);
 
         accessPolicy = policyDAO.save(accessPolicy);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index a15398d403..d32c8baa49 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -957,7 +957,7 @@ public abstract class AbstractITCase {
 
         DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
         conf.setEnabled(true);
-        conf.getRequiredAttrs().add(new Attr.Builder("cn").values("admin", "Admin", "TheAdmin").build());
+        conf.getRequiredAttrs().put("cn", "admin,Admin,TheAdmin");
         policy.setConf(conf);
 
         return policy;
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
index a16e4e1f47..14f783349f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
@@ -32,7 +32,6 @@ import java.util.Set;
 import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.SerializationUtils;
-import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.policy.AccessPolicyTO;
 import org.apache.syncope.common.lib.policy.AccountPolicyTO;
@@ -273,9 +272,9 @@ public class PolicyITCase extends AbstractITCase {
         assertNotNull(newAccessPolicyTO);
 
         DefaultAccessPolicyConf accessPolicyConf = (DefaultAccessPolicyConf) newAccessPolicyTO.getConf();
-        accessPolicyConf.getRequiredAttrs().add(new Attr.Builder("ou").value("test").build());
-        accessPolicyConf.getRequiredAttrs().removeIf(attr -> "cn".equals(attr.getSchema()));
-        accessPolicyConf.getRequiredAttrs().add(new Attr.Builder("cn").values("admin", "Admin").build());
+        accessPolicyConf.getRequiredAttrs().put("ou", "test");
+        accessPolicyConf.getRequiredAttrs().remove("cn");
+        accessPolicyConf.getRequiredAttrs().put("cn", "admin,Admin");
 
         // update new authentication policy
         POLICY_SERVICE.update(PolicyType.ACCESS, newAccessPolicyTO);
@@ -284,8 +283,8 @@ public class PolicyITCase extends AbstractITCase {
 
         accessPolicyConf = (DefaultAccessPolicyConf) newAccessPolicyTO.getConf();
         assertEquals(2, accessPolicyConf.getRequiredAttrs().size());
-        assertTrue(accessPolicyConf.getRequiredAttrs().stream().anyMatch(attr -> "cn".equals(attr.getSchema())));
-        assertTrue(accessPolicyConf.getRequiredAttrs().stream().anyMatch(attr -> "ou".equals(attr.getSchema())));
+        assertTrue(accessPolicyConf.getRequiredAttrs().containsKey("cn"));
+        assertTrue(accessPolicyConf.getRequiredAttrs().containsKey("ou"));
     }
 
     @Test
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index a40a22ec1f..74da17e64d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -29,7 +29,6 @@ import java.util.List;
 import java.util.UUID;
 import javax.ws.rs.core.GenericType;
 import javax.ws.rs.core.Response;
-import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.policy.AccessPolicyTO;
@@ -250,7 +249,7 @@ public class RealmITCase extends AbstractITCase {
     public void deletingAccessPolicy() {
         // 1. create access policy
         DefaultAccessPolicyConf conf = new DefaultAccessPolicyConf();
-        conf.getRequiredAttrs().add(new Attr.Builder("cn").values("admin", "Admin", "TheAdmin").build());
+        conf.getRequiredAttrs().put("cn", "admin,Admin,TheAdmin");
 
         AccessPolicyTO policy = new AccessPolicyTO();
         policy.setName("Test Access policy");
diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.java
index 237cb11b90..aef2e4ee59 100644
--- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.java
+++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAccessMapper.java
@@ -18,7 +18,9 @@
  */
 package org.apache.syncope.wa.starter.mapping;
 
-import java.util.HashSet;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.policy.AccessPolicyTO;
 import org.apache.syncope.common.lib.policy.DefaultAccessPolicyConf;
 import org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy;
@@ -43,10 +45,12 @@ public class DefaultAccessMapper implements AccessMapper {
         accessStrategy.setUnauthorizedRedirectUrl(conf.getUnauthorizedRedirectUrl());
 
         conf.getRequiredAttrs().forEach(
-                attr -> accessStrategy.getRequiredAttributes().put(attr.getSchema(), new HashSet<>(attr.getValues())));
+                (k, v) -> accessStrategy.getRequiredAttributes().put(k,
+                        Stream.of(StringUtils.split(v, ",")).map(String::trim).collect(Collectors.toSet())));
 
         conf.getRejectedAttrs().forEach(
-                attr -> accessStrategy.getRejectedAttributes().put(attr.getSchema(), new HashSet<>(attr.getValues())));
+                (k, v) -> accessStrategy.getRejectedAttributes().put(k,
+                        Stream.of(StringUtils.split(v, ",")).map(String::trim).collect(Collectors.toSet())));
 
         return accessStrategy;
     }
diff --git a/wa/starter/src/test/java/org/apache/syncope/wa/starter/WAServiceRegistryTest.java b/wa/starter/src/test/java/org/apache/syncope/wa/starter/WAServiceRegistryTest.java
index f133f5253b..9e94aa2a10 100644
--- a/wa/starter/src/test/java/org/apache/syncope/wa/starter/WAServiceRegistryTest.java
+++ b/wa/starter/src/test/java/org/apache/syncope/wa/starter/WAServiceRegistryTest.java
@@ -27,7 +27,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.auth.OIDCAuthModuleConf;
 import org.apache.syncope.common.lib.policy.AccessPolicyTO;
 import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
@@ -114,7 +113,7 @@ public class WAServiceRegistryTest extends AbstractTest {
         AccessPolicyTO accessPolicy = new AccessPolicyTO();
         DefaultAccessPolicyConf accessPolicyConf = new DefaultAccessPolicyConf();
         accessPolicyConf.setEnabled(true);
-        accessPolicyConf.getRequiredAttrs().add(new Attr.Builder("cn").values("admin", "Admin", "TheAdmin").build());
+        accessPolicyConf.getRequiredAttrs().put("cn", "admin,Admin,TheAdmin");
         accessPolicy.setConf(accessPolicyConf);
         waClientApp.setAccessPolicy(accessPolicy);