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.logic;
20  
21  import java.lang.reflect.Method;
22  import java.util.List;
23  import java.util.stream.Collectors;
24  import org.apache.commons.lang3.ArrayUtils;
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.syncope.common.lib.SyncopeClientException;
27  import org.apache.syncope.common.lib.to.ImplementationTO;
28  import org.apache.syncope.common.lib.types.ClientExceptionType;
29  import org.apache.syncope.common.lib.types.IdMImplementationType;
30  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
31  import org.apache.syncope.common.lib.types.IdRepoImplementationType;
32  import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
33  import org.apache.syncope.core.persistence.api.dao.DuplicateException;
34  import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
35  import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
36  import org.apache.syncope.core.persistence.api.dao.NotFoundException;
37  import org.apache.syncope.core.persistence.api.dao.NotificationDAO;
38  import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
39  import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
40  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
41  import org.apache.syncope.core.persistence.api.dao.ReportDAO;
42  import org.apache.syncope.core.persistence.api.dao.TaskDAO;
43  import org.apache.syncope.core.persistence.api.entity.Implementation;
44  import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder;
45  import org.springframework.security.access.prepost.PreAuthorize;
46  import org.springframework.transaction.annotation.Transactional;
47  
48  public class ImplementationLogic extends AbstractTransactionalLogic<ImplementationTO> {
49  
50      protected final ImplementationDataBinder binder;
51  
52      protected final ImplementationDAO implementationDAO;
53  
54      protected final ReportDAO reportDAO;
55  
56      protected final PolicyDAO policyDAO;
57  
58      protected final ExternalResourceDAO resourceDAO;
59  
60      protected final TaskDAO taskDAO;
61  
62      protected final RealmDAO realmDAO;
63  
64      protected final PlainSchemaDAO plainSchemaDAO;
65  
66      protected final NotificationDAO notificationDAO;
67  
68      public ImplementationLogic(
69              final ImplementationDataBinder binder,
70              final ImplementationDAO implementationDAO,
71              final ReportDAO reportDAO,
72              final PolicyDAO policyDAO,
73              final ExternalResourceDAO resourceDAO,
74              final TaskDAO taskDAO,
75              final RealmDAO realmDAO,
76              final PlainSchemaDAO plainSchemaDAO,
77              final NotificationDAO notificationDAO) {
78  
79          this.binder = binder;
80          this.implementationDAO = implementationDAO;
81          this.reportDAO = reportDAO;
82          this.policyDAO = policyDAO;
83          this.resourceDAO = resourceDAO;
84          this.taskDAO = taskDAO;
85          this.realmDAO = realmDAO;
86          this.plainSchemaDAO = plainSchemaDAO;
87          this.notificationDAO = notificationDAO;
88      }
89  
90      protected void checkType(final String type) {
91          if (!ImplementationTypesHolder.getInstance().getValues().containsKey(type)) {
92              SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidImplementationType);
93              sce.getElements().add("Implementation type not found: ");
94              throw sce;
95          }
96      }
97  
98      @PreAuthorize("hasRole('" + IdRepoEntitlement.IMPLEMENTATION_LIST + "')")
99      @Transactional(readOnly = true)
100     public List<ImplementationTO> list(final String type) {
101         checkType(type);
102 
103         return implementationDAO.findByType(type).stream().
104                 map(binder::getImplementationTO).collect(Collectors.toList());
105     }
106 
107     @PreAuthorize("hasRole('" + IdRepoEntitlement.IMPLEMENTATION_READ + "')")
108     @Transactional(readOnly = true)
109     public ImplementationTO read(final String type, final String key) {
110         checkType(type);
111 
112         Implementation implementation = implementationDAO.find(key);
113         if (implementation == null) {
114             LOG.error("Could not find implementation '" + key + '\'');
115 
116             throw new NotFoundException(key);
117         }
118 
119         if (!implementation.getType().equals(type)) {
120             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRequest);
121             sce.getElements().add("Found " + type + ", expected " + implementation.getType());
122             throw sce;
123         }
124 
125         return binder.getImplementationTO(implementation);
126     }
127 
128     @PreAuthorize("hasRole('" + IdRepoEntitlement.IMPLEMENTATION_CREATE + "')")
129     public ImplementationTO create(final ImplementationTO implementationTO) {
130         if (StringUtils.isBlank(implementationTO.getKey())) {
131             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
132             sce.getElements().add("Implementation key");
133             throw sce;
134         }
135 
136         checkType(implementationTO.getType());
137 
138         Implementation implementation = implementationDAO.find(implementationTO.getKey());
139         if (implementation != null) {
140             throw new DuplicateException(implementationTO.getKey());
141         }
142 
143         return binder.getImplementationTO(implementationDAO.save(binder.create(implementationTO)));
144     }
145 
146     @PreAuthorize("hasRole('" + IdRepoEntitlement.IMPLEMENTATION_UPDATE + "')")
147     public ImplementationTO update(final ImplementationTO implementationTO) {
148         Implementation implementation = implementationDAO.find(implementationTO.getKey());
149         if (implementation == null) {
150             LOG.error("Could not find implementation '" + implementationTO.getKey() + '\'');
151 
152             throw new NotFoundException(implementationTO.getKey());
153         }
154 
155         checkType(implementationTO.getType());
156 
157         binder.update(implementation, implementationTO);
158         implementation = implementationDAO.save(implementation);
159 
160         return binder.getImplementationTO(implementation);
161     }
162 
163     @PreAuthorize("hasRole('" + IdRepoEntitlement.IMPLEMENTATION_DELETE + "')")
164     public void delete(final String type, final String key) {
165         Implementation implementation = implementationDAO.find(key);
166         if (implementation == null) {
167             LOG.error("Could not find implementation '" + key + '\'');
168 
169             throw new NotFoundException(key);
170         }
171 
172         if (!implementation.getType().equals(type)) {
173             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRequest);
174             sce.getElements().add("Found " + type + ", expected " + implementation.getType());
175             throw sce;
176         }
177 
178         boolean inUse = false;
179         switch (implementation.getType()) {
180             case IdRepoImplementationType.ACCOUNT_RULE:
181                 inUse = !policyDAO.findByAccountRule(implementation).isEmpty();
182                 break;
183 
184             case IdRepoImplementationType.PASSWORD_RULE:
185                 inUse = !policyDAO.findByPasswordRule(implementation).isEmpty();
186                 break;
187 
188             case IdRepoImplementationType.ITEM_TRANSFORMER:
189                 inUse = resourceDAO.anyItemHaving(implementation);
190                 break;
191 
192             case IdRepoImplementationType.TASKJOB_DELEGATE:
193                 inUse = !taskDAO.findByDelegate(implementation).isEmpty();
194                 break;
195 
196             case IdRepoImplementationType.REPORT_DELEGATE:
197                 inUse = !reportDAO.findByDelegate(implementation).isEmpty();
198                 break;
199 
200             case IdRepoImplementationType.COMMAND:
201                 inUse = !taskDAO.findByCommand(implementation).isEmpty();
202                 break;
203 
204             case IdMImplementationType.RECON_FILTER_BUILDER:
205                 inUse = !taskDAO.findByReconFilterBuilder(implementation).isEmpty();
206                 break;
207 
208             case IdRepoImplementationType.LOGIC_ACTIONS:
209                 inUse = !realmDAO.findByLogicActions(implementation).isEmpty();
210                 break;
211 
212             case IdMImplementationType.PROVISION_SORTER:
213                 inUse = !resourceDAO.findByProvisionSorter(implementation).isEmpty();
214                 break;
215 
216             case IdMImplementationType.PROPAGATION_ACTIONS:
217                 inUse = !resourceDAO.findByPropagationActions(implementation).isEmpty();
218                 break;
219 
220             case IdMImplementationType.PULL_ACTIONS:
221                 inUse = !taskDAO.findByPullActions(implementation).isEmpty();
222                 break;
223 
224             case IdMImplementationType.PUSH_ACTIONS:
225                 inUse = !taskDAO.findByPushActions(implementation).isEmpty();
226                 break;
227 
228             case IdMImplementationType.PULL_CORRELATION_RULE:
229                 inUse = !policyDAO.findByPullCorrelationRule(implementation).isEmpty();
230                 break;
231 
232             case IdMImplementationType.PUSH_CORRELATION_RULE:
233                 inUse = !policyDAO.findByPushCorrelationRule(implementation).isEmpty();
234                 break;
235 
236             case IdRepoImplementationType.VALIDATOR:
237                 inUse = !plainSchemaDAO.findByValidator(implementation).isEmpty();
238                 break;
239 
240             case IdRepoImplementationType.RECIPIENTS_PROVIDER:
241                 inUse = !notificationDAO.findByRecipientsProvider(implementation).isEmpty();
242                 break;
243 
244             default:
245         }
246 
247         if (inUse) {
248             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InUse);
249             sce.getElements().add("This implementation is in use");
250             throw sce;
251         }
252 
253         implementationDAO.delete(key);
254     }
255 
256     @Override
257     protected ImplementationTO resolveReference(final Method method, final Object... args)
258             throws UnresolvedReferenceException {
259 
260         String key = null;
261 
262         if (ArrayUtils.isNotEmpty(args)) {
263             for (int i = 0; key == null && i < args.length; i++) {
264                 if (args[i] instanceof String) {
265                     key = (String) args[i];
266                 } else if (args[i] instanceof ImplementationTO) {
267                     key = ((ImplementationTO) args[i]).getKey();
268                 }
269             }
270         }
271 
272         if (StringUtils.isNotBlank(key)) {
273             try {
274                 return binder.getImplementationTO(implementationDAO.find(key));
275             } catch (Throwable ignore) {
276                 LOG.debug("Unresolved reference", ignore);
277                 throw new UnresolvedReferenceException(ignore);
278             }
279         }
280 
281         throw new UnresolvedReferenceException();
282     }
283 }