View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.flowable;
20  
21  import java.util.List;
22  import org.apache.syncope.common.keymaster.client.api.ConfParamOps;
23  import org.apache.syncope.core.flowable.api.UserRequestHandler;
24  import org.apache.syncope.core.flowable.impl.FlowableBpmnProcessManager;
25  import org.apache.syncope.core.flowable.impl.FlowableUserRequestHandler;
26  import org.apache.syncope.core.flowable.impl.FlowableUserWorkflowAdapter;
27  import org.apache.syncope.core.flowable.impl.FlowableWorkflowUtils;
28  import org.apache.syncope.core.flowable.support.DomainProcessEngine;
29  import org.apache.syncope.core.flowable.support.DomainProcessEngineFactoryBean;
30  import org.apache.syncope.core.flowable.support.ShellServiceTaskDisablingBpmnParseHandler;
31  import org.apache.syncope.core.flowable.support.SyncopeEntitiesVariableType;
32  import org.apache.syncope.core.flowable.support.SyncopeFormHandlerHelper;
33  import org.apache.syncope.core.flowable.support.SyncopeIdmIdentityService;
34  import org.apache.syncope.core.flowable.task.AutoActivate;
35  import org.apache.syncope.core.flowable.task.Create;
36  import org.apache.syncope.core.flowable.task.Delete;
37  import org.apache.syncope.core.flowable.task.GenerateToken;
38  import org.apache.syncope.core.flowable.task.Notify;
39  import org.apache.syncope.core.flowable.task.PasswordReset;
40  import org.apache.syncope.core.flowable.task.Reactivate;
41  import org.apache.syncope.core.flowable.task.Suspend;
42  import org.apache.syncope.core.flowable.task.Update;
43  import org.apache.syncope.core.persistence.api.dao.GroupDAO;
44  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
45  import org.apache.syncope.core.persistence.api.dao.UserDAO;
46  import org.apache.syncope.core.persistence.api.entity.EntityFactory;
47  import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
48  import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
49  import org.apache.syncope.core.provisioning.api.rules.RuleEnforcer;
50  import org.apache.syncope.core.spring.security.SecurityProperties;
51  import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
52  import org.flowable.common.engine.impl.AbstractEngineConfiguration;
53  import org.flowable.common.engine.impl.cfg.IdGenerator;
54  import org.flowable.common.engine.impl.persistence.StrongUuidGenerator;
55  import org.flowable.idm.spring.SpringIdmEngineConfiguration;
56  import org.flowable.idm.spring.configurator.SpringIdmEngineConfigurator;
57  import org.flowable.spring.SpringProcessEngineConfiguration;
58  import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
59  import org.springframework.boot.context.properties.EnableConfigurationProperties;
60  import org.springframework.context.ApplicationEventPublisher;
61  import org.springframework.context.ConfigurableApplicationContext;
62  import org.springframework.context.annotation.Bean;
63  import org.springframework.context.annotation.Configuration;
64  import org.springframework.context.annotation.Scope;
65  import org.springframework.core.io.Resource;
66  import org.springframework.core.io.ResourceLoader;
67  
68  @EnableConfigurationProperties(WorkflowFlowableProperties.class)
69  @Configuration(proxyBeanMethods = false)
70  public class FlowableWorkflowContext {
71  
72      @ConditionalOnMissingBean
73      @Bean
74      public SpringIdmEngineConfiguration syncopeIdmEngineConfiguration(final ConfigurableApplicationContext ctx) {
75          SpringIdmEngineConfiguration conf = new SpringIdmEngineConfiguration();
76          conf.setIdmIdentityService(new SyncopeIdmIdentityService(conf, ctx));
77          return conf;
78      }
79  
80      @ConditionalOnMissingBean
81      @Bean
82      public SpringIdmEngineConfigurator syncopeIdmEngineConfigurator(
83              final SpringIdmEngineConfiguration syncopeIdmEngineConfiguration) {
84          SpringIdmEngineConfigurator configurator = new SpringIdmEngineConfigurator();
85          configurator.setIdmEngineConfiguration(syncopeIdmEngineConfiguration);
86          return configurator;
87      }
88  
89      @ConditionalOnMissingBean
90      @Bean
91      public SyncopeFormHandlerHelper syncopeFormHandlerHelper() {
92          return new SyncopeFormHandlerHelper();
93      }
94  
95      @ConditionalOnMissingBean
96      @Bean
97      public FlowableBpmnProcessManager bpmnProcessManager(final DomainProcessEngine engine) {
98          return new FlowableBpmnProcessManager(engine);
99      }
100 
101     @ConditionalOnMissingBean
102     @Bean
103     public FlowableUserRequestHandler userRequestHandler(
104             final SecurityProperties securityProperties,
105             final UserDataBinder userDataBinder,
106             final DomainProcessEngine engine,
107             final UserDAO userDAO,
108             final EntityFactory entityFactory) {
109 
110         return new FlowableUserRequestHandler(
111                 userDataBinder,
112                 securityProperties.getAdminUser(),
113                 engine,
114                 userDAO,
115                 entityFactory);
116     }
117 
118     @ConditionalOnMissingBean
119     @Bean
120     public FlowableWorkflowUtils flowableUtils(final DomainProcessEngine engine) {
121         return new FlowableWorkflowUtils(engine);
122     }
123 
124     @ConditionalOnMissingBean
125     @Bean
126     public SyncopeEntitiesVariableType syncopeEntitiesVariableType() {
127         return new SyncopeEntitiesVariableType();
128     }
129 
130     @ConditionalOnMissingBean
131     @Bean
132     public IdGenerator idGenerator() {
133         return new StrongUuidGenerator();
134     }
135 
136     @ConditionalOnMissingBean
137     @Bean
138     @Scope("prototype")
139     public SpringProcessEngineConfiguration processEngineConfiguration(
140             final WorkflowFlowableProperties props,
141             final SpringIdmEngineConfigurator syncopeIdmEngineConfigurator,
142             final IdGenerator idGenerator,
143             final SyncopeEntitiesVariableType syncopeEntitiesVariableType,
144             final SyncopeFormHandlerHelper syncopeFormHandlerHelper) {
145 
146         SpringProcessEngineConfiguration conf = new SpringProcessEngineConfiguration();
147         conf.setDatabaseSchemaUpdate(AbstractEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
148         conf.setJpaHandleTransaction(true);
149         conf.setJpaCloseEntityManager(false);
150         conf.setHistoryLevel(props.getHistoryLevel());
151         conf.setIdmEngineConfigurator(syncopeIdmEngineConfigurator);
152         conf.setCustomPreVariableTypes(List.of(syncopeEntitiesVariableType));
153         conf.setFormHandlerHelper(syncopeFormHandlerHelper);
154         conf.setIdGenerator(idGenerator);
155         conf.setPreBpmnParseHandlers(List.of(new ShellServiceTaskDisablingBpmnParseHandler()));
156         return conf;
157     }
158 
159     @ConditionalOnMissingBean
160     @Bean
161     public DomainProcessEngineFactoryBean domainProcessEngineFactoryBean(final ConfigurableApplicationContext ctx) {
162         return new DomainProcessEngineFactoryBean(ctx);
163     }
164 
165     @Bean
166     public Resource userWorkflowDef(final WorkflowFlowableProperties props,
167             final ResourceLoader resourceLoader) {
168         return resourceLoader.getResource(props.getUserWorkflowDef());
169     }
170 
171     @ConditionalOnMissingBean(name = "flowableUWFAdapter")
172     @Bean
173     public UserWorkflowAdapter uwfAdapter(
174             final UserDataBinder userDataBinder,
175             final UserDAO userDAO,
176             final RealmDAO realmDAO,
177             final GroupDAO groupDAO,
178             final EntityFactory entityFactory,
179             final SecurityProperties securityProperties,
180             final RuleEnforcer ruleEnforcer,
181             final DomainProcessEngine engine,
182             final UserRequestHandler userRequestHandler,
183             final ApplicationEventPublisher publisher) {
184 
185         return new FlowableUserWorkflowAdapter(
186                 userDataBinder,
187                 userDAO,
188                 realmDAO,
189                 groupDAO,
190                 entityFactory,
191                 securityProperties,
192                 ruleEnforcer,
193                 engine,
194                 userRequestHandler,
195                 publisher);
196     }
197 
198     @ConditionalOnMissingBean
199     @Bean
200     public AutoActivate autoActivate(final UserDataBinder userDataBinder, final UserDAO userDAO) {
201         return new AutoActivate(userDataBinder, userDAO);
202     }
203 
204     @ConditionalOnMissingBean
205     @Bean
206     public Create create(final UserDataBinder userDataBinder, final EntityFactory entityFactory) {
207         return new Create(userDataBinder, entityFactory);
208     }
209 
210     @ConditionalOnMissingBean
211     @Bean
212     public Delete delete() {
213         return new Delete();
214     }
215 
216     @ConditionalOnMissingBean
217     @Bean
218     public GenerateToken generateToken(final ConfParamOps confParamOps) {
219         return new GenerateToken(confParamOps);
220     }
221 
222     @ConditionalOnMissingBean
223     @Bean
224     public Notify notify(final NotificationManager notificationManager) {
225         return new Notify(notificationManager);
226     }
227 
228     @ConditionalOnMissingBean
229     @Bean
230     public PasswordReset passwordReset(final UserDataBinder userDataBinder, final UserDAO userDAO) {
231         return new PasswordReset(userDataBinder, userDAO);
232     }
233 
234     @ConditionalOnMissingBean
235     @Bean
236     public Reactivate reactivate() {
237         return new Reactivate();
238     }
239 
240     @ConditionalOnMissingBean
241     @Bean
242     public Suspend suspend() {
243         return new Suspend();
244     }
245 
246     @ConditionalOnMissingBean
247     @Bean
248     public Update update(final UserDataBinder userDataBinder, final UserDAO userDAO) {
249         return new Update(userDataBinder, userDAO);
250     }
251 }