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.common.lib.types.AnyTypeKind;
26 import org.apache.syncope.core.persistence.api.dao.AnyMatchDAO;
27 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
28 import org.apache.syncope.core.persistence.api.dao.DelegationDAO;
29 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
30 import org.apache.syncope.core.persistence.api.entity.Privilege;
31 import org.apache.syncope.core.persistence.api.entity.Realm;
32 import org.apache.syncope.core.persistence.api.entity.Role;
33 import org.apache.syncope.core.persistence.api.entity.user.User;
34 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
35 import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
36 import org.apache.syncope.core.persistence.jpa.entity.JPARole;
37 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
38 import org.apache.syncope.core.provisioning.api.event.EntityLifecycleEvent;
39 import org.apache.syncope.core.spring.security.AuthContextUtils;
40 import org.identityconnectors.framework.common.objects.SyncDeltaType;
41 import org.springframework.context.ApplicationEventPublisher;
42 import org.springframework.transaction.annotation.Transactional;
43
44 public class JPARoleDAO extends AbstractDAO<Role> implements RoleDAO {
45
46 public static final String DYNMEMB_TABLE = "DynRoleMembers";
47
48 protected final AnyMatchDAO anyMatchDAO;
49
50 protected final ApplicationEventPublisher publisher;
51
52 protected final AnySearchDAO anySearchDAO;
53
54 protected final DelegationDAO delegationDAO;
55
56 protected final SearchCondVisitor searchCondVisitor;
57
58 public JPARoleDAO(
59 final AnyMatchDAO anyMatchDAO,
60 final ApplicationEventPublisher publisher,
61 final AnySearchDAO anySearchDAO,
62 final DelegationDAO delegationDAO,
63 final SearchCondVisitor searchCondVisitor) {
64
65 this.anyMatchDAO = anyMatchDAO;
66 this.publisher = publisher;
67 this.anySearchDAO = anySearchDAO;
68 this.delegationDAO = delegationDAO;
69 this.searchCondVisitor = searchCondVisitor;
70 }
71
72 @Override
73 public int count() {
74 Query query = entityManager().createQuery(
75 "SELECT COUNT(e) FROM " + JPARole.class.getSimpleName() + " e");
76 return ((Number) query.getSingleResult()).intValue();
77 }
78
79 @Override
80 public Role find(final String key) {
81 return entityManager().find(JPARole.class, key);
82 }
83
84 @Override
85 public List<Role> findByRealm(final Realm realm) {
86 TypedQuery<Role> query = entityManager().createQuery(
87 "SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE :realm MEMBER OF e.realms", Role.class);
88 query.setParameter("realm", realm);
89 return query.getResultList();
90 }
91
92 @Override
93 public List<Role> findByPrivilege(final Privilege privilege) {
94 TypedQuery<Role> query = entityManager().createQuery(
95 "SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE :privilege MEMBER OF e.privileges",
96 Role.class);
97 query.setParameter("privilege", privilege);
98 return query.getResultList();
99 }
100
101 @Override
102 public List<Role> findAll() {
103 TypedQuery<Role> query = entityManager().createQuery(
104 "SELECT e FROM " + JPARole.class.getSimpleName() + " e ", Role.class);
105 return query.getResultList();
106 }
107
108 @Override
109 public Role save(final Role role) {
110 ((JPARole) role).list2json();
111 return entityManager().merge(role);
112 }
113
114 @Override
115 public Role saveAndRefreshDynMemberships(final Role role) {
116 Role merged = save(role);
117
118
119 clearDynMembers(merged);
120 if (merged.getDynMembership() != null) {
121 List<User> matching = anySearchDAO.search(
122 SearchCondConverter.convert(searchCondVisitor, merged.getDynMembership().getFIQLCond()),
123 AnyTypeKind.USER);
124
125 matching.forEach(user -> {
126 Query insert = entityManager().createNativeQuery("INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
127 insert.setParameter(1, user.getKey());
128 insert.setParameter(2, merged.getKey());
129 insert.executeUpdate();
130
131 publisher.publishEvent(
132 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, user, AuthContextUtils.getDomain()));
133 });
134 }
135
136 return merged;
137 }
138
139 @Override
140 public void delete(final Role role) {
141 TypedQuery<User> query = entityManager().createQuery(
142 "SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE :role MEMBER OF e.roles", User.class);
143 query.setParameter("role", role);
144
145 query.getResultList().forEach(user -> {
146 user.getRoles().remove(role);
147 publisher.publishEvent(
148 new EntityLifecycleEvent<>(this, SyncDeltaType.UPDATE, user, AuthContextUtils.getDomain()));
149 });
150
151 clearDynMembers(role);
152
153 delegationDAO.findByRole(role).forEach(delegation -> delegation.getRoles().remove(role));
154
155 entityManager().remove(role);
156 }
157
158 @Override
159 public void delete(final String key) {
160 Role role = find(key);
161 if (role == null) {
162 return;
163 }
164
165 delete(role);
166 }
167
168 @Override
169 @SuppressWarnings("unchecked")
170 public List<String> findDynMembers(final Role role) {
171 if (role.getDynMembership() == null) {
172 return List.of();
173 }
174
175 Query query = entityManager().createNativeQuery("SELECT any_id FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
176 query.setParameter(1, role.getKey());
177
178 List<String> result = new ArrayList<>();
179 query.getResultList().stream().map(key -> key instanceof Object[]
180 ? (String) ((Object[]) key)[0]
181 : ((String) key)).
182 forEach(user -> result.add((String) user));
183 return result;
184 }
185
186 @Override
187 public void clearDynMembers(final Role role) {
188 Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
189 delete.setParameter(1, role.getKey());
190 delete.executeUpdate();
191 }
192
193 @Transactional
194 @Override
195 public void refreshDynMemberships(final User user) {
196 Query query = entityManager().createNativeQuery(
197 "SELECT role_id FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
198 query.setParameter(1, user.getKey());
199
200 findAll().stream().filter(role -> role.getDynMembership() != null).forEach(role -> {
201 boolean matches = anyMatchDAO.matches(
202 user, SearchCondConverter.convert(searchCondVisitor, role.getDynMembership().getFIQLCond()));
203
204 Query find = entityManager().createNativeQuery(
205 "SELECT any_id FROM " + DYNMEMB_TABLE + " WHERE role_id=?");
206 find.setParameter(1, role.getKey());
207 boolean existing = !find.getResultList().isEmpty();
208
209 if (matches && !existing) {
210 Query insert = entityManager().createNativeQuery(
211 "INSERT INTO " + DYNMEMB_TABLE + " VALUES(?, ?)");
212 insert.setParameter(1, user.getKey());
213 insert.setParameter(2, role.getKey());
214 insert.executeUpdate();
215 } else if (!matches && existing) {
216 Query delete = entityManager().createNativeQuery(
217 "DELETE FROM " + DYNMEMB_TABLE + " WHERE role_id=? AND any_id=?");
218 delete.setParameter(1, role.getKey());
219 delete.setParameter(2, user.getKey());
220 delete.executeUpdate();
221 }
222 });
223 }
224
225 @Override
226 public void removeDynMemberships(final String key) {
227 Query delete = entityManager().createNativeQuery("DELETE FROM " + DYNMEMB_TABLE + " WHERE any_id=?");
228 delete.setParameter(1, key);
229 delete.executeUpdate();
230 }
231 }