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 import info.magnolia.cms.security.PrincipalUtil;
39 import info.magnolia.cms.security.auth.ACL;
40 import info.magnolia.cms.util.SimpleUrlPattern;
41 import info.magnolia.objectfactory.Classes;
42 import info.magnolia.objectfactory.MgnlInstantiationException;
43
44 import java.security.Principal;
45 import java.util.LinkedList;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Set;
49
50 import javax.jcr.ItemNotFoundException;
51 import javax.jcr.RepositoryException;
52 import javax.jcr.Session;
53 import javax.jcr.security.AccessControlPolicy;
54
55 import org.apache.jackrabbit.core.ItemImpl;
56 import org.apache.jackrabbit.core.security.authorization.AccessControlEditor;
57 import org.apache.jackrabbit.core.security.authorization.CompiledPermissions;
58 import org.apache.jackrabbit.core.security.authorization.combined.CombinedProvider;
59 import org.apache.jackrabbit.spi.Path;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63
64
65
66
67
68
69
70 public class MagnoliaAccessProvider extends CombinedProvider {
71
72 private static final Logger log = LoggerFactory.getLogger(MagnoliaAccessProvider.class);
73
74 private CompiledPermissions RootOnlyPermission;
75
76 private Map<?, ?> configuration;
77
78 private final Class<? extends DefaultACLBasedPermissions> defaultPermissionsClass = DefaultACLBasedPermissions.class;
79
80 private Class<? extends DefaultACLBasedPermissions> permissionsClass;
81
82 private final String compiledPermissionsClass = null;
83
84 @Override
85 public boolean canAccessRoot(Set<Principal> principals) throws RepositoryException {
86 checkInitialized();
87
88
89 return true;
90 }
91
92 @Override
93 public void close() {
94 log.debug("close()");
95 super.close();
96 }
97
98 @Override
99 public CompiledPermissions compilePermissions(Set<Principal> principals) throws RepositoryException {
100 log.debug("compile permissions for {} at {}", printUserNames(principals), session == null ? null : session.getWorkspace().getName());
101 checkInitialized();
102
103
104 if (isAdminOrSystem(principals)) {
105 return getAdminPermissions();
106 }
107
108 final String workspaceName = super.session.getWorkspace().getName();
109
110 ACL acl = PrincipalUtil.findAccessControlList(principals, workspaceName);
111 if (acl != null) {
112 return getUserPermissions(addJcrSystemReadPermissions(acl.getList()));
113 }
114
115 return RootOnlyPermission;
116 }
117
118 private CompiledPermissions getUserPermissions(List<Permission> permissions) {
119 return Classes.getClassFactory().newInstance(permissionsClass, permissions, session, configuration);
120 }
121
122 @Override
123 public AccessControlEditor getEditor(Session editingSession) {
124 log.debug("getEditor({})", editingSession);
125 return new MagnoliaACLEditor(super.getEditor(editingSession));
126 }
127
128 @Override
129 public AccessControlPolicy[] getEffectivePolicies(Path absPath, CompiledPermissions permissions) throws ItemNotFoundException, RepositoryException {
130 log.debug("getEffectivePolicies({}, {})", absPath, permissions);
131 return super.getEffectivePolicies(absPath, permissions);
132 }
133
134 @Override
135 public AccessControlPolicy[] getEffectivePolicies(Set<Principal> principals, CompiledPermissions permissions) throws RepositoryException {
136 log.debug("getEffectivePolicies({}, {})", principals, permissions);
137 return super.getEffectivePolicies(principals, permissions);
138 }
139
140 private final String warnMessage = "Check settings of 'permissionsClass' parameter under Workspace>WorkspaceSecurity>AccessControlProvider>. "
141 + "Using default " + defaultPermissionsClass + " instead. Only classes extended from this default class can be used.";
142
143 @Override
144 public void init(Session systemSession, Map configuration) throws RepositoryException {
145
146 log.debug("init({}, {})", systemSession, configuration);
147 super.init(systemSession, configuration);
148 RootOnlyPermission = new RootOnlyPermissions(session);
149 this.configuration = configuration;
150
151 Object compiledPermissionsClass = configuration.get("permissionsClass");
152 if (compiledPermissionsClass == null) {
153 permissionsClass = defaultPermissionsClass;
154 return;
155 }
156 try {
157 permissionsClass = Classes.getClassFactory().forName((String) compiledPermissionsClass);
158 if (!DefaultACLBasedPermissions.class.isAssignableFrom(permissionsClass)) {
159 log.warn("The '{}' cannot be used as permissionClass. " + warnMessage, permissionsClass, defaultPermissionsClass);
160 permissionsClass = defaultPermissionsClass;
161 } else {
162 Classes.getClassFactory().newInstance(permissionsClass, new LinkedList<Permission>(), session, configuration);
163 log.info("Using {} for resolving permissions.", permissionsClass);
164 }
165 } catch (ClassNotFoundException e) {
166 log.warn("The class '{}' doesn't exist. " + warnMessage, compiledPermissionsClass, defaultPermissionsClass);
167 permissionsClass = defaultPermissionsClass;
168
169 } catch (MgnlInstantiationException e) {
170 log.warn(
171 "Cannot instantiate '{}'. The permissionClass must have constructor with exact same arguments like '{}'. Using the default permission class '{}' instead.",
172 permissionsClass, defaultPermissionsClass);
173 permissionsClass = defaultPermissionsClass;
174
175 } catch (Exception e) {
176
177 log.warn("Cannot instantiate permissionsClass '{}'. " + warnMessage, permissionsClass, e);
178 permissionsClass = defaultPermissionsClass;
179 }
180 }
181
182 @Override
183 public boolean isAcItem(ItemImpl item) throws RepositoryException {
184 log.debug("isAcItem({})", item);
185 return super.isAcItem(item);
186 }
187
188 @Override
189 public boolean isAcItem(Path absPath) throws RepositoryException {
190 log.debug("isAcItem({})", absPath);
191 return super.isAcItem(absPath);
192 }
193
194 private String printUserNames(Set<Principal> principals) {
195 StringBuilder sb = new StringBuilder();
196 for (Principal p : principals) {
197 sb.append(" or ").append(p.getName()).append("[").append(p.getClass().getName()).append("]");
198 }
199 sb.delete(0, 4);
200 return sb.toString();
201 }
202
203 private List<Permission> addJcrSystemReadPermissions(List<Permission> permissions) {
204 Permission permission = new PermissionImpl();
205 permission.setPattern(new SimpleUrlPattern("/jcr:system"));
206 permission.setPermissions(Permission.READ);
207 permissions.add(permission);
208 permission = new PermissionImpl();
209 permission.setPattern(new SimpleUrlPattern("/jcr:system/*"));
210 permission.setPermissions(Permission.READ);
211 permissions.add(permission);
212 return permissions;
213 }
214 }