1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.security;
35
36 import static info.magnolia.cms.security.SecurityConstants.*;
37
38 import info.magnolia.context.MgnlContext;
39 import info.magnolia.jcr.iterator.FilteringPropertyIterator;
40 import info.magnolia.jcr.util.NodeTypes;
41 import info.magnolia.jcr.util.NodeUtil;
42 import info.magnolia.repository.RepositoryConstants;
43
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.List;
49
50 import javax.jcr.ItemNotFoundException;
51 import javax.jcr.Node;
52 import javax.jcr.NodeIterator;
53 import javax.jcr.Property;
54 import javax.jcr.PropertyIterator;
55 import javax.jcr.RepositoryException;
56 import javax.jcr.Session;
57
58 import org.apache.commons.lang3.StringUtils;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61
62
63
64
65 public class MgnlGroupManager extends RepositoryBackedSecurityManager implements GroupManager {
66
67 private static final Logger log = LoggerFactory.getLogger(MgnlGroupManager.class);
68
69 @Override
70 public Group createGroup(final String name) throws AccessDeniedException {
71 return createGroup(null, name);
72 }
73
74
75
76
77
78
79
80 public Group createGroup(final String path, final String name) throws AccessDeniedException {
81 validateGroupName(name);
82 return MgnlContext.doInSystemContext(new SilentSessionOp<MgnlGroup>(getRepositoryName()) {
83
84 @Override
85 public MgnlGroup doExec(Session session) throws RepositoryException {
86 String parentPath = StringUtils.defaultString(path, "/");
87 Node groupNode = session.getNode(parentPath).addNode(name, NodeTypes.Group.NAME);
88 session.save();
89 return new MgnlGroup(groupNode.getIdentifier(), groupNode.getName(), Collections.EMPTY_LIST, Collections.EMPTY_LIST);
90 }
91
92 @Override
93 public String toString() {
94 return "create group " + name;
95 }
96 });
97 }
98
99 @Override
100 public Group getGroup(final String name) throws AccessDeniedException {
101 return MgnlContext.doInSystemContext(new SilentSessionOp<Group>(getRepositoryName()) {
102
103 @Override
104 public Group doExec(Session session) throws RepositoryException {
105 Node privilegedGroupNode = findPrincipalNode(name, session);
106 if (privilegedGroupNode == null) {
107 return null;
108 }
109 return newGroupInstance(privilegedGroupNode);
110 }
111
112 @Override
113 public String toString() {
114 return "get group " + name;
115 }
116 });
117 }
118
119 @Override
120 public Collection<Group> getAllGroups() {
121 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<Group>>(getRepositoryName()) {
122
123 @Override
124 public Collection<Group> doExec(Session session) throws RepositoryException {
125 List<Group> groups = new ArrayList<Group>();
126 Node rootNode = session.getNode("/");
127 findAllGroupsInFolder(rootNode, groups);
128 return groups;
129 }
130
131 @Override
132 public String toString() {
133 return "get all groups";
134 }
135
136 });
137 }
138
139 @Override
140 public Collection<String> getAllGroups(final String name) {
141 return getAllSuperGroups(name);
142 }
143
144 protected Group newGroupInstance(Node node) throws RepositoryException {
145
146 Collection<String> groups = new HashSet<String>();
147 if (node.hasNode(NODE_GROUPS)) {
148 for (PropertyIterator iter = new FilteringPropertyIterator(node.getNode(NODE_GROUPS).getProperties(), NodeUtil.ALL_PROPERTIES_EXCEPT_JCR_AND_MGNL_FILTER); iter.hasNext(); ) {
149 Property subgroup = iter.nextProperty();
150 String resources = getResourceName(subgroup.getString());
151 if (resources != null) {
152 groups.add(resources);
153 }
154 }
155 }
156 Collection<String> roles = new HashSet<String>();
157 if (node.hasNode(NODE_ROLES)) {
158 RoleManager roleMan = SecuritySupport.Factory.getInstance().getRoleManager();
159 for (PropertyIterator iter = new FilteringPropertyIterator(node.getNode(NODE_ROLES).getProperties(), NodeUtil.ALL_PROPERTIES_EXCEPT_JCR_AND_MGNL_FILTER); iter.hasNext(); ) {
160 Property role = iter.nextProperty();
161 try {
162 String roleName = roleMan.getRoleNameById(role.getString());
163 if (roleName != null) {
164 roles.add(roleName);
165 }
166 } catch (ItemNotFoundException e) {
167 log.warn("assigned role {} doesn't exist.", role.getString());
168 }
169 }
170 }
171 MgnlGroup group = new MgnlGroup(node.getIdentifier(), node.getName(), groups, roles);
172 return group;
173 }
174
175
176
177
178
179 @Override
180 protected Node findPrincipalNode(String principalName, Session session) throws RepositoryException {
181 return findPrincipalNode(principalName, session, NodeTypes.Group.NAME);
182 }
183
184 @Override
185 protected String getRepositoryName() {
186 return RepositoryConstants.USER_GROUPS;
187 }
188
189 @Override
190 public Group addRole(Group group, String roleName) throws AccessDeniedException {
191 try {
192 add(group.getName(), roleName, NODE_ROLES);
193 } catch (PrincipalNotFoundException e) {
194
195 return null;
196 }
197 return getGroup(group.getName());
198 }
199
200 @Override
201 public Group addGroup(Group group, String groupName) throws AccessDeniedException {
202 try {
203 add(group.getName(), groupName, NODE_GROUPS);
204 } catch (PrincipalNotFoundException e) {
205
206 return null;
207 }
208 return getGroup(groupName);
209 }
210
211
212
213
214
215 protected void findAllGroupsInFolder(Node node, Collection<Group> addTo) throws RepositoryException {
216 final NodeIterator nodesIter = findPrincipalNodes(node, NodeTypes.Group.NAME);
217 while (nodesIter.hasNext()) {
218 addTo.add(newGroupInstance(nodesIter.nextNode()));
219 }
220 }
221
222 protected void validateGroupName(String name) throws AccessDeniedException {
223 if (StringUtils.isBlank(name)) {
224 throw new IllegalArgumentException(name + " is not a valid group name.");
225 }
226
227 Group group = Security.getGroupManager().getGroup(name);
228
229 if (group != null) {
230 throw new IllegalArgumentException("Group with name " + name + " already exists.");
231 }
232 }
233
234 @Override
235 public Collection<String> getGroupsWithGroup(final String groupName) {
236 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
237
238 @Override
239 public Collection<String> doExec(Session session) throws RepositoryException {
240 final Node groupNode = findPrincipalNode(groupName, session);
241 return findUsersOrGroupsHavingAssignedGroupOrRoleWithUid(session, groupNode, GROUPS_NODE_NAME);
242 }
243
244 @Override
245 public String toString() {
246 return "get group " + groupName;
247 }
248 });
249 }
250
251
252 @Override
253 public Collection<String> getGroupsWithRole(final String roleName) {
254 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
255
256 @Override
257 public Collection<String> doExec(Session session) throws RepositoryException {
258 final Node principalNode = findPrincipalNode(roleName, MgnlContext.getJCRSession(RepositoryConstants.USER_ROLES), NodeTypes.Role.NAME);
259 return findUsersOrGroupsHavingAssignedGroupOrRoleWithUid(session, principalNode, ROLES_NODE_NAME);
260 }
261
262 @Override
263 public String toString() {
264 return "get group with role " + roleName;
265 }
266 });
267 }
268
269 @Override
270 public Group removeGroup(Group group, String groupName) throws AccessDeniedException {
271 try {
272 super.remove(group.getName(), groupName, NODE_GROUPS);
273 } catch (PrincipalNotFoundException e) {
274 throw new IllegalArgumentException("group doesn't exist in this GM" + e);
275 }
276 return getGroup(group.getName());
277 }
278
279 @Override
280 public Group removeRole(Group group, String roleName) throws AccessDeniedException {
281 try {
282 super.remove(group.getName(), roleName, NODE_ROLES);
283 } catch (PrincipalNotFoundException e) {
284 throw new IllegalArgumentException("role doesn't exist in this GM" + e);
285 }
286 return getGroup(group.getName());
287 }
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 public Collection<String> getAllSuperGroups(final String groupName) throws UnsupportedOperationException {
304 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
305
306 List<String> groups;
307
308 @Override
309 public Collection<String> doExec(Session session) throws RepositoryException {
310 Group group = getGroup(groupName);
311 if (group == null) {
312 return null;
313 }
314 groups = new ArrayList<>();
315 collectSuperGroups(group);
316
317 return groups;
318 }
319
320
321
322
323 private void collectSuperGroups(Group group) throws AccessDeniedException {
324 for (String superGroupName : group.getGroups()) {
325 Group superGroup = getGroup(superGroupName);
326 if (superGroup != null && !groups.contains(superGroup.getName())) {
327 groups.add(superGroup.getName());
328 collectSuperGroups(superGroup);
329 }
330 }
331 }
332
333 @Override
334 public String toString() {
335 return "get all super groups";
336 }
337 });
338 }
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 public Collection<String> getAllSubGroups(final String groupName) throws UnsupportedOperationException {
355
356 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
357
358 List<String> allSubGroupNames;
359
360 @Override
361 public Collection<String> doExec(Session session) throws RepositoryException {
362 allSubGroupNames = new ArrayList<>();
363 collectSubGroups(groupName);
364 return allSubGroupNames;
365 }
366
367
368
369
370 private void collectSubGroups(String groupName) throws AccessDeniedException {
371 Collection<String> allSubGroups = getGroupsWithGroup(groupName);
372 for (String subGroup : allSubGroups) {
373
374 if (!allSubGroupNames.contains(subGroup)) {
375 allSubGroupNames.add(subGroup);
376 collectSubGroups(subGroup);
377 }
378 }
379 }
380
381 @Override
382 public String toString() {
383 return "get all sub groups";
384 }
385 });
386 }
387 }