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
.CmsException
;
23 import org
.argeo
.cms
.jcr
.CmsJcrUtils
;
24 import org
.argeo
.jcr
.JcrException
;
25 import org
.argeo
.jcr
.JcrRepositoryWrapper
;
26 import org
.argeo
.jcr
.JcrUtils
;
29 * Make sure each user has a home directory available.
31 class EgoRepository
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 String defaultHomeWorkspace
= CmsConstants
.HOME_WORKSPACE
;
43 private String defaultGroupsWorkspace
= CmsConstants
.SRV_WORKSPACE
;
44 // private String defaultGuestsWorkspace = NodeConstants.GUESTS_WORKSPACE;
45 private final boolean remote
;
47 public EgoRepository(Repository repository
, boolean remote
) {
50 putDescriptor(CmsConstants
.CN
, CmsConstants
.EGO_REPOSITORY
);
54 lc
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_DATA_ADMIN
);
56 } catch (javax
.security
.auth
.login
.LoginException e1
) {
57 throw new IllegalStateException("Cannot login as system", e1
);
59 Subject
.doAs(lc
.getSubject(), new PrivilegedAction
<Void
>() {
63 loginOrCreateWorkspace(defaultHomeWorkspace
);
64 loginOrCreateWorkspace(defaultGroupsWorkspace
);
72 private void loginOrCreateWorkspace(String workspace
) {
73 Session adminSession
= null;
75 adminSession
= JcrUtils
.loginOrCreateWorkspace(getRepository(workspace
), workspace
);
76 // JcrUtils.addPrivilege(adminSession, "/", NodeConstants.ROLE_USER, Privilege.JCR_READ);
78 // initJcr(adminSession);
79 } catch (RepositoryException e
) {
80 throw new JcrException("Cannot init JCR home", e
);
82 JcrUtils
.logoutQuietly(adminSession
);
87 // public Session login(Credentials credentials, String workspaceName)
88 // throws LoginException, NoSuchWorkspaceException, RepositoryException {
89 // if (workspaceName == null) {
90 // return super.login(credentials, getUserHomeWorkspace());
92 // return super.login(credentials, workspaceName);
96 protected String
getUserHomeWorkspace() {
97 // TODO base on JAAS Subject metadata
98 return defaultHomeWorkspace
;
101 protected String
getGroupsWorkspace() {
102 // TODO base on JAAS Subject metadata
103 return defaultGroupsWorkspace
;
106 // protected String getGuestsWorkspace() {
107 // // TODO base on JAAS Subject metadata
108 // return defaultGuestsWorkspace;
112 protected void processNewSession(Session session
, String workspaceName
) {
113 String username
= session
.getUserID();
114 if (username
== null || username
.toString().equals(""))
116 if (session
.getUserID().equals(CmsConstants
.ROLE_ANONYMOUS
))
119 String userHomeWorkspace
= getUserHomeWorkspace();
120 if (workspaceName
== null || !workspaceName
.equals(userHomeWorkspace
))
123 if (checkedUsers
.contains(username
))
125 Session adminSession
= KernelUtils
.openAdminSession(getRepository(workspaceName
), workspaceName
);
127 syncJcr(adminSession
, username
);
128 checkedUsers
.add(username
);
130 JcrUtils
.logoutQuietly(adminSession
);
137 /** Session is logged out. */
138 private void initJcr(Session adminSession
) {
140 // JcrUtils.mkdirs(adminSession, homeBasePath);
141 // JcrUtils.mkdirs(adminSession, groupsBasePath);
144 // JcrUtils.addPrivilege(adminSession, homeBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
145 // JcrUtils.addPrivilege(adminSession, groupsBasePath, NodeConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
147 } catch (RepositoryException e
) {
148 throw new CmsException("Cannot initialize home repository", e
);
150 JcrUtils
.logoutQuietly(adminSession
);
154 protected synchronized void syncJcr(Session adminSession
, String username
) {
155 // only in the default workspace
156 // if (workspaceName != null)
159 if (username
.endsWith(CmsConstants
.ROLES_BASEDN
))
163 Node userHome
= CmsJcrUtils
.getUserHome(adminSession
, username
);
164 if (userHome
== null) {
165 // String homePath = generateUserPath(username);
166 String userId
= extractUserId(username
);
167 // if (adminSession.itemExists(homePath))// duplicate user id
168 // userHome = adminSession.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
170 // userHome = JcrUtils.mkdirs(adminSession, homePath);
171 userHome
= adminSession
.getRootNode().addNode(userId
);
172 // userHome.addMixin(NodeTypes.NODE_USER_HOME);
173 userHome
.addMixin(NodeType
.MIX_CREATED
);
174 userHome
.addMixin(NodeType
.MIX_TITLE
);
175 userHome
.setProperty(Property
.JCR_ID
, username
);
176 // TODO use display name
177 userHome
.setProperty(Property
.JCR_TITLE
, userId
);
178 // userHome.setProperty(NodeNames.LDAP_UID, username);
181 JcrUtils
.clearAccessControList(adminSession
, userHome
.getPath(), username
);
182 JcrUtils
.addPrivilege(adminSession
, userHome
.getPath(), username
, Privilege
.JCR_ALL
);
183 // JackrabbitSecurityUtils.denyPrivilege(adminSession, userHome.getPath(), NodeConstants.ROLE_USER,
184 // Privilege.JCR_READ);
186 if (adminSession
.hasPendingChanges())
188 } catch (RepositoryException e
) {
189 JcrUtils
.discardQuietly(adminSession
);
190 throw new JcrException("Cannot sync node security model for " + username
, e
);
194 /** Generate path for a new user home */
195 private String
generateUserPath(String username
) {
198 dn
= new LdapName(username
);
199 } catch (InvalidNameException e
) {
200 throw new CmsException("Invalid name " + username
, e
);
202 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
204 // int atIndex = userId.indexOf('@');
205 // if (atIndex < 0) {
206 // return homeBasePath+'/' + userId;
208 // return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId;
212 private String
extractUserId(String username
) {
215 dn
= new LdapName(username
);
216 } catch (InvalidNameException e
) {
217 throw new CmsException("Invalid name " + username
, e
);
219 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
221 // int atIndex = userId.indexOf('@');
222 // if (atIndex < 0) {
223 // return homeBasePath+'/' + userId;
225 // return usersBasePath + '/' + usersDatePath.format(new Date()) + '/' + userId;
229 public void createWorkgroup(LdapName dn
) {
230 String groupsWorkspace
= getGroupsWorkspace();
231 Session adminSession
= KernelUtils
.openAdminSession(getRepository(groupsWorkspace
), groupsWorkspace
);
232 String cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
233 Node newWorkgroup
= CmsJcrUtils
.getGroupHome(adminSession
, cn
);
234 if (newWorkgroup
!= null) {
235 JcrUtils
.logoutQuietly(adminSession
);
236 throw new CmsException("Workgroup " + newWorkgroup
+ " already exists for " + dn
);
239 // TODO enhance transformation of cn to a valid node name
240 // String relPath = cn.replaceAll("[^a-zA-Z0-9]", "_");
241 String relPath
= JcrUtils
.replaceInvalidChars(cn
);
242 newWorkgroup
= adminSession
.getRootNode().addNode(relPath
, NodeType
.NT_UNSTRUCTURED
);
243 // newWorkgroup = JcrUtils.mkdirs(adminSession.getNode(groupsBasePath), relPath, NodeType.NT_UNSTRUCTURED);
244 // newWorkgroup.addMixin(NodeTypes.NODE_GROUP_HOME);
245 newWorkgroup
.addMixin(NodeType
.MIX_CREATED
);
246 newWorkgroup
.addMixin(NodeType
.MIX_TITLE
);
247 newWorkgroup
.setProperty(Property
.JCR_ID
, dn
.toString());
248 newWorkgroup
.setProperty(Property
.JCR_TITLE
, cn
);
249 // newWorkgroup.setProperty(NodeNames.LDAP_CN, cn);
251 JcrUtils
.addPrivilege(adminSession
, newWorkgroup
.getPath(), dn
.toString(), Privilege
.JCR_ALL
);
253 } catch (RepositoryException e
) {
254 throw new CmsException("Cannot create workgroup", e
);
256 JcrUtils
.logoutQuietly(adminSession
);
261 public boolean isRemote() {