]> git.argeo.org Git - lgpl/argeo-commons.git/blob - security/runtime/org.argeo.security.jackrabbit/src/main/java/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
Remove annoying warning
[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.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.SecurityConstants;
30 import org.apache.jackrabbit.core.security.SystemPrincipal;
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 public final static String HOME_BASE_PATH = "/home";
40
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 synchronized 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 = null;
108 try {
109 userHome = JcrUtils.getUserHome(getSystemSession(), userId);
110 if (userHome == null)
111 userHome = JcrUtils.createUserHome(getSystemSession(),
112 HOME_BASE_PATH, userId);
113 } catch (Exception e) {
114 // silent
115 }
116
117 if (userHome != null) {
118 String path = userHome.getPath();
119 Principal principal = user.getPrincipal();
120
121 JackrabbitAccessControlManager acm = (JackrabbitAccessControlManager) getSystemSession()
122 .getAccessControlManager();
123 JackrabbitAccessControlPolicy[] ps = acm
124 .getApplicablePolicies(principal);
125 if (ps.length == 0) {
126 // log.warn("No ACL found for " + user);
127 return;
128 }
129
130 JackrabbitAccessControlList list = (JackrabbitAccessControlList) ps[0];
131
132 // add entry
133 Privilege[] privileges = new Privilege[] { acm
134 .privilegeFromName(Privilege.JCR_ALL) };
135 Map<String, Value> restrictions = new HashMap<String, Value>();
136 ValueFactory vf = getSystemSession().getValueFactory();
137 restrictions.put("rep:nodePath",
138 vf.createValue(path, PropertyType.PATH));
139 restrictions.put("rep:glob", vf.createValue("*"));
140 list.addEntry(principal, privileges, true /* allow or deny */,
141 restrictions);
142 }
143 } catch (Exception e) {
144 e.printStackTrace();
145 log.warn("Cannot set authorization on user node for " + userId
146 + ": " + e.getMessage());
147 }
148
149 }
150
151 @Override
152 protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() {
153 WorkspaceAccessManager wam = super
154 .createDefaultWorkspaceAccessManager();
155 return new ArgeoWorkspaceAccessManagerImpl(wam);
156 }
157
158 private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants,
159 WorkspaceAccessManager {
160 private final WorkspaceAccessManager wam;
161
162 // private String defaultWorkspace;
163
164 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) {
165 super();
166 this.wam = wam;
167 }
168
169 public void init(Session systemSession) throws RepositoryException {
170 wam.init(systemSession);
171 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
172 // .getDefaultWorkspaceName();
173 }
174
175 public void close() throws RepositoryException {
176 }
177
178 public boolean grants(Set<Principal> principals, String workspaceName)
179 throws RepositoryException {
180 // everybody has access to all workspaces
181 // TODO: implements finer access to workspaces
182 return true;
183
184 // anonymous has access to the default workspace (required for
185 // remoting which does a default login when initializing the
186 // repository)
187 // Boolean anonymous = false;
188 // for (Principal principal : principals)
189 // if (principal instanceof AnonymousPrincipal)
190 // anonymous = true;
191 //
192 // if (anonymous && workspaceName.equals(defaultWorkspace))
193 // return true;
194 // else
195 // return wam.grants(principals, workspaceName);
196 }
197 }
198
199 }