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