[SYNCOPE-956] Console implementation
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/98890722 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/98890722 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/98890722 Branch: refs/heads/master Commit: 9889072252105c0f3c029ae188a12ead3aff542f Parents: f08a17b Author: Francesco Chicchiriccò <[email protected]> Authored: Fri Oct 6 17:07:52 2017 +0200 Committer: Francesco Chicchiriccò <[email protected]> Committed: Tue Oct 10 08:34:14 2017 +0200 ---------------------------------------------------------------------- .../commands/schema/SchemaResultManager.java | 2 +- .../client/console/commons/Constants.java | 2 + .../init/ClassPathScanImplementationLookup.java | 48 ++- .../NotificationDirectoryPanel.java | 4 +- .../NotificationWizardBuilder.java | 35 +- .../syncope/client/console/pages/Audit.java | 27 +- .../syncope/client/console/pages/BasePage.java | 6 + .../client/console/pages/Implementations.java | 66 ++++ .../panels/ImplementationDirectoryPanel.java | 232 +++++++++++++ .../panels/ImplementationEngineTogglePanel.java | 84 +++++ .../panels/ImplementationModalPanel.java | 329 +++++++++++++++++++ .../panels/ParametersEditModalPanel.java | 9 +- .../console/panels/PlainSchemaDetails.java | 29 +- .../client/console/panels/RealmDetails.java | 36 +- .../policies/AccountPolicyDirectoryPanel.java | 2 +- .../policies/PasswordPolicyDirectoryPanel.java | 2 +- .../policies/PolicyRuleDirectoryPanel.java | 65 +++- .../policies/PolicyRuleWizardBuilder.java | 153 ++++----- .../console/policies/PolicyRuleWrapper.java | 29 +- .../console/policies/PolicySpecModalPanel.java | 82 ++--- .../policies/PullPolicyDirectoryPanel.java | 2 +- .../reports/ReportletDirectoryPanel.java | 57 +++- .../console/reports/ReportletWizardBuilder.java | 113 ++----- .../console/reports/ReportletWrapper.java | 33 +- .../console/rest/ImplementationRestClient.java | 18 +- .../console/tasks/SchedTaskDirectoryPanel.java | 4 +- .../console/tasks/SchedTaskWizardBuilder.java | 104 +++--- .../html/form/ActionLinksTogglePanel.java | 6 +- .../client/console/wizards/any/Ownership.java | 4 +- .../console/wizards/any/Relationships.java | 4 +- .../client/console/wizards/any/Resources.java | 4 +- .../resources/AbstractConnConfPanel.java | 6 +- .../resources/ItemTransformersTogglePanel.java | 22 +- .../resources/ObjectTypeTogglePanel.java | 8 +- .../resources/ProvisionWizardBuilder.java | 3 +- .../wizards/resources/ResourceDetailsPanel.java | 26 +- .../src/main/resources/console.properties | 1 + .../SyncopeConsoleApplication.properties | 1 + .../SyncopeConsoleApplication_it.properties | 1 + .../SyncopeConsoleApplication_pt_BR.properties | 1 + .../SyncopeConsoleApplication_ru.properties | 3 +- .../implementations/MyAccountRule.groovy | 29 ++ .../implementations/MyItemTransformer.groovy | 46 +++ .../implementations/MyLogicActions.groovy | 38 +++ .../implementations/MyPasswordRule.groovy | 28 ++ .../implementations/MyPropagationActions.groovy | 43 +++ .../implementations/MyPullActions.groovy | 125 +++++++ .../MyPullCorrelationRule.groovy | 31 ++ .../implementations/MyPushActions.groovy | 112 +++++++ .../implementations/MyRecipientsProvider.groovy | 31 ++ .../implementations/MyReconFilterBuilder.groovy | 30 ++ .../console/implementations/MyReportlet.groovy | 30 ++ .../MySchedTaskJobDelegate.groovy | 31 ++ .../console/implementations/MyValidator.groovy | 34 ++ .../NotificationWizardBuilder$Recipients.html | 47 ++- ...ificationWizardBuilder$Recipients.properties | 2 +- ...cationWizardBuilder$Recipients_it.properties | 2 +- ...ionWizardBuilder$Recipients_pt_BR.properties | 2 +- ...cationWizardBuilder$Recipients_ru.properties | 2 +- .../syncope/client/console/pages/BasePage.html | 1 + .../client/console/pages/Implementations.html | 36 ++ .../panels/ImplementationDirectoryPanel.html | 23 ++ .../ImplementationDirectoryPanel.properties | 19 ++ .../ImplementationDirectoryPanel_it.properties | 19 ++ ...mplementationDirectoryPanel_pt_BR.properties | 19 ++ .../ImplementationDirectoryPanel_ru.properties | 20 ++ .../panels/ImplementationEngineTogglePanel.html | 32 ++ .../panels/ImplementationModalPanel.html | 62 ++++ .../console/panels/PlainSchemaDetails.html | 2 +- .../panels/PlainSchemaDetails.properties | 2 +- .../panels/PlainSchemaDetails_it.properties | 2 +- .../panels/PlainSchemaDetails_pt_BR.properties | 2 +- .../panels/PlainSchemaDetails_ru.properties | 36 +- .../client/console/panels/RealmDetails.html | 2 +- .../console/panels/RealmDetails.properties | 2 +- .../console/panels/RealmDetails_it.properties | 2 +- .../panels/RealmDetails_pt_BR.properties | 2 +- .../console/panels/RealmDetails_ru.properties | 2 +- .../policies/PolicyDirectoryPanel.properties | 3 +- .../policies/PolicyDirectoryPanel_it.properties | 3 +- .../PolicyDirectoryPanel_pt_BR.properties | 3 +- .../policies/PolicyDirectoryPanel_ru.properties | 3 +- .../PolicyRuleDirectoryPanel.properties | 5 +- .../PolicyRuleDirectoryPanel_it.properties | 5 +- .../PolicyRuleDirectoryPanel_pt_BR.properties | 5 +- .../PolicyRuleDirectoryPanel_ru.properties | 5 +- .../PolicyRuleWizardBuilder$Profile.html | 5 +- ...licySpecModalPanel$CorrelationRulePanel.html | 2 +- .../policies/PolicySpecModalPanel.properties | 4 +- .../policies/PolicySpecModalPanel_it.properties | 4 +- .../PolicySpecModalPanel_pt_BR.properties | 4 +- .../policies/PolicySpecModalPanel_ru.properties | 4 +- .../reports/ReportletDirectoryPanel.properties | 1 + .../ReportletDirectoryPanel_it.properties | 1 + .../ReportletDirectoryPanel_pt_BR.properties | 1 + .../ReportletDirectoryPanel_ru.properties | 1 + .../reports/ReportletWizardBuilder$Profile.html | 3 +- .../ReportletWizardBuilder$Profile.properties | 2 +- ...ReportletWizardBuilder$Profile_it.properties | 2 +- ...ortletWizardBuilder$Profile_pt_BR.properties | 2 +- ...ReportletWizardBuilder$Profile_ru.properties | 2 +- .../tasks/SchedTaskDirectoryPanel.properties | 6 +- .../tasks/SchedTaskDirectoryPanel_it.properties | 6 +- .../SchedTaskDirectoryPanel_pt_BR.properties | 6 +- .../tasks/SchedTaskDirectoryPanel_ru.properties | 9 +- .../tasks/SchedTaskWizardBuilder$Profile.html | 6 +- .../SchedTaskWizardBuilder$Profile.properties | 2 +- ...SchedTaskWizardBuilder$Profile_it.properties | 2 +- ...edTaskWizardBuilder$Profile_pt_BR.properties | 2 +- ...SchedTaskWizardBuilder$Profile_ru.properties | 2 +- .../ObjectTypeTogglePanel_it.properties | 4 +- .../wizards/resources/ResourceDetailsPanel.html | 2 +- .../resources/ResourceDetailsPanel.properties | 2 +- .../ResourceDetailsPanel_it.properties | 2 +- .../ResourceDetailsPanel_pt_BR.properties | 2 +- .../ResourceDetailsPanel_ru.properties | 2 +- .../lib/report/ReconciliationReportletConf.java | 1 - .../syncope/common/lib/to/PlainSchemaTO.java | 10 +- .../syncope/core/logic/ImplementationLogic.java | 14 + .../core/persistence/api/dao/AccountRule.java | 3 +- .../core/persistence/api/dao/PasswordRule.java | 7 +- .../core/persistence/api/dao/Reportlet.java | 3 +- .../test/resources/domains/MasterContent.xml | 4 +- .../java/data/ImplementationDataBinderImpl.java | 12 +- .../java/data/SchemaDataBinderImpl.java | 22 +- .../console/panels/SAML2IdPsDirectoryPanel.java | 4 +- 126 files changed, 2197 insertions(+), 619 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java ---------------------------------------------------------------------- diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java index 95d5628..4da9446 100644 --- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java +++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java @@ -61,7 +61,7 @@ public class SchemaResultManager extends CommonsResultManager { System.out.println(" conversion pattern: " + schemaTO.getConversionPattern()); System.out.println(" mandatory condition: " + schemaTO.getMandatoryCondition()); System.out.println(" mime type: " + schemaTO.getMimeType()); - System.out.println(" validator class: " + schemaTO.getValidatorClass()); + System.out.println(" validator class: " + schemaTO.getValidator()); System.out.println(" cipher algorithm: " + (schemaTO.getCipherAlgorithm() == null ? "" : schemaTO.getCipherAlgorithm().getAlgorithm())); System.out.println(""); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java index 5449097..c71fdbc 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java @@ -121,6 +121,8 @@ public final class Constants { public static final String PREF_NOTIFICATION_PAGINATOR_ROWS = "notification.paginator.rows"; + public static final String PREF_IMPLEMENTATION_PAGINATOR_ROWS = "implementation.paginator.rows"; + public static final String PREF_MAIL_TEMPLATE_PAGINATOR_ROWS = "mail.template.paginator.rows"; public static final String PREF_PROPAGATION_TASKS_PAGINATOR_ROWS = "proagationtasks.paginator.rows"; http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java b/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java index 7a39743..ed60e6c 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java @@ -21,7 +21,9 @@ package org.apache.syncope.client.console.init; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.syncope.client.console.pages.BaseExtPage; @@ -32,6 +34,9 @@ import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.panels.SSOLoginFormPanel; import org.apache.syncope.client.console.wicket.markup.html.form.preview.AbstractBinaryPreviewer; import org.apache.syncope.client.console.widgets.BaseExtWidget; +import org.apache.syncope.common.lib.policy.AccountRuleConf; +import org.apache.syncope.common.lib.policy.PasswordRuleConf; +import org.apache.syncope.common.lib.report.ReportletConf; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; @@ -42,7 +47,7 @@ public class ClassPathScanImplementationLookup { private static final Logger LOG = LoggerFactory.getLogger(ClassPathScanImplementationLookup.class); - private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.client.console"; + private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope"; private List<Class<? extends BasePage>> pages; @@ -54,6 +59,12 @@ public class ClassPathScanImplementationLookup { private List<Class<? extends SSOLoginFormPanel>> ssoLoginFormPanels; + private Map<String, Class<? extends ReportletConf>> reportletConfs; + + private Map<String, Class<? extends AccountRuleConf>> accountRuleConfs; + + private Map<String, Class<? extends PasswordRuleConf>> passwordRuleConfs; + /** * This method can be overridden by subclasses to customize classpath scan. * @@ -70,6 +81,9 @@ public class ClassPathScanImplementationLookup { extPages = new ArrayList<>(); extWidgets = new ArrayList<>(); ssoLoginFormPanels = new ArrayList<>(); + reportletConfs = new HashMap<>(); + accountRuleConfs = new HashMap<>(); + passwordRuleConfs = new HashMap<>(); ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); scanner.addIncludeFilter(new AssignableTypeFilter(BasePage.class)); @@ -77,6 +91,9 @@ public class ClassPathScanImplementationLookup { scanner.addIncludeFilter(new AssignableTypeFilter(BaseExtPage.class)); scanner.addIncludeFilter(new AssignableTypeFilter(BaseExtWidget.class)); scanner.addIncludeFilter(new AssignableTypeFilter(SSOLoginFormPanel.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(ReportletConf.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(AccountRuleConf.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(PasswordRuleConf.class)); scanner.findCandidateComponents(getBasePackage()).forEach(bd -> { try { @@ -105,6 +122,12 @@ public class ClassPathScanImplementationLookup { previewers.add((Class<? extends AbstractBinaryPreviewer>) clazz); } else if (SSOLoginFormPanel.class.isAssignableFrom(clazz)) { ssoLoginFormPanels.add((Class<? extends SSOLoginFormPanel>) clazz); + } else if (ReportletConf.class.isAssignableFrom(clazz)) { + reportletConfs.put(clazz.getName(), (Class<? extends ReportletConf>) clazz); + } else if (AccountRuleConf.class.isAssignableFrom(clazz)) { + accountRuleConfs.put(clazz.getName(), (Class<? extends AccountRuleConf>) clazz); + } else if (PasswordRuleConf.class.isAssignableFrom(clazz)) { + passwordRuleConfs.put(clazz.getName(), (Class<? extends PasswordRuleConf>) clazz); } } } catch (Throwable t) { @@ -128,10 +151,17 @@ public class ClassPathScanImplementationLookup { ssoLoginFormPanels = Collections.unmodifiableList(ssoLoginFormPanels); + reportletConfs = Collections.unmodifiableMap(reportletConfs); + accountRuleConfs = Collections.unmodifiableMap(accountRuleConfs); + passwordRuleConfs = Collections.unmodifiableMap(passwordRuleConfs); + LOG.debug("Binary previewers found: {}", previewers); LOG.debug("Extension pages found: {}", extPages); LOG.debug("Extension widgets found: {}", extWidgets); LOG.debug("SSO Login pages found: {}", ssoLoginFormPanels); + LOG.debug("Reportlet configurations found: {}", reportletConfs); + LOG.debug("Account Rule configurations found: {}", accountRuleConfs); + LOG.debug("Password Rule configurations found: {}", passwordRuleConfs); } public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final String mimeType) { @@ -152,10 +182,6 @@ public class ClassPathScanImplementationLookup { return pages; } - public List<Class<? extends AbstractBinaryPreviewer>> getPreviewerClasses() { - return previewers; - } - public List<Class<? extends BaseExtPage>> getExtPageClasses() { return extPages; } @@ -168,4 +194,16 @@ public class ClassPathScanImplementationLookup { return ssoLoginFormPanels; } + public Map<String, Class<? extends ReportletConf>> getReportletConfs() { + return reportletConfs; + } + + public Map<String, Class<? extends AccountRuleConf>> getAccountRuleConfs() { + return accountRuleConfs; + } + + public Map<String, Class<? extends PasswordRuleConf>> getPasswordRuleConfs() { + return passwordRuleConfs; + } + } http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java index cb33f80..bdc9269 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationDirectoryPanel.java @@ -141,8 +141,8 @@ public class NotificationDirectoryPanel target.add(container); } catch (SyncopeClientException e) { LOG.error("While deleting object {}", model.getObject().getKey(), e); - SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) ? e.getClass(). - getName() : e.getMessage()); + SyncopeConsoleSession.get().error( + StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage()); } ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); } http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/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 9e9097a..3602b44 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 @@ -18,23 +18,22 @@ */ package org.apache.syncope.client.console.notifications; -import org.apache.syncope.client.console.events.EventCategoryPanel; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; -import org.apache.syncope.client.console.SyncopeConsoleSession; import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.events.EventCategoryPanel; import org.apache.syncope.client.console.panels.search.AbstractSearchPanel; import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel; import org.apache.syncope.client.console.panels.search.GroupSearchPanel; import org.apache.syncope.client.console.panels.search.SearchClause; import org.apache.syncope.client.console.panels.search.UserSearchPanel; import org.apache.syncope.client.console.rest.AnyTypeRestClient; +import org.apache.syncope.client.console.rest.ImplementationRestClient; import org.apache.syncope.client.console.rest.LoggerRestClient; import org.apache.syncope.client.console.rest.NotificationRestClient; import org.apache.syncope.client.console.rest.SchemaRestClient; @@ -44,7 +43,6 @@ import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPa import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.MultiPanel; import org.apache.syncope.client.console.wizards.AjaxWizardBuilder; -import org.apache.syncope.common.lib.info.JavaImplInfo; import org.apache.syncope.common.lib.to.DerSchemaTO; import org.apache.syncope.common.lib.to.EntityTO; import org.apache.syncope.common.lib.to.NotificationTO; @@ -80,6 +78,8 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra private final LoggerRestClient loggerRestClient = new LoggerRestClient(); + private final ImplementationRestClient implRestClient = new ImplementationRestClient(); + /** * Construct. * @@ -107,10 +107,10 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra @Override protected WizardModel buildModelSteps(final NotificationWrapper modelObject, final WizardModel wizardModel) { - wizardModel.add(new NotificationWizardBuilder.Details(modelObject)); - wizardModel.add(new NotificationWizardBuilder.Recipients(modelObject)); - wizardModel.add(new NotificationWizardBuilder.Events(modelObject)); - wizardModel.add(new NotificationWizardBuilder.Abouts(modelObject)); + wizardModel.add(new Details(modelObject)); + wizardModel.add(new Recipients(modelObject)); + wizardModel.add(new Events(modelObject)); + wizardModel.add(new Abouts(modelObject)); return wizardModel; } @@ -332,13 +332,8 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra @Override protected List<String> load() { - Optional<JavaImplInfo> providers = SyncopeConsoleSession.get().getPlatformInfo(). - getJavaImplInfo(ImplementationType.RECIPIENTS_PROVIDER); - List<String> load = providers.isPresent() - ? new ArrayList<>(providers.get().getClasses()) - : new ArrayList<>(); - Collections.sort(load); - return load; + return implRestClient.list(ImplementationType.RECIPIENTS_PROVIDER).stream(). + map(EntityTO::getKey).sorted().collect(Collectors.toList()); } }; @@ -371,11 +366,11 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra new PropertyModel<>(modelObject, "recipientClauses")). required(false).build("recipients")); - AjaxDropDownChoicePanel<String> recipientsProviderClassName = new AjaxDropDownChoicePanel<>( - "recipientsProviderClassName", "recipientsProviderClassName", - new PropertyModel<>(notificationTO, "recipientsProviderClassName"), false); - recipientsProviderClassName.setChoices(recipientProviders.getObject()); - add(recipientsProviderClassName); + AjaxDropDownChoicePanel<String> recipientsProvider = new AjaxDropDownChoicePanel<>( + "recipientsProvider", "recipientsProvider", + new PropertyModel<>(notificationTO, "recipientsProvider"), false); + recipientsProvider.setChoices(recipientProviders.getObject()); + add(recipientsProvider); AjaxCheckBoxPanel selfAsRecipient = new AjaxCheckBoxPanel("selfAsRecipient", getString("selfAsRecipient"), new PropertyModel<>(notificationTO, "selfAsRecipient")); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java index 33df05a..09ab57e 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Audit.java @@ -18,10 +18,10 @@ */ package org.apache.syncope.client.console.pages; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.client.console.BookmarkablePageLinkBuilder; @@ -49,15 +49,14 @@ public class Audit extends BasePage { final LoggerRestClient loggerRestClient = new LoggerRestClient(); - List<String> events = new ArrayList<>(); - for (AuditLoggerName audit : loggerRestClient.listAudits()) { - events.add(AuditLoggerName.buildEvent( - audit.getType(), - audit.getCategory(), - audit.getSubcategory(), - audit.getEvent(), - audit.getResult())); - } + List<String> events = loggerRestClient.listAudits().stream(). + map(audit -> AuditLoggerName.buildEvent( + audit.getType(), + audit.getCategory(), + audit.getSubcategory(), + audit.getEvent(), + audit.getResult())). + collect(Collectors.toList()); WebMarkupContainer content = new WebMarkupContainer("content"); content.setOutputMarkupId(true); @@ -89,7 +88,7 @@ public class Audit extends BasePage { final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged = (SelectedEventsPanel.EventSelectionChanged) event.getPayload(); - for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) { + eventSelectionChanged.getToBeRemoved().forEach(toBeRemoved -> { Pair<EventCategoryTO, AuditElements.Result> eventCategory = AuditLoggerName.parseEventCategory(toBeRemoved); @@ -102,9 +101,9 @@ public class Audit extends BasePage { eventCategory.getValue()); loggerRestClient.disableAudit(auditLoggerName); - } + }); - for (String toBeAdded : eventSelectionChanged.getToBeAdded()) { + eventSelectionChanged.getToBeAdded().forEach(toBeAdded -> { Pair<EventCategoryTO, AuditElements.Result> eventCategory = AuditLoggerName.parseEventCategory(toBeAdded); @@ -117,7 +116,7 @@ public class Audit extends BasePage { eventCategory.getValue()); loggerRestClient.enableAudit(auditLoggerName); - } + }); } } }); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/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 fad2ac1..0cff36c 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 @@ -193,6 +193,12 @@ public class BasePage extends WebPage implements IAjaxIndicatorAware { MetaDataRoleAuthorizationStrategy.authorize(link, WebPage.RENDER, StandardEntitlement.AUDIT_LIST); liContainer.add(link); + liContainer = new WebMarkupContainer(getLIContainerId("implementations")); + confULContainer.add(liContainer); + link = BookmarkablePageLinkBuilder.build("implementations", Implementations.class); + MetaDataRoleAuthorizationStrategy.authorize(link, WebPage.RENDER, StandardEntitlement.IMPLEMENTATION_LIST); + liContainer.add(link); + liContainer = new WebMarkupContainer(getLIContainerId("logs")); confULContainer.add(liContainer); link = BookmarkablePageLinkBuilder.build("logs", Logs.class); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java new file mode 100644 index 0000000..0cd1c43 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java @@ -0,0 +1,66 @@ +/* + * 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.client.console.pages; + +import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.syncope.client.console.BookmarkablePageLinkBuilder; +import org.apache.syncope.client.console.panels.ImplementationDirectoryPanel; +import org.apache.syncope.common.lib.types.ImplementationType; +import org.apache.wicket.extensions.markup.html.tabs.AbstractTab; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.Model; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +public class Implementations extends BasePage { + + private static final long serialVersionUID = -4562707092152823781L; + + public Implementations(final PageParameters parameters) { + super(parameters); + + body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class)); + + WebMarkupContainer content = new WebMarkupContainer("content"); + content.setOutputMarkupId(true); + content.setMarkupId("implementations"); + content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList())); + body.add(content); + } + + private List<ITab> buildTabList() { + return Arrays.stream(ImplementationType.values()). + filter(type -> type != ImplementationType.JWT_SSO_PROVIDER + && type != ImplementationType.AUDIT_APPENDER). + sorted(Comparator.comparing(ImplementationType::name)). + map(type -> new AbstractTab(Model.of(type.name())) { + + private static final long serialVersionUID = -5861786415855103549L; + + @Override + public WebMarkupContainer getPanel(final String panelId) { + return new ImplementationDirectoryPanel(panelId, type, getPageReference()); + } + }).collect(Collectors.toList()); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java new file mode 100644 index 0000000..60a56d1 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java @@ -0,0 +1,232 @@ +/* + * 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.client.console.panels; + +import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.DirectoryDataProvider; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.pages.BasePage; +import org.apache.syncope.client.console.panels.ImplementationDirectoryPanel.ImplementationProvider; +import org.apache.syncope.client.console.rest.ImplementationRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.ImplementationTO; +import org.apache.syncope.common.lib.types.ImplementationEngine; +import org.apache.syncope.common.lib.types.ImplementationType; +import org.apache.syncope.common.lib.types.StandardEntitlement; +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.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.StringResourceModel; + +public class ImplementationDirectoryPanel extends DirectoryPanel< + ImplementationTO, ImplementationTO, ImplementationProvider, ImplementationRestClient> { + + private static final long serialVersionUID = 1868839768348072635L; + + private final ImplementationType type; + + public ImplementationDirectoryPanel(final String id, final ImplementationType type, final PageReference pageRef) { + super(id, pageRef, true); + this.type = type; + + ImplementationTO implementation = new ImplementationTO(); + implementation.setType(type); + + disableCheckBoxes(); + + modal.size(Modal.Size.Large); + modal.addSubmitButton(); + modal.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() { + + private static final long serialVersionUID = 8804221891699487139L; + + @Override + public void onClose(final AjaxRequestTarget target) { + implementation.setEngine(null); + updateResultTable(target); + modal.show(false); + } + }); + setFooterVisibility(true); + + restClient = new ImplementationRestClient(); + + initResultTable(); + + ImplementationEngineTogglePanel engineTogglePanel = + new ImplementationEngineTogglePanel("engineTogglePanel", implementation, pageRef) { + + private static final long serialVersionUID = -112426445257072782L; + + @Override + protected void onSubmit(final ImplementationEngine engine, final AjaxRequestTarget target) { + implementation.setKey(null); + implementation.setBody(null); + + target.add(ImplementationDirectoryPanel.this.modal.setContent(new ImplementationModalPanel( + ImplementationDirectoryPanel.this.modal, implementation, pageRef))); + ImplementationDirectoryPanel.this.modal.header( + new StringResourceModel("any.new", Model.of(implementation))); + ImplementationDirectoryPanel.this.modal.show(true); + } + }; + addInnerObject(engineTogglePanel); + + AjaxLink<Void> replaceAddLink = new AjaxLink<Void>("add") { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + send(ImplementationDirectoryPanel.this, Broadcast.BREADTH, + new ActionLinksTogglePanel.ActionLinkToggleCloseEventPayload(target)); + engineTogglePanel.setHeaderLabel(target); + engineTogglePanel.toggle(target, true); + } + }; + ((WebMarkupContainer) get("container:content")).addOrReplace(replaceAddLink); + + MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, StandardEntitlement.IMPLEMENTATION_CREATE); + } + + @Override + protected List<IColumn<ImplementationTO, String>> getColumns() { + List<IColumn<ImplementationTO, String>> columns = new ArrayList<>(); + + columns.add(new PropertyColumn<>(new StringResourceModel("key", this), "key", "key")); + columns.add(new PropertyColumn<>(new StringResourceModel("engine", this), "engine", "engine")); + + return columns; + } + + @Override + protected ActionsPanel<ImplementationTO> getActions(final IModel<ImplementationTO> model) { + final ActionsPanel<ImplementationTO> panel = super.getActions(model); + + panel.add(new ActionLink<ImplementationTO>() { + + private static final long serialVersionUID = -7978723352517770645L; + + @Override + public void onClick(final AjaxRequestTarget target, final ImplementationTO ignore) { + target.add(modal.setContent( + new ImplementationModalPanel(modal, model.getObject(), pageRef))); + modal.header(new StringResourceModel("any.edit", Model.of(model.getObject()))); + modal.show(true); + } + }, ActionLink.ActionType.EDIT, StandardEntitlement.IMPLEMENTATION_UPDATE); + + panel.add(new ActionLink<ImplementationTO>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final ImplementationTO ignore) { + try { + restClient.delete(model.getObject().getKey()); + SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED)); + target.add(container); + } catch (SyncopeClientException e) { + LOG.error("While deleting object {}", model.getObject().getKey(), e); + SyncopeConsoleSession.get().error( + StringUtils.isBlank(e.getMessage()) ? e.getClass().getName() : e.getMessage()); + } + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + }, ActionLink.ActionType.DELETE, StandardEntitlement.IMPLEMENTATION_DELETE, true); + + return panel; + } + + @Override + protected ImplementationProvider dataProvider() { + return new ImplementationProvider(rows); + } + + @Override + protected String paginatorRowsKey() { + return Constants.PREF_IMPLEMENTATION_PAGINATOR_ROWS; + } + + @Override + protected Collection<ActionLink.ActionType> getBulkActions() { + return Collections.<ActionLink.ActionType>emptyList(); + } + + protected class ImplementationProvider extends DirectoryDataProvider<ImplementationTO> { + + private static final long serialVersionUID = 8594921866993979224L; + + private final SortableDataProviderComparator<ImplementationTO> comparator; + + public ImplementationProvider(final int paginatorRows) { + super(paginatorRows); + + setSort("key", SortOrder.ASCENDING); + comparator = new SortableDataProviderComparator<>(this); + } + + @Override + public Iterator<ImplementationTO> iterator(final long first, final long count) { + List<ImplementationTO> list = restClient.list(type); + Collections.sort(list, comparator); + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return restClient.list(type).size(); + } + + @Override + public IModel<ImplementationTO> model(final ImplementationTO implementation) { + return new AbstractReadOnlyModel<ImplementationTO>() { + + private static final long serialVersionUID = 999513782683391483L; + + @Override + public ImplementationTO getObject() { + return implementation; + } + }; + } + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java new file mode 100644 index 0000000..49819d5 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationEngineTogglePanel.java @@ -0,0 +1,84 @@ +/* + * 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.client.console.panels; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.stream.Collectors; +import org.apache.syncope.client.console.pages.BasePage; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; +import org.apache.syncope.common.lib.to.ImplementationTO; +import org.apache.syncope.common.lib.types.ImplementationEngine; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.model.PropertyModel; + +public abstract class ImplementationEngineTogglePanel extends TogglePanel<Serializable> { + + private static final long serialVersionUID = -7869528596656778267L; + + public ImplementationEngineTogglePanel( + final String id, + final ImplementationTO implementation, + final PageReference pageRef) { + + super(id, pageRef); + + Form<?> form = new Form<>("implementationEngineForm"); + addInnerObject(form); + + PropertyModel<ImplementationEngine> engineModel = new PropertyModel<>(implementation, "engine"); + + form.add(new AjaxDropDownChoicePanel<>( + "engine", "Engine", engineModel, false). + setNullValid(false). + setChoices(Arrays.stream(ImplementationEngine.values()).collect(Collectors.toList())). + setStyleSheet("form-control"). + hideLabel()); + + form.add(new AjaxSubmitLink("changeit", form) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + ImplementationEngineTogglePanel.this.onSubmit(engineModel.getObject(), target); + target.add(form); + toggle(target, false); + + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + }); + + } + + protected abstract void onSubmit(ImplementationEngine engine, AjaxRequestTarget target); + + public void setHeaderLabel(final AjaxRequestTarget target) { + setHeader(target, getString("engine")); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java new file mode 100644 index 0000000..a2d4690 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java @@ -0,0 +1,329 @@ +/* + * 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.client.console.panels; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.SyncopeConsoleApplication; +import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup; +import org.apache.syncope.client.console.init.ConsoleInitializer; +import org.apache.syncope.client.console.pages.BasePage; +import org.apache.syncope.client.console.rest.ImplementationRestClient; +import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.common.lib.info.JavaImplInfo; +import org.apache.syncope.common.lib.to.ImplementationTO; +import org.apache.syncope.common.lib.types.ImplementationEngine; +import org.apache.syncope.common.lib.types.ImplementationType; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxEventBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.head.IHeaderResponse; +import org.apache.wicket.markup.head.OnLoadHeaderItem; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.TextArea; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.util.io.IOUtils; + +public class ImplementationModalPanel extends AbstractModalPanel<ImplementationTO> { + + private static final long serialVersionUID = 5283548960927517342L; + + private enum ViewMode { + JAVA_CLASS, + JSON_BODY, + GROOVY_BODY + + } + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private final ImplementationRestClient restClient = new ImplementationRestClient(); + + private final ImplementationTO implementation; + + private final ViewMode viewMode; + + private boolean create = false; + + public ImplementationModalPanel( + final BaseModal<ImplementationTO> modal, + final ImplementationTO implementation, + final PageReference pageRef) { + + super(modal, pageRef); + this.implementation = implementation; + this.viewMode = implementation.getEngine() == ImplementationEngine.GROOVY + ? ViewMode.GROOVY_BODY + : implementation.getType() == ImplementationType.REPORTLET + || implementation.getType() == ImplementationType.ACCOUNT_RULE + || implementation.getType() == ImplementationType.PASSWORD_RULE + ? ViewMode.JSON_BODY + : ViewMode.JAVA_CLASS; + this.create = implementation.getKey() == null; + + add(new AjaxTextFieldPanel( + "key", "key", new PropertyModel<>(implementation, "key"), false). + addRequiredLabel().setEnabled(create)); + + List<String> classes = Collections.emptyList(); + if (viewMode == ViewMode.JAVA_CLASS) { + Optional<JavaImplInfo> javaClasses = SyncopeConsoleSession.get().getPlatformInfo(). + getJavaImplInfo(implementation.getType()); + classes = javaClasses.isPresent() + ? new ArrayList<>(javaClasses.get().getClasses()) + : new ArrayList<>(); + } else if (viewMode == ViewMode.JSON_BODY) { + ClassPathScanImplementationLookup implementationLookup = + (ClassPathScanImplementationLookup) SyncopeConsoleApplication.get(). + getServletContext().getAttribute(ConsoleInitializer.CLASSPATH_LOOKUP); + + switch (implementation.getType()) { + case REPORTLET: + classes = implementationLookup.getReportletConfs().keySet().stream(). + collect(Collectors.toList()); + break; + + case ACCOUNT_RULE: + classes = implementationLookup.getAccountRuleConfs().keySet().stream(). + collect(Collectors.toList()); + break; + + case PASSWORD_RULE: + classes = implementationLookup.getPasswordRuleConfs().keySet().stream(). + collect(Collectors.toList()); + break; + + default: + } + } + Collections.sort(classes); + + AjaxDropDownChoicePanel<String> javaClass = new AjaxDropDownChoicePanel<>( + "javaClass", "Class", new PropertyModel<>(implementation, "body")); + javaClass.setNullValid(false); + javaClass.setChoices(classes); + javaClass.addRequiredLabel(); + javaClass.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true); + javaClass.setVisible(viewMode == ViewMode.JAVA_CLASS); + add(javaClass); + + AjaxDropDownChoicePanel<String> jsonClass = new AjaxDropDownChoicePanel<>( + "jsonClass", "Class", new Model<>()); + jsonClass.setNullValid(false); + jsonClass.setChoices(classes); + jsonClass.addRequiredLabel(); + jsonClass.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true); + jsonClass.setVisible(viewMode == ViewMode.JSON_BODY); + if (viewMode == ViewMode.JSON_BODY && StringUtils.isNotBlank(implementation.getBody())) { + try { + JsonNode node = MAPPER.readTree(implementation.getBody()); + if (node.has("@class")) { + jsonClass.setModelObject(node.get("@class").asText()); + } + } catch (IOException e) { + LOG.error("Could not parse as JSON payload: {}", implementation.getBody(), e); + } + } + jsonClass.setReadOnly(jsonClass.getModelObject() != null); + add(jsonClass); + + WebMarkupContainer groovyClassContainer = new WebMarkupContainer("groovyClassContainer"); + groovyClassContainer.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true); + groovyClassContainer.setVisible(viewMode != ViewMode.JAVA_CLASS); + add(groovyClassContainer); + + if (StringUtils.isBlank(implementation.getBody()) + && implementation.getEngine() == ImplementationEngine.GROOVY) { + + String templateClassName = null; + + switch (implementation.getType()) { + case REPORTLET: + templateClassName = "MyReportlet"; + break; + + case ACCOUNT_RULE: + templateClassName = "MyAccountRule"; + break; + + case PASSWORD_RULE: + templateClassName = "MyPasswordRule"; + break; + + case ITEM_TRANSFORMER: + templateClassName = "MyItemTransformer"; + break; + + case TASKJOB_DELEGATE: + templateClassName = "MySchedTaskJobDelegate"; + break; + + case RECON_FILTER_BUILDER: + templateClassName = "MyReconFilterBuilder"; + break; + + case LOGIC_ACTIONS: + templateClassName = "MyLogicActions"; + break; + + case PROPAGATION_ACTIONS: + templateClassName = "MyPropagationActions"; + break; + + case PULL_ACTIONS: + templateClassName = "MyPullActions"; + break; + + case PUSH_ACTIONS: + templateClassName = "MyPushActions"; + break; + + case PULL_CORRELATION_RULE: + templateClassName = "MyPullCorrelationRule"; + break; + + case VALIDATOR: + templateClassName = "MyValidator"; + break; + + case RECIPIENTS_PROVIDER: + templateClassName = "MyRecipientsProvider"; + break; + + default: + } + + if (templateClassName != null) { + try { + implementation.setBody(StringUtils.substringAfter(IOUtils.toString(getClass(). + getResourceAsStream( + "/org/apache/syncope/client/console/implementations/" + templateClassName + + ".groovy")), + "*/\n")); + } catch (IOException e) { + LOG.error("Could not load the expected Groovy template {} for {}", + templateClassName, implementation.getType(), e); + } + } + } + + TextArea<String> groovyClass = new TextArea<>("groovyClass", new PropertyModel<>(implementation, "body")); + groovyClass.setMarkupId("groovyClass").setOutputMarkupPlaceholderTag(true); + groovyClass.setVisible(viewMode != ViewMode.JAVA_CLASS); + groovyClass.setRequired(true); + groovyClassContainer.add(groovyClass); + + jsonClass.add(new AjaxEventBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = 5538299138211283825L; + + @Override + protected void onEvent(final AjaxRequestTarget target) { + ClassPathScanImplementationLookup implementationLookup = + (ClassPathScanImplementationLookup) SyncopeConsoleApplication.get(). + getServletContext().getAttribute(ConsoleInitializer.CLASSPATH_LOOKUP); + + Class<?> clazz = null; + switch (implementation.getType()) { + case REPORTLET: + clazz = implementationLookup.getReportletConfs().get(jsonClass.getModelObject()); + break; + + case ACCOUNT_RULE: + clazz = implementationLookup.getAccountRuleConfs().get(jsonClass.getModelObject()); + break; + + case PASSWORD_RULE: + clazz = implementationLookup.getPasswordRuleConfs().get(jsonClass.getModelObject()); + break; + + default: + } + + if (clazz != null) { + try { + target.appendJavaScript("editor.getDoc().setValue('" + + MAPPER.writeValueAsString(clazz.newInstance()) + + "');"); + } catch (Exception e) { + LOG.error("Could not generate a value for {}", jsonClass.getModelObject(), e); + } + } + } + }); + } + + @Override + public ImplementationTO getItem() { + return implementation; + } + + @Override + public void renderHead(final IHeaderResponse response) { + super.renderHead(response); + if (viewMode != ViewMode.JAVA_CLASS) { + response.render(OnLoadHeaderItem.forScript( + "editor = CodeMirror.fromTextArea(" + + "document.getElementById('groovyClassForm').children['groovyClass'], {" + + " readOnly: false, " + + " lineNumbers: true, " + + " lineWrapping: true, " + + " matchBrackets: true," + + " autoCloseBrackets: true," + + (viewMode == ViewMode.GROOVY_BODY ? " mode: 'text/x-groovy'," : "") + + " autoRefresh: true" + + "});" + + "editor.on('change', updateTextArea);")); + } + } + + @Override + public void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + try { + if (create) { + restClient.create(implementation); + } else { + restClient.update(implementation); + } + + modal.close(target); + SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (Exception e) { + LOG.error("While creating or updating AttrTO", e); + SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage()) + ? e.getClass().getName() + : e.getMessage()); + } + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersEditModalPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersEditModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersEditModalPanel.java index 85a04b4..e85a39e 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersEditModalPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersEditModalPanel.java @@ -35,9 +35,7 @@ public class ParametersEditModalPanel extends AbstractModalPanel<AttrTO> { private final AttrTO attrTO; - private final BaseModal<AttrTO> parametersModal; - - private final ConfRestClient confRestClient = new ConfRestClient(); + private final ConfRestClient restClient = new ConfRestClient(); public ParametersEditModalPanel( final BaseModal<AttrTO> modal, @@ -46,7 +44,6 @@ public class ParametersEditModalPanel extends AbstractModalPanel<AttrTO> { super(modal, pageRef); this.attrTO = attrTO; - this.parametersModal = modal; add(new ParametersDetailsPanel("parametersDetailsPanel", getItem())); } @@ -58,8 +55,8 @@ public class ParametersEditModalPanel extends AbstractModalPanel<AttrTO> { @Override public void onSubmit(final AjaxRequestTarget target, final Form<?> form) { try { - confRestClient.set(attrTO); - parametersModal.close(target); + restClient.set(attrTO); + modal.close(target); SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED)); } catch (Exception e) { LOG.error("While creating or updating AttrTO", e); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java index ceff741..e79c013 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java @@ -24,21 +24,21 @@ import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Optional; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.console.SyncopeConsoleApplication; -import org.apache.syncope.client.console.SyncopeConsoleSession; import org.apache.syncope.client.console.commons.Constants; import org.apache.syncope.client.console.commons.PropertyList; import org.apache.syncope.client.console.init.ConsoleInitializer; import org.apache.syncope.client.console.init.MIMETypesLoader; +import org.apache.syncope.client.console.rest.ImplementationRestClient; import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel; -import org.apache.syncope.common.lib.info.JavaImplInfo; import org.apache.syncope.common.lib.to.AbstractSchemaTO; +import org.apache.syncope.common.lib.to.EntityTO; import org.apache.syncope.common.lib.to.PlainSchemaTO; import org.apache.syncope.common.lib.types.AttrSchemaType; import org.apache.syncope.common.lib.types.CipherAlgorithm; @@ -61,6 +61,8 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel { private static final MIMETypesLoader MIME_TYPES_LOADER = (MIMETypesLoader) SyncopeConsoleApplication.get(). getServletContext().getAttribute(ConsoleInitializer.MIMETYPES_LOADER); + private final ImplementationRestClient implRestClient = new ImplementationRestClient(); + private final MultiFieldPanel<String> enumerationValues; private final MultiFieldPanel<String> enumerationKeys; @@ -235,26 +237,21 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel { } ); - IModel<List<String>> validatorsList = new LoadableDetachableModel<List<String>>() { + IModel<List<String>> validators = new LoadableDetachableModel<List<String>>() { private static final long serialVersionUID = 5275935387613157437L; @Override protected List<String> load() { - Optional<JavaImplInfo> validators = SyncopeConsoleSession.get().getPlatformInfo(). - getJavaImplInfo(ImplementationType.VALIDATOR); - List<String> load = validators.isPresent() - ? new ArrayList<>(validators.get().getClasses()) - : new ArrayList<>(); - Collections.sort(load); - return load; + return implRestClient.list(ImplementationType.VALIDATOR).stream(). + map(EntityTO::getKey).sorted().collect(Collectors.toList()); } }; - final AjaxDropDownChoicePanel<String> validatorClass = new AjaxDropDownChoicePanel<>("validatorClass", - getString("validatorClass"), new PropertyModel<>(schemaTO, "validatorClass")); - ((DropDownChoice) validatorClass.getField()).setNullValid(true); - validatorClass.setChoices(validatorsList.getObject()); - schemaForm.add(validatorClass); + final AjaxDropDownChoicePanel<String> validator = new AjaxDropDownChoicePanel<>("validator", + getString("validator"), new PropertyModel<>(schemaTO, "validator")); + ((DropDownChoice) validator.getField()).setNullValid(true); + validator.setChoices(validators.getObject()); + schemaForm.add(validator); AutoCompleteTextField<String> mandatoryCondition = new AutoCompleteTextField<String>("mandatoryCondition") { http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java index 0c7c3dc..763422e 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java @@ -19,12 +19,10 @@ package org.apache.syncope.client.console.panels; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; -import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.rest.ImplementationRestClient; import org.apache.syncope.client.console.rest.PolicyRestClient; import org.apache.syncope.client.console.rest.ResourceRestClient; import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel; @@ -34,7 +32,6 @@ import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPa import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel; import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer; import org.apache.syncope.common.lib.SyncopeConstants; -import org.apache.syncope.common.lib.info.JavaImplInfo; import org.apache.syncope.common.lib.to.EntityTO; import org.apache.syncope.common.lib.to.RealmTO; import org.apache.syncope.common.lib.types.ImplementationType; @@ -59,6 +56,8 @@ public class RealmDetails extends Panel { private final PolicyRestClient policyRestClient = new PolicyRestClient(); + private final ImplementationRestClient implRestClient = new ImplementationRestClient(); + private final IModel<Map<String, String>> accountPolicies = new LoadableDetachableModel<Map<String, String>>() { private static final long serialVersionUID = -2012833443695917883L; @@ -81,19 +80,14 @@ public class RealmDetails extends Panel { } }; - private final IModel<List<String>> logicActionsClasses = new LoadableDetachableModel<List<String>>() { + private final IModel<List<String>> logicActions = new LoadableDetachableModel<List<String>>() { private static final long serialVersionUID = 5275935387613157437L; @Override protected List<String> load() { - Optional<JavaImplInfo> actions = SyncopeConsoleSession.get().getPlatformInfo(). - getJavaImplInfo(ImplementationType.LOGIC_ACTIONS); - List<String> load = actions.isPresent() - ? new ArrayList<>(actions.get().getClasses()) - : new ArrayList<>(); - Collections.sort(load); - return load; + return implRestClient.list(ImplementationType.LOGIC_ACTIONS).stream(). + map(EntityTO::getKey).sorted().collect(Collectors.toList()); } }; @@ -106,7 +100,7 @@ public class RealmDetails extends Panel { public RealmDetails( final String id, final RealmTO realmTO, - final ActionsPanel<?> actions, + final ActionsPanel<?> actionsPanel, final boolean unwrapped) { super(id); @@ -149,13 +143,13 @@ public class RealmDetails extends Panel { ((DropDownChoice<?>) passwordPolicy.getField()).setNullValid(true); container.add(passwordPolicy); - AjaxPalettePanel<String> actionsClassNames = new AjaxPalettePanel.Builder<String>(). + AjaxPalettePanel<String> actions = new AjaxPalettePanel.Builder<String>(). setAllowMoveAll(true).setAllowOrder(true). - build("actionsClassNames", - new PropertyModel<List<String>>(realmTO, "actionsClassNames"), - new ListModel<>(logicActionsClasses.getObject())); - actionsClassNames.setOutputMarkupId(true); - container.add(actionsClassNames); + build("actions", + new PropertyModel<List<String>>(realmTO, "actions"), + new ListModel<>(logicActions.getObject())); + actions.setOutputMarkupId(true); + container.add(actions); container.add(new AjaxPalettePanel.Builder<>().build("resources", new PropertyModel<>(realmTO, "resources"), @@ -165,11 +159,11 @@ public class RealmDetails extends Panel { setEnabled(!SyncopeConstants.ROOT_REALM.equals(realmTO.getName())). setVisible(!SyncopeConstants.ROOT_REALM.equals(realmTO.getName()))); - if (actions == null) { + if (actionsPanel == null) { add(new Fragment("actions", "emptyFragment", this).setRenderBodyOnly(true)); } else { Fragment fragment = new Fragment("actions", "actionsFragment", this); - fragment.add(actions); + fragment.add(actionsPanel); add(fragment.setRenderBodyOnly(true)); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java index a2535d9..dd89ea1 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java @@ -75,7 +75,7 @@ public class AccountPolicyDirectoryPanel extends PolicyDirectoryPanel<AccountPol ruleCompositionModal, model.getObject().getKey(), PolicyType.ACCOUNT, pageRef))); ruleCompositionModal.header(new StringResourceModel( - "policy.rule.conf", AccountPolicyDirectoryPanel.this, Model.of(model.getObject()))); + "policy.rules", AccountPolicyDirectoryPanel.this, Model.of(model.getObject()))); MetaDataRoleAuthorizationStrategy.authorize( ruleCompositionModal.getForm(), ENABLE, StandardEntitlement.POLICY_UPDATE); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/policies/PasswordPolicyDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/policies/PasswordPolicyDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/policies/PasswordPolicyDirectoryPanel.java index 8e3663d..32fce97 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/policies/PasswordPolicyDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/policies/PasswordPolicyDirectoryPanel.java @@ -72,7 +72,7 @@ public class PasswordPolicyDirectoryPanel extends PolicyDirectoryPanel<PasswordP ruleCompositionModal, model.getObject().getKey(), PolicyType.PASSWORD, pageRef))); ruleCompositionModal.header(new StringResourceModel( - "policy.rule.conf", PasswordPolicyDirectoryPanel.this, Model.of(model.getObject()))); + "policy.rules", PasswordPolicyDirectoryPanel.this, Model.of(model.getObject()))); MetaDataRoleAuthorizationStrategy.authorize( ruleCompositionModal.getForm(), ENABLE, StandardEntitlement.POLICY_UPDATE); http://git-wip-us.apache.org/repos/asf/syncope/blob/98890722/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java index 8b06630..2b5f8d4 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java @@ -18,12 +18,14 @@ */ package org.apache.syncope.client.console.policies; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.lang3.SerializationUtils; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.console.SyncopeConsoleSession; @@ -33,6 +35,7 @@ import org.apache.syncope.client.console.commons.SortableDataProviderComparator; import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.panels.DirectoryPanel; import org.apache.syncope.client.console.panels.ModalPanel; +import org.apache.syncope.client.console.rest.ImplementationRestClient; 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.ActionLink; @@ -44,6 +47,8 @@ import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.policy.AbstractPolicyTO; import org.apache.syncope.common.lib.policy.ComposablePolicy; import org.apache.syncope.common.lib.policy.RuleConf; +import org.apache.syncope.common.lib.to.ImplementationTO; +import org.apache.syncope.common.lib.types.ImplementationEngine; import org.apache.syncope.common.lib.types.PolicyType; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -72,6 +77,8 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct private static final long serialVersionUID = 4984337552918213290L; + private static final ObjectMapper MAPPER = new ObjectMapper(); + private final BaseModal<T> baseModal; private final String policy; @@ -88,7 +95,8 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct enableExitButton(); - this.addNewItemPanelBuilder(new PolicyRuleWizardBuilder(policy, type, new PolicyRuleWrapper(), pageRef), true); + this.addNewItemPanelBuilder( + new PolicyRuleWizardBuilder(policy, type, new PolicyRuleWrapper(true), pageRef), true); MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, StandardEntitlement.POLICY_UPDATE); initResultTable(); @@ -99,7 +107,7 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct final List<IColumn<PolicyRuleWrapper, String>> columns = new ArrayList<>(); columns.add(new PropertyColumn<>( - new StringResourceModel("ruleConf", this), "name", "name")); + new StringResourceModel("rule", this), "implementationKey", "implementationKey")); columns.add(new AbstractColumn<PolicyRuleWrapper, String>( new StringResourceModel("configuration", this)) { @@ -111,7 +119,12 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct final Item<ICellPopulator<PolicyRuleWrapper>> cellItem, final String componentId, final IModel<PolicyRuleWrapper> rowModel) { - cellItem.add(new Label(componentId, rowModel.getObject().getConf().getClass().getName())); + + if (rowModel.getObject().getConf() == null) { + cellItem.add(new Label(componentId, "")); + } else { + cellItem.add(new Label(componentId, rowModel.getObject().getConf().getClass().getName())); + } } }); return columns; @@ -131,9 +144,7 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct PolicyRuleDirectoryPanel.this.getTogglePanel().close(target); send(PolicyRuleDirectoryPanel.this, Broadcast.EXACT, - new AjaxWizard.EditItemActionEvent<>( - new PolicyRuleWrapper().setConf(clone).setName(null), - target)); + new AjaxWizard.EditItemActionEvent<>(new PolicyRuleWrapper(true).setConf(clone), target)); } }, ActionLink.ActionType.CLONE, StandardEntitlement.POLICY_CREATE); panel.add(new ActionLink<PolicyRuleWrapper>() { @@ -143,8 +154,13 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct @Override public void onClick(final AjaxRequestTarget target, final PolicyRuleWrapper ignore) { PolicyRuleDirectoryPanel.this.getTogglePanel().close(target); - send(PolicyRuleDirectoryPanel.this, Broadcast.EXACT, - new AjaxWizard.EditItemActionEvent<>(model.getObject(), target)); + if (model.getObject().getConf() == null) { + SyncopeConsoleSession.get().info(getString("noConf")); + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } else { + send(PolicyRuleDirectoryPanel.this, Broadcast.EXACT, + new AjaxWizard.EditItemActionEvent<>(model.getObject(), target)); + } } }, ActionLink.ActionType.EDIT, StandardEntitlement.POLICY_UPDATE); panel.add(new ActionLink<PolicyRuleWrapper>() { @@ -214,21 +230,46 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct private static final long serialVersionUID = 4725679400450513556L; + private final ImplementationRestClient implementationClient = new ImplementationRestClient(); + private final SortableDataProviderComparator<PolicyRuleWrapper> comparator; public PolicyRuleDataProvider(final int paginatorRows) { super(paginatorRows); // Default sorting - setSort("name", SortOrder.ASCENDING); + setSort("implementationKey", SortOrder.ASCENDING); comparator = new SortableDataProviderComparator<>(this); } + @SuppressWarnings("unchecked") + private List<PolicyRuleWrapper> getPolicyRuleWrappers(final ComposablePolicy policy) { + return policy.getRules().stream().map(rule -> { + ImplementationTO implementation = implementationClient.read(rule); + + PolicyRuleWrapper wrapper = new PolicyRuleWrapper(false). + setImplementationKey(implementation.getKey()). + setImplementationEngine(implementation.getEngine()); + if (implementation.getEngine() == ImplementationEngine.JAVA) { + try { + RuleConf ruleConf = MAPPER.readValue(implementation.getBody(), RuleConf.class); + wrapper.setConf(ruleConf); + } catch (Exception e) { + LOG.error("During deserialization", e); + } + } + + return wrapper; + }).collect(Collectors.toList()); + } + @Override public Iterator<PolicyRuleWrapper> iterator(final long first, final long count) { final T actual = restClient.getPolicy(policy); - List<PolicyRuleWrapper> rules = PolicyRuleWizardBuilder.getPolicyRuleWrappers(actual); + List<PolicyRuleWrapper> rules = actual instanceof ComposablePolicy + ? getPolicyRuleWrappers((ComposablePolicy) actual) + : Collections.emptyList(); Collections.sort(rules, comparator); return rules.subList((int) first, (int) (first + count)).iterator(); @@ -237,7 +278,9 @@ public class PolicyRuleDirectoryPanel<T extends AbstractPolicyTO> extends Direct @Override public long size() { final T actual = restClient.getPolicy(policy); - return PolicyRuleWizardBuilder.getPolicyRuleWrappers(actual).size(); + return actual instanceof ComposablePolicy + ? getPolicyRuleWrappers((ComposablePolicy) actual).size() + : 0; } @Override
