]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Working JCR based preferences
[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.HashMap;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import javax.jcr.Node;
12 import javax.jcr.PropertyType;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15 import javax.jcr.Value;
16 import javax.jcr.ValueFactory;
17 import javax.jcr.security.AccessControlPolicy;
18 import javax.jcr.security.AccessControlPolicyIterator;
19 import javax.jcr.security.Privilege;
20 import javax.security.auth.Subject;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
25 import org.apache.jackrabbit.api.security.JackrabbitAccessControlManager;
26 import org.apache.jackrabbit.api.security.JackrabbitAccessControlPolicy;
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 public final static String HOME_BASE_PATH = "/home";
42
43 private Log log = LogFactory.getLog(ArgeoSecurityManager.class);
44
45 @Override
46 /** Since this is called once when the session is created, we take the opportunity to synchronize Spring and Jackrabbit users and groups.*/
47 public String getUserID(Subject subject, String workspaceName)
48 throws RepositoryException {
49 long begin = System.currentTimeMillis();
50
51 if (!subject.getPrincipals(SystemPrincipal.class).isEmpty())
52 return super.getUserID(subject, workspaceName);
53
54 Authentication authen;
55 Set<Authentication> authens = subject
56 .getPrincipals(Authentication.class);
57 if (authens.size() == 0)
58 throw new ArgeoException("No Spring authentication found in "
59 + subject);
60 else
61 authen = authens.iterator().next();
62
63 UserManager systemUm = getSystemUserManager(workspaceName);
64
65 String userId = authen.getName();
66 User user = (User) systemUm.getAuthorizable(userId);
67 if (user == null) {
68 user = systemUm.createUser(userId, authen.getCredentials()
69 .toString(), authen, null);
70 log.info(userId + " added as " + user);
71 }
72
73 setHomeNodeAuthorizations(user);
74
75 // process groups
76 List<String> userGroupIds = new ArrayList<String>();
77 for (GrantedAuthority ga : authen.getAuthorities()) {
78 Group group = (Group) systemUm.getAuthorizable(ga.getAuthority());
79 if (group == null) {
80 group = systemUm.createGroup(ga.getAuthority());
81 log.info(ga.getAuthority() + " added as " + group);
82 }
83 if (!group.isMember(user))
84 group.addMember(user);
85 userGroupIds.add(ga.getAuthority());
86
87 }
88
89 // check if user has not been removed from some groups
90 for (Iterator<Group> it = user.declaredMemberOf(); it.hasNext();) {
91 Group group = it.next();
92 if (!userGroupIds.contains(group.getID()))
93 group.removeMember(user);
94 }
95
96 if (log.isTraceEnabled())
97 log.trace("Spring and Jackrabbit Security synchronized for user "
98 + userId + " in " + (System.currentTimeMillis() - begin)
99 + " ms");
100 return userId;
101 }
102
103 protected void setHomeNodeAuthorizations(User user) {
104 // give all privileges on user home
105 // FIXME: fails on an empty repo
106 String userId = "<not yet set>";
107 try {
108 userId = user.getID();
109 Node userHome = null;
110 try {
111 userHome = JcrUtils.getUserHome(getSystemSession(), userId);
112 if (userHome == null)
113 userHome = JcrUtils.createUserHome(getSystemSession(),
114 HOME_BASE_PATH, userId);
115 } catch (Exception e) {
116 // silent
117 }
118
119 if (userHome != null) {
120 String path = userHome.getPath();
121 Principal principal = user.getPrincipal();
122
123 JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession()
124 .getAccessControlManager();
125 JackrabbitAccessControlPolicy[] ps = acm
126 .getApplicablePolicies(principal);
127 if (ps.length == 0) {
128 log.warn("No ACL found for " + user);
129 return;
130 }
131
132 JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];
133
134 // add entry
135 Privilege[] privileges = new Privilege[] { acm
136 .privilegeFromName(Privilege.JCR_ALL) };
137 Map<String, Value> restrictions = new HashMap<String, Value>();
138 ValueFactory vf = getSystemSession().getValueFactory();
139 restrictions.put("rep:nodePath",
140 vf.createValue(path, PropertyType.PATH));
141 restrictions.put("rep:glob", vf.createValue("*"));
142 list.addEntry(principal, privileges, true /* allow or deny */,
143 restrictions);
144 }
145 } catch (Exception e) {
146 e.printStackTrace();
147 log.warn("Cannot set authorization on user node for " + userId
148 + ": " + e.getMessage());
149 }
150
151 }
152
153 @Override
154 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
155 WorkspaceAccessManager wam = super
156 .createDefaultWorkspaceAccessManager();
157 return new ArgeoWorkspaceAccessManagerImpl(wam);
158 }
159
160 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
161 WorkspaceAccessManager {
162 private final WorkspaceAccessManager wam;
163
164 // private String defaultWorkspace;
165
166 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
167 super();
168 this.wam = wam;
169 }
170
171 public void init(Session systemSession) throws RepositoryException {
172 wam.init(systemSession);
173 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
174 // .getDefaultWorkspaceName();
175 }
176
177 public void close() throws RepositoryException {
178 }
179
180 public boolean grants(Set<Principal> principals, String workspaceName)
181 throws RepositoryException {
182 // everybody has access to all workspaces
183 // TODO: implements finer access to workspaces
184 return true;
185
186 // anonymous has access to the default workspace (required for
187 // remoting which does a default login when initializing the
188 // repository)
189 // Boolean anonymous = false;
190 // for (Principal principal : principals)
191 // if (principal instanceof AnonymousPrincipal)
192 // anonymous = true;
193 //
194 // if (anonymous && workspaceName.equals(defaultWorkspace))
195 // return true;
196 // else
197 // return wam.grants(principals, workspaceName);
198 }
199 }
200
201 }