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 getDirectSubGroups(groupName);
237 }
238
239 @Override
240 public Collection<String> getDirectSubGroups(String groupName) {
241 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
242
243 @Override
244 public Collection<String> doExec(Session session) throws RepositoryException {
245 final Node groupNode = findPrincipalNode(groupName, session);
246 return findUsersOrGroupsHavingAssignedGroupOrRoleWithUid(session, groupNode, GROUPS_NODE_NAME);
247 }
248
249 @Override
250 public String toString() {
251 return "get direct sub groups " + groupName;
252 }
253 });
254 }
255
256 @Override
257 public Collection<String> getDirectSuperGroups(String groupName) {
258 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
259
260 @Override
261 public Collection<String> doExec(Session session) throws RepositoryException {
262 Group group = getGroup(groupName);
263 return group != null ? group.getGroups() : new ArrayList<>();
264 }
265
266 @Override
267 public String toString() {
268 return "get direct super groups " + groupName;
269 }
270 });
271 }
272
273 @Override
274 public Collection<String> getGroupsWithRole(final String roleName) {
275 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
276
277 @Override
278 public Collection<String> doExec(Session session) throws RepositoryException {
279 final Node principalNode = findPrincipalNode(roleName, MgnlContext.getJCRSession(RepositoryConstants.USER_ROLES), NodeTypes.Role.NAME);
280 return findUsersOrGroupsHavingAssignedGroupOrRoleWithUid(session, principalNode, ROLES_NODE_NAME);
281 }
282
283 @Override
284 public String toString() {
285 return "get group with role " + roleName;
286 }
287 });
288 }
289
290 @Override
291 public Group removeGroup(Group group, String groupName) throws AccessDeniedException {
292 try {
293 super.remove(group.getName(), groupName, NODE_GROUPS);
294 } catch (PrincipalNotFoundException e) {
295 throw new IllegalArgumentException("group doesn't exist in this GM" + e);
296 }
297 return getGroup(group.getName());
298 }
299
300 @Override
301 public Group removeRole(Group group, String roleName) throws AccessDeniedException {
302 try {
303 super.remove(group.getName(), roleName, NODE_ROLES);
304 } catch (PrincipalNotFoundException e) {
305 throw new IllegalArgumentException("role doesn't exist in this GM" + e);
306 }
307 return getGroup(group.getName());
308 }
309
310 @Override
311 public Collection<String> getAllSuperGroups(final String groupName) throws UnsupportedOperationException {
312 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
313
314 List<String> groups;
315
316 @Override
317 public Collection<String> doExec(Session session) throws RepositoryException {
318 Group group = getGroup(groupName);
319 if (group == null) {
320 return null;
321 }
322 groups = new ArrayList<>();
323 collectSuperGroups(group);
324
325 return groups;
326 }
327
328
329
330
331 private void collectSuperGroups(Group group) throws AccessDeniedException {
332 for (String superGroupName : group.getGroups()) {
333 Group superGroup = getGroup(superGroupName);
334 if (superGroup != null && !groups.contains(superGroup.getName())) {
335 groups.add(superGroup.getName());
336 collectSuperGroups(superGroup);
337 }
338 }
339 }
340
341 @Override
342 public String toString() {
343 return "get all super groups";
344 }
345 });
346 }
347
348 @Override
349 public Collection<String> getAllSubGroups(final String groupName) throws UnsupportedOperationException {
350
351 return MgnlContext.doInSystemContext(new SilentSessionOp<Collection<String>>(getRepositoryName()) {
352
353 List<String> allSubGroupNames;
354
355 @Override
356 public Collection<String> doExec(Session session) throws RepositoryException {
357 allSubGroupNames = new ArrayList<>();
358 collectSubGroups(groupName);
359 return allSubGroupNames;
360 }
361
362
363
364
365 private void collectSubGroups(String groupName) throws AccessDeniedException {
366 Collection<String> allSubGroups = getDirectSubGroups(groupName);
367 for (String subGroup : allSubGroups) {
368
369 if (!allSubGroupNames.contains(subGroup)) {
370 allSubGroupNames.add(subGroup);
371 collectSubGroups(subGroup);
372 }
373 }
374 }
375
376 @Override
377 public String toString() {
378 return "get all sub groups";
379 }
380 });
381 }
382 }