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.core;
35
36 import info.magnolia.cms.security.Permission;
37 import info.magnolia.cms.security.PermissionImpl;
38
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Set;
43
44 import javax.jcr.AccessDeniedException;
45 import javax.jcr.ItemNotFoundException;
46 import javax.jcr.NamespaceException;
47 import javax.jcr.Node;
48 import javax.jcr.RepositoryException;
49
50 import org.apache.jackrabbit.core.SessionImpl;
51 import org.apache.jackrabbit.core.id.ItemId;
52 import org.apache.jackrabbit.core.id.PropertyId;
53 import org.apache.jackrabbit.spi.Name;
54 import org.apache.jackrabbit.spi.Path;
55 import org.apache.jackrabbit.spi.commons.conversion.CachingPathResolver;
56 import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
57 import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
58 import org.apache.jackrabbit.spi.commons.conversion.ParsingPathResolver;
59 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63
64
65
66
67
68 public class NodeTypeBasedPermissions extends DefaultACLBasedPermissions {
69
70 private final Set<String> allowedNodeTypes = new HashSet<String>();
71
72 private static final Logger log = LoggerFactory.getLogger(NodeTypeBasedPermissions.class);
73
74
75
76
77 private final PathResolver pathResolver = new CachingPathResolver(new ParsingPathResolver(null, new NameResolver() {
78
79 @Override
80 public Name getQName(String name) throws IllegalNameException, NamespaceException {
81 throw new UnsupportedOperationException();
82 }
83
84 @Override
85 public String getJCRName(Name name) throws NamespaceException {
86 return name.getLocalName();
87 }
88 }));
89
90
91
92
93
94
95
96 public NodeTypeBasedPermissions(List<Permission> permissions, SessionImpl session, Map<?, ?> configuration) {
97 super(permissions,session, configuration);
98 String nodeTypes = (String)configuration.get("nodeTypes");
99
100 if (nodeTypes != null) {
101 String[] splittedTypes = nodeTypes.split(",");
102 for (String type: splittedTypes) {
103 allowedNodeTypes.add(type);
104 }
105 }
106 }
107
108 @Override
109 public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
110
111 if ((itemId != null && "cafebabe-cafe-babe-cafe-babecafebabe".equals(itemId.toString())) || (itemPath != null && "/".equals(itemPath.toString()))) {
112
113 return true;
114 }
115
116 if (itemPath == null) {
117
118
119 if (!itemId.denotesNode()) {
120 itemId = ((PropertyId)itemId).getParentId();
121 }
122
123 synchronized (monitor) {
124
125 if (readCache.containsKey(itemId)) {
126 return readCache.get(itemId);
127 }
128
129 itemPath = session.getHierarchyManager().getPath(itemId);
130 boolean canRead = canRead(itemPath, itemId);
131 readCache.put(itemId, canRead);
132 return canRead;
133 }
134 }
135
136 String originalPath = pathResolver.getJCRPath(itemPath);
137 int emersion = getEmersion(originalPath);
138 String path = pathResolver.getJCRPath(itemPath.getAncestor(emersion));
139
140 log.debug("Read request for " + originalPath + " :: " + itemId + ". The permissions will be retrieved from ancestor path: " + path + ".");
141 return ami.isGranted(path, Permission.READ);
142 }
143
144 @Override
145 public boolean grants(Path itemPath, int permissions) throws RepositoryException {
146
147 long magnoliaPermissions = convertJackrabbitPermissionsToMagnoliaPermissions(permissions);
148 String originalPath = pathResolver.getJCRPath(itemPath);
149 int emersion = getEmersion(originalPath);
150 String path = pathResolver.getJCRPath(itemPath.getAncestor(emersion));
151
152 log.debug(PermissionImpl.getPermissionAsName(permissions) + "permission request for " + originalPath +
153 ". The permissions will be retrieved from ancestor path: " + path + ".");
154 return ami.isGranted(path, magnoliaPermissions);
155 }
156
157 private int getEmersion(String originalPath) throws AccessDeniedException, RepositoryException {
158 int emersion = 0;
159
160 if (session.nodeExists(originalPath)) {
161 Node node = session.getNode(originalPath);
162 try {
163 while (!isAllowedNodeType(node)) {
164 node = node.getParent();
165 emersion++;
166 }
167 } catch (ItemNotFoundException e) {
168 return 0;
169 }
170 }
171 return emersion;
172 }
173
174 private boolean isAllowedNodeType(Node node) throws RepositoryException {
175 if (allowedNodeTypes.isEmpty()) {
176 return true;
177 }
178 for(String nodeType: allowedNodeTypes) {
179 if (node.isNodeType(nodeType)) {
180 return true;
181 }
182 }
183 return false;
184 }
185 }