From 4ebd208a7a3f498eace7c4cea6d4d1effcc47fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Tue, 30 May 2023 16:50:56 +0200 Subject: [PATCH 1/2] [SYNCOPE-1738] Re-adding support for Report conf management in Console --- .../AuthProfileWizardBuilder.java | 2 +- ...ameAttributeProviderModalPanelBuilder.java | 6 +- .../policies/AccessPolicyModalPanel.java | 2 +- .../TicketExpirationPolicyModalPanel.java | 2 +- .../wizards/AttrRepoWizardBuilder.java | 2 +- .../wizards/AuthModuleWizardBuilder.java | 5 +- .../client/console/IdRepoConsoleContext.java | 10 +-- .../console/SyncopeConsoleApplication.java | 7 +- .../client/console/SyncopeWebApplication.java | 9 ++- .../console/panels/AjaxDataTablePanel.java | 2 +- .../client/console/panels/BeanPanel.java | 64 +++++++++++++++++-- .../policies/PolicyRuleWizardBuilder.java | 2 +- .../console/reports/ReportConfWrapper.java | 54 ++++++++++++++++ .../console/reports/ReportWizardBuilder.java | 56 ++++++++-------- .../tasks/CommandComposeWizardBuilder.java | 2 +- .../console/wizards/CommandWizardBuilder.java | 2 +- .../console/panels/DirectoryPanel.properties | 5 ++ .../panels/DirectoryPanel_fr_CA.properties | 23 ++++--- .../panels/DirectoryPanel_it.properties | 5 ++ .../panels/DirectoryPanel_ja.properties | 5 ++ .../panels/DirectoryPanel_pt_BR.properties | 5 ++ .../panels/DirectoryPanel_ru.properties | 5 ++ .../syncope/client/console/AbstractTest.java | 6 +- .../common/lib/report/SearchCondition.java | 31 +++++++++ .../apache/syncope/core/logic/AuditLogic.java | 9 ++- .../core/logic/IdRepoLogicContext.java | 9 ++- .../syncope/core/logic/init/AuditLoader.java | 10 +-- .../persistence/jpa/PersistenceContext.java | 6 +- .../persistence/jpa/RuntimeDomainLoader.java | 11 +--- .../syncope/wa/bootstrap/WARestClient.java | 6 +- .../syncope/wa/starter/config/WAContext.java | 11 ++-- .../wa/starter/mapping/AuthMapper.java | 4 +- .../mapping/CASSPClientAppTOMapper.java | 6 +- .../wa/starter/mapping/ClientAppMapper.java | 6 +- .../wa/starter/mapping/DefaultAuthMapper.java | 5 +- .../mapping/OIDCRPClientAppTOMapper.java | 6 +- .../mapping/RegisteredServiceMapper.java | 24 ++++--- .../mapping/SAML2SPClientAppTOMapper.java | 6 +- 38 files changed, 299 insertions(+), 132 deletions(-) create mode 100644 client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportConfWrapper.java create mode 100644 common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/SearchCondition.java diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/authprofiles/AuthProfileWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/authprofiles/AuthProfileWizardBuilder.java index ae9bf98a3ba..08475c41109 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/authprofiles/AuthProfileWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/authprofiles/AuthProfileWizardBuilder.java @@ -66,7 +66,7 @@ protected class Step extends WizardStep { Step(final T modelObject) { model.setObject(modelObject); model.setInitialModelObject(modelObject); - add(new BeanPanel<>("bean", model).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", model, pageRef).setRenderBodyOnly(true)); } } } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/UsernameAttributeProviderModalPanelBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/UsernameAttributeProviderModalPanelBuilder.java index e077d0bdc5f..ce06802be48 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/UsernameAttributeProviderModalPanelBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/UsernameAttributeProviderModalPanelBuilder.java @@ -99,11 +99,7 @@ private class Profile extends AbstractModalPanel { PropertyModel beanPanelModel = new PropertyModel<>(clientAppTO, "usernameAttributeProviderConf"); - BeanPanel bean = new BeanPanel<>( - "bean", - beanPanelModel, - Constants.NAME_FIELD_NAME, - "reportlet"); + BeanPanel bean = new BeanPanel<>("bean", beanPanelModel, pageRef); add(bean.setRenderBodyOnly(false)); conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) { diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java index 1be95418187..abb8ec28f58 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/AccessPolicyModalPanel.java @@ -46,7 +46,7 @@ public AccessPolicyModalPanel( super(modal, pageRef); this.model = model; - add(new BeanPanel<>("bean", new PropertyModel<>(model, "conf")).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", new PropertyModel<>(model, "conf"), pageRef).setRenderBodyOnly(true)); } @Override diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/TicketExpirationPolicyModalPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/TicketExpirationPolicyModalPanel.java index 1431c662871..617069f71f8 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/policies/TicketExpirationPolicyModalPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/policies/TicketExpirationPolicyModalPanel.java @@ -89,7 +89,7 @@ protected void onUpdate(final AjaxRequestTarget target) { }); add(enable); - add(new BeanPanel<>("bean." + field, beanPanelModel).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean." + field, beanPanelModel, pageRef).setRenderBodyOnly(true)); } @Override diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AttrRepoWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AttrRepoWizardBuilder.java index 1423d08680c..7598e12821a 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AttrRepoWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AttrRepoWizardBuilder.java @@ -159,7 +159,7 @@ protected class Configuration extends WizardStep { private static final long serialVersionUID = -785981096328637758L; Configuration(final AttrRepoTO attrRepo) { - add(new BeanPanel<>("bean", new PropertyModel<>(attrRepo, "conf")).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", new PropertyModel<>(attrRepo, "conf"), pageRef).setRenderBodyOnly(true)); } } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java index ca48c4d3bc6..b523734fdfe 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder.java @@ -162,7 +162,8 @@ protected class Configuration extends WizardStep { private static final long serialVersionUID = -785981096328637758L; Configuration(final AuthModuleTO authModule) { - add(new BeanPanel<>("bean", new PropertyModel<>(authModule, "conf"), "ldap").setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", new PropertyModel<>(authModule, "conf"), pageRef, "ldap"). + setRenderBodyOnly(true)); } } @@ -210,7 +211,7 @@ protected void onUpdate(final AjaxRequestTarget target) { }); add(enable); - add(new BeanPanel<>("bean", beanPanelModel).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", beanPanelModel, pageRef).setRenderBodyOnly(true)); setOutputMarkupId(true); } diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/IdRepoConsoleContext.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/IdRepoConsoleContext.java index 2109a3fb1c3..d0baebffa7f 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/IdRepoConsoleContext.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/IdRepoConsoleContext.java @@ -18,7 +18,7 @@ */ package org.apache.syncope.client.console; -import java.util.HashSet; +import java.util.List; import org.apache.syncope.client.console.commons.AccessPolicyConfProvider; import org.apache.syncope.client.console.commons.AnyDirectoryPanelAdditionalActionLinksProvider; import org.apache.syncope.client.console.commons.AnyDirectoryPanelAdditionalActionsProvider; @@ -44,7 +44,6 @@ import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup; import org.apache.syncope.client.ui.commons.MIMETypesLoader; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -54,10 +53,11 @@ public class IdRepoConsoleContext { @ConditionalOnMissingBean @Bean public ClassPathScanImplementationLookup classPathScanImplementationLookup( - final ApplicationContext ctx, final ConsoleProperties props) { + final ConsoleProperties props, + final List classPathScanImplementationContributors) { - ClassPathScanImplementationLookup lookup = new ClassPathScanImplementationLookup( - new HashSet<>(ctx.getBeansOfType(ClassPathScanImplementationContributor.class).values()), props); + ClassPathScanImplementationLookup lookup = + new ClassPathScanImplementationLookup(classPathScanImplementationContributors, props); lookup.load(); return lookup; } diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java index 141e017a08c..219e73a74ba 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java @@ -19,6 +19,7 @@ package org.apache.syncope.client.console; import com.giffing.wicket.spring.boot.starter.web.config.WicketWebInitializerAutoConfig.WebSocketWicketWebInitializerAutoConfiguration; +import java.util.List; import java.util.Map; import org.apache.syncope.client.console.actuate.SyncopeConsoleInfoContributor; import org.apache.syncope.client.console.commons.AccessPolicyConfProvider; @@ -27,6 +28,7 @@ import org.apache.syncope.client.console.commons.AnyWizardBuilderAdditionalSteps; import org.apache.syncope.client.console.commons.ExternalResourceProvider; import org.apache.syncope.client.console.commons.ImplementationInfoProvider; +import org.apache.syncope.client.console.commons.PolicyTabProvider; import org.apache.syncope.client.console.commons.StatusProvider; import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider; import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup; @@ -42,7 +44,6 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @SpringBootApplication(exclude = { @@ -79,7 +80,7 @@ public SyncopeWebApplication syncopeWebApplication( final VirSchemaDetailsPanelProvider virSchemaDetailsPanelProvider, final ImplementationInfoProvider implementationInfoProvider, final AccessPolicyConfProvider accessPolicyConfProvider, - final ApplicationContext ctx) { + final List policyTabProviders) { return new SyncopeWebApplication( props, @@ -92,7 +93,7 @@ public SyncopeWebApplication syncopeWebApplication( virSchemaDetailsPanelProvider, implementationInfoProvider, accessPolicyConfProvider, - ctx); + policyTabProviders); } @ConditionalOnMissingBean diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java index 122529779bf..3aa49b65081 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java @@ -72,7 +72,6 @@ import org.apache.wicket.request.resource.ResourceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationContext; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ClassUtils; @@ -106,7 +105,7 @@ public static SyncopeWebApplication get() { protected final AccessPolicyConfProvider accessPolicyConfProvider; - protected final ApplicationContext ctx; + protected final List policyTabProviders; public SyncopeWebApplication( final ConsoleProperties props, @@ -120,7 +119,7 @@ public SyncopeWebApplication( final VirSchemaDetailsPanelProvider virSchemaDetailsPanelProvider, final ImplementationInfoProvider implementationInfoProvider, final AccessPolicyConfProvider accessPolicyConfProvider, - final ApplicationContext ctx) { + final List policyTabProviders) { this.props = props; this.lookup = lookup; @@ -133,7 +132,7 @@ public SyncopeWebApplication( this.virSchemaDetailsPanelProvider = virSchemaDetailsPanelProvider; this.implementationInfoProvider = implementationInfoProvider; this.accessPolicyConfProvider = accessPolicyConfProvider; - this.ctx = ctx; + this.policyTabProviders = policyTabProviders; } @Override @@ -344,7 +343,7 @@ public ImplementationInfoProvider getImplementationInfoProvider() { } public Collection getPolicyTabProviders() { - return ctx.getBeansOfType(PolicyTabProvider.class).values(); + return policyTabProviders; } public List getFormFinalizers(final AjaxWizard.Mode mode) { diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java index 343710b9169..c891a4daa26 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java @@ -169,7 +169,7 @@ private AjaxDataTablePanel(final String id, final Builder builder) { super(id); batchModal = new BaseModal<>("batchModal"); - batchModal.size(Modal.Size.Default); + batchModal.size(Modal.Size.Extra_large); add(batchModal); batchModal.setWindowClosedCallback(target -> { diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java index d15cfa0649c..fa1f79aa1d0 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java @@ -34,11 +34,18 @@ import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Triple; import org.apache.syncope.client.console.SyncopeConsoleSession; import org.apache.syncope.client.console.SyncopeWebApplication; +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.SearchUtils; +import org.apache.syncope.client.console.panels.search.UserSearchPanel; import org.apache.syncope.client.console.rest.SchemaRestClient; import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel; +import org.apache.syncope.client.lib.SyncopeClient; import org.apache.syncope.client.ui.commons.DateOps; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel; @@ -48,8 +55,11 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel; +import org.apache.syncope.common.lib.report.SearchCondition; +import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder; import org.apache.syncope.common.lib.to.SchemaTO; import org.apache.syncope.common.lib.types.SchemaType; +import org.apache.wicket.PageReference; import org.apache.wicket.core.util.lang.PropertyResolver; import org.apache.wicket.core.util.lang.PropertyResolverConverter; import org.apache.wicket.markup.html.basic.Label; @@ -65,6 +75,8 @@ import org.apache.wicket.model.util.ListModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.PropertyAccessorFactory; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -76,10 +88,24 @@ public class BeanPanel extends Panel { private final List excluded; - public BeanPanel(final String id, final IModel bean, final String... excluded) { + private final Map, List>> sCondWrapper; + + public BeanPanel(final String id, final IModel bean, final PageReference pageRef, final String... excluded) { + this(id, bean, null, pageRef, excluded); + } + + public BeanPanel( + final String id, + final IModel bean, + final Map, List>> sCondWrapper, + final PageReference pageRef, + final String... excluded) { + super(id, bean); setOutputMarkupId(true); + this.sCondWrapper = sCondWrapper; + this.excluded = new ArrayList<>(List.of(excluded)); this.excluded.add("serialVersionUID"); this.excluded.add("class"); @@ -148,7 +174,37 @@ protected void populateItem(final ListItem item) { Panel panel; - if (List.class.equals(field.getType())) { + SearchCondition scondAnnot = field.getAnnotation(SearchCondition.class); + if (scondAnnot != null) { + BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean.getObject()); + String fiql = (String) wrapper.getPropertyValue(fieldName); + + List clauses = SearchUtils.getSearchClauses(fiql); + + AbstractFiqlSearchConditionBuilder builder; + switch (scondAnnot.type()) { + case "USER": + panel = new UserSearchPanel.Builder( + new ListModel<>(clauses), pageRef).required(false).build("value"); + builder = SyncopeClient.getUserSearchConditionBuilder(); + break; + + case "GROUP": + panel = new GroupSearchPanel.Builder( + new ListModel<>(clauses), pageRef).required(false).build("value"); + builder = SyncopeClient.getGroupSearchConditionBuilder(); + break; + + default: + panel = new AnyObjectSearchPanel.Builder( + scondAnnot.type(), + new ListModel<>(clauses), pageRef).required(false).build("value"); + builder = SyncopeClient.getAnyObjectSearchConditionBuilder(scondAnnot.type()); + } + + Optional.ofNullable(BeanPanel.this.sCondWrapper). + ifPresent(scw -> scw.put(fieldName, Pair.of(builder, clauses))); + } else if (List.class.equals(field.getType())) { Class listItemType = field.getGenericType() instanceof ParameterizedType ? (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0] : String.class; @@ -206,8 +262,8 @@ protected void populateItem(final ListItem item) { } else if (Map.class.equals(field.getType())) { panel = new AjaxGridFieldPanel( "value", fieldName, new PropertyModel<>(bean, fieldName)).hideLabel(); - Optional.ofNullable(field.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class)) - .ifPresent(annot -> setDescription(item, annot.description())); + Optional.ofNullable(field.getAnnotation(io.swagger.v3.oas.annotations.media.Schema.class)). + ifPresent(annot -> setDescription(item, annot.description())); } else { Triple> single = buildSinglePanel(bean.getObject(), field.getType(), field.getName(), diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java index 91420306adf..b4fa3e11c52 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java @@ -183,7 +183,7 @@ protected Serializable load() { return rule.getConf(); } }; - add(new BeanPanel<>("bean", bean).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", bean, pageRef).setRenderBodyOnly(true)); } } } diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportConfWrapper.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportConfWrapper.java new file mode 100644 index 00000000000..f975b3b7725 --- /dev/null +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportConfWrapper.java @@ -0,0 +1,54 @@ +/* + * 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.reports; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.syncope.client.console.panels.search.SearchClause; +import org.apache.syncope.common.lib.report.ReportConf; +import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder; + +public class ReportConfWrapper implements Serializable { + + private static final long serialVersionUID = -1817829104060261892L; + + private ReportConf conf; + + private final Map, List>> scondWrapper; + + public ReportConfWrapper() { + this.scondWrapper = new HashMap<>(); + } + + public ReportConf getConf() { + return conf; + } + + public ReportConfWrapper setConf(final ReportConf conf) { + this.conf = conf; + return this; + } + + public Map, List>> getSCondWrapper() { + return scondWrapper; + } +} diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java index b0e5e867989..c654a6efc9a 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java @@ -24,6 +24,7 @@ import java.util.Optional; import org.apache.syncope.client.console.SyncopeWebApplication; import org.apache.syncope.client.console.panels.BeanPanel; +import org.apache.syncope.client.console.panels.search.SearchUtils; import org.apache.syncope.client.console.rest.ImplementationRestClient; import org.apache.syncope.client.console.rest.ReportRestClient; import org.apache.syncope.client.console.tasks.CrontabPanel; @@ -47,6 +48,8 @@ import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.PropertyAccessorFactory; public class ReportWizardBuilder extends BaseAjaxWizardBuilder { @@ -56,7 +59,7 @@ public class ReportWizardBuilder extends BaseAjaxWizardBuilder { private final MIMETypesLoader mimeTypesLoader; - private final Model conf = new Model<>(); + private final Model conf = new Model<>(); private CrontabPanel crontabPanel; @@ -76,7 +79,11 @@ protected Serializable onApplyInternal(final ReportTO modelObject) { ImplementationTO implementation = ImplementationRestClient.read( IdRepoImplementationType.REPORT_DELEGATE, modelObject.getJobDelegate()); if (implementation.getEngine() == ImplementationEngine.JAVA) { - implementation.setBody(MAPPER.writeValueAsString(conf.getObject())); + BeanWrapper confWrapper = PropertyAccessorFactory.forBeanPropertyAccess(conf.getObject().getConf()); + conf.getObject().getSCondWrapper().forEach((fieldName, pair) -> confWrapper.setPropertyValue( + fieldName, SearchUtils.buildFIQL(pair.getRight(), pair.getLeft()))); + + implementation.setBody(MAPPER.writeValueAsString(conf.getObject().getConf())); ImplementationRestClient.update(implementation); } } catch (Exception e) { @@ -95,21 +102,24 @@ protected Serializable onApplyInternal(final ReportTO modelObject) { return modelObject; } - @Override - protected WizardModel buildModelSteps(final ReportTO modelObject, final WizardModel wizardModel) { - if (modelObject.getJobDelegate() != null) { - try { - ImplementationTO implementation = ImplementationRestClient.read( - IdRepoImplementationType.REPORT_DELEGATE, modelObject.getJobDelegate()); - if (implementation.getEngine() == ImplementationEngine.JAVA) { - conf.setObject(MAPPER.readValue(implementation.getBody(), ReportConf.class)); - } else { - conf.setObject(null); - } - } catch (Exception e) { - LOG.error("Could not read or parse {}", modelObject.getJobDelegate(), e); + protected void setConf(final String jobDelegate) { + try { + ImplementationTO implementation = ImplementationRestClient.read( + IdRepoImplementationType.REPORT_DELEGATE, jobDelegate); + if (implementation.getEngine() == ImplementationEngine.JAVA) { + conf.setObject(new ReportConfWrapper()); + conf.getObject().setConf(MAPPER.readValue(implementation.getBody(), ReportConf.class)); + } else { + conf.setObject(null); } + } catch (Exception e) { + LOG.error("Could not read or parse {}", jobDelegate, e); } + } + + @Override + protected WizardModel buildModelSteps(final ReportTO modelObject, final WizardModel wizardModel) { + Optional.ofNullable(modelObject.getJobDelegate()).ifPresent(this::setConf); wizardModel.add(new Profile(modelObject)); wizardModel.add(new Configuration()); @@ -164,17 +174,7 @@ protected void onUpdate(final AjaxRequestTarget target) { @Override protected void onUpdate(final AjaxRequestTarget target) { - try { - ImplementationTO implementation = ImplementationRestClient.read( - IdRepoImplementationType.REPORT_DELEGATE, jobDelegate.getModelObject()); - if (implementation.getEngine() == ImplementationEngine.JAVA) { - conf.setObject(MAPPER.readValue(implementation.getBody(), ReportConf.class)); - } else { - conf.setObject(null); - } - } catch (Exception e) { - LOG.error("Could not read or parse {}", jobDelegate.getModelObject(), e); - } + setConf(jobDelegate.getModelObject()); } }); } @@ -185,7 +185,9 @@ public class Configuration extends WizardStep implements WizardModel.ICondition private static final long serialVersionUID = -785981096328637758L; public Configuration() { - add(new BeanPanel<>("bean", conf).setRenderBodyOnly(true)); + add(new BeanPanel<>( + "bean", new PropertyModel<>(conf.getObject(), "conf"), conf.getObject().getSCondWrapper(), pageRef). + setRenderBodyOnly(true)); } @Override diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CommandComposeWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CommandComposeWizardBuilder.java index da1e9276857..93a24e40f9b 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CommandComposeWizardBuilder.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/CommandComposeWizardBuilder.java @@ -155,7 +155,7 @@ protected Serializable load() { return command.getCommand().getArgs(); } }; - add(new BeanPanel<>("bean", bean).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", bean, pageRef).setRenderBodyOnly(true)); } } } diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/CommandWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/CommandWizardBuilder.java index 15fc94d2434..cd27db62e60 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/CommandWizardBuilder.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/CommandWizardBuilder.java @@ -60,7 +60,7 @@ protected Serializable load() { return command.getArgs(); } }; - add(new BeanPanel<>("bean", bean).setRenderBodyOnly(true)); + add(new BeanPanel<>("bean", bean, pageRef).setRenderBodyOnly(true)); } } } diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties index ea31e874e40..9c394fc9553 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel.properties @@ -41,3 +41,8 @@ any.notification.tasks=Notification tasks for ${type} ${name} notification.tasks=Tasks about notification ${key} typeExtensions=Type extensions for GROUP ${name} +creator=Creator +creationContext=Creation Context +lastChangeContext=Last Change Context +lastChangeDate=Last Change Date +lastModifier=Last Modifier diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_fr_CA.properties index c289a28a933..2b04856ffce 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_fr_CA.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_fr_CA.properties @@ -14,16 +14,16 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -displayRows=Afficher rangées -mustChangePassword=Mot de passe doit être changé +displayRows=Afficher rang\u00e9es +mustChangePassword=Mot de passe doit \u00eatre chang\u00e9 edit=Modifier delete=Supprimer status=Statut token=Jeton username=Nom d'utilisateur -creationDate=Date de création -tokenValued=Évalué -tokenNotValued=Non évalué +creationDate=Date de cr\u00e9ation +tokenValued=\u00c9valu\u00e9 +tokenNotValued=Non \u00e9valu\u00e9 realm=Domaine subject=Sujet recipients=Destinataires @@ -31,9 +31,14 @@ any.edit=Modifier ${anyTO.type} ${anyTO.name} any.new=Nouveau ${anyTO.type} any.finish=Soumettre ${anyTO.type} any.cancel=Annuler ${anyTO.type} -any.attr.display=Attributs à afficher +any.attr.display=Attributs \u00e0 afficher batch=Lot -any.propagation.tasks=Tâches de propagation pour ${type} ${name} -any.notification.tasks=Tâches de notification pour ${type} ${name} -notification.tasks=Tâches à propos de la notification ${key} +any.propagation.tasks=T\u00e2ches de propagation pour ${type} ${name} +any.notification.tasks=T\u00e2ches de notification pour ${type} ${name} +notification.tasks=T\u00e2ches \u00e0 propos de la notification ${key} typeExtensions=Taper les extensions pour GROUPE ${name} +creator=Cr\u00e9ateur +creationContext=Creation Context +lastChangeContext=Last Change Context +lastChangeDate=Date de la derni\u00e8re modification +lastModifier=\u00daltima Dernier modificateur diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties index 2a80d888d2a..e36a31d674b 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_it.properties @@ -40,3 +40,8 @@ any.propagation.tasks=Task di Propagazione per ${type} ${name} any.notification.tasks=Task di Notifica per ${type} ${name} notification.tasks=Task relativi alla notifica ${key} typeExtensions=Type extensions per GROUP ${name} +creator=Creatore +creationContext=Contesto Di Crezione +lastChangeContext=Contesto Di Ultima Modifica +lastChangeDate=Data Di Ultima Modifica +lastModifier=Ultimo Modificatore diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ja.properties index cb3638e62e3..a62d3a840f7 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ja.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ja.properties @@ -41,3 +41,8 @@ any.notification.tasks=${type} ${name} \u306e\u901a\u77e5\u30bf\u30b9\u30af notification.tasks=\u901a\u77e5 ${key} \u306b\u95a2\u3059\u308b\u30bf\u30b9\u30af typeExtensions=\u30b0\u30eb\u30fc\u30d7 ${name} \u306e\u30bf\u30a4\u30d7\u62e1\u5f35 +creator=\u4f5c\u6210\u8005 +creationContext=Creation Context +lastChangeContext=Last Change Context +lastChangeDate=\u6700\u7d42\u66f4\u65b0\u65e5 +lastModifier=\u6700\u7d42\u66f4\u65b0\u8005 diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties index 8f55e7bf7a2..bd1d7260a33 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_pt_BR.properties @@ -40,3 +40,8 @@ any.propagation.tasks=Propagation tasks for ${type} ${name} any.notification.tasks=Notification tasks for ${type} ${name} notification.tasks=Tasks about notification ${key} typeExtensions=Type extensions for GROUP ${name} +creator=Criador +creationContext=Creation Context +lastChangeContext=Last Change Context +lastChangeDate=Data De \u00daltima Altera\u00e7\u00e3o +lastModifier=\u00daltima Modificador diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ru.properties index b88d40e79ba..26076067753 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ru.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/DirectoryPanel_ru.properties @@ -41,3 +41,8 @@ any.propagation.tasks=\u0417\u0430\u0434\u0430\u0447\u0438 \u0432\u044b\u043f\u0 any.notification.tasks=\u0417\u0430\u0434\u0430\u0447\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0434\u043b\u044f ${type} ${name} notification.tasks=\u0417\u0430\u0434\u0430\u0447\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 ${key} typeExtensions=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u0434\u043b\u044f \u0413\u0440\u0443\u043f\u043f\u044b ${name} +creator=\u0421\u043e\u0437\u0434\u0430\u043b +creationContext=Creation Context +lastChangeContext=Last Change Context +lastChangeDate=\u0414\u0430\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f +lastModifier=\u0418\u0437\u043c\u0435\u043d\u0438\u043b diff --git a/client/idrepo/console/src/test/java/org/apache/syncope/client/console/AbstractTest.java b/client/idrepo/console/src/test/java/org/apache/syncope/client/console/AbstractTest.java index 30df5d9ecf6..3ba9c828a61 100644 --- a/client/idrepo/console/src/test/java/org/apache/syncope/client/console/AbstractTest.java +++ b/client/idrepo/console/src/test/java/org/apache/syncope/client/console/AbstractTest.java @@ -81,7 +81,6 @@ import org.apache.wicket.util.tester.WicketTester; import org.junit.jupiter.api.BeforeAll; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -219,11 +218,12 @@ public TestSyncopeWebApplication( final VirSchemaDetailsPanelProvider virSchemaDetailsPanelProvider, final ImplementationInfoProvider implementationInfoProvider, final AccessPolicyConfProvider accessPolicyConfProvider, - final ApplicationContext ctx) { + final List policyTabProviders) { super(props, lookup, serviceOps, resourceProvider, anyDirectoryPanelAdditionalActionsProvider, anyDirectoryPanelAdditionalActionLinksProvider, anyWizardBuilderAdditionalSteps, statusProvider, - virSchemaDetailsPanelProvider, implementationInfoProvider, accessPolicyConfProvider, ctx); + virSchemaDetailsPanelProvider, implementationInfoProvider, accessPolicyConfProvider, + policyTabProviders); } public interface SyncopeServiceClient extends SyncopeService, Client { diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/SearchCondition.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/SearchCondition.java new file mode 100644 index 00000000000..0570dabdfe1 --- /dev/null +++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/report/SearchCondition.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.report; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface SearchCondition { + + String type() default "USER"; +} diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java index 40858082c81..267f19f575f 100644 --- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java +++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/AuditLogic.java @@ -59,7 +59,6 @@ import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate; import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate; import org.apache.syncope.core.spring.security.AuthContextUtils; -import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -85,7 +84,7 @@ public class AuditLogic extends AbstractTransactionalLogic { protected final AuditManager auditManager; - protected final ApplicationContext ctx; + protected final List auditAppenders; public AuditLogic( final AuditConfDAO auditConfDAO, @@ -93,14 +92,14 @@ public AuditLogic( final EntityFactory entityFactory, final AuditDataBinder binder, final AuditManager auditManager, - final ApplicationContext ctx) { + final List auditAppenders) { this.auditConfDAO = auditConfDAO; this.resourceDAO = resourceDAO; this.entityFactory = entityFactory; this.binder = binder; this.auditManager = auditManager; - this.ctx = ctx; + this.auditAppenders = auditAppenders; } @PreAuthorize("hasRole('" + IdRepoEntitlement.AUDIT_LIST + "')") @@ -146,7 +145,7 @@ protected void setLevel(final String key, final Level level) { LoggerConfig logConf = logCtx.getConfiguration().getLoggerConfig(auditLoggerName); // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger - ctx.getBeansOfType(AuditAppender.class).values().stream(). + auditAppenders.stream(). filter(appender -> appender.getEvents().stream(). anyMatch(event -> key.equalsIgnoreCase(event.toAuditKey()))). forEach(auditAppender -> AuditLoader.addAppenderToLoggerContext(logCtx, auditAppender, logConf)); diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java index dcc594a2a71..cc5959d8696 100644 --- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java +++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/IdRepoLogicContext.java @@ -110,7 +110,6 @@ import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter; import org.apache.syncope.core.workflow.api.UserWorkflowAdapter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @@ -145,9 +144,9 @@ public AuditAccessor auditAccessor(final AuditConfDAO auditConfDAO) { @Bean public AuditLoader auditLoader( final AuditAccessor auditAccessor, - final ApplicationContext ctx) { + final List auditAppenders) { - return new AuditLoader(auditAccessor, ctx); + return new AuditLoader(auditAccessor, auditAppenders); } @ConditionalOnMissingBean(name = "defaultAuditAppenders") @@ -255,7 +254,7 @@ public AuditLogic auditLogic( final EntityFactory entityFactory, final AuditDataBinder binder, final AuditManager auditManager, - final ApplicationContext ctx) { + final List auditAppenders) { return new AuditLogic( auditConfDAO, @@ -263,7 +262,7 @@ public AuditLogic auditLogic( entityFactory, binder, auditManager, - ctx); + auditAppenders); } @ConditionalOnMissingBean diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java index f906c52ed81..828f2722014 100644 --- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java +++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/AuditLoader.java @@ -18,6 +18,7 @@ */ package org.apache.syncope.core.logic.init; +import java.util.List; import java.util.Optional; import javax.sql.DataSource; import org.apache.logging.log4j.Level; @@ -30,7 +31,6 @@ import org.apache.syncope.core.logic.audit.AuditAppender; import org.apache.syncope.core.persistence.api.SyncopeCoreLoader; import org.apache.syncope.core.spring.security.AuthContextUtils; -import org.springframework.context.ApplicationContext; public class AuditLoader implements SyncopeCoreLoader { @@ -59,11 +59,11 @@ public static void addAppenderToLoggerContext( protected final AuditAccessor auditAccessor; - protected final ApplicationContext ctx; + protected final List auditAppenders; - public AuditLoader(final AuditAccessor auditAccessor, final ApplicationContext ctx) { + public AuditLoader(final AuditAccessor auditAccessor, final List auditAppenders) { this.auditAccessor = auditAccessor; - this.ctx = ctx; + this.auditAppenders = auditAppenders; } @Override @@ -76,7 +76,7 @@ public void load(final String domain, final DataSource datasource) { LoggerContext logCtx = (LoggerContext) LogManager.getContext(false); // SYNCOPE-1144 For each custom audit appender class add related appenders to log4j logger - ctx.getBeansOfType(AuditAppender.class).values().forEach(auditAppender -> auditAppender.getEvents().stream(). + auditAppenders.forEach(auditAppender -> auditAppender.getEvents().stream(). map(event -> AuditLoggerName.getAuditEventLoggerName(domain, event.toAuditKey())). forEach(domainAuditLoggerName -> { LoggerConfig eventLogConf = logCtx.getConfiguration().getLoggerConfig(domainAuditLoggerName); diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java index 4887a6cb1c1..3c2b99d6b43 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java @@ -142,7 +142,6 @@ import org.apache.syncope.core.spring.security.SecurityProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -250,10 +249,9 @@ public DomainRegistry domainRegistry(final Environment env) { @Bean public RuntimeDomainLoader runtimeDomainLoader( final DomainHolder domainHolder, - final DomainRegistry domainRegistry, - final ListableBeanFactory beanFactory) { + final DomainRegistry domainRegistry) { - return new RuntimeDomainLoader(domainHolder, domainRegistry, beanFactory); + return new RuntimeDomainLoader(domainHolder, domainRegistry); } @ConditionalOnMissingBean diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java index c40cc79b0f0..64061d208fd 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/RuntimeDomainLoader.java @@ -28,7 +28,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.ListableBeanFactory; public class RuntimeDomainLoader implements DomainWatcher { @@ -38,16 +37,12 @@ public class RuntimeDomainLoader implements DomainWatcher { protected final DomainRegistry domainRegistry; - protected final ListableBeanFactory beanFactory; - public RuntimeDomainLoader( final DomainHolder domainHolder, - final DomainRegistry domainRegistry, - final ListableBeanFactory beanFactory) { + final DomainRegistry domainRegistry) { this.domainHolder = domainHolder; this.domainRegistry = domainRegistry; - this.beanFactory = beanFactory; } @Override @@ -78,8 +73,8 @@ public void removed(final String domain) { if (domainHolder.getDomains().containsKey(domain)) { LOG.info("Domain {} unregistration", domain); - beanFactory.getBeansOfType(SyncopeCoreLoader.class).values().stream(). - sorted(Comparator.comparing(SyncopeCoreLoader::getOrder).reversed()). + ApplicationContextProvider.getApplicationContext().getBeansOfType(SyncopeCoreLoader.class).values(). + stream().sorted(Comparator.comparing(SyncopeCoreLoader::getOrder).reversed()). forEachOrdered(loader -> { String loaderName = AopUtils.getTargetClass(loader).getName(); diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java index 7d71da2e59e..88ee068169e 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java @@ -59,12 +59,12 @@ public WARestClient( private Optional getCore() { try { - ApplicationContext context = ApplicationContextProvider.getApplicationContext(); - if (context == null) { + ApplicationContext ctx = ApplicationContextProvider.getApplicationContext(); + if (ctx == null) { return Optional.empty(); } - Collection serviceOpsList = context.getBeansOfType(ServiceOps.class).values(); + Collection serviceOpsList = ctx.getBeansOfType(ServiceOps.class).values(); if (serviceOpsList.isEmpty()) { return Optional.empty(); } diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java index e14d0dd9a6a..8871cfb159b 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java @@ -70,6 +70,7 @@ import org.apereo.cas.adaptors.u2f.storage.U2FDeviceRepository; import org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer; import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; +import org.apereo.cas.authentication.MultifactorAuthenticationProvider; import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.configuration.model.support.mfa.gauth.LdapGoogleAuthenticatorMultifactorProperties; @@ -196,25 +197,27 @@ public ClientAppMapper saml2SPClientAppTOMapper() { @ConditionalOnMissingBean @Bean public RegisteredServiceMapper registeredServiceMapper( - final ConfigurableApplicationContext ctx, final CasConfigurationProperties casProperties, final ObjectProvider authenticationEventExecutionPlan, + final List multifactorAuthenticationProviders, final List authMappers, final List accessMappers, final List attrReleaseMappers, final List ticketExpirationMappers, - final List clientAppMappers) { + final List clientAppMappers, + final CasConfigurationProperties properties) { return new RegisteredServiceMapper( - ctx, Optional.ofNullable(casProperties.getAuthn().getPac4j().getCore().getName()). orElse(DelegatedClientAuthenticationHandler.class.getSimpleName()), authenticationEventExecutionPlan, + multifactorAuthenticationProviders, authMappers, accessMappers, attrReleaseMappers, ticketExpirationMappers, - clientAppMappers); + clientAppMappers, + properties); } @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java index d2f3f23e023..72ced91d01f 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AuthMapper.java @@ -23,17 +23,17 @@ import org.apache.syncope.common.lib.policy.AuthPolicyTO; import org.apache.syncope.common.lib.to.AuthModuleTO; import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; +import org.apereo.cas.authentication.MultifactorAuthenticationProvider; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.ConfigurableApplicationContext; public interface AuthMapper { boolean supports(AuthPolicyConf conf); AuthMapperResult build( - ConfigurableApplicationContext ctx, String pac4jCoreName, ObjectProvider authenticationEventExecutionPlan, + List multifactorAuthenticationProviders, AuthPolicyTO policy, List authModules); } diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java index 47872bc6c87..26b8042b805 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java @@ -21,6 +21,7 @@ import org.apache.syncope.common.lib.to.CASSPClientAppTO; import org.apache.syncope.common.lib.to.ClientAppTO; import org.apache.syncope.common.lib.wa.WAClientApp; +import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.services.CasRegisteredService; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.RegisteredServiceAccessStrategy; @@ -31,7 +32,6 @@ import org.apereo.cas.services.RegisteredServiceProxyTicketExpirationPolicy; import org.apereo.cas.services.RegisteredServiceServiceTicketExpirationPolicy; import org.apereo.cas.services.RegisteredServiceTicketGrantingTicketExpirationPolicy; -import org.springframework.context.ConfigurableApplicationContext; public class CASSPClientAppTOMapper extends AbstractClientAppMapper { @@ -42,7 +42,6 @@ public boolean supports(final ClientAppTO clientApp) { @Override public RegisteredService map( - final ConfigurableApplicationContext ctx, final WAClientApp clientApp, final RegisteredServiceAuthenticationPolicy authPolicy, final RegisteredServiceMultifactorPolicy mfaPolicy, @@ -51,7 +50,8 @@ public RegisteredService map( final RegisteredServiceTicketGrantingTicketExpirationPolicy tgtExpirationPolicy, final RegisteredServiceServiceTicketExpirationPolicy stExpirationPolicy, final RegisteredServiceProxyGrantingTicketExpirationPolicy tgtProxyExpirationPolicy, - final RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy) { + final RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy, + final CasConfigurationProperties properties) { CASSPClientAppTO cas = CASSPClientAppTO.class.cast(clientApp.getClientAppTO()); diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java index 5dd8e7c9bb1..e9fb97a459c 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java @@ -20,6 +20,7 @@ import org.apache.syncope.common.lib.to.ClientAppTO; import org.apache.syncope.common.lib.wa.WAClientApp; +import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.RegisteredServiceAccessStrategy; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy; @@ -29,14 +30,12 @@ import org.apereo.cas.services.RegisteredServiceProxyTicketExpirationPolicy; import org.apereo.cas.services.RegisteredServiceServiceTicketExpirationPolicy; import org.apereo.cas.services.RegisteredServiceTicketGrantingTicketExpirationPolicy; -import org.springframework.context.ConfigurableApplicationContext; public interface ClientAppMapper { boolean supports(ClientAppTO clientApp); RegisteredService map( - ConfigurableApplicationContext ctx, WAClientApp clientApp, RegisteredServiceAuthenticationPolicy authPolicy, RegisteredServiceMultifactorPolicy mfaPolicy, @@ -45,5 +44,6 @@ RegisteredService map( RegisteredServiceTicketGrantingTicketExpirationPolicy tgtExpirationPolicy, RegisteredServiceServiceTicketExpirationPolicy stExpirationPolicy, RegisteredServiceProxyGrantingTicketExpirationPolicy tgtProxyExpirationPolicy, - RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy); + RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy, + CasConfigurationProperties properties); } diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java index 676de5a0ba6..e656adabb14 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAuthMapper.java @@ -41,7 +41,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.ConfigurableApplicationContext; public class DefaultAuthMapper implements AuthMapper { @@ -54,9 +53,9 @@ public boolean supports(final AuthPolicyConf conf) { @Override public AuthMapperResult build( - final ConfigurableApplicationContext ctx, final String pac4jCoreName, final ObjectProvider authEventExecPlan, + final List multifactorAuthenticationProviders, final AuthPolicyTO policy, final List authModules) { @@ -105,7 +104,7 @@ public AuthMapperResult build( map(am -> ((MFAAuthModuleConf) am.getConf()).getFriendlyName()). collect(Collectors.toSet()); - Set mfaProviders = ctx.getBeansOfType(MultifactorAuthenticationProvider.class).values().stream(). + Set mfaProviders = multifactorAuthenticationProviders.stream(). filter(map -> fns.contains(map.getFriendlyName())). map(MultifactorAuthenticationProvider::getId). collect(Collectors.toSet()); diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java index 33c6eb05c4c..e3f3a881adb 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java @@ -50,7 +50,6 @@ import org.apereo.cas.services.RegisteredServiceServiceTicketExpirationPolicy; import org.apereo.cas.services.RegisteredServiceTicketGrantingTicketExpirationPolicy; import org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy; -import org.springframework.context.ConfigurableApplicationContext; public class OIDCRPClientAppTOMapper extends AbstractClientAppMapper { @@ -63,7 +62,6 @@ public boolean supports(final ClientAppTO clientApp) { @Override public RegisteredService map( - final ConfigurableApplicationContext ctx, final WAClientApp clientApp, final RegisteredServiceAuthenticationPolicy authPolicy, final RegisteredServiceMultifactorPolicy mfaPolicy, @@ -72,7 +70,8 @@ public RegisteredService map( final RegisteredServiceTicketGrantingTicketExpirationPolicy tgtExpirationPolicy, final RegisteredServiceServiceTicketExpirationPolicy stExpirationPolicy, final RegisteredServiceProxyGrantingTicketExpirationPolicy tgtProxyExpirationPolicy, - final RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy) { + final RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy, + final CasConfigurationProperties properties) { OIDCRPClientAppTO rp = OIDCRPClientAppTO.class.cast(clientApp.getClientAppTO()); OidcRegisteredService service = new OidcRegisteredService(); @@ -152,7 +151,6 @@ public RegisteredService map( customClaims.removeAll(OidcPhoneScopeAttributeReleasePolicy.ALLOWED_CLAIMS); } if (!customClaims.isEmpty()) { - CasConfigurationProperties properties = ctx.getBean(CasConfigurationProperties.class); List supportedClaims = properties.getAuthn().getOidc().getDiscovery().getClaims(); if (!supportedClaims.containsAll(customClaims)) { properties.getAuthn().getOidc().getDiscovery().setClaims( diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java index f58104134fd..c7e8ca34e9b 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java @@ -24,6 +24,8 @@ import org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf; import org.apache.syncope.common.lib.wa.WAClientApp; import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; +import org.apereo.cas.authentication.MultifactorAuthenticationProvider; +import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.RegisteredServiceAccessStrategy; @@ -38,18 +40,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.ConfigurableApplicationContext; public class RegisteredServiceMapper { private static final Logger LOG = LoggerFactory.getLogger(RegisteredServiceMapper.class); - protected final ConfigurableApplicationContext ctx; - protected final String pac4jCoreName; protected final ObjectProvider authEventExecPlan; + protected final List multifactorAuthenticationProviders; + protected final List authMappers; protected final List accessMappers; @@ -60,24 +61,28 @@ public class RegisteredServiceMapper { protected final List clientAppMappers; + protected final CasConfigurationProperties properties; + public RegisteredServiceMapper( - final ConfigurableApplicationContext ctx, final String pac4jCoreName, final ObjectProvider authEventExecPlan, + final List multifactorAuthenticationProviders, final List authMappers, final List accessMappers, final List attrReleaseMappers, final List ticketExpirationMappers, - final List clientAppMappers) { + final List clientAppMappers, + final CasConfigurationProperties properties) { - this.ctx = ctx; this.pac4jCoreName = pac4jCoreName; this.authEventExecPlan = authEventExecPlan; + this.multifactorAuthenticationProviders = multifactorAuthenticationProviders; this.authMappers = authMappers; this.accessMappers = accessMappers; this.attrReleaseMappers = attrReleaseMappers; this.ticketExpirationMappers = ticketExpirationMappers; this.clientAppMappers = clientAppMappers; + this.properties = properties; } public RegisteredService toRegisteredService(final WAClientApp clientApp) { @@ -98,7 +103,8 @@ public RegisteredService toRegisteredService(final WAClientApp clientApp) { filter(m -> m.supports(clientApp.getAuthPolicy().getConf())). findFirst(); AuthMapperResult result = authMapper.map(mapper -> mapper.build( - ctx, pac4jCoreName, authEventExecPlan, clientApp.getAuthPolicy(), clientApp.getAuthModules())). + pac4jCoreName, authEventExecPlan, multifactorAuthenticationProviders, clientApp.getAuthPolicy(), + clientApp.getAuthModules())). orElse(AuthMapperResult.EMPTY); authPolicy = result.getAuthPolicy(); mfaPolicy = result.getMfaPolicy(); @@ -154,7 +160,6 @@ public RegisteredService toRegisteredService(final WAClientApp clientApp) { } return clientAppMapper.map( - ctx, clientApp, authPolicy, mfaPolicy, @@ -163,6 +168,7 @@ public RegisteredService toRegisteredService(final WAClientApp clientApp) { tgtExpirationPolicy, stExpirationPolicy, tgtProxyExpirationPolicy, - stProxyExpirationPolicy); + stProxyExpirationPolicy, + properties); } } diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java index 1fd3d4d30de..4510592800f 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java @@ -23,6 +23,7 @@ import org.apache.syncope.common.lib.to.ClientAppTO; import org.apache.syncope.common.lib.to.SAML2SPClientAppTO; import org.apache.syncope.common.lib.wa.WAClientApp; +import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.services.RegisteredService; import org.apereo.cas.services.RegisteredServiceAccessStrategy; import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy; @@ -34,7 +35,6 @@ import org.apereo.cas.services.RegisteredServiceTicketGrantingTicketExpirationPolicy; import org.apereo.cas.support.saml.services.SamlRegisteredService; import org.apereo.cas.util.model.TriStateBoolean; -import org.springframework.context.ConfigurableApplicationContext; public class SAML2SPClientAppTOMapper extends AbstractClientAppMapper { @@ -45,7 +45,6 @@ public boolean supports(final ClientAppTO clientApp) { @Override public RegisteredService map( - final ConfigurableApplicationContext ctx, final WAClientApp clientApp, final RegisteredServiceAuthenticationPolicy authPolicy, final RegisteredServiceMultifactorPolicy mfaPolicy, @@ -54,7 +53,8 @@ public RegisteredService map( final RegisteredServiceTicketGrantingTicketExpirationPolicy tgtExpirationPolicy, final RegisteredServiceServiceTicketExpirationPolicy stExpirationPolicy, final RegisteredServiceProxyGrantingTicketExpirationPolicy tgtProxyExpirationPolicy, - final RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy) { + final RegisteredServiceProxyTicketExpirationPolicy stProxyExpirationPolicy, + final CasConfigurationProperties properties) { SAML2SPClientAppTO sp = SAML2SPClientAppTO.class.cast(clientApp.getClientAppTO()); SamlRegisteredService service = new SamlRegisteredService(); From 9a3b876165311bbf887752fae5706734d1958817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francesco=20Chicchiricc=C3=B2?= Date: Wed, 31 May 2023 08:51:50 +0200 Subject: [PATCH 2/2] Fix Report creation --- .../console/reports/ReportWizardBuilder.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java index c654a6efc9a..316d644d0ad 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportWizardBuilder.java @@ -45,6 +45,7 @@ import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.wizard.WizardModel; import org.apache.wicket.extensions.wizard.WizardStep; +import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; @@ -121,8 +122,9 @@ protected void setConf(final String jobDelegate) { protected WizardModel buildModelSteps(final ReportTO modelObject, final WizardModel wizardModel) { Optional.ofNullable(modelObject.getJobDelegate()).ifPresent(this::setConf); - wizardModel.add(new Profile(modelObject)); - wizardModel.add(new Configuration()); + Configuration configuration = new Configuration(); + wizardModel.add(new Profile(modelObject, configuration)); + wizardModel.add(configuration); wizardModel.add(new Schedule(modelObject)); return wizardModel; } @@ -134,7 +136,7 @@ public class Profile extends WizardStep { private final IModel> reportJobDelegates = SyncopeWebApplication.get(). getImplementationInfoProvider().getReportJobDelegates(); - public Profile(final ReportTO modelObject) { + public Profile(final ReportTO modelObject, final Configuration configuration) { AjaxTextFieldPanel name = new AjaxTextFieldPanel( Constants.NAME_FIELD_NAME, Constants.NAME_FIELD_NAME, new PropertyModel<>(modelObject, Constants.NAME_FIELD_NAME), false); @@ -175,6 +177,7 @@ protected void onUpdate(final AjaxRequestTarget target) { @Override protected void onUpdate(final AjaxRequestTarget target) { setConf(jobDelegate.getModelObject()); + configuration.update(); } }); } @@ -185,9 +188,20 @@ public class Configuration extends WizardStep implements WizardModel.ICondition private static final long serialVersionUID = -785981096328637758L; public Configuration() { - add(new BeanPanel<>( - "bean", new PropertyModel<>(conf.getObject(), "conf"), conf.getObject().getSCondWrapper(), pageRef). - setRenderBodyOnly(true)); + update(); + } + + protected void update() { + if (conf.getObject() == null) { + addOrReplace(new Label("bean", Model.of())); + } else { + addOrReplace(new BeanPanel<>( + "bean", + new PropertyModel<>(conf.getObject(), "conf"), + conf.getObject().getSCondWrapper(), + pageRef). + setRenderBodyOnly(true)); + } } @Override