1 package org
.argeo
.security
.jackrabbit
;
3 import java
.security
.Principal
;
4 import java
.util
.ArrayList
;
5 import java
.util
.Iterator
;
10 import javax
.jcr
.RepositoryException
;
11 import javax
.jcr
.Session
;
12 import javax
.jcr
.security
.AccessControlList
;
13 import javax
.jcr
.security
.AccessControlManager
;
14 import javax
.jcr
.security
.AccessControlPolicy
;
15 import javax
.jcr
.security
.AccessControlPolicyIterator
;
16 import javax
.jcr
.security
.Privilege
;
17 import javax
.security
.auth
.Subject
;
19 import org
.apache
.commons
.logging
.Log
;
20 import org
.apache
.commons
.logging
.LogFactory
;
21 import org
.apache
.jackrabbit
.api
.security
.user
.Group
;
22 import org
.apache
.jackrabbit
.api
.security
.user
.User
;
23 import org
.apache
.jackrabbit
.api
.security
.user
.UserManager
;
24 import org
.apache
.jackrabbit
.core
.DefaultSecurityManager
;
25 import org
.apache
.jackrabbit
.core
.security
.SecurityConstants
;
26 import org
.apache
.jackrabbit
.core
.security
.SystemPrincipal
;
27 import org
.apache
.jackrabbit
.core
.security
.authorization
.WorkspaceAccessManager
;
28 import org
.argeo
.ArgeoException
;
29 import org
.argeo
.jcr
.JcrUtils
;
30 import org
.springframework
.security
.Authentication
;
31 import org
.springframework
.security
.GrantedAuthority
;
33 /** Intermediary class in order to have a consistent naming in config files. */
34 public class ArgeoSecurityManager
extends DefaultSecurityManager
{
35 public final static String HOME_BASE_PATH
= "/home";
37 private Log log
= LogFactory
.getLog(ArgeoSecurityManager
.class);
40 /** Since this is called once when the session is created, we take the opportunity to synchronize Spring and Jackrabbit users and groups.*/
41 public String
getUserID(Subject subject
, String workspaceName
)
42 throws RepositoryException
{
43 long begin
= System
.currentTimeMillis();
45 if (!subject
.getPrincipals(SystemPrincipal
.class).isEmpty())
46 return super.getUserID(subject
, workspaceName
);
48 Authentication authen
;
49 Set
<Authentication
> authens
= subject
50 .getPrincipals(Authentication
.class);
51 if (authens
.size() == 0)
52 throw new ArgeoException("No Spring authentication found in "
55 authen
= authens
.iterator().next();
57 UserManager systemUm
= getSystemUserManager(workspaceName
);
59 String userId
= authen
.getName();
60 User user
= (User
) systemUm
.getAuthorizable(userId
);
62 user
= systemUm
.createUser(userId
, authen
.getCredentials()
63 .toString(), authen
, null);
64 log
.info(userId
+ " added as " + user
);
67 setHomeNodeAuthorizations(user
);
70 List
<String
> userGroupIds
= new ArrayList
<String
>();
71 for (GrantedAuthority ga
: authen
.getAuthorities()) {
72 Group group
= (Group
) systemUm
.getAuthorizable(ga
.getAuthority());
74 group
= systemUm
.createGroup(ga
.getAuthority());
75 log
.info(ga
.getAuthority() + " added as " + group
);
77 if (!group
.isMember(user
))
78 group
.addMember(user
);
79 userGroupIds
.add(ga
.getAuthority());
83 // check if user has not been removed from some groups
84 for (Iterator
<Group
> it
= user
.declaredMemberOf(); it
.hasNext();) {
85 Group group
= it
.next();
86 if (!userGroupIds
.contains(group
.getID()))
87 group
.removeMember(user
);
90 if (log
.isTraceEnabled())
91 log
.trace("Spring and Jackrabbit Security synchronized for user "
92 + userId
+ " in " + (System
.currentTimeMillis() - begin
)
97 protected void setHomeNodeAuthorizations(User user
) {
98 // give all privileges on user home
99 // FIXME: fails on an empty repo
100 String userId
= "<not yet set>";
102 userId
= user
.getID();
103 Node userHome
= JcrUtils
.getUserHome(getSystemSession(), userId
);
104 // autocreate home node?
105 // if (userHome == null)
106 // userHome = JcrUtils.createUserHome(getSystemSession(),
107 // HOME_BASE_PATH, userId);
109 if (userHome
!= null) {
110 String path
= userHome
.getPath();
111 AccessControlPolicy policy
= null;
112 AccessControlManager acm
= getSystemSession()
113 .getAccessControlManager();
114 AccessControlPolicyIterator policyIterator
= acm
115 .getApplicablePolicies(path
);
116 if (policyIterator
.hasNext()) {
117 policy
= policyIterator
.nextAccessControlPolicy();
119 AccessControlPolicy
[] existingPolicies
= acm
121 policy
= existingPolicies
[0];
123 if (policy
instanceof AccessControlList
) {
124 Privilege
[] privileges
= { acm
125 .privilegeFromName(Privilege
.JCR_ALL
) };
126 ((AccessControlList
) policy
).addAccessControlEntry(
127 user
.getPrincipal(), privileges
);
128 acm
.setPolicy(path
, policy
);
131 } catch (Exception e
) {
132 log
.warn("Cannot set authorization on user node for " + userId
133 + ": " + e
.getMessage());
139 protected WorkspaceAccessManager
createDefaultWorkspaceAccessManager() {
140 WorkspaceAccessManager wam
= super
141 .createDefaultWorkspaceAccessManager();
142 return new ArgeoWorkspaceAccessManagerImpl(wam
);
145 private class ArgeoWorkspaceAccessManagerImpl
implements SecurityConstants
,
146 WorkspaceAccessManager
{
147 private final WorkspaceAccessManager wam
;
149 // private String defaultWorkspace;
151 public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam
) {
156 public void init(Session systemSession
) throws RepositoryException
{
157 wam
.init(systemSession
);
158 // defaultWorkspace = ((RepositoryImpl) getRepository()).getConfig()
159 // .getDefaultWorkspaceName();
162 public void close() throws RepositoryException
{
165 public boolean grants(Set
<Principal
> principals
, String workspaceName
)
166 throws RepositoryException
{
167 // everybody has access to all workspaces
168 // TODO: implements finer access to workspaces
171 // anonymous has access to the default workspace (required for
172 // remoting which does a default login when initializing the
174 // Boolean anonymous = false;
175 // for (Principal principal : principals)
176 // if (principal instanceof AnonymousPrincipal)
179 // if (anonymous && workspaceName.equals(defaultWorkspace))
182 // return wam.grants(principals, workspaceName);