1 package org
.argeo
.cms
.internal
.kernel
;
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
.NodeConstants
;
21 import org
.argeo
.api
.NodeUtils
;
22 import org
.argeo
.cms
.CmsException
;
23 import org
.argeo
.jcr
.JcrRepositoryWrapper
;
24 import org
.argeo
.jcr
.JcrUtils
;
27 * Make sure each user has a home directory available.
29 class EgoRepository
extends JcrRepositoryWrapper
implements KernelConstants
{
31 /** The home base path. */
32 // private String homeBasePath = KernelConstants.DEFAULT_HOME_BASE_PATH;
33 // private String usersBasePath = KernelConstants.DEFAULT_USERS_BASE_PATH;
34 // private String groupsBasePath = KernelConstants.DEFAULT_GROUPS_BASE_PATH;
36 private Set
<String
> checkedUsers
= new HashSet
<String
>();
38 private SimpleDateFormat usersDatePath
= new SimpleDateFormat("YYYY/MM");
40 private String defaultHomeWorkspace
= NodeConstants
.HOME
;
41 private String defaultGroupsWorkspace
= NodeConstants
.SRV
;
42 // private String defaultGuestsWorkspace = NodeConstants.GUESTS;
43 private final boolean remote
;
45 public EgoRepository(Repository repository
, boolean remote
) {
48 putDescriptor(NodeConstants
.CN
, NodeConstants
.EGO
);
52 lc
= new LoginContext(NodeConstants
.LOGIN_CONTEXT_DATA_ADMIN
);
54 } catch (javax
.security
.auth
.login
.LoginException e1
) {
55 throw new CmsException("Cannot login as systrem", e1
);
57 Subject
.doAs(lc
.getSubject(), new PrivilegedAction
<Void
>() {
61 loginOrCreateWorkspace(defaultHomeWorkspace
);
62 loginOrCreateWorkspace(defaultGroupsWorkspace
);
70 private void loginOrCreateWorkspace(String workspace
) {
71 Session adminSession
= null;
73 adminSession
= JcrUtils
.loginOrCreateWorkspace(getRepository(workspace
), workspace
);
74 // JcrUtils.addPrivilege(adminSession, "/", NodeConstants.ROLE_USER, Privilege.JCR_READ);
76 // initJcr(adminSession);
77 } catch (RepositoryException e
) {
78 throw new CmsException("Cannot init JCR home", e
);
80 JcrUtils
.logoutQuietly(adminSession
);
85 // public Session login(Credentials credentials, String workspaceName)
86 // throws LoginException, NoSuchWorkspaceException, RepositoryException {
87 // if (workspaceName == null) {
88 // return super.login(credentials, getUserHomeWorkspace());
90 // return super.login(credentials, workspaceName);
94 protected String
getUserHomeWorkspace() {
95 // TODO base on JAAS Subject metadata
96 return defaultHomeWorkspace
;
99 protected String
getGroupsWorkspace() {
100 // TODO base on JAAS Subject metadata
101 return defaultGroupsWorkspace
;
104 // protected String getGuestsWorkspace() {
105 // // TODO base on JAAS Subject metadata
106 // return defaultGuestsWorkspace;
110 protected void processNewSession(Session session
, String workspaceName
) {
111 String username
= session
.getUserID();
112 if (username
== null || username
.toString().equals(""))
114 if (session
.getUserID().equals(NodeConstants
.ROLE_ANONYMOUS
))
117 String userHomeWorkspace
= getUserHomeWorkspace();
118 if (workspaceName
== null || !workspaceName
.equals(userHomeWorkspace
))
121 if (checkedUsers
.contains(username
))
123 Session adminSession
= KernelUtils
.openAdminSession(getRepository(workspaceName
), workspaceName
);
125 syncJcr(adminSession
, username
);
126 checkedUsers
.add(username
);
128 JcrUtils
.logoutQuietly(adminSession
);
135 /** Session is logged out. */
136 private void initJcr(Session adminSession
) {
138 // JcrUtils.mkdirs(adminSession, homeBasePath);
139 // JcrUtils.mkdirs(adminSession, groupsBasePath);
142 // JcrUtils.addPrivilege(adminSession, homeBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
143 // JcrUtils.addPrivilege(adminSession, groupsBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
145 } catch (RepositoryException e
) {
146 throw new CmsException("Cannot initialize home repository", e
);
148 JcrUtils
.logoutQuietly(adminSession
);
152 protected synchronized void syncJcr(Session adminSession
, String username
) {
153 // only in the default workspace
154 // if (workspaceName != null)
157 if (username
.endsWith(NodeConstants
.ROLES_BASEDN
))
161 Node userHome
= NodeUtils
.getUserHome(adminSession
, username
);
162 if (userHome
== null) {
163 // String homePath = generateUserPath(username);
164 String userId
= extractUserId(username
);
165 // if (adminSession.itemExists(homePath))// duplicate user id
166 // userHome = adminSession.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
168 // userHome = JcrUtils.mkdirs(adminSession, homePath);
169 userHome
= adminSession
.getRootNode().addNode(userId
);
170 // userHome.addMixin(NodeTypes.NODE_USER_HOME);
171 userHome
.addMixin(NodeType
.MIX_CREATED
);
172 userHome
.addMixin(NodeType
.MIX_TITLE
);
173 userHome
.setProperty(Property
.JCR_ID
, username
);
174 // TODO use display name
175 userHome
.setProperty(Property
.JCR_TITLE
, userId
);
176 // userHome.setProperty(NodeNames.LDAP_UID, username);
179 JcrUtils
.clearAccessControList(adminSession
, userHome
.getPath(), username
);
180 JcrUtils
.addPrivilege(adminSession
, userHome
.getPath(), username
, Privilege
.JCR_ALL
);
181 // JackrabbitSecurityUtils.denyPrivilege(adminSession, userHome.getPath(), NodeConstants.ROLE_USER,
182 // Privilege.JCR_READ);
184 if (adminSession
.hasPendingChanges())
186 } catch (RepositoryException e
) {
187 JcrUtils
.discardQuietly(adminSession
);
188 throw new CmsException("Cannot sync node security model for " + username
, e
);
192 /** Generate path for a new user home */
193 private String
generateUserPath(String username
) {
196 dn
= new LdapName(username
);
197 } catch (InvalidNameException e
) {
198 throw new CmsException("Invalid name " + username
, e
);
200 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
202 // int atIndex = userId.indexOf('@');
203 // if (atIndex < 0) {
204 // return homeBasePath+'/' + userId;
206 // return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId;
210 private String
extractUserId(String username
) {
213 dn
= new LdapName(username
);
214 } catch (InvalidNameException e
) {
215 throw new CmsException("Invalid name " + username
, e
);
217 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
219 // int atIndex = userId.indexOf('@');
220 // if (atIndex < 0) {
221 // return homeBasePath+'/' + userId;
223 // return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId;
227 public void createWorkgroup(LdapName dn
) {
228 String groupsWorkspace
= getGroupsWorkspace();
229 Session adminSession
= KernelUtils
.openAdminSession(getRepository(groupsWorkspace
), groupsWorkspace
);
230 String cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
231 Node newWorkgroup
= NodeUtils
.getGroupHome(adminSession
, cn
);
232 if (newWorkgroup
!= null) {
233 JcrUtils
.logoutQuietly(adminSession
);
234 throw new CmsException("Workgroup " + newWorkgroup
+ " already exists for " + dn
);
237 // TODO enhance transformation of cn to a valid node name
238 // String relPath = cn.replaceAll("[^a-zA-Z0-9]", "_");
239 String relPath
= JcrUtils
.replaceInvalidChars(cn
);
240 newWorkgroup
= adminSession
.getRootNode().addNode(relPath
, NodeType
.NT_UNSTRUCTURED
);
241 // newWorkgroup = JcrUtils.mkdirs(adminSession.getNode(groupsBasePath), relPath, NodeType.NT_UNSTRUCTURED);
242 // newWorkgroup.addMixin(NodeTypes.NODE_GROUP_HOME);
243 newWorkgroup
.addMixin(NodeType
.MIX_CREATED
);
244 newWorkgroup
.addMixin(NodeType
.MIX_TITLE
);
245 newWorkgroup
.setProperty(Property
.JCR_ID
, dn
.toString());
246 newWorkgroup
.setProperty(Property
.JCR_TITLE
, cn
);
247 // newWorkgroup.setProperty(NodeNames.LDAP_CN, cn);
249 JcrUtils
.addPrivilege(adminSession
, newWorkgroup
.getPath(), dn
.toString(), Privilege
.JCR_ALL
);
251 } catch (RepositoryException e
) {
252 throw new CmsException("Cannot create workgroup", e
);
254 JcrUtils
.logoutQuietly(adminSession
);
259 public boolean isRemote() {