]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
6b58c6f6903fcec70f7b0e5d8174d4f45be264e3
[lgpl/argeo-commons.git] / security / runtime / org.argeo.security.jackrabbit / src / main / java / org / argeo / security / jackrabbit / ArgeoSecurityManager.java
1 package org.argeo.security.jackrabbit;
2
3 import java.security.Principal;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.Set;
8
9 import javax.jcr.AccessDeniedException;
10 import javax.jcr.Node;
11 import javax.jcr.PathNotFoundException;
12 import javax.jcr.RepositoryException;
13 import javax.jcr.Session;
14 import javax.jcr.UnsupportedRepositoryOperationException;
15 import javax.jcr.lock.LockException;
16 import javax.jcr.security.AccessControlException;
17 import javax.jcr.security.AccessControlList;
18 import javax.jcr.security.AccessControlManager;
19 import javax.jcr.security.AccessControlPolicy;
20 import javax.jcr.security.AccessControlPolicyIterator;
21 import javax.jcr.security.Privilege;
22 import javax.jcr.version.VersionException;
23 import javax.security.auth.Subject;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.jackrabbit.api.security.user.Group;
28 import org.apache.jackrabbit.api.security.user.User;
29 import org.apache.jackrabbit.api.security.user.UserManager;
30 import org.apache.jackrabbit.core.DefaultSecurityManager;
31 import org.apache.jackrabbit.core.security.SecurityConstants;
32 import org.apache.jackrabbit.core.security.SystemPrincipal;
33 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
34 import org.argeo.ArgeoException;
35 import org.argeo.jcr.JcrUtils;
36 import org.springframework.security.Authentication;
37 import org.springframework.security.GrantedAuthority;
38
39 /** Intermediary class in order to have a consistent naming in config files. */
40 public class ArgeoSecurityManager extends DefaultSecurityManager {
41 private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
42
43 @Override
44 /** Since this is called once when the session is created, we take the opportunity to synchronize Spring and Jackrabbit users and groups.*/
45 public String getUserID(Subject subject, String workspaceName)
46 throws RepositoryException {
47 long begin = System.currentTimeMillis();
48
49 if (!subject.getPrincipals(SystemPrincipal.class).isEmpty())
50 return super.getUserID(subject, workspaceName);
51
52 Authentication authen;
53 Set<Authentication> authens = subject
54 .getPrincipals(Authentication.class);
55 if (authens.size() == 0)
56 throw new ArgeoException("No Spring authentication found in "
57 + subject);
58 else
59 authen = authens.iterator().next();
60
61 UserManager systemUm = getSystemUserManager(workspaceName);
62
63 String userId = authen.getName();
64 User user = (User) systemUm.getAuthorizable(userId);
65 if (user == null) {
66 user = systemUm.createUser(userId, authen.getCredentials()
67 .toString(), authen, null);
68 log.info(userId + " added as " + user);
69 }
70
71 setHomeNodeAuthorizations(user);
72
73 // process groups
74 List<String> userGroupIds = new ArrayList<String>();
75 for (GrantedAuthority ga : authen.getAuthorities()) {
76 Group group = (Group) systemUm.getAuthorizable(ga.getAuthority());
77 if (group == null) {
78 group = systemUm.createGroup(ga.getAuthority());
79 log.info(ga.getAuthority() + " added as " + group);
80 }
81 if (!group.isMember(user))
82 group.addMember(user);
83 userGroupIds.add(ga.getAuthority());
84
85 }
86
87 // check if user has not been removed from some groups
88 for (Iterator<Group> it = user.declaredMemberOf(); it.hasNext();) {
89 Group group = it.next();
90 if (!userGroupIds.contains(group.getID()))
91 group.removeMember(user);
92 }
93
94 if (log.isTraceEnabled())
95 log.trace("Spring and Jackrabbit Security synchronized for user "
96 + userId + " in " + (System.currentTimeMillis() - begin)
97 + " ms");
98 return userId;
99 }
100
101 protected void setHomeNodeAuthorizations(User user) {
102 // give all privileges on user home
103 // FIXME: fails on an empty repo
104 String userId = "<not yet set>";
105 try {
106 userId = user.getID();
107 Node userHome = JcrUtils.getUserHome(getSystemSession(), userId);
108 if (userHome != null) {
109 String path = userHome.getPath();
110 AccessControlPolicy policy = null;
111 AccessControlManager acm = getSystemSession()
112 .getAccessControlManager();
113 AccessControlPolicyIterator policyIterator = acm
114 .getApplicablePolicies(path);
115 if (policyIterator.hasNext()) {
116 policy = policyIterator.nextAccessControlPolicy();
117 } else {
118 AccessControlPolicy[] existingPolicies = acm
119 .getPolicies(path);
120 policy = existingPolicies[0];
121 }
122 if (policy instanceof AccessControlList) {
123 Privilege[] privileges = { acm
124 .privilegeFromName(Privilege.JCR_ALL) };
125 ((AccessControlList) policy).addAccessControlEntry(
126 user.getPrincipal(), privileges);
127 acm.setPolicy(path, policy);
128 }
129 }
130 } catch (Exception e) {
131 log.warn("Cannot set authorization on user node for " + userId
132 + ": " + e.getMessage());
133 }
134
135 }
136
137 @Override
138 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
139 WorkspaceAccessManager wam = super
140 .createDefaultWorkspaceAccessManager();
141 return new ArgeoWorkspaceAccessManagerImpl(wam);
142 }
143
144 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
145 WorkspaceAccessManager {
146 private final WorkspaceAccessManager wam;
147
148 // private String defaultWorkspace;
149
150 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
151 super();
152 this.wam = wam;
153 }
154
155 public void init(Session systemSession) throws RepositoryException {
156 wam.init(systemSession);
157 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
158 // .getDefaultWorkspaceName();
159 }
160
161 public void close() throws RepositoryException {
162 }
163
164 public boolean grants(Set<Principal> principals, String workspaceName)
165 throws RepositoryException {
166 // everybody has access to all workspaces
167 // TODO: implements finer access to workspaces
168 return true;
169
170 // anonymous has access to the default workspace (required for
171 // remoting which does a default login when initializing the
172 // repository)
173 // Boolean anonymous = false;
174 // for (Principal principal : principals)
175 // if (principal instanceof AnonymousPrincipal)
176 // anonymous = true;
177 //
178 // if (anonymous && workspaceName.equals(defaultWorkspace))
179 // return true;
180 // else
181 // return wam.grants(principals, workspaceName);
182 }
183 }
184
185 }