1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.persistence.jpa.dao;
20
21 import java.util.ArrayList;
22 import java.util.List;
23 import javax.persistence.Query;
24 import javax.persistence.TypedQuery;
25 import org.apache.syncope.core.persistence.api.dao.AnyMatchDAO;
26 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
27 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
28 import org.apache.syncope.core.persistence.api.dao.DynRealmDAO;
29 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
30 import org.apache.syncope.core.persistence.api.dao.UserDAO;
31 import org.apache.syncope.core.persistence.api.entity.Any;
32 import org.apache.syncope.core.persistence.api.entity.DynRealm;
33 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
34 import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
35 import org.apache.syncope.core.persistence.jpa.entity.JPADynRealm;
36 import org.apache.syncope.core.provisioning.api.event.EntityLifecycleEvent;
37 import org.apache.syncope.core.spring.security.AuthContextUtils;
38 import org.identityconnectors.framework.common.objects.SyncDeltaType;
39 import org.springframework.context.ApplicationEventPublisher;
40 import org.springframework.transaction.annotation.Transactional;
41
42 public class JPADynRealmDAO extends AbstractDAO<DynRealm> implements DynRealmDAO {
43
44 public static final String DYNMEMB_TABLE = "DynRealmMembers";
45
46 protected final ApplicationEventPublisher publisher;
47
48 protected final UserDAO userDAO;
49
50 protected final GroupDAO groupDAO;
51
52 protected final AnyObjectDAO anyObjectDAO;
53
54 protected final AnySearchDAO searchDAO;
55
56 protected final AnyMatchDAO anyMatchDAO;
57
58 protected final SearchCondVisitor searchCondVisitor;
59
60 public JPADynRealmDAO(
61 final ApplicationEventPublisher publisher,
62 final UserDAO userDAO,
63 final GroupDAO groupDAO,
64 final AnyObjectDAO anyObjectDAO,
65 final AnySearchDAO searchDAO,
66 final AnyMatchDAO anyMatchDAO,
67 final SearchCondVisitor searchCondVisitor) {
68
69 this.publisher = publisher;
70 this.userDAO = userDAO;
71 this.groupDAO = groupDAO;
72 this.anyObjectDAO = anyObjectDAO;
73 this.searchDAO = searchDAO;
74 this.anyMatchDAO = anyMatchDAO;
75 this.searchCondVisitor = searchCondVisitor;
76 }
77
78 @Override
79 public DynRealm find(final String key) {
80 return entityManager().find(JPADynRealm.class, key);
81 }
82
83 @Override
84 public List<DynRealm> findAll() {
85 TypedQuery<DynRealm> query = entityManager().createQuery(
86 "SELECT e FROM " + JPADynRealm.class.getSimpleName() + " e ", DynRealm.class);
87 return query.getResultList();
88 }
89
90 @Override
91 public DynRealm save(final DynRealm dynRealm) {
92 return entityManager().merge(dynRealm);
93 }
94
95 @SuppressWarnings("unchecked")
96 protected List<String> clearDynMembers(final DynRealm dynRealm) {
97 Query find = entityManager().createNativeQuery(
98 "SELECT any_id FROM " + DYNMEMB_TABLE + " WHERE dynRealm_id=?");
99 find.setParameter(1, dynRealm.getKey());
100
101 List<String> cleared = new ArrayList<>();
102 find.getResultList().stream().map(key -> key instanceof Object[]
103 ? (String) ((Object[]) key)[0]
104 : ((String) key)).
105 forEach(key -> cleared.add((String) key));
106
107 Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE dynRealm_id=?");
108 delete.setParameter(1, dynRealm.getKey());
109 delete.executeUpdate();
110
111 return cleared;
112 }
113
114 protected void notifyDynMembershipRemoval(final List<String> anyKeys) {
115 anyKeys.forEach(key -> {
116 Any<?> any = userDAO.find(key);
117 if (any == null) {
118 any = groupDAO.find(key);
119 }
120 if (any == null) {
121 any = anyObjectDAO.find(key);
122 }
123 if (any != null) {
124 publisher.publishEvent(
125 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, any, AuthContextUtils.getDomain()));
126 }
127 });
128 }
129
130 @Override
131 public DynRealm saveAndRefreshDynMemberships(final DynRealm dynRealm) {
132 DynRealm merged = save(dynRealm);
133
134
135 List<String> cleared = clearDynMembers(merged);
136
137 merged.getDynMemberships().stream().map(memb -> searchDAO.search(
138 SearchCondConverter.convert(searchCondVisitor, memb.getFIQLCond()), memb.getAnyType().getKind())).
139 forEach(matching -> matching.forEach(any -> {
140
141 Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
142 insert.setParameter(1, any.getKey());
143 insert.setParameter(2, merged.getKey());
144 insert.executeUpdate();
145
146 publisher.publishEvent(
147 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, any, AuthContextUtils.getDomain()));
148 cleared.remove(any.getKey());
149 }));
150
151 notifyDynMembershipRemoval(cleared);
152
153 return merged;
154 }
155
156 @Override
157 public void delete(final String key) {
158 DynRealm dynRealm = find(key);
159 if (dynRealm == null) {
160 return;
161 }
162
163 notifyDynMembershipRemoval(clearDynMembers(dynRealm));
164
165 entityManager().remove(dynRealm);
166 }
167
168 @Transactional
169 @Override
170 public void refreshDynMemberships(final Any<?> any) {
171 findAll().forEach(dynRealm -> dynRealm.getDynMembership(any.getType()).ifPresent(memb -> {
172 boolean matches = anyMatchDAO.matches(
173 any, SearchCondConverter.convert(searchCondVisitor, memb.getFIQLCond()));
174
175 Query find = entityManager().createNativeQuery(
176 "SELECT dynRealm_id FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
177 find.setParameter(1, any.getKey());
178 boolean existing = !find.getResultList().isEmpty();
179
180 if (matches && !existing) {
181 Query insert = entityManager().
182 createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
183 insert.setParameter(1, any.getKey());
184 insert.setParameter(2, dynRealm.getKey());
185 insert.executeUpdate();
186 } else if (!matches && existing) {
187 Query delete = entityManager().createNativeQuery(
188 "DELETE FROM " + DYNMEMB_TABLE + " WHERE dynRealm_id=? AND any_id=?");
189 delete.setParameter(1, dynRealm.getKey());
190 delete.setParameter(2, any.getKey());
191 delete.executeUpdate();
192 }
193 }));
194 }
195
196 @Override
197 public void removeDynMemberships(final String anyKey) {
198 Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
199 delete.setParameter(1, anyKey);
200 delete.executeUpdate();
201 }
202 }