1 package org
.argeo
.cms
.jcr
.internal
;
3 import java
.security
.PrivilegedAction
;
4 import java
.text
.SimpleDateFormat
;
5 import java
.util
.HashSet
;
9 import javax
.jcr
.Property
;
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
.api
.cms
.CmsAuth
;
21 import org
.argeo
.api
.cms
.CmsConstants
;
22 import org
.argeo
.cms
.jcr
.CmsJcrUtils
;
23 import org
.argeo
.jcr
.JcrException
;
24 import org
.argeo
.jcr
.JcrRepositoryWrapper
;
25 import org
.argeo
.jcr
.JcrUtils
;
28 * Make sure each user has a home directory available.
30 class EgoRepository
extends JcrRepositoryWrapper
{
32 /** The home base path. */
33 // private String homeBasePath = KernelConstants.DEFAULT_HOME_BASE_PATH;
34 // private String usersBasePath = KernelConstants.DEFAULT_USERS_BASE_PATH;
35 // private String groupsBasePath = KernelConstants.DEFAULT_GROUPS_BASE_PATH;
37 private Set
<String
> checkedUsers
= new HashSet
<String
>();
39 private SimpleDateFormat usersDatePath
= new SimpleDateFormat("YYYY/MM");
41 private String defaultHomeWorkspace
= CmsConstants
.HOME_WORKSPACE
;
42 private String defaultGroupsWorkspace
= CmsConstants
.SRV_WORKSPACE
;
43 // private String defaultGuestsWorkspace = NodeConstants.GUESTS_WORKSPACE;
44 private final boolean remote
;
46 public EgoRepository(Repository repository
, boolean remote
) {
49 putDescriptor(CmsConstants
.CN
, CmsConstants
.EGO_REPOSITORY
);
53 lc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_DATA_ADMIN
);
55 } catch (javax
.security
.auth
.login
.LoginException e1
) {
56 throw new IllegalStateException("Cannot login as system", e1
);
58 Subject
.doAs(lc
.getSubject(), new PrivilegedAction
<Void
>() {
62 loginOrCreateWorkspace(defaultHomeWorkspace
);
63 loginOrCreateWorkspace(defaultGroupsWorkspace
);
71 private void loginOrCreateWorkspace(String workspace
) {
72 Session adminSession
= null;
74 adminSession
= JcrUtils
.loginOrCreateWorkspace(getRepository(workspace
), workspace
);
75 // JcrUtils.addPrivilege(adminSession, "/", NodeConstants.ROLE_USER, Privilege.JCR_READ);
77 // initJcr(adminSession);
78 } catch (RepositoryException e
) {
79 throw new JcrException("Cannot init JCR home", e
);
81 JcrUtils
.logoutQuietly(adminSession
);
86 // public Session login(Credentials credentials, String workspaceName)
87 // throws LoginException, NoSuchWorkspaceException, RepositoryException {
88 // if (workspaceName == null) {
89 // return super.login(credentials, getUserHomeWorkspace());
91 // return super.login(credentials, workspaceName);
95 protected String
getUserHomeWorkspace() {
96 // TODO base on JAAS Subject metadata
97 return defaultHomeWorkspace
;
100 protected String
getGroupsWorkspace() {
101 // TODO base on JAAS Subject metadata
102 return defaultGroupsWorkspace
;
105 // protected String getGuestsWorkspace() {
106 // // TODO base on JAAS Subject metadata
107 // return defaultGuestsWorkspace;
111 protected void processNewSession(Session session
, String workspaceName
) {
112 String username
= session
.getUserID();
113 if (username
== null || username
.toString().equals(""))
115 if (session
.getUserID().equals(CmsConstants
.ROLE_ANONYMOUS
))
118 String userHomeWorkspace
= getUserHomeWorkspace();
119 if (workspaceName
== null || !workspaceName
.equals(userHomeWorkspace
))
122 if (checkedUsers
.contains(username
))
124 Session adminSession
= KernelUtils
.openAdminSession(getRepository(workspaceName
), workspaceName
);
126 syncJcr(adminSession
, username
);
127 checkedUsers
.add(username
);
129 JcrUtils
.logoutQuietly(adminSession
);
136 /** Session is logged out. */
137 private void initJcr(Session adminSession
) {
139 // JcrUtils.mkdirs(adminSession, homeBasePath);
140 // JcrUtils.mkdirs(adminSession, groupsBasePath);
143 // JcrUtils.addPrivilege(adminSession, homeBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
144 // JcrUtils.addPrivilege(adminSession, groupsBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
146 } catch (RepositoryException e
) {
147 throw new JcrException("Cannot initialize home repository", e
);
149 JcrUtils
.logoutQuietly(adminSession
);
153 protected synchronized void syncJcr(Session adminSession
, String username
) {
154 // only in the default workspace
155 // if (workspaceName != null)
158 if (username
.endsWith(CmsConstants
.SYSTEM_ROLES_BASEDN
))
162 Node userHome
= CmsJcrUtils
.getUserHome(adminSession
, username
);
163 if (userHome
== null) {
164 // String homePath = generateUserPath(username);
165 String userId
= extractUserId(username
);
166 // if (adminSession.itemExists(homePath))// duplicate user id
167 // userHome = adminSession.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
169 // userHome = JcrUtils.mkdirs(adminSession, homePath);
170 userHome
= adminSession
.getRootNode().addNode(userId
);
171 // userHome.addMixin(NodeTypes.NODE_USER_HOME);
172 userHome
.addMixin(NodeType
.MIX_CREATED
);
173 userHome
.addMixin(NodeType
.MIX_TITLE
);
174 userHome
.setProperty(Property
.JCR_ID
, username
);
175 // TODO use display name
176 userHome
.setProperty(Property
.JCR_TITLE
, userId
);
177 // userHome.setProperty(NodeNames.LDAP_UID, username);
180 JcrUtils
.clearAccessControList(adminSession
, userHome
.getPath(), username
);
181 JcrUtils
.addPrivilege(adminSession
, userHome
.getPath(), username
, Privilege
.JCR_ALL
);
182 // JackrabbitSecurityUtils.denyPrivilege(adminSession, userHome.getPath(), NodeConstants.ROLE_USER,
183 // Privilege.JCR_READ);
185 if (adminSession
.hasPendingChanges())
187 } catch (RepositoryException e
) {
188 JcrUtils
.discardQuietly(adminSession
);
189 throw new JcrException("Cannot sync node security model for " + username
, e
);
193 /** Generate path for a new user home */
194 private String
generateUserPath(String username
) {
197 dn
= new LdapName(username
);
198 } catch (InvalidNameException e
) {
199 throw new IllegalArgumentException("Invalid name " + username
, e
);
201 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
203 // int atIndex = userId.indexOf('@');
204 // if (atIndex < 0) {
205 // return homeBasePath+'/' + userId;
207 // return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId;
211 private String
extractUserId(String username
) {
214 dn
= new LdapName(username
);
215 } catch (InvalidNameException e
) {
216 throw new IllegalArgumentException("Invalid name " + username
, e
);
218 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
220 // int atIndex = userId.indexOf('@');
221 // if (atIndex < 0) {
222 // return homeBasePath+'/' + userId;
224 // return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId;
228 public void createWorkgroup(LdapName dn
) {
229 String groupsWorkspace
= getGroupsWorkspace();
230 Session adminSession
= KernelUtils
.openAdminSession(getRepository(groupsWorkspace
), groupsWorkspace
);
231 String cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
232 Node newWorkgroup
= CmsJcrUtils
.getGroupHome(adminSession
, cn
);
233 if (newWorkgroup
!= null) {
234 JcrUtils
.logoutQuietly(adminSession
);
235 throw new IllegalStateException("Workgroup " + newWorkgroup
+ " already exists for " + dn
);
238 // TODO enhance transformation of cn to a valid node name
239 // String relPath = cn.replaceAll("[^a-zA-Z0-9]", "_");
240 String relPath
= JcrUtils
.replaceInvalidChars(cn
);
241 newWorkgroup
= adminSession
.getRootNode().addNode(relPath
, NodeType
.NT_UNSTRUCTURED
);
242 // newWorkgroup = JcrUtils.mkdirs(adminSession.getNode(groupsBasePath), relPath, NodeType.NT_UNSTRUCTURED);
243 // newWorkgroup.addMixin(NodeTypes.NODE_GROUP_HOME);
244 newWorkgroup
.addMixin(NodeType
.MIX_CREATED
);
245 newWorkgroup
.addMixin(NodeType
.MIX_TITLE
);
246 newWorkgroup
.setProperty(Property
.JCR_ID
, dn
.toString());
247 newWorkgroup
.setProperty(Property
.JCR_TITLE
, cn
);
248 // newWorkgroup.setProperty(NodeNames.LDAP_CN, cn);
250 JcrUtils
.addPrivilege(adminSession
, newWorkgroup
.getPath(), dn
.toString(), Privilege
.JCR_ALL
);
252 } catch (RepositoryException e
) {
253 throw new JcrException("Cannot create workgroup", e
);
255 JcrUtils
.logoutQuietly(adminSession
);
260 public boolean isRemote() {