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