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.persistence.jpa.dao;
20  
21  import java.util.List;
22  import java.util.Set;
23  import java.util.concurrent.atomic.AtomicBoolean;
24  import java.util.stream.Collectors;
25  import javax.persistence.Query;
26  import javax.persistence.TypedQuery;
27  import org.apache.syncope.common.lib.to.Provision;
28  import org.apache.syncope.common.lib.types.IdMEntitlement;
29  import org.apache.syncope.common.lib.types.TaskType;
30  import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
31  import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
32  import org.apache.syncope.core.persistence.api.dao.GroupDAO;
33  import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
34  import org.apache.syncope.core.persistence.api.dao.RealmDAO;
35  import org.apache.syncope.core.persistence.api.dao.TaskDAO;
36  import org.apache.syncope.core.persistence.api.dao.UserDAO;
37  import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
38  import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
39  import org.apache.syncope.core.persistence.api.entity.ExternalResource;
40  import org.apache.syncope.core.persistence.api.entity.Implementation;
41  import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
42  import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
43  import org.apache.syncope.core.persistence.api.entity.policy.Policy;
44  import org.apache.syncope.core.persistence.api.entity.policy.PropagationPolicy;
45  import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
46  import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
47  import org.apache.syncope.core.persistence.jpa.entity.JPAExternalResource;
48  import org.apache.syncope.core.spring.security.AuthContextUtils;
49  import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
50  import org.springframework.transaction.annotation.Transactional;
51  import org.springframework.util.CollectionUtils;
52  
53  public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource> implements ExternalResourceDAO {
54  
55      protected final TaskDAO taskDAO;
56  
57      protected final AnyObjectDAO anyObjectDAO;
58  
59      protected final UserDAO userDAO;
60  
61      protected final GroupDAO groupDAO;
62  
63      protected final PolicyDAO policyDAO;
64  
65      protected final VirSchemaDAO virSchemaDAO;
66  
67      protected final RealmDAO realmDAO;
68  
69      public JPAExternalResourceDAO(
70              final TaskDAO taskDAO,
71              final AnyObjectDAO anyObjectDAO,
72              final UserDAO userDAO,
73              final GroupDAO groupDAO,
74              final PolicyDAO policyDAO,
75              final VirSchemaDAO virSchemaDAO,
76              final RealmDAO realmDAO) {
77  
78          this.taskDAO = taskDAO;
79          this.anyObjectDAO = anyObjectDAO;
80          this.userDAO = userDAO;
81          this.groupDAO = groupDAO;
82          this.policyDAO = policyDAO;
83          this.virSchemaDAO = virSchemaDAO;
84          this.realmDAO = realmDAO;
85      }
86  
87      @Transactional(readOnly = true)
88      @Override
89      public int count() {
90          Query query = entityManager().createQuery(
91                  "SELECT COUNT(e) FROM  " + JPAExternalResource.class.getSimpleName() + " e");
92          return ((Number) query.getSingleResult()).intValue();
93      }
94  
95      @Transactional(readOnly = true)
96      @Override
97      public ExternalResource find(final String name) {
98          return entityManager().find(JPAExternalResource.class, name);
99      }
100 
101     @Override
102     public ExternalResource authFind(final String key) {
103         ExternalResource resource = find(key);
104         if (resource == null) {
105             return null;
106         }
107 
108         Set<String> authRealms = AuthContextUtils.getAuthorizations().get(IdMEntitlement.RESOURCE_READ);
109         if (authRealms == null || authRealms.isEmpty()
110                 || !authRealms.stream().anyMatch(realm -> resource.getConnector() != null
111                 && resource.getConnector().getAdminRealm().getFullPath().startsWith(realm))) {
112 
113             throw new DelegatedAdministrationException(
114                     resource.getConnector().getAdminRealm().getFullPath(),
115                     ExternalResource.class.getSimpleName(),
116                     resource.getKey());
117         }
118 
119         return resource;
120     }
121 
122     @Override
123     public List<Provision> findProvisionsByAuxClass(final AnyTypeClass anyTypeClass) {
124         return findAll().stream().
125                 flatMap(resource -> resource.getProvisions().stream()).
126                 filter(provision -> provision.getAuxClasses().contains(anyTypeClass.getKey())).
127                 collect(Collectors.toList());
128     }
129 
130     @Override
131     public boolean anyItemHaving(final Implementation transformer) {
132         return findAll().stream().
133                 flatMap(resource -> resource.getProvisions().stream()).
134                 flatMap(provision -> provision.getMapping().getItems().stream()).
135                 filter(item -> item.getTransformers().contains(transformer.getKey())).
136                 count() > 0;
137     }
138 
139     @Transactional(readOnly = true)
140     @Override
141     public List<ExternalResource> findByConnInstance(final String connInstance) {
142         TypedQuery<ExternalResource> query = entityManager().createQuery(
143                 "SELECT e FROM " + JPAExternalResource.class.getSimpleName() + " e "
144                 + "WHERE e.connector.id=:connInstance", ExternalResource.class);
145         query.setParameter("connInstance", connInstance);
146 
147         return query.getResultList();
148     }
149 
150     @Override
151     public List<ExternalResource> findByPropagationActions(final Implementation propagationActions) {
152         TypedQuery<ExternalResource> query = entityManager().createQuery(
153                 "SELECT e FROM " + JPAExternalResource.class.getSimpleName() + " e "
154                 + "WHERE :propagationActions MEMBER OF e.propagationActions", ExternalResource.class);
155         query.setParameter("propagationActions", propagationActions);
156 
157         return query.getResultList();
158     }
159 
160     @Override
161     public List<ExternalResource> findByProvisionSorter(final Implementation provisionSorter) {
162         TypedQuery<ExternalResource> query = entityManager().createQuery(
163                 "SELECT e FROM " + JPAExternalResource.class.getSimpleName() + " e "
164                 + "WHERE e.provisionSorter=:provisionSorter", ExternalResource.class);
165         query.setParameter("provisionSorter", provisionSorter);
166 
167         return query.getResultList();
168     }
169 
170     protected StringBuilder getByPolicyQuery(final Class<? extends Policy> policyClass) {
171         StringBuilder query = new StringBuilder("SELECT e FROM ").
172                 append(JPAExternalResource.class.getSimpleName()).
173                 append(" e WHERE e.");
174 
175         if (AccountPolicy.class.isAssignableFrom(policyClass)) {
176             query.append("accountPolicy");
177         } else if (PasswordPolicy.class.isAssignableFrom(policyClass)) {
178             query.append("passwordPolicy");
179         } else if (PropagationPolicy.class.isAssignableFrom(policyClass)) {
180             query.append("propagationPolicy");
181         } else if (PullPolicy.class.isAssignableFrom(policyClass)) {
182             query.append("pullPolicy");
183         } else if (PushPolicy.class.isAssignableFrom(policyClass)) {
184             query.append("pushPolicy");
185         }
186 
187         return query;
188     }
189 
190     @Override
191     public List<ExternalResource> findByPolicy(final Policy policy) {
192         TypedQuery<ExternalResource> query = entityManager().createQuery(
193                 getByPolicyQuery(policy.getClass()).append("=:policy").toString(), ExternalResource.class);
194         query.setParameter("policy", policy);
195         return query.getResultList();
196     }
197 
198     @Transactional(readOnly = true)
199     @Override
200     public List<ExternalResource> findAll() {
201         Set<String> authRealms = AuthContextUtils.getAuthorizations().get(IdMEntitlement.RESOURCE_LIST);
202         if (CollectionUtils.isEmpty(authRealms)) {
203             return List.of();
204         }
205 
206         TypedQuery<ExternalResource> query = entityManager().createQuery(
207                 "SELECT e FROM  " + JPAExternalResource.class.getSimpleName() + " e", ExternalResource.class);
208 
209         return query.getResultList().stream().filter(resource -> authRealms.stream().
210                 anyMatch(realm -> resource.getConnector() != null
211                 && resource.getConnector().getAdminRealm().getFullPath().startsWith(realm))).
212                 collect(Collectors.toList());
213     }
214 
215     @Transactional(rollbackFor = { Throwable.class })
216     @Override
217     public ExternalResource save(final ExternalResource resource) {
218         ((JPAExternalResource) resource).list2json();
219         return entityManager().merge(resource);
220     }
221 
222     @Override
223     public void deleteMapping(final String intAttrName) {
224         findAll().forEach(resource -> {
225             AtomicBoolean removed = new AtomicBoolean(false);
226 
227             resource.getProvisions().forEach(provision -> removed.set(
228                     removed.get()
229                     || (provision.getMapping() != null
230                     && provision.getMapping().getItems().removeIf(item -> intAttrName.equals(item.getIntAttrName())))));
231 
232             if (removed.get()) {
233                 entityManager().merge(resource);
234             }
235         });
236     }
237 
238     @Override
239     public void delete(final String name) {
240         ExternalResource resource = find(name);
241         if (resource == null) {
242             return;
243         }
244 
245         taskDAO.deleteAll(resource, TaskType.PROPAGATION);
246         taskDAO.deleteAll(resource, TaskType.PULL);
247         taskDAO.deleteAll(resource, TaskType.PUSH);
248 
249         realmDAO.findByResource(resource).
250                 forEach(realm -> realm.getResources().remove(resource));
251         anyObjectDAO.findByResource(resource).
252                 forEach(anyObject -> anyObject.getResources().remove(resource));
253         userDAO.findLinkedAccountsByResource(resource).forEach(account -> {
254             account.getOwner().getLinkedAccounts().remove(account);
255             account.setOwner(null);
256         });
257         userDAO.findByResource(resource).
258                 forEach(user -> user.getResources().remove(resource));
259         groupDAO.findByResource(resource).
260                 forEach(group -> group.getResources().remove(resource));
261         policyDAO.findByResource(resource).
262                 forEach(policy -> policy.getResources().remove(resource));
263 
264         virSchemaDAO.find(resource).forEach(virSchemaDAO::delete);
265 
266         if (resource.getConnector() != null
267                 && resource.getConnector().getResources() != null
268                 && !resource.getConnector().getResources().isEmpty()) {
269 
270             resource.getConnector().getResources().remove(resource);
271         }
272         resource.setConnector(null);
273 
274         entityManager().remove(resource);
275     }
276 }