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 {} :: {}. The permissions will be retrieved from ancestor path: {}.", originalPath, itemId, 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("{} permission request for {}. The permissions will be retrieved from ancestor path: {}.", PermissionImpl.getPermissionAsName(permissions), originalPath, path);
153 return ami.isGranted(path, magnoliaPermissions);
154 }
155
156 private int getEmersion(String originalPath) throws AccessDeniedException, RepositoryException {
157 int emersion = 0;
158
159 if (session.nodeExists(originalPath)) {
160 Node node = session.getNode(originalPath);
161 try {
162 while (!isAllowedNodeType(node)) {
163 node = node.getParent();
164 emersion++;
165 }
166 } catch (ItemNotFoundException e) {
167 return 0;
168 }
169 }
170 return emersion;
171 }
172
173 private boolean isAllowedNodeType(Node node) throws RepositoryException {
174 if (allowedNodeTypes.isEmpty()) {
175 return true;
176 }
177 for(String nodeType: allowedNodeTypes) {
178 if (node.isNodeType(nodeType)) {
179 return true;
180 }
181 }
182 return false;
183 }
184 }