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.security.app.dialog.field;
35
36 import info.magnolia.cms.core.Path;
37 import info.magnolia.jcr.util.NodeTypes;
38 import info.magnolia.jcr.util.NodeUtil;
39
40 import java.util.Collection;
41 import java.util.LinkedHashMap;
42
43 import javax.jcr.Node;
44 import javax.jcr.RepositoryException;
45
46 import org.apache.commons.lang3.StringUtils;
47
48
49
50
51 public class AccessControlList {
52
53 public static final String PERMISSIONS_PROPERTY_NAME = "permissions";
54 public static final String PATH_PROPERTY_NAME = "path";
55
56 public static final long ACCESS_TYPE_NODE = 1;
57 public static final long ACCESS_TYPE_CHILDREN = 2;
58 public static final long ACCESS_TYPE_NODE_AND_CHILDREN = ACCESS_TYPE_NODE | ACCESS_TYPE_CHILDREN;
59
60
61
62
63 public static final class EntryKey {
64
65 private long permissions;
66 private String path;
67
68 public EntryKey(long permissions, String path) {
69 this.permissions = permissions;
70 this.path = path;
71 }
72
73 @Override
74 public boolean equals(Object o) {
75 if (this == o) return true;
76 if (o == null || getClass() != o.getClass()) return false;
77
78 EntryKey entryKey = (EntryKey) o;
79
80 if (permissions != entryKey.permissions) return false;
81 if (!path.equals(entryKey.path)) return false;
82
83 return true;
84 }
85
86 @Override
87 public int hashCode() {
88 int result = (int) (permissions ^ (permissions >>> 32));
89 result = 31 * result + path.hashCode();
90 return result;
91 }
92 }
93
94
95
96
97 public static class Entry {
98
99 private long permissions;
100 private long accessType;
101 private String path;
102
103 public Entry(long permissions, long accessType, String path) {
104 this.permissions = permissions;
105 this.accessType = accessType;
106 this.path = path;
107 }
108
109 public long getPermissions() {
110 return permissions;
111 }
112
113 public void setPermissions(long permissions) {
114 this.permissions = permissions;
115 }
116
117 public long getAccessType() {
118 return accessType;
119 }
120
121 public void setAccessType(long accessType) {
122 this.accessType = accessType;
123 }
124
125 public String getPath() {
126 return path;
127 }
128
129 public void setPath(String path) {
130 this.path = path;
131 }
132
133 public void merge(Entry entry) {
134 accessType |= entry.getAccessType();
135 }
136
137 public EntryKey createKey() {
138 return new EntryKey(permissions, path);
139 }
140
141 @Override
142 public boolean equals(Object o) {
143 if (this == o) return true;
144 if (!(o instanceof Entry)) return false;
145
146 return createKey().equals(((Entry)o).createKey());
147 }
148
149 @Override
150 public int hashCode() {
151 return createKey().hashCode();
152 }
153 }
154
155 private LinkedHashMap<EntryKey, Entry> entries = new LinkedHashMap<EntryKey, Entry>();
156
157 public Collection<Entry> getEntries() {
158 return entries.values();
159 }
160
161 public void addEntry(Entry entry) {
162 EntryKey key = entry.createKey();
163 Entry existingEntry = entries.get(key);
164 if (existingEntry == null) {
165 entries.put(key, entry);
166 } else {
167 existingEntry.merge(entry);
168 }
169 }
170
171 public void readEntries(Node aclNode) throws RepositoryException {
172 for (Node entryNode : NodeUtil.getNodes(aclNode)) {
173 readEntry(entryNode);
174 }
175 }
176
177 public void readEntry(Node entryNode) throws RepositoryException {
178 addEntry(doGetEntryFromNode(entryNode));
179 }
180
181 public Entry getEntryByNode(Node entryNode) throws RepositoryException {
182 Entry entry = doGetEntryFromNode(entryNode);
183 Entry existingEntry = entries.get(entry.createKey());
184 if (existingEntry != null) {
185 return existingEntry;
186 }
187 return entry;
188 }
189
190 private Entry doGetEntryFromNode(Node entryNode) throws RepositoryException {
191 long permissions = entryNode.getProperty(PERMISSIONS_PROPERTY_NAME).getLong();
192 String path = entryNode.getProperty(PATH_PROPERTY_NAME).getString();
193
194 long accessType;
195
196 if (path.equals("/")) {
197 accessType = ACCESS_TYPE_NODE;
198 } else if (path.equals("/*")) {
199 accessType = ACCESS_TYPE_NODE_AND_CHILDREN;
200 path = "/";
201 } else if (path.endsWith("/*")) {
202 accessType = ACCESS_TYPE_CHILDREN;
203 path = StringUtils.substringBeforeLast(path, "/*");
204 } else {
205 accessType = ACCESS_TYPE_NODE;
206 path = StringUtils.removeEnd(path, "/");
207 }
208
209 return new Entry(permissions, accessType, path);
210 }
211
212 public void saveEntries(Node aclNode) throws RepositoryException {
213 for (Entry entry : entries.values()) {
214
215 Node entryNode = aclNode.addNode(Path.getUniqueLabel(aclNode.getSession(), aclNode.getPath(), "0"), NodeTypes.ContentNode.NAME);
216
217 String path = entry.getPath();
218 long permissions = entry.getPermissions();
219 long accessType = entry.getAccessType();
220
221 if (path.equals("/")) {
222 switch ((int) accessType) {
223 case (int) ACCESS_TYPE_CHILDREN:
224 path = "/*";
225 break;
226 case (int) ACCESS_TYPE_NODE:
227 path = "/";
228 break;
229 case (int) ACCESS_TYPE_NODE_AND_CHILDREN:
230 path = "/*";
231 break;
232 }
233 } else {
234 switch ((int) accessType) {
235 case (int) ACCESS_TYPE_CHILDREN:
236 path += "/*";
237 break;
238 case (int) ACCESS_TYPE_NODE:
239 break;
240 case (int) ACCESS_TYPE_NODE_AND_CHILDREN:
241 String nodeName = Path.getUniqueLabel(aclNode.getSession(), aclNode.getPath(), "0");
242 Node extraEntry = aclNode.addNode(nodeName, NodeTypes.ContentNode.NAME);
243 extraEntry.setProperty(PATH_PROPERTY_NAME, path + "/*");
244 extraEntry.setProperty(PERMISSIONS_PROPERTY_NAME, permissions);
245 break;
246 }
247 }
248
249 entryNode.setProperty(PERMISSIONS_PROPERTY_NAME, permissions);
250 entryNode.setProperty(PATH_PROPERTY_NAME, path);
251 }
252 }
253 }