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
97 public NodeTypeBasedPermissions(List<Permission> permissions, SessionImpl session, Map<?, ?> configuration) {
98 super(permissions, session, configuration);
99 String nodeTypes = (String) configuration.get("nodeTypes");
100
101 if (nodeTypes != null) {
102 String[] splittedTypes = nodeTypes.split(",");
103 for (String type : splittedTypes) {
104 allowedNodeTypes.add(type);
105 }
106 }
107 }
108
109 @Override
110 public boolean canRead(Path itemPath, ItemId itemId) throws RepositoryException {
111
112 if ((itemId != null && "cafebabe-cafe-babe-cafe-babecafebabe".equals(itemId.toString())) || (itemPath != null && "/".equals(itemPath.toString()))) {
113
114 return true;
115 }
116
117 if (itemPath == null) {
118
119
120 if (!itemId.denotesNode()) {
121 itemId = ((PropertyId) itemId).getParentId();
122 }
123
124 synchronized (monitor) {
125
126 if (readCache.containsKey(itemId)) {
127 return readCache.get(itemId);
128 }
129
130 itemPath = session.getHierarchyManager().getPath(itemId);
131 boolean canRead = canRead(itemPath, itemId);
132 readCache.put(itemId, canRead);
133 return canRead;
134 }
135 }
136
137 String originalPath = pathResolver.getJCRPath(itemPath);
138 int emersion = getEmersion(originalPath);
139 String path = pathResolver.getJCRPath(itemPath.getAncestor(emersion));
140
141 log.debug("Read request for {} :: {}. The permissions will be retrieved from ancestor path: {}.", originalPath, itemId, path);
142 return ami.isGranted(path, Permission.READ);
143 }
144
145 @Override
146 public boolean grants(Path itemPath, int permissions) throws RepositoryException {
147
148 long magnoliaPermissions = convertJackrabbitPermissionsToMagnoliaPermissions(permissions);
149 String originalPath = pathResolver.getJCRPath(itemPath);
150 int emersion = getEmersion(originalPath);
151 String path = pathResolver.getJCRPath(itemPath.getAncestor(emersion));
152
153 log.debug("{} permission request for {}. The permissions will be retrieved from ancestor path: {}.", PermissionImpl.getPermissionAsName(permissions), originalPath, 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 }