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