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.endsWith("/*")) {
197 accessType = ACCESS_TYPE_CHILDREN;
198 path = path.equals("/*") ? "/" : StringUtils.substringBeforeLast(path, "/*");
199 } else {
200 accessType = ACCESS_TYPE_NODE;
201 path = path.equals("/") ? path : StringUtils.removeEnd(path, "/");
202 }
203
204 return new Entry(permissions, accessType, path);
205 }
206
207 public void saveEntries(Node aclNode) throws RepositoryException {
208 for (Entry entry : entries.values()) {
209
210 Node entryNode = aclNode.addNode(Path.getUniqueLabel(aclNode.getSession(), aclNode.getPath(), "0"), NodeTypes.ContentNode.NAME);
211
212 String path = entry.getPath();
213 long permissions = entry.getPermissions();
214 long accessType = entry.getAccessType();
215
216 String suffixForChildren = path.equals("/") ? "*" : "/*";
217 switch ((int) accessType) {
218 case (int) ACCESS_TYPE_CHILDREN:
219 path += suffixForChildren;
220 break;
221 case (int) ACCESS_TYPE_NODE_AND_CHILDREN:
222 String nodeName = Path.getUniqueLabel(aclNode.getSession(), aclNode.getPath(), "0");
223 Node extraEntry = aclNode.addNode(nodeName, NodeTypes.ContentNode.NAME);
224 extraEntry.setProperty(PATH_PROPERTY_NAME, path + suffixForChildren);
225 extraEntry.setProperty(PERMISSIONS_PROPERTY_NAME, permissions);
226 break;
227 }
228
229 entryNode.setProperty(PERMISSIONS_PROPERTY_NAME, permissions);
230 entryNode.setProperty(PATH_PROPERTY_NAME, path);
231 }
232 }
233 }