Browse code

BM-14963 Feat: add LDAP export enhancer support

Anthony Prades authored on 20/06/2019 16:50:17
Showing 13 changed files
... ...
@@ -1,12 +1,12 @@
1 1
 Manifest-Version: 1.0
2 2
 Bundle-ManifestVersion: 2
3 3
 Bundle-Name: net.bluemind.system.ldap.export.tests
4
-Bundle-SymbolicName: net.bluemind.system.ldap.export.tests
4
+Bundle-SymbolicName: net.bluemind.system.ldap.export.tests;singleton:=true
5 5
 Bundle-Version: 4.1.0.qualifier
6 6
 Bundle-Vendor: bluemind.net
7 7
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
8
-Require-Bundle: net.bluemind.pool,
9
- org.junit,
8
+Require-Bundle: org.junit,
9
+ net.bluemind.pool,
10 10
  net.bluemind.node.client,
11 11
  net.bluemind.core.jdbc.testshelper,
12 12
  net.bluemind.tests.defaultdata,
13 13
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<?eclipse version="3.4"?>
3
+<plugin>
4
+   <extension
5
+         point="net.bluemind.system.ldap.export.entityenhancer">
6
+      <hook
7
+            impl="net.bluemind.system.ldap.export.enhancer.EnhancerTestImpl">
8
+      </hook>
9
+   </extension>
10
+
11
+</plugin>
... ...
@@ -1,6 +1,6 @@
1 1
 [
2 2
 	{ 
3
-        	"name":"bluemind/postgres-tests"
3
+        "name":"bluemind/postgres-tests"
4 4
 	},
5 5
 	{ 
6 6
  		"name":"bluemind/ldap"
7 7
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+package net.bluemind.system.ldap.export.enhancer;
2
+
3
+import java.util.Arrays;
4
+import java.util.List;
5
+
6
+import org.apache.directory.api.ldap.model.entry.Entry;
7
+import org.apache.directory.api.ldap.model.exception.LdapException;
8
+
9
+import net.bluemind.core.container.model.ItemValue;
10
+import net.bluemind.domain.api.Domain;
11
+import net.bluemind.group.api.Group;
12
+import net.bluemind.user.api.User;
13
+
14
+public class EnhancerTestImpl implements IEntityEnhancer {
15
+	private final List<String> userAttrs = Arrays.asList("audio");
16
+
17
+	@Override
18
+	public Entry enhanceUser(ItemValue<Domain> domain, ItemValue<User> user, Entry entry) throws LdapException {
19
+		entry.add("audio", "11119999");
20
+		return entry;
21
+	}
22
+
23
+	@Override
24
+	public List<String> userEnhancerAttributes() {
25
+		return userAttrs;
26
+	}
27
+
28
+	@Override
29
+	public Entry enhanceGroup(ItemValue<Domain> domain, ItemValue<Group> group, Entry entry) throws LdapException {
30
+		return entry;
31
+	}
32
+
33
+	@Override
34
+	public List<String> groupEnhancerAttributes() {
35
+		return null;
36
+	}
37
+
38
+}
... ...
@@ -164,6 +164,10 @@ public class DomainDirectoryUserTests {
164 164
 		assertEquals(1, attrs.size());
165 165
 		assertEquals("{SASL}login@domain.tld", attrs.get(0));
166 166
 
167
+		attrs = getAttributeValues(entry, "audio");
168
+		assertEquals(1, attrs.size());
169
+		assertEquals("11119999", attrs.get(0));
170
+
167 171
 		attrs = getAttributeValues(entry, "employeeType");
168 172
 		assertEquals(0, attrs.size());
169 173
 
... ...
@@ -24,9 +24,14 @@ Require-Bundle: net.bluemind.system.domaintemplate;bundle-version="4.1.0",
24 24
  net.bluemind.group.api,
25 25
  net.bluemind.metrics.registry,
26 26
  net.bluemind.system.schemaupgrader,
27
- net.bluemind.network.utils
27
+ net.bluemind.network.utils,
28
+ org.eclipse.osgi,
29
+ net.bluemind.eclipse.common
30
+Bundle-Activator: net.bluemind.system.ldap.export.Activator
31
+Bundle-ActivationPolicy: lazy
28 32
 Export-Package: net.bluemind.system.ldap.export,
29 33
  net.bluemind.system.ldap.export.conf,
34
+ net.bluemind.system.ldap.export.enhancer,
30 35
  net.bluemind.system.ldap.export.hook,
31 36
  net.bluemind.system.ldap.export.objects,
32 37
  net.bluemind.system.ldap.export.verticle
... ...
@@ -4,4 +4,5 @@ bin.includes = META-INF/,\
4 4
                .,\
5 5
                plugin.xml,\
6 6
                data/,\
7
-               templates/
7
+               templates/,\
8
+               schema/
... ...
@@ -1,6 +1,7 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <?eclipse version="3.4"?>
3 3
 <plugin>
4
+   <extension-point id="net.bluemind.system.ldap.export.entityenhancer" name="entityenhancer" schema="schema/net.bluemind.system.ldap.export.entityenhancer.exsd"/>
4 5
    <extension
5 6
          point="net.bluemind.system.domaintemplate">
6 7
       <domain-template-extension
... ...
@@ -28,5 +29,4 @@
28 29
             code="net.bluemind.system.ldap.export.upgrader.AddBmUuidIndex">
29 30
       </java>
30 31
    </extension>
31
-
32 32
 </plugin>
33 33
new file mode 100644
... ...
@@ -0,0 +1,109 @@
1
+<?xml version='1.0' encoding='UTF-8'?>
2
+<!-- Schema file written by PDE -->
3
+<schema targetNamespace="net.bluemind.system.ldap.export" xmlns="http://www.w3.org/2001/XMLSchema">
4
+<annotation>
5
+      <appinfo>
6
+         <meta.schema plugin="net.bluemind.system.ldap.export" id="net.bluemind.system.ldap.export.entityenhancer" name="entityenhancer"/>
7
+      </appinfo>
8
+      <documentation>
9
+         [Enter description of this extension point.]
10
+      </documentation>
11
+   </annotation>
12
+
13
+   <element name="extension">
14
+      <annotation>
15
+         <appinfo>
16
+            <meta.element />
17
+         </appinfo>
18
+      </annotation>
19
+      <complexType>
20
+         <sequence>
21
+            <element ref="hook" minOccurs="1" maxOccurs="unbounded"/>
22
+         </sequence>
23
+         <attribute name="point" type="string" use="required">
24
+            <annotation>
25
+               <documentation>
26
+                  
27
+               </documentation>
28
+            </annotation>
29
+         </attribute>
30
+         <attribute name="id" type="string">
31
+            <annotation>
32
+               <documentation>
33
+                  
34
+               </documentation>
35
+            </annotation>
36
+         </attribute>
37
+         <attribute name="name" type="string">
38
+            <annotation>
39
+               <documentation>
40
+                  
41
+               </documentation>
42
+               <appinfo>
43
+                  <meta.attribute translatable="true"/>
44
+               </appinfo>
45
+            </annotation>
46
+         </attribute>
47
+      </complexType>
48
+   </element>
49
+
50
+   <element name="hook">
51
+      <complexType>
52
+         <attribute name="impl" type="string">
53
+            <annotation>
54
+               <documentation>
55
+                  
56
+               </documentation>
57
+               <appinfo>
58
+                  <meta.attribute kind="java" basedOn=":net.bluemind.system.ldap.export.enhancer.IEntityEnhancer"/>
59
+               </appinfo>
60
+            </annotation>
61
+         </attribute>
62
+         <attribute name="priority" type="string">
63
+            <annotation>
64
+               <documentation>
65
+                  
66
+               </documentation>
67
+            </annotation>
68
+         </attribute>
69
+      </complexType>
70
+   </element>
71
+
72
+   <annotation>
73
+      <appinfo>
74
+         <meta.section type="since"/>
75
+      </appinfo>
76
+      <documentation>
77
+         [Enter the first release in which this extension point appears.]
78
+      </documentation>
79
+   </annotation>
80
+
81
+   <annotation>
82
+      <appinfo>
83
+         <meta.section type="examples"/>
84
+      </appinfo>
85
+      <documentation>
86
+         [Enter extension point usage example here.]
87
+      </documentation>
88
+   </annotation>
89
+
90
+   <annotation>
91
+      <appinfo>
92
+         <meta.section type="apiinfo"/>
93
+      </appinfo>
94
+      <documentation>
95
+         [Enter API information here.]
96
+      </documentation>
97
+   </annotation>
98
+
99
+   <annotation>
100
+      <appinfo>
101
+         <meta.section type="implementation"/>
102
+      </appinfo>
103
+      <documentation>
104
+         [Enter information about supplied implementation of this extension point.]
105
+      </documentation>
106
+   </annotation>
107
+
108
+
109
+</schema>
0 110
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+package net.bluemind.system.ldap.export;
2
+
3
+import java.util.List;
4
+
5
+import org.osgi.framework.BundleActivator;
6
+import org.osgi.framework.BundleContext;
7
+
8
+import net.bluemind.eclipse.common.RunnableExtensionLoader;
9
+import net.bluemind.system.ldap.export.enhancer.IEntityEnhancer;
10
+
11
+public class Activator implements BundleActivator {
12
+	private static final List<IEntityEnhancer> entityEnhancerHooks = loadEntityEnhancerHooks();
13
+
14
+	@Override
15
+	public void start(BundleContext context) throws Exception {
16
+	}
17
+
18
+	@Override
19
+	public void stop(BundleContext context) throws Exception {
20
+	}
21
+
22
+	private static List<IEntityEnhancer> loadEntityEnhancerHooks() {
23
+		RunnableExtensionLoader<IEntityEnhancer> loader = new RunnableExtensionLoader<IEntityEnhancer>();
24
+		return loader.loadExtensionsWithPriority("net.bluemind.system.ldap.export", "entityenhancer", "hook", "impl");
25
+	}
26
+
27
+	public static List<IEntityEnhancer> getEntityEnhancerHooks() {
28
+		return entityEnhancerHooks;
29
+	}
30
+}
0 31
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+/* BEGIN LICENSE
2
+  * Copyright © Blue Mind SAS, 2012-2017
3
+  *
4
+  * This file is part of BlueMind. BlueMind is a messaging and collaborative
5
+  * solution.
6
+  *
7
+  * This program is free software; you can redistribute it and/or modify
8
+  * it under the terms of either the GNU Affero General Public License as
9
+  * published by the Free Software Foundation (version 3 of the License).
10
+  *
11
+  * This program is distributed in the hope that it will be useful,
12
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
+  *
15
+  * See LICENSE.txt
16
+  * END LICENSE
17
+  */
18
+package net.bluemind.system.ldap.export.enhancer;
19
+
20
+import java.util.List;
21
+
22
+import org.apache.directory.api.ldap.model.entry.Entry;
23
+import org.apache.directory.api.ldap.model.exception.LdapException;
24
+
25
+import net.bluemind.core.container.model.ItemValue;
26
+import net.bluemind.domain.api.Domain;
27
+import net.bluemind.group.api.Group;
28
+import net.bluemind.user.api.User;
29
+
30
+public interface IEntityEnhancer {
31
+	Entry enhanceUser(ItemValue<Domain> domain, ItemValue<User> user, Entry entry) throws LdapException;
32
+
33
+	List<String> userEnhancerAttributes();
34
+
35
+	Entry enhanceGroup(ItemValue<Domain> domain, ItemValue<Group> group, Entry entry) throws LdapException;
36
+
37
+	List<String> groupEnhancerAttributes();
38
+}
... ...
@@ -18,8 +18,11 @@
18 18
 package net.bluemind.system.ldap.export.objects;
19 19
 
20 20
 import java.util.ArrayList;
21
+import java.util.Collection;
21 22
 import java.util.List;
23
+import java.util.Objects;
22 24
 import java.util.stream.Collectors;
25
+import java.util.stream.Stream;
23 26
 import java.util.stream.StreamSupport;
24 27
 
25 28
 import org.apache.directory.api.ldap.model.entry.Attribute;
... ...
@@ -37,6 +40,8 @@ import net.bluemind.core.api.fault.ServerFault;
37 40
 import net.bluemind.core.container.model.ItemValue;
38 41
 import net.bluemind.domain.api.Domain;
39 42
 import net.bluemind.group.api.Group;
43
+import net.bluemind.system.ldap.export.Activator;
44
+import net.bluemind.system.ldap.export.enhancer.IEntityEnhancer;
40 45
 
41 46
 public class DomainDirectoryGroup extends LdapObjects {
42 47
 	private static final String RDN_ATTRIBUTE = "cn";
... ...
@@ -103,6 +108,16 @@ public class DomainDirectoryGroup extends LdapObjects {
103 108
 			if (!members.memberUid.isEmpty()) {
104 109
 				ldapEntry.add("memberUid", members.memberUid.toArray(new String[members.memberUid.size()]));
105 110
 			}
111
+
112
+			for (IEntityEnhancer entityEnhancer : Activator.getEntityEnhancerHooks()) {
113
+				Entry enhancedEntry = entityEnhancer.enhanceGroup(domain, group, ldapEntry);
114
+				if (enhancedEntry != null) {
115
+					ldapEntry = enhancedEntry;
116
+				}
117
+			}
118
+
119
+			ldapEntry.removeAttributes("bmUid");
120
+			ldapEntry.add("bmUid", group.uid);
106 121
 		} catch (LdapException e) {
107 122
 			throw new ServerFault("Fail to manage group: " + getDn(), e);
108 123
 		}
... ...
@@ -117,13 +132,19 @@ public class DomainDirectoryGroup extends LdapObjects {
117 132
 
118 133
 		Entry entry = getLdapEntry();
119 134
 
120
-		for (String attr : ldapAttrsStringsValues) {
135
+		for (String attr : Stream.concat(ldapAttrsStringsValues.stream(), getEnhancerAttributeList().stream())
136
+				.collect(Collectors.toList())) {
121 137
 			modifyRequest = updateLdapAttribute(modifyRequest, currentEntry, entry, attr);
122 138
 		}
123 139
 
124 140
 		return modifyRequest;
125 141
 	}
126 142
 
143
+	private Collection<String> getEnhancerAttributeList() {
144
+		return Activator.getEntityEnhancerHooks().stream().map(IEntityEnhancer::groupEnhancerAttributes)
145
+				.filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toList());
146
+	}
147
+
127 148
 	public List<String> getRemovedMembersUid(Entry entry) {
128 149
 		List<String> removedUids = new ArrayList<>();
129 150
 
... ...
@@ -20,8 +20,10 @@ package net.bluemind.system.ldap.export.objects;
20 20
 import java.util.ArrayList;
21 21
 import java.util.Iterator;
22 22
 import java.util.List;
23
+import java.util.Objects;
23 24
 import java.util.Set;
24 25
 import java.util.stream.Collectors;
26
+import java.util.stream.Stream;
25 27
 
26 28
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
27 29
 import org.apache.directory.api.ldap.model.entry.Entry;
... ...
@@ -38,6 +40,8 @@ import net.bluemind.addressbook.api.VCard.Parameter;
38 40
 import net.bluemind.core.api.fault.ServerFault;
39 41
 import net.bluemind.core.container.model.ItemValue;
40 42
 import net.bluemind.domain.api.Domain;
43
+import net.bluemind.system.ldap.export.Activator;
44
+import net.bluemind.system.ldap.export.enhancer.IEntityEnhancer;
41 45
 import net.bluemind.user.api.User;
42 46
 
43 47
 public class DomainDirectoryUser extends LdapObjects {
... ...
@@ -210,13 +214,22 @@ public class DomainDirectoryUser extends LdapObjects {
210 214
 
211 215
 		try {
212 216
 			ldapEntry = new DefaultEntry(getDn(), "objectclass: inetOrgPerson", "objectclass: bmUser");
213
-			ldapEntry.add("bmUid", user.uid);
214 217
 
215 218
 			initIdentity(ldapEntry);
216 219
 			initEmail(ldapEntry);
217 220
 			initPhone(ldapEntry);
218 221
 			initAddress(ldapEntry);
219 222
 			initPassword(ldapEntry);
223
+
224
+			for (IEntityEnhancer entityEnhancer : Activator.getEntityEnhancerHooks()) {
225
+				Entry enhancedEntry = entityEnhancer.enhanceUser(domain, user, ldapEntry);
226
+				if (enhancedEntry != null) {
227
+					ldapEntry = enhancedEntry;
228
+				}
229
+			}
230
+
231
+			ldapEntry.removeAttributes("bmUid");
232
+			ldapEntry.add("bmUid", user.uid);
220 233
 		} catch (LdapException e) {
221 234
 			throw new ServerFault("Fail to manage user: " + getDn(), e);
222 235
 		}
... ...
@@ -296,10 +309,16 @@ public class DomainDirectoryUser extends LdapObjects {
296 309
 
297 310
 		Entry entry = getLdapEntry();
298 311
 
299
-		for (String attr : ldapAttrsStringsValues) {
312
+		for (String attr : Stream.concat(ldapAttrsStringsValues.stream(), getEnhancerAttributeList().stream())
313
+				.collect(Collectors.toList())) {
300 314
 			modifyRequest = updateLdapAttribute(modifyRequest, currentEntry, entry, attr);
301 315
 		}
302 316
 
303 317
 		return modifyRequest;
304 318
 	}
319
+
320
+	private List<String> getEnhancerAttributeList() {
321
+		return Activator.getEntityEnhancerHooks().stream().map(IEntityEnhancer::userEnhancerAttributes)
322
+				.filter(Objects::nonNull).flatMap(List::stream).collect(Collectors.toList());
323
+	}
305 324
 }