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