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 info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.HierarchyManager;
38 import info.magnolia.context.MgnlContext;
39 import info.magnolia.jcr.iterator.SameChildNodeTypeIterator;
40 import info.magnolia.jcr.util.NodeNameHelper;
41 import info.magnolia.jcr.util.NodeTypes;
42 import info.magnolia.repository.RepositoryConstants;
43
44 import javax.inject.Inject;
45 import javax.jcr.Node;
46 import javax.jcr.NodeIterator;
47 import javax.jcr.PathNotFoundException;
48 import javax.jcr.RepositoryException;
49 import javax.jcr.Session;
50
51 import org.apache.commons.lang3.StringUtils;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55
56
57
58
59 public class MgnlRoleManager extends RepositoryBackedSecurityManager implements RoleManager {
60
61 public static final String NODE_ACLROLES = "acl_userroles";
62
63 private static final Logger log = LoggerFactory.getLogger(MgnlRoleManager.class);
64
65 @Inject
66 public MgnlRoleManager(NodeNameHelper nodeNameHelper) {
67 super(nodeNameHelper);
68 }
69
70
71
72
73 @Deprecated
74 public MgnlRoleManager() {
75 }
76
77 @Override
78 public Role getRole(final String name) {
79 return MgnlContext.doInSystemContext(new SilentSessionOp<MgnlRole>(getRepositoryName()) {
80
81 @Override
82 public MgnlRole doExec(Session session) throws RepositoryException {
83 Node roleNode = findPrincipalNode(name, MgnlContext.getJCRSession(getRepositoryName()));
84 if (roleNode == null) {
85 log.debug("can't find role [{}]", name);
86 return null;
87 }
88 return newRoleInstance(roleNode);
89 }
90
91 @Override
92 public String toString() {
93 return "get role " + name;
94 }
95 });
96 }
97
98 @Override
99 public Role createRole(String name) throws AccessDeniedException {
100 return createRole(null, name);
101 }
102
103
104
105
106
107
108
109 @Override
110 public Role createRole(final String path, final String name) throws AccessDeniedException {
111 validateRoleName(name);
112 return MgnlContext.doInSystemContext(new SilentSessionOp<MgnlRole>(getRepositoryName()) {
113
114 @Override
115 public MgnlRole doExec(Session session) throws RepositoryException {
116 String parentPath = StringUtils.defaultString(path, "/");
117 Node roleNode = session.getNode(parentPath).addNode(name, NodeTypes.Role.NAME);
118 final Node acls = roleNode.addNode(NODE_ACLROLES, NodeTypes.ContentNode.NAME);
119
120 Node acl = acls.addNode(nodeNameHelper.getUniqueName(session, acls.getPath(), "0"), NodeTypes.ContentNode.NAME);
121 acl.setProperty("path", roleNode.getPath());
122 acl.setProperty("permissions", Permission.READ);
123
124 session.save();
125 return newRoleInstance(roleNode);
126 }
127
128 @Override
129 public String toString() {
130 return "create role " + name;
131 }
132 });
133 }
134
135
136
137
138 @Deprecated
139 protected MgnlRole newRoleInstance(Content node) throws RepositoryException {
140 return newRoleInstance(node.getJCRNode());
141 }
142
143 protected MgnlRole newRoleInstance(Node node) throws RepositoryException {
144 return new MgnlRole(node.getName(), node.getIdentifier(), getACLs(node).values());
145 }
146
147
148
149
150 @Deprecated
151 protected HierarchyManager getHierarchyManager() {
152 return MgnlContext.getHierarchyManager(RepositoryConstants.USER_ROLES);
153 }
154
155 @Override
156 public void removePermission(final Role role, final String workspace, final String path, final long permission) {
157 MgnlContext.doInSystemContext(new SilentSessionOp<Object>(getRepositoryName()) {
158
159 @Override
160 public Object doExec(Session session) throws Throwable {
161 Node roleNode = session.getNodeByIdentifier(role.getId());
162 Node aclNode = getAclNode(roleNode, workspace);
163 NodeIterator children = new SameChildNodeTypeIterator(aclNode);
164 while (children.hasNext()) {
165 Node child = children.nextNode();
166 if (child.getProperty("path").getString().equals(path)) {
167 if (permission == MgnlRole.PERMISSION_ANY || child.getProperty("permissions").getLong() == permission) {
168 child.remove();
169 }
170 }
171 }
172 session.save();
173 return null;
174 }
175
176 @Override
177 public String toString() {
178 return "add permission to role " + role.getName();
179 }
180 });
181 }
182
183
184
185
186 private Node getAclNode(Node roleNode, String repository) throws RepositoryException, PathNotFoundException,
187 AccessDeniedException {
188 Node aclNode;
189 if (!roleNode.hasNode("acl_" + repository)) {
190 aclNode = roleNode.addNode("acl_" + repository, NodeTypes.ContentNode.NAME);
191 } else {
192 aclNode = roleNode.getNode("acl_" + repository);
193 }
194 return aclNode;
195 }
196
197
198
199
200 private boolean existsPermission(Node aclNode, String path, long permission) throws RepositoryException {
201 NodeIterator children = aclNode.getNodes();
202 while (children.hasNext()) {
203 Node child = children.nextNode();
204 if (child.hasProperty("path") && child.getProperty("path").getString().equals(path)) {
205 if (permission == MgnlRole.PERMISSION_ANY
206 || child.getProperty("permissions").getLong() == permission) {
207 return true;
208 }
209 }
210 }
211 return false;
212 }
213
214 @Override
215 public void addPermission(final Role role, final String workspace, final String path, final long permission) {
216 MgnlContext.doInSystemContext(new SilentSessionOp<Object>(getRepositoryName()) {
217
218 @Override
219 public Object doExec(Session session) throws Throwable {
220 Node roleNode = session.getNodeByIdentifier(role.getId());
221 Node aclNode = getAclNode(roleNode, workspace);
222 if (!existsPermission(aclNode, path, permission)) {
223 String nodeName = nodeNameHelper.getUniqueName(session, aclNode.getPath(), "0");
224 Node node = aclNode.addNode(nodeName, NodeTypes.ContentNode.NAME);
225 node.setProperty("path", path);
226 node.setProperty("permissions", permission);
227 session.save();
228 }
229 return null;
230 }
231
232 @Override
233 public String toString() {
234 return "remove permission from role " + role.getName();
235 }
236 });
237 }
238
239
240
241
242
243 @Override
244 protected Node findPrincipalNode(String principalName, Session session) throws RepositoryException {
245 return findPrincipalNode(principalName, session, NodeTypes.Role.NAME);
246 }
247
248 @Override
249 protected String getRepositoryName() {
250 return RepositoryConstants.USER_ROLES;
251 }
252
253 @Override
254 public String getRoleNameById(String string) {
255 return getResourceName(string);
256 }
257
258 protected void validateRoleName(String name) throws AccessDeniedException {
259 if (StringUtils.isBlank(name)) {
260 throw new IllegalArgumentException(name + " is not a valid role name.");
261 }
262
263 Role role = Security.getRoleManager().getRole(name);
264
265 if (role != null) {
266 throw new IllegalArgumentException("Role with name " + name + " already exists.");
267 }
268 }
269 }