]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/kernel/HomeRepository.java
Don't use context user to generate path.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / HomeRepository.java
1 package org.argeo.cms.internal.kernel;
2
3 import java.security.PrivilegedAction;
4 import java.util.HashSet;
5 import java.util.Set;
6
7 import javax.jcr.Node;
8 import javax.jcr.Repository;
9 import javax.jcr.RepositoryException;
10 import javax.jcr.Session;
11 import javax.jcr.security.Privilege;
12 import javax.naming.InvalidNameException;
13 import javax.naming.ldap.LdapName;
14 import javax.security.auth.Subject;
15 import javax.security.auth.login.LoginContext;
16
17 import org.apache.jackrabbit.core.security.SecurityConstants;
18 import org.argeo.cms.CmsException;
19 import org.argeo.cms.auth.AuthConstants;
20 import org.argeo.jcr.ArgeoJcrConstants;
21 import org.argeo.jcr.ArgeoNames;
22 import org.argeo.jcr.ArgeoTypes;
23 import org.argeo.jcr.JcrRepositoryWrapper;
24 import org.argeo.jcr.JcrUtils;
25 import org.argeo.jcr.UserJcrUtils;
26
27 /**
28 * Make sure each user has a home directory available in the default workspace.
29 */
30 class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, ArgeoJcrConstants {
31 // private final Kernel kernel;
32
33 /** The home base path. */
34 private String homeBasePath = "/home";
35 private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH;
36
37 private Set<String> checkedUsers = new HashSet<String>();
38
39 public HomeRepository(Repository repository) {
40 // this.kernel = kernel;
41 setRepository(repository);
42 LoginContext lc;
43 try {
44 lc = new LoginContext(AuthConstants.LOGIN_CONTEXT_DATA_ADMIN);
45 lc.login();
46 } catch (javax.security.auth.login.LoginException e1) {
47 throw new CmsException("Cannot login as systrem", e1);
48 }
49 Subject.doAs(lc.getSubject(), new PrivilegedAction<Void>() {
50
51 @Override
52 public Void run() {
53 try {
54 initJcr(getRepository().login());
55 } catch (RepositoryException e) {
56 throw new CmsException("Cannot init JCR home", e);
57 }
58 return null;
59 }
60
61 });
62 }
63
64 // @Override
65 // public Session login() throws LoginException, RepositoryException {
66 // Session session = super.login();
67 // String username = session.getUserID();
68 // if (username == null)
69 // return session;
70 // if (session.getUserID().equals(AuthConstants.ROLE_ANONYMOUS))
71 // return session;
72 //
73 // if (checkedUsers.contains(username))
74 // return session;
75 // Session adminSession = KernelUtils.openAdminSession(getRepository(),
76 // session.getWorkspace().getName());
77 // try {
78 // syncJcr(adminSession, username);
79 // checkedUsers.add(username);
80 // } finally {
81 // JcrUtils.logoutQuietly(adminSession);
82 // }
83 // return session;
84 // }
85
86 @Override
87 protected void processNewSession(Session session) {
88 String username = session.getUserID();
89 if (username == null)
90 return;
91 if (session.getUserID().equals(AuthConstants.ROLE_ANONYMOUS))
92 return;
93 if (session.getUserID().equals(AuthConstants.ROLE_KERNEL))
94 return;
95 if (session.getUserID().equals(SecurityConstants.ADMIN_ID))
96 return;
97
98 if (checkedUsers.contains(username))
99 return;
100 Session adminSession = KernelUtils.openAdminSession(getRepository(), session.getWorkspace().getName());
101 try {
102 syncJcr(adminSession, username);
103 checkedUsers.add(username);
104 } finally {
105 JcrUtils.logoutQuietly(adminSession);
106 }
107 }
108
109 /*
110 * JCR
111 */
112 /** Session is logged out. */
113 private void initJcr(Session adminSession) {
114 try {
115 JcrUtils.mkdirs(adminSession, homeBasePath);
116 JcrUtils.mkdirs(adminSession, peopleBasePath);
117 adminSession.save();
118
119 JcrUtils.addPrivilege(adminSession, homeBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
120 JcrUtils.addPrivilege(adminSession, peopleBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL);
121 adminSession.save();
122 } catch (RepositoryException e) {
123 throw new CmsException("Cannot initialize node user admin", e);
124 } finally {
125 JcrUtils.logoutQuietly(adminSession);
126 }
127 }
128
129 private Node syncJcr(Session session, String username) {
130 try {
131 Node userHome = UserJcrUtils.getUserHome(session, username);
132 if (userHome == null) {
133 String homePath = generateUserPath(homeBasePath, username);
134 if (session.itemExists(homePath))// duplicate user id
135 userHome = session.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
136 else
137 userHome = JcrUtils.mkdirs(session, homePath);
138 // userHome = JcrUtils.mkfolders(session, homePath);
139 userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
140 userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
141 session.save();
142
143 JcrUtils.clearAccessControList(session, homePath, username);
144 JcrUtils.addPrivilege(session, homePath, username, Privilege.JCR_ALL);
145 }
146
147 Node userProfile = UserJcrUtils.getUserProfile(session, username);
148 // new user
149 if (userProfile == null) {
150 String personPath = generateUserPath(peopleBasePath, username);
151 Node personBase;
152 if (session.itemExists(personPath))// duplicate user id
153 personBase = session.getNode(personPath).getParent().addNode(JcrUtils.lastPathElement(personPath));
154 else
155 personBase = JcrUtils.mkdirs(session, personPath);
156 userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
157 userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
158 userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
159 // userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
160 // userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED,
161 // true);
162 // userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED,
163 // true);
164 // userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED,
165 // true);
166 session.save();
167
168 JcrUtils.clearAccessControList(session, userProfile.getPath(), username);
169 JcrUtils.addPrivilege(session, userProfile.getPath(), username, Privilege.JCR_READ);
170 }
171
172 // Remote roles
173 // if (roles != null) {
174 // writeRemoteRoles(userProfile, roles);
175 // }
176 if (session.hasPendingChanges())
177 session.save();
178 return userProfile;
179 } catch (RepositoryException e) {
180 JcrUtils.discardQuietly(session);
181 throw new CmsException("Cannot sync node security model for " + username, e);
182 }
183 }
184
185 /** Generate path for a new user home */
186 private String generateUserPath(String base, String username) {
187 LdapName dn;
188 try {
189 dn = new LdapName(username);
190 } catch (InvalidNameException e) {
191 throw new CmsException("Invalid name " + username, e);
192 }
193 String userId = dn.getRdn(dn.size() - 1).getValue().toString();
194 int atIndex = userId.indexOf('@');
195 if (atIndex > 0) {
196 String domain = userId.substring(0, atIndex);
197 String name = userId.substring(atIndex + 1);
198 return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + domain + '/'
199 + JcrUtils.firstCharsToPath(name, 2) + '/' + name;
200 } else if (atIndex == 0 || atIndex == (userId.length() - 1)) {
201 throw new CmsException("Unsupported username " + userId);
202 } else {
203 return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + userId;
204 }
205 }
206
207 }