You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/03/20 13:44:15 UTC
[1/2] syncope git commit: [SYNCOPE-1281] Added the possibility to map
privileges for propagation
Repository: syncope
Updated Branches:
refs/heads/2_0_X fa079531e -> 93ef03e69
refs/heads/master a413dbca5 -> fb3a30e6e
[SYNCOPE-1281] Added the possibility to map privileges for propagation
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/fb3a30e6
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/fb3a30e6
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/fb3a30e6
Branch: refs/heads/master
Commit: fb3a30e6ec8440354546804396504178e94201ce
Parents: a413dbc
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Mar 20 14:38:05 2018 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Mar 20 14:38:05 2018 +0100
----------------------------------------------------------------------
.../NotificationWizardBuilder.java | 9 ++--
.../console/wizards/AbstractMappingPanel.java | 11 ++--
.../SyncopeConsoleApplication.properties | 2 +-
.../SyncopeConsoleApplication_it.properties | 2 +-
.../SyncopeConsoleApplication_pt_BR.properties | 2 +-
.../core/persistence/api/entity/Role.java | 2 +
.../persistence/jpa/entity/JPAApplication.java | 2 +
.../persistence/jpa/entity/JPAPrivilege.java | 2 +
.../core/persistence/jpa/entity/JPARole.java | 9 ++++
.../jpa/validation/entity/ApplicationCheck.java | 41 +++++++++++++++
.../validation/entity/ApplicationValidator.java | 40 +++++++++++++++
.../jpa/validation/entity/PrivilegeCheck.java | 41 +++++++++++++++
.../validation/entity/PrivilegeValidator.java | 40 +++++++++++++++
.../core/provisioning/api/IntAttrName.java | 10 ++++
.../provisioning/java/IntAttrNameParser.java | 16 ++++--
.../provisioning/java/MappingManagerImpl.java | 53 +++++++++++++++-----
.../java/data/ResourceDataBinderImpl.java | 16 +++++-
.../java/IntAttrNameParserTest.java | 22 ++++++++
.../syncope/fit/core/PropagationTaskITCase.java | 38 ++++++++++++++
.../concepts/externalresources.adoc | 2 +
20 files changed, 328 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index e4442a4..471e549 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -352,11 +352,10 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
recipientAttrName.setChoices(getSchemas());
recipientAttrName.addRequiredLabel();
recipientAttrName.setTitle(getString("intAttrNameInfo.help")
- + "<div style=\"font-size: 10px;\">"
- + "<code>groups[groupName].attribute</code>\n"
- + "<code>anyObjects[anyObjectName].attribute</code>\n"
- + "<code>memberships[groupName].attribute</code>\n"
- + "</div>", true);
+ + "<code>groups[groupName].attribute</code>, "
+ + "<code>anyObjects[anyObjectName].attribute</code>, "
+ + "<code>memberships[groupName].attribute</code> or "
+ + "<code>privileges[applicationKey]</code>", true);
add(recipientAttrName);
AjaxTextFieldPanel staticRecipientsFieldPanel =
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
index f344917..c35be6a 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
@@ -151,12 +151,11 @@ public abstract class AbstractMappingPanel extends Panel {
mappingContainer.add(new Label("intAttrNameInfo", Model.of()).add(new PopoverBehavior(
Model.<String>of(),
Model.of(getString("intAttrNameInfo.help")
- + "<div style=\"font-size: 10px;\">"
- + "<code>groups[groupName].attribute</code>\n"
- + "<code>anyObjects[anyObjectName].attribute</code>\n"
- + "<code>memberships[groupName].attribute</code>\n"
- + "</div>"),
- new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.bottom)) {
+ + "<code>groups[groupName].attribute</code>, "
+ + "<code>anyObjects[anyObjectName].attribute</code>, "
+ + "<code>memberships[groupName].attribute</code> or "
+ + "<code>privileges[applicationKey]</code>"),
+ new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.right)) {
private static final long serialVersionUID = -7867802555691605021L;
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
index 2a36516..1d093bc 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
@@ -67,7 +67,7 @@ OrderByLink.CSS.none=sorting
entitlements=Entitlements
audit=Audit
connectors.confirm.reload=This request is potentially dangerous for running operations, continue?
-intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships (if applicable); for example:
+intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects, memberships or privileges; for example:
confirmGlobalLogout=Do you really want to perform global logout?
implementations=Implementations
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
index f1b3985..a4514ff 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
@@ -67,7 +67,7 @@ OrderByLink.CSS.none=sorting
entitlements=Entitlement
audit=Audit
connectors.confirm.reload=Questa richiesta \u00e8 potenzialmente dannosa per le operazioni in corso, proseguire?
-intAttrNameInfo.help=Oltre agli attributi auto-completati, \u00e8 possibile fare riferimento anche a gruppi, any object e membership (se applicabile); ad esempio:
+intAttrNameInfo.help=Oltre agli attributi auto-completati, \u00e8 possibile fare riferimento anche a gruppi, any object, membership e privilegi; ad esempio:
confirmGlobalLogout=Vuoi davvero procedere al logout globale?
implementations=Implementazioni
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
index 9516f2b..3d40751 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
@@ -67,7 +67,7 @@ OrderByLink.CSS.none=sorting
entitlements=Entitlement
audit=Audit
connectors.confirm.reload=Esta requis\u00e7\u00e3o \u00e9 potencialmente perigosa para opera\u00e7\u00f5es em execu\u00e7\u00e3o, prosseguir?
-intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships (if applicable); for example:
+intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects, memberships or privileges; for example:
confirmGlobalLogout=Do you really want to perform global logout?
implementations=Implementa\u00e7\u00f5es
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Role.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Role.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Role.java
index 619c228..e4cf8a2 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Role.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Role.java
@@ -44,5 +44,7 @@ public interface Role extends ProvidedKeyEntity {
boolean add(Privilege privilege);
+ Set<? extends Privilege> getPrivileges(Application application);
+
Set<? extends Privilege> getPrivileges();
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAApplication.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAApplication.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAApplication.java
index 0b5f093..756ce12 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAApplication.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAApplication.java
@@ -28,9 +28,11 @@ import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.apache.syncope.core.persistence.api.entity.Application;
import org.apache.syncope.core.persistence.api.entity.Privilege;
+import org.apache.syncope.core.persistence.jpa.validation.entity.ApplicationCheck;
@Entity
@Table(name = JPAApplication.TABLE)
+@ApplicationCheck
public class JPAApplication extends AbstractProvidedKeyEntity implements Application {
private static final long serialVersionUID = -5951400197744722305L;
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPrivilege.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPrivilege.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPrivilege.java
index 0e1a3b5..d09bb1d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPrivilege.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPrivilege.java
@@ -24,9 +24,11 @@ import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.syncope.core.persistence.api.entity.Application;
import org.apache.syncope.core.persistence.api.entity.Privilege;
+import org.apache.syncope.core.persistence.jpa.validation.entity.PrivilegeCheck;
@Entity
@Table(name = JPAPrivilege.TABLE)
+@PrivilegeCheck
public class JPAPrivilege extends AbstractProvidedKeyEntity implements Privilege {
private static final long serialVersionUID = -6479069294944858456L;
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
index 728c360..4dbddbf 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
@@ -36,6 +37,7 @@ import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.validation.Valid;
+import org.apache.syncope.core.persistence.api.entity.Application;
import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership;
import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.Role;
@@ -147,6 +149,13 @@ public class JPARole extends AbstractProvidedKeyEntity implements Role {
}
@Override
+ public Set<? extends Privilege> getPrivileges(final Application application) {
+ return privileges.stream().
+ filter(privilege -> privilege.getApplication().equals(application)).
+ collect(Collectors.toSet());
+ }
+
+ @Override
public Set<? extends Privilege> getPrivileges() {
return privileges;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationCheck.java
new file mode 100644
index 0000000..674a5b1
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = ApplicationValidator.class)
+@Documented
+public @interface ApplicationCheck {
+
+ String message() default "{org.apache.syncope.core.persistence.validation.application}";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationValidator.java
new file mode 100644
index 0000000..7360021
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ApplicationValidator.java
@@ -0,0 +1,40 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.Application;
+
+public class ApplicationValidator extends AbstractValidator<ApplicationCheck, Application> {
+
+ @Override
+ public boolean isValid(final Application application, final ConstraintValidatorContext context) {
+ context.disableDefaultConstraintViolation();
+
+ if (application.getKey() == null || !KEY_PATTERN.matcher(application.getKey()).matches()) {
+ context.buildConstraintViolationWithTemplate(
+ getTemplate(EntityViolationType.InvalidKey, "Invalid application key")).
+ addPropertyNode("key").addConstraintViolation();
+ return false;
+ }
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeCheck.java
new file mode 100644
index 0000000..aabc552
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = PrivilegeValidator.class)
+@Documented
+public @interface PrivilegeCheck {
+
+ String message() default "{org.apache.syncope.core.persistence.validation.privilege}";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeValidator.java
new file mode 100644
index 0000000..6f035d8
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PrivilegeValidator.java
@@ -0,0 +1,40 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.Privilege;
+
+public class PrivilegeValidator extends AbstractValidator<PrivilegeCheck, Privilege> {
+
+ @Override
+ public boolean isValid(final Privilege privilege, final ConstraintValidatorContext context) {
+ context.disableDefaultConstraintViolation();
+
+ if (privilege.getKey() == null || !KEY_PATTERN.matcher(privilege.getKey()).matches()) {
+ context.buildConstraintViolationWithTemplate(
+ getTemplate(EntityViolationType.InvalidKey, "Invalid privilege key")).
+ addPropertyNode("key").addConstraintViolation();
+ return false;
+ }
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
index f46384e..1c42ec9 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
@@ -39,6 +39,8 @@ public class IntAttrName {
private String membershipOfGroup;
+ private String privilegesOfApplication;
+
public AnyTypeKind getAnyTypeKind() {
return anyTypeKind;
}
@@ -95,6 +97,14 @@ public class IntAttrName {
this.membershipOfGroup = membershipOfGroup;
}
+ public String getPrivilegesOfApplication() {
+ return privilegesOfApplication;
+ }
+
+ public void setPrivilegesOfApplication(final String privilegesOfApplication) {
+ this.privilegesOfApplication = privilegesOfApplication;
+ }
+
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
index 2b77a61..2d42609 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
@@ -35,6 +35,9 @@ import org.springframework.transaction.annotation.Transactional;
public class IntAttrNameParser {
+ private static final Pattern PRIVILEGE_PATTERN = Pattern.compile(
+ "^privileges\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]");
+
private static final Pattern ENCLOSING_GROUP_PATTERN = Pattern.compile(
"^groups\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]\\.(.+)");
@@ -92,11 +95,18 @@ public class IntAttrNameParser {
public IntAttrName parse(final String intAttrName, final AnyTypeKind provisionAnyTypeKind) throws ParseException {
IntAttrName result = new IntAttrName();
+ Matcher matcher;
if (intAttrName.indexOf('.') == -1) {
- result.setAnyTypeKind(provisionAnyTypeKind);
- setFieldOrSchemaName(intAttrName, result.getAnyTypeKind(), result);
+ matcher = PRIVILEGE_PATTERN.matcher(intAttrName);
+ if (matcher.matches()) {
+ result.setAnyTypeKind(AnyTypeKind.USER);
+ result.setPrivilegesOfApplication(matcher.group(1));
+ } else {
+ result.setAnyTypeKind(provisionAnyTypeKind);
+ setFieldOrSchemaName(intAttrName, result.getAnyTypeKind(), result);
+ }
} else {
- Matcher matcher = ENCLOSING_GROUP_PATTERN.matcher(intAttrName);
+ matcher = ENCLOSING_GROUP_PATTERN.matcher(intAttrName);
if (matcher.matches()) {
result.setAnyTypeKind(AnyTypeKind.GROUP);
result.setEnclosingGroup(matcher.group(1));
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index 8685d39..aced103 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -43,14 +43,17 @@ import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.ApplicationDAO;
import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
import org.apache.syncope.core.persistence.api.entity.Any;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.Application;
import org.apache.syncope.core.persistence.api.entity.DerSchema;
import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
import org.apache.syncope.core.persistence.api.entity.Membership;
@@ -112,6 +115,9 @@ public class MappingManagerImpl implements MappingManager {
private VirSchemaDAO virSchemaDAO;
@Autowired
+ private UserDAO userDAO;
+
+ @Autowired
private AnyObjectDAO anyObjectDAO;
@Autowired
@@ -121,6 +127,9 @@ public class MappingManagerImpl implements MappingManager {
private RealmDAO realmDAO;
@Autowired
+ private ApplicationDAO applicationDAO;
+
+ @Autowired
private DerAttrHandler derAttrHandler;
@Autowired
@@ -526,7 +535,10 @@ public class MappingManagerImpl implements MappingManager {
attr = ((GroupableRelatable<?, ?, ?, ?, ?>) reference).getPlainAttr(
intAttrName.getSchemaName(), membership).orElse(null);
}
- if (attr != null) {
+ if (attr == null) {
+ LOG.warn("Invalid PlainSchema {} or PlainAttr not found for {}",
+ intAttrName.getSchemaName(), reference);
+ } else {
if (attr.getUniqueValue() != null) {
values.add(anyUtils.clonePlainAttrValue(attr.getUniqueValue()));
} else if (attr.getValues() != null) {
@@ -537,13 +549,15 @@ public class MappingManagerImpl implements MappingManager {
case DERIVED:
DerSchema derSchema = derSchemaDAO.find(intAttrName.getSchemaName());
- if (derSchema != null) {
- String value = membership == null
+ if (derSchema == null) {
+ LOG.warn("Invalid DerSchema: {}", intAttrName.getSchemaName());
+ } else {
+ String derValue = membership == null
? derAttrHandler.getValue(reference, derSchema)
: derAttrHandler.getValue(reference, membership, derSchema);
- if (value != null) {
+ if (derValue != null) {
PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
- attrValue.setStringValue(value);
+ attrValue.setStringValue(derValue);
values.add(attrValue);
}
}
@@ -554,7 +568,9 @@ public class MappingManagerImpl implements MappingManager {
transform = false;
VirSchema virSchema = virSchemaDAO.find(intAttrName.getSchemaName());
- if (virSchema != null) {
+ if (virSchema == null) {
+ LOG.warn("Invalid VirSchema: {}", intAttrName.getSchemaName());
+ } else {
LOG.debug("Expire entry cache {}-{}", reference, intAttrName.getSchemaName());
virAttrCache.expire(
reference.getType().getKey(), reference.getKey(), intAttrName.getSchemaName());
@@ -562,18 +578,29 @@ public class MappingManagerImpl implements MappingManager {
List<String> virValues = membership == null
? virAttrHandler.getValues(reference, virSchema)
: virAttrHandler.getValues(reference, membership, virSchema);
- virValues.stream().
- map(value -> {
- PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
- attrValue.setStringValue(value);
- return attrValue;
- }).
- forEachOrdered(attrValue -> values.add(attrValue));
+ virValues.forEach(virValue -> {
+ PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+ attrValue.setStringValue(virValue);
+ values.add(attrValue);
+ });
}
break;
default:
}
+ } else if (intAttrName.getPrivilegesOfApplication() != null && reference instanceof User) {
+ Application application = applicationDAO.find(intAttrName.getPrivilegesOfApplication());
+ if (application == null) {
+ LOG.warn("Invalid application: {}", intAttrName.getPrivilegesOfApplication());
+ } else {
+ userDAO.findAllRoles((User) reference).stream().
+ flatMap(role -> role.getPrivileges(application).stream()).
+ forEach(privilege -> {
+ PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+ attrValue.setStringValue(privilege.getKey());
+ values.add(attrValue);
+ });
+ }
}
LOG.debug("Internal values: {}", values);
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 7e5cea6..1db8e56 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -410,14 +410,19 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
LOG.error("Invalid intAttrName '{}'", itemTO.getIntAttrName(), e);
}
- if (intAttrName == null || intAttrName.getSchemaType() == null && intAttrName.getField() == null) {
+ if (intAttrName == null
+ || intAttrName.getSchemaType() == null && intAttrName.getField() == null
+ && intAttrName.getPrivilegesOfApplication() == null) {
+
LOG.error("'{}' not existing", itemTO.getIntAttrName());
invalidMapping.getElements().add("'" + itemTO.getIntAttrName() + "' not existing");
} else {
boolean allowed = true;
if (intAttrName.getSchemaType() != null
&& intAttrName.getEnclosingGroup() == null
- && intAttrName.getRelatedAnyObject() == null) {
+ && intAttrName.getRelatedAnyObject() == null
+ && intAttrName.getPrivilegesOfApplication() == null) {
+
switch (intAttrName.getSchemaType()) {
case PLAIN:
allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchemaName());
@@ -492,6 +497,13 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
"Only " + MappingPurpose.PROPAGATION.name()
+ " allowed when referring to any objects");
}
+ if (intAttrName.getPrivilegesOfApplication() != null
+ && item.getPurpose() != MappingPurpose.PROPAGATION) {
+
+ invalidMapping.getElements().add(
+ "Only " + MappingPurpose.PROPAGATION.name()
+ + " allowed when referring to privileges");
+ }
if (intAttrName.getSchemaType() == SchemaType.DERIVED
&& item.getPurpose() != MappingPurpose.PROPAGATION) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
index beeb7b0..0316a12 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
@@ -49,6 +49,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
intAttrName = intAttrNameParser.parse("name", AnyTypeKind.GROUP);
assertNotNull(intAttrName);
@@ -60,6 +61,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
intAttrName = intAttrNameParser.parse("userOwner", AnyTypeKind.GROUP);
assertNotNull(intAttrName);
@@ -71,6 +73,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
intAttrName = intAttrNameParser.parse("name", AnyTypeKind.USER);
assertNotNull(intAttrName);
@@ -89,6 +92,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
intAttrName = intAttrNameParser.parse("cn", AnyTypeKind.ANY_OBJECT);
assertNotNull(intAttrName);
@@ -99,6 +103,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
intAttrName = intAttrNameParser.parse("rvirtualdata", AnyTypeKind.ANY_OBJECT);
assertNotNull(intAttrName);
@@ -109,6 +114,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
}
@Test
@@ -122,6 +128,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertEquals("readers", intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
}
@Test
@@ -135,6 +142,7 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertEquals("hp", intAttrName.getRelatedAnyObject());
assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getPrivilegesOfApplication());
}
@Test
@@ -148,6 +156,20 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertEquals("top", intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getPrivilegesOfApplication());
+ }
+
+ @Test
+ public void privileges() throws ParseException {
+ IntAttrName intAttrName = intAttrNameParser.parse("privileges[mightyApp]", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertNull(intAttrName.getSchemaName());
+ assertNull(intAttrName.getSchemaType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+ assertEquals("mightyApp", intAttrName.getPrivilegesOfApplication());
}
@Test
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index f74b224..834eb10 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -29,6 +29,7 @@ import java.util.Optional;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.syncope.common.lib.to.TaskTO;
import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AttrTO;
import org.apache.syncope.common.lib.to.BulkAction;
import org.apache.syncope.common.lib.to.ConnObjectTO;
import org.apache.syncope.common.lib.to.PagedResult;
@@ -36,9 +37,11 @@ import org.apache.syncope.common.lib.to.PropagationTaskTO;
import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.ItemTO;
import org.apache.syncope.common.lib.to.ProvisionTO;
+import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.MappingPurpose;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
import org.apache.syncope.common.rest.api.beans.ExecQuery;
@@ -144,6 +147,41 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
}
@Test
+ public void privileges() {
+ ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP);
+ ldap.setKey("ldapWithPrivileges");
+
+ ItemTO item = new ItemTO();
+ item.setIntAttrName("privileges[mightyApp]");
+ item.setExtAttrName("businessCategory");
+ item.setPurpose(MappingPurpose.PROPAGATION);
+
+ ProvisionTO provision = ldap.getProvision(AnyTypeKind.USER.name()).get();
+ provision.getVirSchemas().clear();
+ provision.getMapping().add(item);
+
+ ldap = createResource(ldap);
+
+ try {
+ UserTO user = UserITCase.getUniqueSampleTO("privilege@syncope.apache.org");
+ user.getResources().add(ldap.getKey());
+ user.getRoles().add("Other");
+
+ ProvisioningResult<UserTO> result = createUser(user);
+ assertEquals(1, result.getPropagationStatuses().size());
+ assertNotNull(result.getPropagationStatuses().get(0).getAfterObj());
+
+ AttrTO businessCategory =
+ result.getPropagationStatuses().get(0).getAfterObj().getAttr("businessCategory").orElse(null);
+ assertNotNull(businessCategory);
+ assertEquals(1, businessCategory.getValues().size());
+ assertEquals("postMighty", businessCategory.getValues().get(0));
+ } finally {
+ resourceService.delete(ldap.getKey());
+ }
+ }
+
+ @Test
public void issueSYNCOPE741() {
for (int i = 0; i < 3; i++) {
taskService.execute(new ExecuteQuery.Builder().
http://git-wip-us.apache.org/repos/asf/syncope/blob/fb3a30e6/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/concepts/externalresources.adoc b/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
index 32b71d2..3c54e42 100644
--- a/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
@@ -110,6 +110,8 @@ specified by an expression matching one of the following models:
name `anyObjectName`, if a relationship with the mapped entity exists
** `memberships[groupName].schema` - resolves to the attribute for the given `schema`, owned by the membership for group
`groupName` of the mapped entity (user, any object), if such a membership exists
+** `privileges[applicationKey]` - resolves to the list of privileges, related to the given <<application,applicaton>>,
+owned by the mapped entity (which can only be user, in this case)
* external attribute - the name of the attribute on the Identity Store
* transformers - http://commons.apache.org/proper/commons-jexl/[JEXL^] expression or Java class implementing
ifeval::["{snapshotOrRelease}" == "release"]
[2/2] syncope git commit: Adjusting internal attribute's popover
appearance
Posted by il...@apache.org.
Adjusting internal attribute's popover appearance
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/93ef03e6
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/93ef03e6
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/93ef03e6
Branch: refs/heads/2_0_X
Commit: 93ef03e692fd745320fd86c149aa01ef56ee5950
Parents: fa07953
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Mar 20 14:44:07 2018 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Mar 20 14:44:07 2018 +0100
----------------------------------------------------------------------
.../console/notifications/NotificationWizardBuilder.java | 8 +++-----
.../client/console/wizards/AbstractMappingPanel.java | 10 ++++------
2 files changed, 7 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/93ef03e6/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index aa34be9..3ccfab0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -357,11 +357,9 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
recipientAttrName.setChoices(getSchemas());
recipientAttrName.addRequiredLabel();
recipientAttrName.setTitle(getString("intAttrNameInfo.help")
- + "<div style=\"font-size: 10px;\">"
- + "<code>groups[groupName].attribute</code>\n"
- + "<code>anyObjects[anyObjectName].attribute</code>\n"
- + "<code>memberships[groupName].attribute</code>\n"
- + "</div>", true);
+ + "<code>groups[groupName].attribute</code>, "
+ + "<code>anyObjects[anyObjectName].attribute</code> or "
+ + "<code>memberships[groupName].attribute</code>", true);
add(recipientAttrName);
AjaxTextFieldPanel staticRecipientsFieldPanel =
http://git-wip-us.apache.org/repos/asf/syncope/blob/93ef03e6/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
index 5532f86..42475c0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
@@ -152,12 +152,10 @@ public abstract class AbstractMappingPanel extends Panel {
mappingContainer.add(new Label("intAttrNameInfo", Model.of()).add(new PopoverBehavior(
Model.<String>of(),
Model.of(getString("intAttrNameInfo.help")
- + "<div style=\"font-size: 10px;\">"
- + "<code>groups[groupName].attribute</code>\n"
- + "<code>anyObjects[anyObjectName].attribute</code>\n"
- + "<code>memberships[groupName].attribute</code>\n"
- + "</div>"),
- new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.bottom)) {
+ + "<code>groups[groupName].attribute</code>, "
+ + "<code>anyObjects[anyObjectName].attribute</code> or "
+ + "<code>memberships[groupName].attribute</code>"),
+ new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.right)) {
private static final long serialVersionUID = -7867802555691605021L;