1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.ext.opensearch.client;
20
21 import com.fasterxml.jackson.databind.JsonNode;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Optional;
30 import java.util.Set;
31 import java.util.stream.Collectors;
32 import org.apache.commons.lang3.ArrayUtils;
33 import org.apache.syncope.common.lib.types.AnyTypeKind;
34 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
35 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
36 import org.apache.syncope.core.persistence.api.dao.UserDAO;
37 import org.apache.syncope.core.persistence.api.entity.Any;
38 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
39 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
40 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
41 import org.apache.syncope.core.persistence.api.entity.Privilege;
42 import org.apache.syncope.core.persistence.api.entity.Realm;
43 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
44 import org.apache.syncope.core.persistence.api.entity.group.Group;
45 import org.apache.syncope.core.persistence.api.entity.user.User;
46 import org.springframework.transaction.annotation.Transactional;
47
48
49
50
51 public class OpenSearchUtils {
52
53 public static String getAnyIndex(final String domain, final AnyTypeKind kind) {
54 return domain.toLowerCase() + '_' + kind.name().toLowerCase();
55 }
56
57 public static String getRealmIndex(final String domain) {
58 return domain.toLowerCase() + "_realm";
59 }
60
61 public static String getAuditIndex(final String domain) {
62 return domain.toLowerCase() + "_audit";
63 }
64
65 protected static final char[] ELASTICSEARCH_REGEX_CHARS = new char[] {
66 '.', '?', '+', '*', '|', '{', '}', '[', ']', '(', ')', '"', '\\', '&' };
67
68 public static String escapeForLikeRegex(final char c) {
69 StringBuilder output = new StringBuilder();
70
71 if (ArrayUtils.contains(ELASTICSEARCH_REGEX_CHARS, c)) {
72 output.append('\\');
73 }
74
75 output.append(c);
76
77 return output.toString();
78 }
79
80 protected final UserDAO userDAO;
81
82 protected final GroupDAO groupDAO;
83
84 protected final AnyObjectDAO anyObjectDAO;
85
86 public OpenSearchUtils(
87 final UserDAO userDAO,
88 final GroupDAO groupDAO,
89 final AnyObjectDAO anyObjectDAO) {
90
91 this.userDAO = userDAO;
92 this.groupDAO = groupDAO;
93 this.anyObjectDAO = anyObjectDAO;
94 }
95
96
97
98
99
100
101
102 @Transactional
103 public Map<String, Object> document(final Any<?> any) {
104 Collection<String> resources = any instanceof User
105 ? userDAO.findAllResourceKeys(any.getKey())
106 : any instanceof AnyObject
107 ? anyObjectDAO.findAllResourceKeys(any.getKey())
108 : groupDAO.findAllResourceKeys(any.getKey());
109 Collection<String> dynRealms = any instanceof User
110 ? userDAO.findDynRealms(any.getKey())
111 : any instanceof AnyObject
112 ? anyObjectDAO.findDynRealms(any.getKey())
113 : groupDAO.findDynRealms(any.getKey());
114
115 Map<String, Object> builder = new HashMap<>();
116 builder.put("id", any.getKey());
117 builder.put("realm", any.getRealm().getKey());
118 builder.put("anyType", any.getType().getKey());
119 builder.put("creationDate", any.getCreationDate());
120 builder.put("creationContext", any.getCreationContext());
121 builder.put("creator", any.getCreator());
122 builder.put("lastChangeDate", any.getLastChangeDate());
123 builder.put("lastModifier", any.getLastModifier());
124 builder.put("lastChangeContext", any.getLastChangeContext());
125 builder.put("status", any.getStatus());
126 builder.put("auxClasses", any.getAuxClasses().stream().map(AnyTypeClass::getKey).collect(Collectors.toList()));
127 builder.put("resources", resources);
128 builder.put("dynRealms", dynRealms);
129
130 if (any instanceof AnyObject) {
131 AnyObject anyObject = ((AnyObject) any);
132 builder.put("name", anyObject.getName());
133
134 builder.put("memberships", anyObjectDAO.findAllGroupKeys(anyObject));
135
136 List<String> relationships = new ArrayList<>();
137 List<String> relationshipTypes = new ArrayList<>();
138 anyObjectDAO.findAllRelationships(anyObject).forEach(relationship -> {
139 relationships.add(relationship.getRightEnd().getKey());
140 relationshipTypes.add(relationship.getType().getKey());
141 });
142 builder.put("relationships", relationships);
143 builder.put("relationshipTypes", relationshipTypes);
144
145 customizeDocument(builder, anyObject);
146 } else if (any instanceof Group) {
147 Group group = ((Group) any);
148 builder.put("name", group.getName());
149 Optional.ofNullable(group.getUserOwner()).ifPresent(uo -> builder.put("userOwner", uo.getKey()));
150 Optional.ofNullable(group.getGroupOwner()).ifPresent(go -> builder.put("groupOwner", go.getKey()));
151
152 Set<String> members = new HashSet<>();
153 members.addAll(groupDAO.findUMemberships(group).stream().
154 map(membership -> membership.getLeftEnd().getKey()).collect(Collectors.toList()));
155 members.addAll(groupDAO.findUDynMembers(group));
156 members.addAll(groupDAO.findAMemberships(group).stream().
157 map(membership -> membership.getLeftEnd().getKey()).collect(Collectors.toList()));
158 members.addAll(groupDAO.findADynMembers(group));
159 builder.put("members", members);
160
161 customizeDocument(builder, group);
162 } else if (any instanceof User) {
163 User user = ((User) any);
164 builder.put("username", user.getUsername());
165 builder.put("token", user.getToken());
166 builder.put("tokenExpireTime", user.getTokenExpireTime());
167 builder.put("changePwdDate", user.getChangePwdDate());
168 builder.put("failedLogins", user.getFailedLogins());
169 builder.put("lastLoginDate", user.getLastLoginDate());
170 builder.put("suspended", user.isSuspended());
171 builder.put("mustChangePassword", user.isMustChangePassword());
172
173 List<String> roles = new ArrayList<>();
174 Set<String> privileges = new HashSet<>();
175 userDAO.findAllRoles(user).forEach(role -> {
176 roles.add(role.getKey());
177 privileges.addAll(role.getPrivileges().stream().map(Privilege::getKey).collect(Collectors.toSet()));
178 });
179 builder.put("roles", roles);
180 builder.put("privileges", privileges);
181
182 builder.put("memberships", userDAO.findAllGroupKeys(user));
183
184 List<String> relationships = new ArrayList<>();
185 Set<String> relationshipTypes = new HashSet<>();
186 user.getRelationships().forEach(relationship -> {
187 relationships.add(relationship.getRightEnd().getKey());
188 relationshipTypes.add(relationship.getType().getKey());
189 });
190 builder.put("relationships", relationships);
191 builder.put("relationshipTypes", relationshipTypes);
192
193 customizeDocument(builder, user);
194 }
195
196 for (PlainAttr<?> plainAttr : any.getPlainAttrs()) {
197 List<Object> values = plainAttr.getValues().stream().
198 map(PlainAttrValue::getValue).collect(Collectors.toList());
199
200 Optional.ofNullable(plainAttr.getUniqueValue()).ifPresent(v -> values.add(v.getValue()));
201
202 builder.put(plainAttr.getSchema().getKey(), values.size() == 1 ? values.get(0) : values);
203 }
204
205 return builder;
206 }
207
208 protected void customizeDocument(final Map<String, Object> builder, final AnyObject anyObject) {
209 }
210
211 protected void customizeDocument(final Map<String, Object> builder, final Group group) {
212 }
213
214 protected void customizeDocument(final Map<String, Object> builder, final User user) {
215 }
216
217 public Map<String, Object> document(final Realm realm) {
218 Map<String, Object> builder = new HashMap<>();
219 builder.put("id", realm.getKey());
220 builder.put("name", realm.getName());
221 builder.put("parent_id", realm.getParent() == null ? null : realm.getParent().getKey());
222 builder.put("fullPath", realm.getFullPath());
223
224 customizeDocument(builder, realm);
225
226 return builder;
227 }
228
229 protected void customizeDocument(final Map<String, Object> builder, final Realm realm) {
230 }
231
232 public Map<String, Object> document(
233 final long instant,
234 final JsonNode message,
235 final String domain) throws IOException {
236
237 Map<String, Object> builder = new HashMap<>();
238
239 builder.put("instant", instant);
240 builder.put("message", message);
241
242 customizeDocument(builder, instant, message, domain);
243
244 return builder;
245 }
246
247 protected void customizeDocument(
248 final Map<String, Object> builder,
249 final long instant,
250 final JsonNode message,
251 final String domain)
252 throws IOException {
253 }
254 }