1 package org
.argeo
.cms
.internal
.kernel
;
3 import java
.security
.PrivilegedAction
;
4 import java
.text
.SimpleDateFormat
;
6 import java
.util
.HashSet
;
10 import javax
.jcr
.Repository
;
11 import javax
.jcr
.RepositoryException
;
12 import javax
.jcr
.Session
;
13 import javax
.jcr
.nodetype
.NodeType
;
14 import javax
.jcr
.security
.Privilege
;
15 import javax
.naming
.InvalidNameException
;
16 import javax
.naming
.ldap
.LdapName
;
17 import javax
.security
.auth
.Subject
;
18 import javax
.security
.auth
.login
.LoginContext
;
20 import org
.argeo
.cms
.CmsException
;
21 import org
.argeo
.jcr
.JcrRepositoryWrapper
;
22 import org
.argeo
.jcr
.JcrUtils
;
23 import org
.argeo
.node
.NodeConstants
;
24 import org
.argeo
.node
.NodeNames
;
25 import org
.argeo
.node
.NodeTypes
;
26 import org
.argeo
.node
.NodeUtils
;
29 * Make sure each user has a home directory available in the default workspace.
31 class HomeRepository
extends JcrRepositoryWrapper
implements KernelConstants
{
33 /** The home base path. */
34 private String homeBasePath
= KernelConstants
.DEFAULT_HOME_BASE_PATH
;
35 private String usersBasePath
= KernelConstants
.DEFAULT_USERS_BASE_PATH
;
36 private String groupsBasePath
= KernelConstants
.DEFAULT_GROUPS_BASE_PATH
;
38 private Set
<String
> checkedUsers
= new HashSet
<String
>();
40 private SimpleDateFormat usersDatePath
= new SimpleDateFormat("YYYY/MM");
42 private final boolean remote
;
44 public HomeRepository(Repository repository
, boolean remote
) {
47 putDescriptor(NodeConstants
.CN
, NodeConstants
.HOME
);
51 lc
= new LoginContext(NodeConstants
.LOGIN_CONTEXT_DATA_ADMIN
);
53 } catch (javax
.security
.auth
.login
.LoginException e1
) {
54 throw new CmsException("Cannot login as systrem", e1
);
56 Subject
.doAs(lc
.getSubject(), new PrivilegedAction
<Void
>() {
61 Session adminSession
= getRepository().login();
62 initJcr(adminSession
);
63 } catch (RepositoryException e
) {
64 throw new CmsException("Cannot init JCR home", e
);
74 protected void processNewSession(Session session
) {
75 String username
= session
.getUserID();
76 if (username
== null || username
.toString().equals(""))
78 if (session
.getUserID().equals(NodeConstants
.ROLE_ANONYMOUS
))
81 if (checkedUsers
.contains(username
))
83 Session adminSession
= KernelUtils
.openAdminSession(getRepository(), session
.getWorkspace().getName());
85 syncJcr(adminSession
, username
);
86 checkedUsers
.add(username
);
88 JcrUtils
.logoutQuietly(adminSession
);
95 /** Session is logged out. */
96 private void initJcr(Session adminSession
) {
98 JcrUtils
.mkdirs(adminSession
, homeBasePath
);
99 JcrUtils
.mkdirs(adminSession
, groupsBasePath
);
102 JcrUtils
.addPrivilege(adminSession
, homeBasePath
, NodeConstants
.ROLE_USER_ADMIN
, Privilege
.JCR_READ
);
103 JcrUtils
.addPrivilege(adminSession
, groupsBasePath
, NodeConstants
.ROLE_USER_ADMIN
, Privilege
.JCR_READ
);
105 } catch (RepositoryException e
) {
106 throw new CmsException("Cannot initialize home repository", e
);
108 JcrUtils
.logoutQuietly(adminSession
);
112 private void syncJcr(Session session
, String username
) {
114 Node userHome
= NodeUtils
.getUserHome(session
, username
);
115 if (userHome
== null) {
116 String homePath
= generateUserPath(username
);
117 if (session
.itemExists(homePath
))// duplicate user id
118 userHome
= session
.getNode(homePath
).getParent().addNode(JcrUtils
.lastPathElement(homePath
));
120 userHome
= JcrUtils
.mkdirs(session
, homePath
);
121 // userHome = JcrUtils.mkfolders(session, homePath);
122 userHome
.addMixin(NodeTypes
.NODE_USER_HOME
);
123 userHome
.setProperty(NodeNames
.LDAP_UID
, username
);
126 JcrUtils
.clearAccessControList(session
, homePath
, username
);
127 JcrUtils
.addPrivilege(session
, homePath
, username
, Privilege
.JCR_ALL
);
129 if (session
.hasPendingChanges())
131 } catch (RepositoryException e
) {
132 JcrUtils
.discardQuietly(session
);
133 throw new CmsException("Cannot sync node security model for " + username
, e
);
137 /** Generate path for a new user home */
138 private String
generateUserPath(String username
) {
141 dn
= new LdapName(username
);
142 } catch (InvalidNameException e
) {
143 throw new CmsException("Invalid name " + username
, e
);
145 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
146 int atIndex
= userId
.indexOf('@');
148 return homeBasePath
+ '/' + userId
;
150 return usersBasePath
+ '/' + usersDatePath
.format(new Date()) + '/' + userId
;
152 // if (atIndex > 0) {
153 // String domain = userId.substring(0, atIndex);
154 // String name = userId.substring(atIndex + 1);
155 // return base + '/' + domain + '/' + name;
156 // } else if (atIndex == 0 || atIndex == (userId.length() - 1)) {
157 // throw new CmsException("Unsupported username " + userId);
159 // return base + '/' + userId;
163 public void createWorkgroup(LdapName dn
) {
164 Session adminSession
= KernelUtils
.openAdminSession(this);
165 String cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
166 Node newWorkgroup
= NodeUtils
.getGroupHome(adminSession
, cn
);
167 if (newWorkgroup
!= null) {
168 JcrUtils
.logoutQuietly(adminSession
);
169 throw new CmsException("Workgroup " + newWorkgroup
+ " already exists for " + dn
);
172 // TODO enhance transformation of cn to a valid node name
173 // String relPath = cn.replaceAll("[^a-zA-Z0-9]", "_");
174 String relPath
= JcrUtils
.replaceInvalidChars(cn
);
175 newWorkgroup
= JcrUtils
.mkdirs(adminSession
.getNode(groupsBasePath
), relPath
, NodeType
.NT_UNSTRUCTURED
);
176 newWorkgroup
.addMixin(NodeTypes
.NODE_GROUP_HOME
);
177 newWorkgroup
.setProperty(NodeNames
.LDAP_CN
, cn
);
179 JcrUtils
.addPrivilege(adminSession
, newWorkgroup
.getPath(), dn
.toString(), Privilege
.JCR_ALL
);
181 } catch (RepositoryException e
) {
182 throw new CmsException("Cannot create workgroup", e
);
184 JcrUtils
.logoutQuietly(adminSession
);