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