1 package org
.argeo
.security
.jackrabbit
;
3 import java
.security
.Principal
;
4 import java
.util
.ArrayList
;
5 import java
.util
.HashMap
;
6 import java
.util
.Iterator
;
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
;
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
;
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);
42 /** Since this is called once when the session is created, we take the opportunity to synchronize Spring and Jackrabbit users and groups.*/
43 public String
getUserID(Subject subject
, String workspaceName
)
44 throws RepositoryException
{
45 long begin
= System
.currentTimeMillis();
47 // skip Jackrabbit system user
48 if (!subject
.getPrincipals(SystemPrincipal
.class).isEmpty())
49 return super.getUserID(subject
, workspaceName
);
51 Authentication authen
;
52 Set
<Authentication
> authens
= subject
53 .getPrincipals(Authentication
.class);
54 if (authens
.size() == 0)
55 throw new ArgeoException("No Spring authentication found in "
58 authen
= authens
.iterator().next();
60 // skip argeo system authenticated
61 // if (authen instanceof SystemAuthentication)
62 // return super.getUserID(subject, workspaceName);
64 UserManager systemUm
= getSystemUserManager(workspaceName
);
66 String userId
= authen
.getName();
67 User user
= (User
) systemUm
.getAuthorizable(userId
);
69 user
= systemUm
.createUser(userId
, authen
.getCredentials()
70 .toString(), authen
, null);
71 log
.info(userId
+ " added as " + user
);
74 //setHomeNodeAuthorizations(user);
77 List
<String
> userGroupIds
= new ArrayList
<String
>();
78 for (GrantedAuthority ga
: authen
.getAuthorities()) {
79 Group group
= (Group
) systemUm
.getAuthorizable(ga
.getAuthority());
81 group
= systemUm
.createGroup(ga
.getAuthority());
82 log
.info(ga
.getAuthority() + " added as " + group
);
84 if (!group
.isMember(user
))
85 group
.addMember(user
);
86 userGroupIds
.add(ga
.getAuthority());
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
);
96 // write roles in profile for easy access
97 // if (!(authen instanceof SystemAuthentication)) {
98 // Node userProfile = JcrUtils.getUserProfile(getSystemSession(),
100 // boolean writeRoles = false;
101 // if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
102 // Value[] roles = userProfile.getProperty(ArgeoNames.ARGEO_REMOTE_ROLES)
104 // if (roles.length != userGroupIds.size())
105 // writeRoles = true;
107 // for (int i = 0; i < roles.length; i++)
108 // if (!roles[i].getString().equals(userGroupIds.get(i)))
109 // writeRoles = true;
111 // writeRoles = true;
114 // userProfile.getSession().getWorkspace().getVersionManager()
115 // .checkout(userProfile.getPath());
116 // String[] roleIds = userGroupIds.toArray(new String[userGroupIds
118 // userProfile.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
119 // JcrUtils.updateLastModified(userProfile);
120 // userProfile.getSession().save();
121 // userProfile.getSession().getWorkspace().getVersionManager()
122 // .checkin(userProfile.getPath());
126 if (log
.isTraceEnabled())
127 log
.trace("Spring and Jackrabbit Security synchronized for user "
128 + userId
+ " in " + (System
.currentTimeMillis() - begin
)
133 protected synchronized void setHomeNodeAuthorizations(User user
) {
134 // give all privileges on user home
135 // FIXME: fails on an empty repo
136 String userId
= "<not yet set>";
138 userId
= user
.getID();
139 Node userHome
= null;
141 userHome
= JcrUtils
.getUserHome(getSystemSession(), userId
);
142 if (userHome
== null) {
143 userHome
= JcrUtils
.createUserHomeIfNeeded(getSystemSession(), userId
);
144 //log.warn("No home available for user "+userId);
147 } catch (Exception e
) {
151 if (userHome
!= null) {
152 String path
= userHome
.getPath();
153 Principal principal
= user
.getPrincipal();
155 JackrabbitAccessControlManager acm
= (JackrabbitAccessControlManager
) getSystemSession()
156 .getAccessControlManager();
157 JackrabbitAccessControlPolicy
[] ps
= acm
158 .getApplicablePolicies(principal
);
159 if (ps
.length
== 0) {
160 // log.warn("No ACL found for " + user);
164 JackrabbitAccessControlList list
= (JackrabbitAccessControlList
) ps
[0];
167 Privilege
[] privileges
= new Privilege
[] { acm
168 .privilegeFromName(Privilege
.JCR_ALL
) };
169 Map
<String
, Value
> restrictions
= new HashMap
<String
, Value
>();
170 ValueFactory vf
= getSystemSession().getValueFactory();
171 restrictions
.put("rep:nodePath",
172 vf
.createValue(path
, PropertyType
.PATH
));
173 restrictions
.put("rep:glob", vf
.createValue("*"));
174 list
.addEntry(principal
, privileges
, true /* allow or deny */,
177 } catch (Exception e
) {
179 log
.warn("Cannot set authorization on user node for " + userId
180 + ": " + e
.getMessage());
186 protected WorkspaceAccessManager
createDefaultWorkspaceAccessManager() {
187 WorkspaceAccessManager wam
= super
188 .createDefaultWorkspaceAccessManager();
189 return new ArgeoWorkspaceAccessManagerImpl(wam
);
192 private class ArgeoWorkspaceAccessManagerImpl
implements SecurityConstants
,
193 WorkspaceAccessManager
{
194 private final WorkspaceAccessManager wam
;
196 // private String defaultWorkspace;
198 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam
) {
203 public void init(Session systemSession
) throws RepositoryException
{
204 wam
.init(systemSession
);
205 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
206 // .getDefaultWorkspaceName();
209 public void close() throws RepositoryException
{
212 public boolean grants(Set
<Principal
> principals
, String workspaceName
)
213 throws RepositoryException
{
214 // everybody has access to all workspaces
215 // TODO: implements finer access to workspaces
218 // anonymous has access to the default workspace (required for
219 // remoting which does a default login when initializing the
221 // Boolean anonymous = false;
222 // for (Principal principal : principals)
223 // if (principal instanceof AnonymousPrincipal)
226 // if (anonymous && workspaceName.equals(defaultWorkspace))
229 // return wam.grants(principals, workspaceName);